dcbnl.c revision 7ec79270d7de0c8ca602c47cb25a9652ec28f37f
12f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/*
22f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Copyright (c) 2008, Intel Corporation.
32f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
42f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * This program is free software; you can redistribute it and/or modify it
52f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * under the terms and conditions of the GNU General Public License,
62f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * version 2, as published by the Free Software Foundation.
72f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
82f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * This program is distributed in the hope it will be useful, but WITHOUT
92f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * more details.
122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * You should have received a copy of the GNU General Public License along with
142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Place - Suite 330, Boston, MA 02111-1307 USA.
162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Author: Lucy Liu <lucy.liu@intel.com>
182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck */
192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <linux/netdevice.h>
212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <linux/netlink.h>
225a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <net/netlink.h>
242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <net/rtnetlink.h>
252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <linux/dcbnl.h>
2696b99684e365f28d49bdb1221ca022b75cb91a98John Fastabend#include <net/dcbevent.h>
272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <linux/rtnetlink.h>
282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <net/sock.h>
292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/**
312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Data Center Bridging (DCB) is a collection of Ethernet enhancements
322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * intended to allow network traffic with differing requirements
332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * (highly reliable, no drops vs. best effort vs. low latency) to operate
342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * and co-exist on Ethernet.  Current DCB features are:
352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Enhanced Transmission Selection (aka Priority Grouping [PG]) - provides a
372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *   framework for assigning bandwidth guarantees to traffic classes.
382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Priority-based Flow Control (PFC) - provides a flow control mechanism which
402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *   can work independently for each 802.1p priority.
412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Congestion Notification - provides a mechanism for end-to-end congestion
432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *   control for protocols which do not have built-in congestion management.
442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * More information about the emerging standards for these Ethernet features
462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * can be found at: http://www.ieee802.org/1/pages/dcbridges.html
472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * This file implements an rtnetlink interface to allow configuration of DCB
492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * features for capable devices.
502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck */
512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander DuyckMODULE_AUTHOR("Lucy Liu, <lucy.liu@intel.com>");
537a6b6f515f77d1c62a2f383b6dce18cb0af0cf4fJeff KirsherMODULE_DESCRIPTION("Data Center Bridging netlink interface");
542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander DuyckMODULE_LICENSE("GPL");
552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/**************** DCB attribute policies *************************************/
572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB netlink attributes policy */
59b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = {
60859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_IFNAME]      = {.type = NLA_NUL_STRING, .len = IFNAMSIZ - 1},
61859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_STATE]       = {.type = NLA_U8},
62859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_PFC_CFG]     = {.type = NLA_NESTED},
63859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_PG_CFG]      = {.type = NLA_NESTED},
64859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_SET_ALL]     = {.type = NLA_U8},
652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG},
66859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_CAP]         = {.type = NLA_NESTED},
67859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_PFC_STATE]   = {.type = NLA_U8},
68859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_BCN]         = {.type = NLA_NESTED},
696fa382af61338908e5713234bcee598423f661c3Yi Zou	[DCB_ATTR_APP]         = {.type = NLA_NESTED},
703e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	[DCB_ATTR_IEEE]	       = {.type = NLA_NESTED},
716241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	[DCB_ATTR_DCBX]        = {.type = NLA_U8},
72ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_ATTR_FEATCFG]     = {.type = NLA_NESTED},
732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck};
742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB priority flow control to User Priority nested attributes */
76b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = {
772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_0]   = {.type = NLA_U8},
782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_1]   = {.type = NLA_U8},
792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_2]   = {.type = NLA_U8},
802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_3]   = {.type = NLA_U8},
812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_4]   = {.type = NLA_U8},
822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_5]   = {.type = NLA_U8},
832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_6]   = {.type = NLA_U8},
842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_7]   = {.type = NLA_U8},
852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_ALL] = {.type = NLA_FLAG},
862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck};
872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB priority grouping nested attributes */
89b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = {
902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_0]      = {.type = NLA_NESTED},
912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_1]      = {.type = NLA_NESTED},
922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_2]      = {.type = NLA_NESTED},
932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_3]      = {.type = NLA_NESTED},
942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_4]      = {.type = NLA_NESTED},
952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_5]      = {.type = NLA_NESTED},
962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_6]      = {.type = NLA_NESTED},
972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_7]      = {.type = NLA_NESTED},
982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_ALL]    = {.type = NLA_NESTED},
992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_0]   = {.type = NLA_U8},
1002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_1]   = {.type = NLA_U8},
1012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_2]   = {.type = NLA_U8},
1022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_3]   = {.type = NLA_U8},
1032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_4]   = {.type = NLA_U8},
1042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_5]   = {.type = NLA_U8},
1052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_6]   = {.type = NLA_U8},
1062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_7]   = {.type = NLA_U8},
1072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_ALL] = {.type = NLA_FLAG},
1082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck};
1092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB traffic class nested attributes. */
111b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = {
1122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_PGID]            = {.type = NLA_U8},
1132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_UP_MAPPING]      = {.type = NLA_U8},
1142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_STRICT_PRIO]     = {.type = NLA_U8},
1152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_BW_PCT]          = {.type = NLA_U8},
1162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_ALL]             = {.type = NLA_FLAG},
1172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck};
1182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
11946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck/* DCB capabilities nested attributes. */
120b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = {
12146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_ALL]     = {.type = NLA_FLAG},
12246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_PG]      = {.type = NLA_U8},
12346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_PFC]     = {.type = NLA_U8},
12446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_UP2TC]   = {.type = NLA_U8},
12546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_PG_TCS]  = {.type = NLA_U8},
12646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8},
12746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_GSP]     = {.type = NLA_U8},
12846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_BCN]     = {.type = NLA_U8},
1296241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	[DCB_CAP_ATTR_DCBX]    = {.type = NLA_U8},
13046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck};
1312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
13233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck/* DCB capabilities nested attributes. */
133b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = {
13433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	[DCB_NUMTCS_ATTR_ALL]     = {.type = NLA_FLAG},
13533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	[DCB_NUMTCS_ATTR_PG]      = {.type = NLA_U8},
13633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	[DCB_NUMTCS_ATTR_PFC]     = {.type = NLA_U8},
13733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck};
13833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
139859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck/* DCB BCN nested attributes. */
140b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = {
141859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_0]         = {.type = NLA_U8},
142859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_1]         = {.type = NLA_U8},
143859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_2]         = {.type = NLA_U8},
144859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_3]         = {.type = NLA_U8},
145859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_4]         = {.type = NLA_U8},
146859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_5]         = {.type = NLA_U8},
147859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_6]         = {.type = NLA_U8},
148859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_7]         = {.type = NLA_U8},
149859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_ALL]       = {.type = NLA_FLAG},
150f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	[DCB_BCN_ATTR_BCNA_0]       = {.type = NLA_U32},
151f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	[DCB_BCN_ATTR_BCNA_1]       = {.type = NLA_U32},
152859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_ALPHA]        = {.type = NLA_U32},
153859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_BETA]         = {.type = NLA_U32},
154859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_GD]           = {.type = NLA_U32},
155859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_GI]           = {.type = NLA_U32},
156859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_TMAX]         = {.type = NLA_U32},
157859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_TD]           = {.type = NLA_U32},
158859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RMIN]         = {.type = NLA_U32},
159859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_W]            = {.type = NLA_U32},
160859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RD]           = {.type = NLA_U32},
161859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RU]           = {.type = NLA_U32},
162859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_WRTT]         = {.type = NLA_U32},
163859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RI]           = {.type = NLA_U32},
164859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_C]            = {.type = NLA_U32},
165859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_ALL]          = {.type = NLA_FLAG},
166859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck};
167859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1686fa382af61338908e5713234bcee598423f661c3Yi Zou/* DCB APP nested attributes. */
169b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = {
1706fa382af61338908e5713234bcee598423f661c3Yi Zou	[DCB_APP_ATTR_IDTYPE]       = {.type = NLA_U8},
1716fa382af61338908e5713234bcee598423f661c3Yi Zou	[DCB_APP_ATTR_ID]           = {.type = NLA_U16},
1726fa382af61338908e5713234bcee598423f661c3Yi Zou	[DCB_APP_ATTR_PRIORITY]     = {.type = NLA_U8},
1736fa382af61338908e5713234bcee598423f661c3Yi Zou};
1746fa382af61338908e5713234bcee598423f661c3Yi Zou
1753e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend/* IEEE 802.1Qaz nested attributes. */
1763e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabendstatic const struct nla_policy dcbnl_ieee_policy[DCB_ATTR_IEEE_MAX + 1] = {
1773e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	[DCB_ATTR_IEEE_ETS]	    = {.len = sizeof(struct ieee_ets)},
1783e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	[DCB_ATTR_IEEE_PFC]	    = {.len = sizeof(struct ieee_pfc)},
1793e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	[DCB_ATTR_IEEE_APP_TABLE]   = {.type = NLA_NESTED},
1803e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend};
1813e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
1823e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabendstatic const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = {
1833e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	[DCB_ATTR_IEEE_APP]	    = {.len = sizeof(struct dcb_app)},
1843e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend};
1853e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
186ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid/* DCB number of traffic classes nested attributes. */
187ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravidstatic const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = {
188ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_FEATCFG_ATTR_ALL]      = {.type = NLA_FLAG},
189ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_FEATCFG_ATTR_PG]       = {.type = NLA_U8},
190ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_FEATCFG_ATTR_PFC]      = {.type = NLA_U8},
191ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_FEATCFG_ATTR_APP]      = {.type = NLA_U8},
192ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid};
193ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1949ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendstatic LIST_HEAD(dcb_app_list);
1959ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendstatic DEFINE_SPINLOCK(dcb_lock);
1969ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
1972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* standard netlink reply call */
1982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
1992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                       u32 seq, u16 flags)
2002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
2022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
2032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
2042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
2052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
2082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
2092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags);
2112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
2132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
2142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = cmd;
2152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_pad = 0;
2162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_put_u8(dcbnl_skb, attr, value);
2182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
2192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
2202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	/* end the message, assign the nlmsg_len. */
2222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
2232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
2242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
2257eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		return -EINVAL;
2262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
2282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
2292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
230858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
2312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
2322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getstate(struct net_device *netdev, struct nlattr **tb,
2352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                          u32 pid, u32 seq, u16 flags)
2362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
2382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	/* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */
2402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops->getstate)
2412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
2422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(netdev->dcbnl_ops->getstate(netdev), RTM_GETDCB,
2442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  DCB_CMD_GSTATE, DCB_ATTR_STATE, pid, seq, flags);
2452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
2472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb,
2502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                           u32 pid, u32 seq, u16 flags)
2512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
2532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
2542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
2552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest;
2562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
2572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
2582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
2592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int getall = 0;
2602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->getpfccfg)
2622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
2632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
2652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PFC_CFG],
2662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       dcbnl_pfc_up_nest);
2672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
2682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
2692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
2722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
2732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
2752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
2772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
2782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = DCB_CMD_PFC_GCFG;
2792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG);
2812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!nest)
2822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
2832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (data[DCB_PFC_UP_ATTR_ALL])
2852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
2862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
2882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !data[i])
2892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
2902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0,
2922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                             &value);
2932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_put_u8(dcbnl_skb, i, value);
2942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret) {
2962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			nla_nest_cancel(dcbnl_skb, nest);
2972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err;
2982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
2992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
3002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_end(dcbnl_skb, nest);
3012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
3032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
3052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
3067eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
3072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
3092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
3102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
311858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
3122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out:
3132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return -EINVAL;
3142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
3152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb,
3172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                                u32 pid, u32 seq, u16 flags)
3182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
3192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
3202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
3212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
3222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 perm_addr[MAX_ADDR_LEN];
3232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
3242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops->getpermhwaddr)
3262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
3272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
3302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
3312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
3332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
3352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
3362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = DCB_CMD_GPERM_HWADDR;
3372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
3392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr),
3412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	              perm_addr);
3422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
3442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
3462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
3477eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
3482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
3502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
352858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
3532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out:
3542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return -EINVAL;
3552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
3562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
35746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckstatic int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb,
35846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck                        u32 pid, u32 seq, u16 flags)
35946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck{
36046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct sk_buff *dcbnl_skb;
36146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct nlmsghdr *nlh;
36246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct dcbmsg *dcb;
36346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest;
36446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	u8 value;
36546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int ret = -EINVAL;
36646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int i;
36746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int getall = 0;
36846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
36946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap)
37046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		return ret;
37146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
37246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP],
37346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	                       dcbnl_cap_nest);
37446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (ret)
37546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto err_out;
37646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
37746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
37846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!dcbnl_skb)
37946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto err_out;
38046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
38146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
38246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
38346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcb = NLMSG_DATA(nlh);
38446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
38546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcb->cmd = DCB_CMD_GCAP;
38646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
38746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP);
38846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!nest)
38946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto err;
39046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
39146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (data[DCB_CAP_ATTR_ALL])
39246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		getall = 1;
39346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
39446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) {
39546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		if (!getall && !data[i])
39646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			continue;
39746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
39846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) {
39946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			ret = nla_put_u8(dcbnl_skb, i, value);
40046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
40146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			if (ret) {
40246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck				nla_nest_cancel(dcbnl_skb, nest);
40346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck				goto err;
40446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			}
40546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		}
40646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	}
40746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nla_nest_end(dcbnl_skb, nest);
40846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
40946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
41046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
41146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
41246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (ret)
4137eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
41446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
41546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	return 0;
41646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duycknlmsg_failure:
41746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckerr:
418858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
41946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckerr_out:
42046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	return -EINVAL;
42146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck}
42246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
42333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckstatic int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb,
42433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck                           u32 pid, u32 seq, u16 flags)
42533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{
42633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct sk_buff *dcbnl_skb;
42733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlmsghdr *nlh;
42833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct dcbmsg *dcb;
42933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest;
43033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	u8 value;
43133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int ret = -EINVAL;
43233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int i;
43333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int getall = 0;
43433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
43533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs)
43633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		return ret;
43733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
43833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
43933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                       dcbnl_numtcs_nest);
44033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (ret) {
44133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
44233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err_out;
44333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
44433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
44533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
44633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (!dcbnl_skb) {
44733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
44833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err_out;
44933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
45033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
45133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
45233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
45333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcb = NLMSG_DATA(nlh);
45433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
45533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcb->cmd = DCB_CMD_GNUMTCS;
45633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
45733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS);
45833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (!nest) {
45933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
46033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err;
46133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
46233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
46333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (data[DCB_NUMTCS_ATTR_ALL])
46433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		getall = 1;
46533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
46633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
46733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (!getall && !data[i])
46833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			continue;
46933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
47033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value);
47133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (!ret) {
47233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			ret = nla_put_u8(dcbnl_skb, i, value);
47333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
47433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			if (ret) {
47533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck				nla_nest_cancel(dcbnl_skb, nest);
47633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck				ret = -EINVAL;
47733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck				goto err;
47833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			}
47933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		} else {
48033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			goto err;
48133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		}
48233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
48333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nla_nest_end(dcbnl_skb, nest);
48433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
48533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
48633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
48733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
48833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (ret) {
48933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
4907eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
49133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
49233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
49333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return 0;
49433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duycknlmsg_failure:
49533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr:
496858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
49733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr_out:
49833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return ret;
49933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck}
50033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
50133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckstatic int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb,
50233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck                           u32 pid, u32 seq, u16 flags)
50333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{
50433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1];
50533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int ret = -EINVAL;
50633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	u8 value;
50733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int i;
50833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
5098b124a8e14c04378466ddfe63e41fc5035f957ebDon Skidmore	if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setnumtcs)
51033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		return ret;
51133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
51233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
51333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                       dcbnl_numtcs_nest);
51433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
51533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (ret) {
51633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
51733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err;
51833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
51933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
52033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
52133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (data[i] == NULL)
52233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			continue;
52333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
52433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		value = nla_get_u8(data[i]);
52533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
52633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value);
52733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
52833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (ret)
52933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			goto operr;
53033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
53133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
53233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckoperr:
53333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS,
53433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                  DCB_ATTR_NUMTCS, pid, seq, flags);
53533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
53633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr:
53733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return ret;
53833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck}
53933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
5400eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyckstatic int dcbnl_getpfcstate(struct net_device *netdev, struct nlattr **tb,
5410eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
5420eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{
5430eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	int ret = -EINVAL;
5440eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5450eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	if (!netdev->dcbnl_ops->getpfcstate)
5460eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		return ret;
5470eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5480eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	ret = dcbnl_reply(netdev->dcbnl_ops->getpfcstate(netdev), RTM_GETDCB,
5490eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	                  DCB_CMD_PFC_GSTATE, DCB_ATTR_PFC_STATE,
5500eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	                  pid, seq, flags);
5510eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5520eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	return ret;
5530eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck}
5540eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5550eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyckstatic int dcbnl_setpfcstate(struct net_device *netdev, struct nlattr **tb,
5560eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
5570eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{
5580eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	int ret = -EINVAL;
5590eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	u8 value;
5600eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5610eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	if (!tb[DCB_ATTR_PFC_STATE] || !netdev->dcbnl_ops->setpfcstate)
5620eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		return ret;
5630eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5640eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]);
5650eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5660eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	netdev->dcbnl_ops->setpfcstate(netdev, value);
5670eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5680eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SSTATE, DCB_ATTR_PFC_STATE,
5690eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	                  pid, seq, flags);
5700eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5710eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	return ret;
5720eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck}
5730eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
574579496865cf4ea429146382d62047ffdbaab0deeYi Zoustatic int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb,
575579496865cf4ea429146382d62047ffdbaab0deeYi Zou                        u32 pid, u32 seq, u16 flags)
576579496865cf4ea429146382d62047ffdbaab0deeYi Zou{
577579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct sk_buff *dcbnl_skb;
578579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlmsghdr *nlh;
579579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct dcbmsg *dcb;
580579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_nest;
581579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
582579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u16 id;
583579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u8 up, idtype;
584579496865cf4ea429146382d62047ffdbaab0deeYi Zou	int ret = -EINVAL;
585579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5863dce38a02d6370dca690cd923619d4b00024b723John Fastabend	if (!tb[DCB_ATTR_APP])
587579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
588579496865cf4ea429146382d62047ffdbaab0deeYi Zou
589579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
590579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                       dcbnl_app_nest);
591579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
592579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
593579496865cf4ea429146382d62047ffdbaab0deeYi Zou
594579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = -EINVAL;
595579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* all must be non-null */
596579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
597579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_ID]))
598579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
599579496865cf4ea429146382d62047ffdbaab0deeYi Zou
600579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* either by eth type or by socket number */
601579496865cf4ea429146382d62047ffdbaab0deeYi Zou	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
602579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
603579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (idtype != DCB_APP_IDTYPE_PORTNUM))
604579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
605579496865cf4ea429146382d62047ffdbaab0deeYi Zou
606579496865cf4ea429146382d62047ffdbaab0deeYi Zou	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
6073dce38a02d6370dca690cd923619d4b00024b723John Fastabend
6083dce38a02d6370dca690cd923619d4b00024b723John Fastabend	if (netdev->dcbnl_ops->getapp) {
6093dce38a02d6370dca690cd923619d4b00024b723John Fastabend		up = netdev->dcbnl_ops->getapp(netdev, idtype, id);
6103dce38a02d6370dca690cd923619d4b00024b723John Fastabend	} else {
6113dce38a02d6370dca690cd923619d4b00024b723John Fastabend		struct dcb_app app = {
6123dce38a02d6370dca690cd923619d4b00024b723John Fastabend					.selector = idtype,
6133dce38a02d6370dca690cd923619d4b00024b723John Fastabend					.protocol = id,
6143dce38a02d6370dca690cd923619d4b00024b723John Fastabend				     };
6153dce38a02d6370dca690cd923619d4b00024b723John Fastabend		up = dcb_getapp(netdev, &app);
6163dce38a02d6370dca690cd923619d4b00024b723John Fastabend	}
617579496865cf4ea429146382d62047ffdbaab0deeYi Zou
618579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* send this back */
619579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
620579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (!dcbnl_skb)
621579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
622579496865cf4ea429146382d62047ffdbaab0deeYi Zou
623579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
624579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcb = NLMSG_DATA(nlh);
625579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcb->dcb_family = AF_UNSPEC;
626579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcb->cmd = DCB_CMD_GAPP;
627579496865cf4ea429146382d62047ffdbaab0deeYi Zou
628579496865cf4ea429146382d62047ffdbaab0deeYi Zou	app_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_APP);
629579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype);
630579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
631579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
632579496865cf4ea429146382d62047ffdbaab0deeYi Zou
633579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_put_u16(dcbnl_skb, DCB_APP_ATTR_ID, id);
634579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
635579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
636579496865cf4ea429146382d62047ffdbaab0deeYi Zou
637579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_PRIORITY, up);
638579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
639579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
640579496865cf4ea429146382d62047ffdbaab0deeYi Zou
641579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nla_nest_end(dcbnl_skb, app_nest);
642579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nlmsg_end(dcbnl_skb, nlh);
643579496865cf4ea429146382d62047ffdbaab0deeYi Zou
644579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
645579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
646579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto nlmsg_failure;
647579496865cf4ea429146382d62047ffdbaab0deeYi Zou
648579496865cf4ea429146382d62047ffdbaab0deeYi Zou	goto out;
649579496865cf4ea429146382d62047ffdbaab0deeYi Zou
650579496865cf4ea429146382d62047ffdbaab0deeYi Zouout_cancel:
651579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nla_nest_cancel(dcbnl_skb, app_nest);
652579496865cf4ea429146382d62047ffdbaab0deeYi Zounlmsg_failure:
653579496865cf4ea429146382d62047ffdbaab0deeYi Zou	kfree_skb(dcbnl_skb);
654579496865cf4ea429146382d62047ffdbaab0deeYi Zouout:
655579496865cf4ea429146382d62047ffdbaab0deeYi Zou	return ret;
656579496865cf4ea429146382d62047ffdbaab0deeYi Zou}
657579496865cf4ea429146382d62047ffdbaab0deeYi Zou
658579496865cf4ea429146382d62047ffdbaab0deeYi Zoustatic int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb,
659579496865cf4ea429146382d62047ffdbaab0deeYi Zou                        u32 pid, u32 seq, u16 flags)
660579496865cf4ea429146382d62047ffdbaab0deeYi Zou{
6619ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	int err, ret = -EINVAL;
662579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u16 id;
663579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u8 up, idtype;
664579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
665579496865cf4ea429146382d62047ffdbaab0deeYi Zou
6669ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (!tb[DCB_ATTR_APP])
667579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
668579496865cf4ea429146382d62047ffdbaab0deeYi Zou
669579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
670579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                       dcbnl_app_nest);
671579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
672579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
673579496865cf4ea429146382d62047ffdbaab0deeYi Zou
674579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = -EINVAL;
675579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* all must be non-null */
676579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
677579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_ID]) ||
678579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_PRIORITY]))
679579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
680579496865cf4ea429146382d62047ffdbaab0deeYi Zou
681579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* either by eth type or by socket number */
682579496865cf4ea429146382d62047ffdbaab0deeYi Zou	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
683579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
684579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (idtype != DCB_APP_IDTYPE_PORTNUM))
685579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
686579496865cf4ea429146382d62047ffdbaab0deeYi Zou
687579496865cf4ea429146382d62047ffdbaab0deeYi Zou	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
688579496865cf4ea429146382d62047ffdbaab0deeYi Zou	up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]);
689579496865cf4ea429146382d62047ffdbaab0deeYi Zou
6909ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (netdev->dcbnl_ops->setapp) {
6919ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		err = netdev->dcbnl_ops->setapp(netdev, idtype, id, up);
6929ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	} else {
6939ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		struct dcb_app app;
6949ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.selector = idtype;
6959ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.protocol = id;
6969ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.priority = up;
6979ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		err = dcb_setapp(netdev, &app);
6989ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
6999ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
7009ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	ret = dcbnl_reply(err, RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP,
7019ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			  pid, seq, flags);
702579496865cf4ea429146382d62047ffdbaab0deeYi Zouout:
703579496865cf4ea429146382d62047ffdbaab0deeYi Zou	return ret;
704579496865cf4ea429146382d62047ffdbaab0deeYi Zou}
705579496865cf4ea429146382d62047ffdbaab0deeYi Zou
7062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb,
7072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags, int dir)
7082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
7092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
7102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
7112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
7122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_nest, *param_nest, *data;
7132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
7142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
7152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 prio, pgid, tc_pct, up_map;
7162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret  = -EINVAL;
7172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int getall = 0;
7182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
7192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PG_CFG] ||
7212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgtccfgtx ||
7222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgtccfgrx ||
7232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgbwgcfgtx ||
7242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgbwgcfgrx)
7252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
7262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
7282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
7292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
7312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
7322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
7352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
7362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
7382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
7402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
7412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = (dir) ? DCB_CMD_PGRX_GCFG : DCB_CMD_PGTX_GCFG;
7422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	pg_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PG_CFG);
7442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!pg_nest)
7452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
7462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (pg_tb[DCB_PG_ATTR_TC_ALL])
7482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
7492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
7512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !pg_tb[i])
7522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
7532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (pg_tb[DCB_PG_ATTR_TC_ALL])
7552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data = pg_tb[DCB_PG_ATTR_TC_ALL];
7562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		else
7572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data = pg_tb[i];
7582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
7592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				       data, dcbnl_tc_param_nest);
7602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
7612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
7622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		param_nest = nla_nest_start(dcbnl_skb, i);
7642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!param_nest)
7652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
7662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		pgid = DCB_ATTR_VALUE_UNDEFINED;
7682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		prio = DCB_ATTR_VALUE_UNDEFINED;
7692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
7702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		up_map = DCB_ATTR_VALUE_UNDEFINED;
7712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
7732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
7742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgtccfgrx(netdev,
7752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						i - DCB_PG_ATTR_TC_0, &prio,
7762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						&pgid, &tc_pct, &up_map);
7772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
7782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
7792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgtccfgtx(netdev,
7802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						i - DCB_PG_ATTR_TC_0, &prio,
7812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						&pgid, &tc_pct, &up_map);
7822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
7832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_PGID] ||
7852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb,
7872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_PGID, pgid);
7882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
7892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
7902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
7912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] ||
7922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb,
7942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
7952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
7962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
7972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
7982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] ||
7992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
8002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb,
8012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
8022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
8032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
8042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] ||
8062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
8072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_BW_PCT,
8082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 tc_pct);
8092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
8102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
8112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		nla_nest_end(dcbnl_skb, param_nest);
8132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
8142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (pg_tb[DCB_PG_ATTR_BW_ID_ALL])
8162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
8172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	else
8182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 0;
8192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
8212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !pg_tb[i])
8222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
8232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
8252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
8272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
8282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgbwgcfgrx(netdev,
8292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
8302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
8312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
8322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgbwgcfgtx(netdev,
8332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
8342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_put_u8(dcbnl_skb, i, tc_pct);
8362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
8382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
8392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
8402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_end(dcbnl_skb, pg_nest);
8422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
8442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
8462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
8477eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
8482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
8502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_param:
8522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_cancel(dcbnl_skb, param_nest);
8532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_pg:
8542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_cancel(dcbnl_skb, pg_nest);
8552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
8562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
857858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
8582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out:
8592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret  = -EINVAL;
8602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
8612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlattr **tb,
8642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
8652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 0);
8672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlattr **tb,
8702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
8712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 1);
8732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb,
8762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                          u32 pid, u32 seq, u16 flags)
8772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
8792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
8802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate)
8822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
8832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	value = nla_get_u8(tb[DCB_ATTR_STATE]);
8852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8861486a61ebcd2711532f8163d30babc40e11e7b40Don Skidmore	ret = dcbnl_reply(netdev->dcbnl_ops->setstate(netdev, value),
8871486a61ebcd2711532f8163d30babc40e11e7b40Don Skidmore	                  RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE,
8882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  pid, seq, flags);
8892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
8912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb,
8942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                           u32 pid, u32 seq, u16 flags)
8952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1];
8972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
8982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
8992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
9002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->setpfccfg)
9022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
9032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
9052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PFC_CFG],
9062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       dcbnl_pfc_up_nest);
9072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
9082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
9092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
9112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (data[i] == NULL)
9122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
9132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		value = nla_get_u8(data[i]);
9142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		netdev->dcbnl_ops->setpfccfg(netdev,
9152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data[i]->nla_type - DCB_PFC_UP_ATTR_0, value);
9162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
9172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SCFG, DCB_ATTR_PFC_CFG,
9192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  pid, seq, flags);
9202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
9212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
9222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
9232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setall(struct net_device *netdev, struct nlattr **tb,
9252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                        u32 pid, u32 seq, u16 flags)
9262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
9272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
9282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall)
9302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
9312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(netdev->dcbnl_ops->setall(netdev), RTM_SETDCB,
9332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  DCB_CMD_SET_ALL, DCB_ATTR_SET_ALL, pid, seq, flags);
9342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
9362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
9372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb,
9392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags, int dir)
9402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
9412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
9422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
9432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
9442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
9452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 pgid;
9462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 up_map;
9472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 prio;
9482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 tc_pct;
9492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PG_CFG] ||
9512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgtccfgtx ||
9522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgtccfgrx ||
9532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgbwgcfgtx ||
9542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgbwgcfgrx)
9552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
9562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
9582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
9592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
9602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
9612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
9632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!pg_tb[i])
9642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
9652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
9672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                       pg_tb[i], dcbnl_tc_param_nest);
9682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
9692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err;
9702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		pgid = DCB_ATTR_VALUE_UNDEFINED;
9722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		prio = DCB_ATTR_VALUE_UNDEFINED;
9732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
9742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		up_map = DCB_ATTR_VALUE_UNDEFINED;
9752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO])
9772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			prio =
9782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			    nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]);
9792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_PGID])
9812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]);
9822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT])
9842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]);
9852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING])
9872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			up_map =
9882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			     nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]);
9892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		/* dir: Tx = 0, Rx = 1 */
9912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
9922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
9932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgtccfgrx(netdev,
9942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				i - DCB_PG_ATTR_TC_0,
9952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				prio, pgid, tc_pct, up_map);
9962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
9972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
9982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgtccfgtx(netdev,
9992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				i - DCB_PG_ATTR_TC_0,
10002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				prio, pgid, tc_pct, up_map);
10012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
10022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
10032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
10052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!pg_tb[i])
10062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
10072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = nla_get_u8(pg_tb[i]);
10092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		/* dir: Tx = 0, Rx = 1 */
10112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
10122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
10132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgbwgcfgrx(netdev,
10142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
10152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
10162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
10172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgbwgcfgtx(netdev,
10182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
10192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
10202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
10212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB,
10232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG),
10242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  DCB_ATTR_PG_CFG, pid, seq, flags);
10252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
10272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
10282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
10292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlattr **tb,
10312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
10322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
10332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 0);
10342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
10352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb,
10372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
10382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
10392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1);
10402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
10412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1042859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckstatic int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb,
1043859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck                            u32 pid, u32 seq, u16 flags)
1044859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck{
1045859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct sk_buff *dcbnl_skb;
1046859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlmsghdr *nlh;
1047859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct dcbmsg *dcb;
1048859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *bcn_nest;
1049859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1];
1050859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u8 value_byte;
1051859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u32 value_integer;
1052859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int ret  = -EINVAL;
1053859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	bool getall = false;
1054859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int i;
1055859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1056859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->getbcnrp ||
1057859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	    !netdev->dcbnl_ops->getbcncfg)
1058859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		return ret;
1059859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1060859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX,
1061859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       tb[DCB_ATTR_BCN], dcbnl_bcn_nest);
1062859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1063859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
1064859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err_out;
1065859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1066859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1067859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!dcbnl_skb)
1068859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err_out;
1069859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1070859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1071859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1072859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcb = NLMSG_DATA(nlh);
1073859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
1074859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcb->cmd = DCB_CMD_BCN_GCFG;
1075859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1076859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	bcn_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_BCN);
1077859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!bcn_nest)
1078859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err;
1079859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1080859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (bcn_tb[DCB_BCN_ATTR_ALL])
1081859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		getall = true;
1082859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1083859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
1084859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (!getall && !bcn_tb[i])
1085859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1086859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1087859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0,
1088859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                            &value_byte);
1089859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = nla_put_u8(dcbnl_skb, i, value_byte);
1090859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (ret)
1091859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			goto err_bcn;
1092859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1093859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1094f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
1095859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (!getall && !bcn_tb[i])
1096859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1097859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1098859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->getbcncfg(netdev, i,
1099859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                             &value_integer);
1100859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = nla_put_u32(dcbnl_skb, i, value_integer);
1101859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (ret)
1102859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			goto err_bcn;
1103859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1104859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1105859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nla_nest_end(dcbnl_skb, bcn_nest);
1106859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1107859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
1108859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1109859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
1110859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
11117eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
1112859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1113859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return 0;
1114859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1115859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr_bcn:
1116859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nla_nest_cancel(dcbnl_skb, bcn_nest);
1117859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duycknlmsg_failure:
1118859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr:
1119858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
1120859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr_out:
1121859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret  = -EINVAL;
1122859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return ret;
1123859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck}
1124859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1125859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckstatic int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlattr **tb,
1126859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck                            u32 pid, u32 seq, u16 flags)
1127859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck{
1128859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *data[DCB_BCN_ATTR_MAX + 1];
1129859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int i;
1130859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int ret = -EINVAL;
1131859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u8 value_byte;
1132859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u32 value_int;
1133859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1134f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches	if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg ||
1135f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches	    !netdev->dcbnl_ops->setbcnrp)
1136859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		return ret;
1137859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1138859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX,
1139859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       tb[DCB_ATTR_BCN],
1140859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       dcbnl_pfc_up_nest);
1141859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
1142859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err;
1143859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1144859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
1145859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (data[i] == NULL)
1146859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1147859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		value_byte = nla_get_u8(data[i]);
1148859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->setbcnrp(netdev,
1149859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte);
1150859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1151859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1152f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
1153859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (data[i] == NULL)
1154859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1155859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		value_int = nla_get_u32(data[i]);
1156859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->setbcncfg(netdev,
1157859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                                     i, value_int);
1158859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1159859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1160859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_BCN_SCFG, DCB_ATTR_BCN,
1161859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                  pid, seq, flags);
1162859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr:
1163859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return ret;
1164859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck}
1165859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
11663e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
11673e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend * be completed the entire msg is aborted and error value is returned.
11683e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend * No attempt is made to reconcile the case where only part of the
11693e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend * cmd can be completed.
11703e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend */
11713e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabendstatic int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
11723e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend			  u32 pid, u32 seq, u16 flags)
11733e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend{
11743e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
11753e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
11763e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	int err = -EOPNOTSUPP;
11773e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
11783e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (!ops)
11793e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		goto err;
11803e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
11813e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
11823e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
11833e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (err)
11843e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		goto err;
11853e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
11863e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
11873e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
11883e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		err = ops->ieee_setets(netdev, ets);
11893e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		if (err)
11903e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend			goto err;
11913e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	}
11923e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
11933e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setets) {
11943e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
11953e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		err = ops->ieee_setpfc(netdev, pfc);
11963e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		if (err)
11973e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend			goto err;
11983e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	}
11993e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12009ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
12013e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		struct nlattr *attr;
12023e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		int rem;
12033e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12043e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
12053e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend			struct dcb_app *app_data;
12063e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
12073e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend				continue;
12083e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend			app_data = nla_data(attr);
12099ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			if (ops->ieee_setapp)
12109ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend				err = ops->ieee_setapp(netdev, app_data);
12119ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			else
12129ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend				err = dcb_setapp(netdev, app_data);
12133e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend			if (err)
12143e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend				goto err;
12153e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		}
12163e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	}
12173e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12183e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabenderr:
12193e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
12203e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		    pid, seq, flags);
12213e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	return err;
12223e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend}
12233e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12243e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12253e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend/* Handle IEEE 802.1Qaz GET commands. */
12263e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabendstatic int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
12273e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend			  u32 pid, u32 seq, u16 flags)
12283e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend{
12293e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	struct sk_buff *skb;
12303e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	struct nlmsghdr *nlh;
12313e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	struct dcbmsg *dcb;
12329ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct nlattr *ieee, *app;
12339ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
12343e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
12353e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	int err;
12363e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12373e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (!ops)
12383e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		return -EOPNOTSUPP;
12393e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12403e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12413e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (!skb)
12423e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		return -ENOBUFS;
12433e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12443e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
12453e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12463e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	dcb = NLMSG_DATA(nlh);
12473e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	dcb->dcb_family = AF_UNSPEC;
12483e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	dcb->cmd = DCB_CMD_IEEE_GET;
12493e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12503e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
12513e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12523e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	ieee = nla_nest_start(skb, DCB_ATTR_IEEE);
12533e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (!ieee)
12543e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		goto nla_put_failure;
12553e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12563e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (ops->ieee_getets) {
12573e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		struct ieee_ets ets;
12583e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		err = ops->ieee_getets(netdev, &ets);
12593e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		if (!err)
12603e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend			NLA_PUT(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets);
12613e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	}
12623e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12633e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (ops->ieee_getpfc) {
12643e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		struct ieee_pfc pfc;
12653e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		err = ops->ieee_getpfc(netdev, &pfc);
12663e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		if (!err)
12673e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend			NLA_PUT(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc);
12683e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	}
12693e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12709ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE);
12719ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (!app)
12729ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		goto nla_put_failure;
12739ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
12749ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
12759ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
127670bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter		if (strncmp(itr->name, netdev->name, IFNAMSIZ) == 0) {
127770bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app),
127870bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter					 &itr->app);
127970bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			if (err) {
128070bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter				spin_unlock(&dcb_lock);
128170bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter				goto nla_put_failure;
128270bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			}
128370bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter		}
12849ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
12859ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
12869ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	nla_nest_end(skb, app);
12879ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
12883e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	nla_nest_end(skb, ieee);
12893e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	nlmsg_end(skb, nlh);
12903e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12913e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	return rtnl_unicast(skb, &init_net, pid);
12923e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabendnla_put_failure:
12933e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	nlmsg_cancel(skb, nlh);
12943e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabendnlmsg_failure:
12953e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	kfree_skb(skb);
12963e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	return -1;
12973e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend}
12983e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12996241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid/* DCBX configuration */
13006241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravidstatic int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
13016241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			 u32 pid, u32 seq, u16 flags)
13026241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid{
13037f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret;
13046241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
13056241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	if (!netdev->dcbnl_ops->getdcbx)
13067f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
13076241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
13086241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	ret = dcbnl_reply(netdev->dcbnl_ops->getdcbx(netdev), RTM_GETDCB,
13096241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			  DCB_CMD_GDCBX, DCB_ATTR_DCBX, pid, seq, flags);
13106241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
13116241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	return ret;
13126241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid}
13136241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
13146241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravidstatic int dcbnl_setdcbx(struct net_device *netdev, struct nlattr **tb,
13156241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			 u32 pid, u32 seq, u16 flags)
13166241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid{
13177f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret;
13186241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	u8 value;
13196241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
13207f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->setdcbx)
13217f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
13227f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
13237f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_DCBX])
13247f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
13256241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
13266241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	value = nla_get_u8(tb[DCB_ATTR_DCBX]);
13276241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
13286241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	ret = dcbnl_reply(netdev->dcbnl_ops->setdcbx(netdev, value),
13296241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			  RTM_SETDCB, DCB_CMD_SDCBX, DCB_ATTR_DCBX,
13306241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			  pid, seq, flags);
13316241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
13326241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	return ret;
13336241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid}
13346241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
1335ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravidstatic int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb,
1336ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			    u32 pid, u32 seq, u16 flags)
1337ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid{
1338ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct sk_buff *dcbnl_skb;
1339ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct nlmsghdr *nlh;
1340ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct dcbmsg *dcb;
1341ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest;
1342ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	u8 value;
13437f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret, i;
1344ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	int getall = 0;
1345ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
13467f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->getfeatcfg)
13477f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
13487f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
13497f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_FEATCFG])
13507f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
1351ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1352ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1353ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			       dcbnl_featcfg_nest);
13547f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (ret)
1355ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto err_out;
1356ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1357ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1358ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	if (!dcbnl_skb) {
13597f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		ret = -ENOBUFS;
1360ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto err_out;
1361ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1362ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1363ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1364ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1365ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	dcb = NLMSG_DATA(nlh);
1366ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	dcb->dcb_family = AF_UNSPEC;
1367ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	dcb->cmd = DCB_CMD_GFEATCFG;
1368ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1369ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_FEATCFG);
1370ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	if (!nest) {
13717f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		ret = -EMSGSIZE;
13727f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		goto nla_put_failure;
1373ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1374ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1375ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	if (data[DCB_FEATCFG_ATTR_ALL])
1376ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		getall = 1;
1377ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1378ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1379ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (!getall && !data[i])
1380ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			continue;
1381ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1382ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value);
13837f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		if (!ret)
1384ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			ret = nla_put_u8(dcbnl_skb, i, value);
1385ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
13867f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		if (ret) {
13877f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid			nla_nest_cancel(dcbnl_skb, nest);
13887f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid			goto nla_put_failure;
13897f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		}
1390ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1391ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	nla_nest_end(dcbnl_skb, nest);
1392ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1393ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	nlmsg_end(dcbnl_skb, nlh);
1394ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
13957f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	return rtnl_unicast(dcbnl_skb, &init_net, pid);
13967f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravidnla_put_failure:
13977f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	nlmsg_cancel(dcbnl_skb, nlh);
1398ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravidnlmsg_failure:
1399ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	kfree_skb(dcbnl_skb);
1400ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Raviderr_out:
1401ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	return ret;
1402ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid}
1403ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1404ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravidstatic int dcbnl_setfeatcfg(struct net_device *netdev, struct nlattr **tb,
1405ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			    u32 pid, u32 seq, u16 flags)
1406ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid{
1407ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1];
14087f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret, i;
1409ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	u8 value;
1410ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
14117f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->setfeatcfg)
14127f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -ENOTSUPP;
14137f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
14147f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_FEATCFG])
14157f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
1416ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1417ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1418ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			       dcbnl_featcfg_nest);
1419ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
14207f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (ret)
1421ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto err;
1422ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1423ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1424ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (data[i] == NULL)
1425ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			continue;
1426ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1427ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		value = nla_get_u8(data[i]);
1428ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1429ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = netdev->dcbnl_ops->setfeatcfg(netdev, i, value);
1430ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1431ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (ret)
14327f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid			goto err;
1433ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1434ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Raviderr:
14357f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	dcbnl_reply(ret, RTM_SETDCB, DCB_CMD_SFEATCFG, DCB_ATTR_FEATCFG,
14367f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		    pid, seq, flags);
14377f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
1438ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	return ret;
1439ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid}
1440ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
14412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
14422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
14432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct net *net = sock_net(skb->sk);
14442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct net_device *netdev;
14452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg  *dcb = (struct dcbmsg *)NLMSG_DATA(nlh);
14462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *tb[DCB_ATTR_MAX + 1];
14472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u32 pid = skb ? NETLINK_CB(skb).pid : 0;
14482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
14492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
145009ad9bc752519cc167d0a573e1acf69b5c707c67Octavian Purdila	if (!net_eq(net, &init_net))
14512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
14522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
14532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
14542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  dcbnl_rtnl_policy);
14552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret < 0)
14562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
14572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
14582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_IFNAME])
14592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
14602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
14612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME]));
14622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev)
14632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
14642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
14652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops)
14662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto errout;
14672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
14682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	switch (dcb->cmd) {
14692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_GSTATE:
14702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq,
14712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                     nlh->nlmsg_flags);
14722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
14732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PFC_GCFG:
14742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
14752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                      nlh->nlmsg_flags);
14762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
14772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_GPERM_HWADDR:
14782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq,
14792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                           nlh->nlmsg_flags);
14802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
14812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGTX_GCFG:
14822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
14832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
14842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
14852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGRX_GCFG:
14862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
14872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
14882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
1489859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	case DCB_CMD_BCN_GCFG:
1490859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = dcbnl_bcn_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
1491859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                       nlh->nlmsg_flags);
1492859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto out;
14932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_SSTATE:
14942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq,
14952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                     nlh->nlmsg_flags);
14962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
14972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PFC_SCFG:
14982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
14992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                      nlh->nlmsg_flags);
15002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
15012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
15022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_SET_ALL:
15032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq,
15042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                   nlh->nlmsg_flags);
15052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
15062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGTX_SCFG:
15072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
15082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
15092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
15102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGRX_SCFG:
15112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
15122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
15132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
151446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	case DCB_CMD_GCAP:
151546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq,
151646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		                   nlh->nlmsg_flags);
151746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto out;
151833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	case DCB_CMD_GNUMTCS:
151933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
152033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		                      nlh->nlmsg_flags);
152133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto out;
152233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	case DCB_CMD_SNUMTCS:
152333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
152433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		                      nlh->nlmsg_flags);
152533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto out;
15260eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	case DCB_CMD_PFC_GSTATE:
15270eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		ret = dcbnl_getpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
15280eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		                        nlh->nlmsg_flags);
15290eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		goto out;
15300eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	case DCB_CMD_PFC_SSTATE:
15310eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
15320eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		                        nlh->nlmsg_flags);
15330eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		goto out;
1534859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	case DCB_CMD_BCN_SCFG:
1535859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
1536859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                       nlh->nlmsg_flags);
1537859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto out;
1538579496865cf4ea429146382d62047ffdbaab0deeYi Zou	case DCB_CMD_GAPP:
1539579496865cf4ea429146382d62047ffdbaab0deeYi Zou		ret = dcbnl_getapp(netdev, tb, pid, nlh->nlmsg_seq,
1540579496865cf4ea429146382d62047ffdbaab0deeYi Zou		                   nlh->nlmsg_flags);
1541579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
1542579496865cf4ea429146382d62047ffdbaab0deeYi Zou	case DCB_CMD_SAPP:
1543579496865cf4ea429146382d62047ffdbaab0deeYi Zou		ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq,
1544579496865cf4ea429146382d62047ffdbaab0deeYi Zou		                   nlh->nlmsg_flags);
1545579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
15463e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	case DCB_CMD_IEEE_SET:
15473e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq,
15483e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend				 nlh->nlmsg_flags);
15493e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		goto out;
15503e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	case DCB_CMD_IEEE_GET:
15513e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq,
15523e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend				 nlh->nlmsg_flags);
15533e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		goto out;
15546241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	case DCB_CMD_GDCBX:
15556241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid		ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq,
15566241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid				    nlh->nlmsg_flags);
15576241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid		goto out;
15586241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	case DCB_CMD_SDCBX:
15596241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid		ret = dcbnl_setdcbx(netdev, tb, pid, nlh->nlmsg_seq,
15606241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid				    nlh->nlmsg_flags);
15616241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid		goto out;
1562ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	case DCB_CMD_GFEATCFG:
1563ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = dcbnl_getfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
1564ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid				       nlh->nlmsg_flags);
1565ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto out;
1566ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	case DCB_CMD_SFEATCFG:
1567ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = dcbnl_setfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
1568ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid				       nlh->nlmsg_flags);
1569ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto out;
15702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	default:
15712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto errout;
15722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
15732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerrout:
15742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = -EINVAL;
15752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckout:
15762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dev_put(netdev);
15772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
15782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
15792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
15809ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend/**
15819ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * dcb_getapp - retrieve the DCBX application user priority
15829ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend *
15839ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * On success returns a non-zero 802.1p user priority bitmap
15849ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * otherwise returns 0 as the invalid user priority bitmap to
15859ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * indicate an error.
15869ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend */
15879ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendu8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
15889ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
15899ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
15909ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	u8 prio = 0;
15919ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
15929ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
15939ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
15949ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		if (itr->app.selector == app->selector &&
15959ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		    itr->app.protocol == app->protocol &&
15969ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		    (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
15979ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			prio = itr->app.priority;
15989ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			break;
15999ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		}
16009ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
16019ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
16029ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
16039ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	return prio;
16049ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
16059ab933ab2cc80f04690d6aa385b1110075c5e507John FastabendEXPORT_SYMBOL(dcb_getapp);
16069ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
16079ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend/**
16089ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * ixgbe_dcbnl_setapp - add dcb application data to app list
16099ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend *
16109ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * Priority 0 is the default priority this removes applications
16119ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * from the app list if the priority is set to zero.
16129ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend */
16139ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendu8 dcb_setapp(struct net_device *dev, struct dcb_app *new)
16149ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
16159ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
16167ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	struct dcb_app_type event;
16177ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend
16187ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	memcpy(&event.name, dev->name, sizeof(event.name));
16197ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	memcpy(&event.app, new, sizeof(event.app));
16209ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
16219ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
16229ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	/* Search for existing match and replace */
16239ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
16249ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		if (itr->app.selector == new->selector &&
16259ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		    itr->app.protocol == new->protocol &&
16269ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		    (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
16279ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			if (new->priority)
16289ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend				itr->app.priority = new->priority;
16299ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			else {
16309ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend				list_del(&itr->list);
16319ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend				kfree(itr);
16329ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			}
16339ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			goto out;
16349ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		}
16359ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
16369ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	/* App type does not exist add new application type */
16379ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (new->priority) {
16389ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		struct dcb_app_type *entry;
16399ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
16409ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		if (!entry) {
16419ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			spin_unlock(&dcb_lock);
16429ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			return -ENOMEM;
16439ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		}
16449ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
16459ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		memcpy(&entry->app, new, sizeof(*new));
16469ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		strncpy(entry->name, dev->name, IFNAMSIZ);
16479ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		list_add(&entry->list, &dcb_app_list);
16489ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
16499ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendout:
16509ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
16517ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	call_dcbevent_notifiers(DCB_APP_EVENT, &event);
16529ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	return 0;
16539ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
16549ab933ab2cc80f04690d6aa385b1110075c5e507John FastabendEXPORT_SYMBOL(dcb_setapp);
16559ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
16567c14c3f10e6dcd7f70e49f77b6e1ae605c4861e6Shmulik Ravidstatic void dcb_flushapp(void)
16579ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
16589ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *app;
16592a8fe003741aa90b6b9453e90af4bbb7bc42918cDan Carpenter	struct dcb_app_type *tmp;
16609ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
16619ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
16622a8fe003741aa90b6b9453e90af4bbb7bc42918cDan Carpenter	list_for_each_entry_safe(app, tmp, &dcb_app_list, list) {
16639ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		list_del(&app->list);
16649ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		kfree(app);
16659ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
16669ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
16679ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
16689ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
16692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __init dcbnl_init(void)
16702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
16719ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	INIT_LIST_HEAD(&dcb_app_list);
16729ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
16732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL);
16742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL);
16752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
16762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
16772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
16782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_init(dcbnl_init);
16792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
16802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic void __exit dcbnl_exit(void)
16812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
16822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_unregister(PF_UNSPEC, RTM_GETDCB);
16832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_unregister(PF_UNSPEC, RTM_SETDCB);
16849ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	dcb_flushapp();
16852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
16862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_exit(dcbnl_exit);
1687