12f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/*
2698e1d23cfc15312be2e7665014afd98c49ae9a1Mark Rustad * Copyright (c) 2008-2011, 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>
283a9a231d977222eea36eae091df2c358e03ac839Paul Gortmaker#include <linux/module.h>
292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <net/sock.h>
302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
31ae86b9e3846f6fc5509dee721f2bdba1db8ab96aBen Hutchings/* 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},
18008f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	[DCB_ATTR_IEEE_MAXRATE]   = {.len = sizeof(struct ieee_maxrate)},
1813e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend};
1823e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
1833e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabendstatic const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = {
1843e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	[DCB_ATTR_IEEE_APP]	    = {.len = sizeof(struct dcb_app)},
1853e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend};
1863e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
187ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid/* DCB number of traffic classes nested attributes. */
188ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravidstatic const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = {
189ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_FEATCFG_ATTR_ALL]      = {.type = NLA_FLAG},
190ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_FEATCFG_ATTR_PG]       = {.type = NLA_U8},
191ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_FEATCFG_ATTR_PFC]      = {.type = NLA_U8},
192ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_FEATCFG_ATTR_APP]      = {.type = NLA_U8},
193ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid};
194ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1959ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendstatic LIST_HEAD(dcb_app_list);
1969ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendstatic DEFINE_SPINLOCK(dcb_lock);
1979ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
19833a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Grafstatic struct sk_buff *dcbnl_newmsg(int type, u8 cmd, u32 port, u32 seq,
19933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf				    u32 flags, struct nlmsghdr **nlhp)
20033a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf{
20133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	struct sk_buff *skb;
20233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	struct dcbmsg *dcb;
20333a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	struct nlmsghdr *nlh;
20433a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
20533a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
20633a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	if (!skb)
20733a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		return NULL;
20833a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
20933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	nlh = nlmsg_put(skb, port, seq, type, sizeof(*dcb), flags);
210b3908e22ad8bb6074934496ef171fd83605d7d3eThomas Graf	BUG_ON(!nlh);
21133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
21233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	dcb = nlmsg_data(nlh);
21333a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	dcb->dcb_family = AF_UNSPEC;
21433a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	dcb->cmd = cmd;
21533a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	dcb->dcb_pad = 0;
21633a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
21733a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	if (nlhp)
21833a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		*nlhp = nlh;
21933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
22033a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	return skb;
22133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf}
22233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
2237be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getstate(struct net_device *netdev, struct nlmsghdr *nlh,
2247be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
2252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	/* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */
2272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops->getstate)
2283d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
2292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2307be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_STATE,
2317be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  netdev->dcbnl_ops->getstate(netdev));
2322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2347be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getpfccfg(struct net_device *netdev, struct nlmsghdr *nlh,
2357be994138b188387691322921c08e19bddf6d3c5Thomas Graf			   u32 seq, struct nlattr **tb, struct sk_buff *skb)
2362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest;
2382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
2393d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
2402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
2412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int getall = 0;
2422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2433d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_PFC_CFG])
2443d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
2453d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
2463d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->getpfccfg)
2473d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
2482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
2502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PFC_CFG],
2512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       dcbnl_pfc_up_nest);
2522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
2533d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
2542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2557be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nest = nla_nest_start(skb, DCB_ATTR_PFC_CFG);
2562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!nest)
2573d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
2582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (data[DCB_PFC_UP_ATTR_ALL])
2602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
2612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
2632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !data[i])
2642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
2652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0,
2672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                             &value);
2687be994138b188387691322921c08e19bddf6d3c5Thomas Graf		ret = nla_put_u8(skb, i, value);
2692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret) {
2707be994138b188387691322921c08e19bddf6d3c5Thomas Graf			nla_nest_cancel(skb, nest);
2713d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return ret;
2722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
2732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
2747be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, nest);
2752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
2772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2797be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlmsghdr *nlh,
2807be994138b188387691322921c08e19bddf6d3c5Thomas Graf				u32 seq, struct nlattr **tb, struct sk_buff *skb)
2812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 perm_addr[MAX_ADDR_LEN];
2832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops->getpermhwaddr)
2853d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
2862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
28729cd8ae0e1a39e239a3a7b67da1986add1199fc0Mathias Krause	memset(perm_addr, 0, sizeof(perm_addr));
2882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
2892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2907be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put(skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), perm_addr);
2912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2937be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getcap(struct net_device *netdev, struct nlmsghdr *nlh,
2947be994138b188387691322921c08e19bddf6d3c5Thomas Graf			u32 seq, struct nlattr **tb, struct sk_buff *skb)
29546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck{
29646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest;
29746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	u8 value;
2983d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
29946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int i;
30046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int getall = 0;
30146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
3023d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_CAP])
3033d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
3043d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
3053d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->getcap)
3063d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
30746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
30846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP],
30946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	                       dcbnl_cap_nest);
31046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (ret)
3113d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
31246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
3137be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nest = nla_nest_start(skb, DCB_ATTR_CAP);
31446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!nest)
3153d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
31646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
31746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (data[DCB_CAP_ATTR_ALL])
31846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		getall = 1;
31946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
32046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) {
32146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		if (!getall && !data[i])
32246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			continue;
32346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
32446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) {
3257be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb, i, value);
32646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			if (ret) {
3277be994138b188387691322921c08e19bddf6d3c5Thomas Graf				nla_nest_cancel(skb, nest);
3283d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf				return ret;
32946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			}
33046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		}
33146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	}
3327be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, nest);
33346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
33446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	return 0;
33546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck}
33646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
3377be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getnumtcs(struct net_device *netdev, struct nlmsghdr *nlh,
3387be994138b188387691322921c08e19bddf6d3c5Thomas Graf			   u32 seq, struct nlattr **tb, struct sk_buff *skb)
33933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{
34033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest;
34133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	u8 value;
3423d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
34333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int i;
34433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int getall = 0;
34533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
3463d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_NUMTCS])
3473d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
3483d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
3493d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->getnumtcs)
3503d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
35133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
35233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
35333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                       dcbnl_numtcs_nest);
3543d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (ret)
3553d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
35633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
3577be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nest = nla_nest_start(skb, DCB_ATTR_NUMTCS);
3583d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!nest)
3593d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
36033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
36133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (data[DCB_NUMTCS_ATTR_ALL])
36233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		getall = 1;
36333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
36433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
36533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (!getall && !data[i])
36633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			continue;
36733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
36833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value);
36933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (!ret) {
3707be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb, i, value);
37133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			if (ret) {
3727be994138b188387691322921c08e19bddf6d3c5Thomas Graf				nla_nest_cancel(skb, nest);
3733d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf				return ret;
37433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			}
3753d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		} else
3763d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EINVAL;
37733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
3787be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, nest);
37933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
38033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return 0;
38133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck}
38233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
3837be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setnumtcs(struct net_device *netdev, struct nlmsghdr *nlh,
3847be994138b188387691322921c08e19bddf6d3c5Thomas Graf			   u32 seq, struct nlattr **tb, struct sk_buff *skb)
38533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{
38633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1];
3873d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
38833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	u8 value;
38933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int i;
39033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
3913d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_NUMTCS])
3923d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
3933d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
3943d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setnumtcs)
3953d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
39633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
39733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
39833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                       dcbnl_numtcs_nest);
3997be994138b188387691322921c08e19bddf6d3c5Thomas Graf	if (ret)
4003d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
40133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
40233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
40333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (data[i] == NULL)
40433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			continue;
40533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
40633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		value = nla_get_u8(data[i]);
40733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
40833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value);
40933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (ret)
4107be994138b188387691322921c08e19bddf6d3c5Thomas Graf			break;
41133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
41233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
4137be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_NUMTCS, !!ret);
41433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck}
41533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
4167be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getpfcstate(struct net_device *netdev, struct nlmsghdr *nlh,
4177be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
4180eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{
4190eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	if (!netdev->dcbnl_ops->getpfcstate)
4203d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
4210eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4227be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_PFC_STATE,
4237be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  netdev->dcbnl_ops->getpfcstate(netdev));
4240eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck}
4250eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4267be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setpfcstate(struct net_device *netdev, struct nlmsghdr *nlh,
4277be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
4280eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{
4290eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	u8 value;
4300eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4313d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_PFC_STATE])
4327be994138b188387691322921c08e19bddf6d3c5Thomas Graf		return -EINVAL;
4330eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4343d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setpfcstate)
4353d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
4363d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
4370eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]);
4380eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4390eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	netdev->dcbnl_ops->setpfcstate(netdev, value);
4400eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4417be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_PFC_STATE, 0);
4420eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck}
4430eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4447be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getapp(struct net_device *netdev, struct nlmsghdr *nlh,
4457be994138b188387691322921c08e19bddf6d3c5Thomas Graf			u32 seq, struct nlattr **tb, struct sk_buff *skb)
446579496865cf4ea429146382d62047ffdbaab0deeYi Zou{
447579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_nest;
448579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
449579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u16 id;
450579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u8 up, idtype;
4513d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
452579496865cf4ea429146382d62047ffdbaab0deeYi Zou
4533dce38a02d6370dca690cd923619d4b00024b723John Fastabend	if (!tb[DCB_ATTR_APP])
4543d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
455579496865cf4ea429146382d62047ffdbaab0deeYi Zou
456579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
457579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                       dcbnl_app_nest);
458579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
4593d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
460579496865cf4ea429146382d62047ffdbaab0deeYi Zou
461579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* all must be non-null */
462579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
463579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_ID]))
4643d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
465579496865cf4ea429146382d62047ffdbaab0deeYi Zou
466579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* either by eth type or by socket number */
467579496865cf4ea429146382d62047ffdbaab0deeYi Zou	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
468579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
469579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (idtype != DCB_APP_IDTYPE_PORTNUM))
4703d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
471579496865cf4ea429146382d62047ffdbaab0deeYi Zou
472579496865cf4ea429146382d62047ffdbaab0deeYi Zou	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
4733dce38a02d6370dca690cd923619d4b00024b723John Fastabend
4743dce38a02d6370dca690cd923619d4b00024b723John Fastabend	if (netdev->dcbnl_ops->getapp) {
4753dce38a02d6370dca690cd923619d4b00024b723John Fastabend		up = netdev->dcbnl_ops->getapp(netdev, idtype, id);
4763dce38a02d6370dca690cd923619d4b00024b723John Fastabend	} else {
4773dce38a02d6370dca690cd923619d4b00024b723John Fastabend		struct dcb_app app = {
4783dce38a02d6370dca690cd923619d4b00024b723John Fastabend					.selector = idtype,
4793dce38a02d6370dca690cd923619d4b00024b723John Fastabend					.protocol = id,
4803dce38a02d6370dca690cd923619d4b00024b723John Fastabend				     };
4813dce38a02d6370dca690cd923619d4b00024b723John Fastabend		up = dcb_getapp(netdev, &app);
4823dce38a02d6370dca690cd923619d4b00024b723John Fastabend	}
483579496865cf4ea429146382d62047ffdbaab0deeYi Zou
4847be994138b188387691322921c08e19bddf6d3c5Thomas Graf	app_nest = nla_nest_start(skb, DCB_ATTR_APP);
485d3337de52af7fb0ebe605b02b740be4ee7dee9ebJesper Juhl	if (!app_nest)
4863d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
487d3337de52af7fb0ebe605b02b740be4ee7dee9ebJesper Juhl
4887be994138b188387691322921c08e19bddf6d3c5Thomas Graf	ret = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE, idtype);
489579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
490579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
491579496865cf4ea429146382d62047ffdbaab0deeYi Zou
4927be994138b188387691322921c08e19bddf6d3c5Thomas Graf	ret = nla_put_u16(skb, DCB_APP_ATTR_ID, id);
493579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
494579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
495579496865cf4ea429146382d62047ffdbaab0deeYi Zou
4967be994138b188387691322921c08e19bddf6d3c5Thomas Graf	ret = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY, up);
497579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
498579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
499579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5007be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, app_nest);
501579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5023d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	return 0;
503579496865cf4ea429146382d62047ffdbaab0deeYi Zou
504579496865cf4ea429146382d62047ffdbaab0deeYi Zouout_cancel:
5057be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_cancel(skb, app_nest);
506579496865cf4ea429146382d62047ffdbaab0deeYi Zou	return ret;
507579496865cf4ea429146382d62047ffdbaab0deeYi Zou}
508579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5097be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setapp(struct net_device *netdev, struct nlmsghdr *nlh,
5107be994138b188387691322921c08e19bddf6d3c5Thomas Graf			u32 seq, struct nlattr **tb, struct sk_buff *skb)
511579496865cf4ea429146382d62047ffdbaab0deeYi Zou{
5123d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
513579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u16 id;
514579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u8 up, idtype;
515579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
516579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5179ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (!tb[DCB_ATTR_APP])
5183d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
519579496865cf4ea429146382d62047ffdbaab0deeYi Zou
520579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
521579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                       dcbnl_app_nest);
522579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
5233d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
524579496865cf4ea429146382d62047ffdbaab0deeYi Zou
525579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* all must be non-null */
526579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
527579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_ID]) ||
528579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_PRIORITY]))
5293d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
530579496865cf4ea429146382d62047ffdbaab0deeYi Zou
531579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* either by eth type or by socket number */
532579496865cf4ea429146382d62047ffdbaab0deeYi Zou	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
533579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
534579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (idtype != DCB_APP_IDTYPE_PORTNUM))
5353d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
536579496865cf4ea429146382d62047ffdbaab0deeYi Zou
537579496865cf4ea429146382d62047ffdbaab0deeYi Zou	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
538579496865cf4ea429146382d62047ffdbaab0deeYi Zou	up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]);
539579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5409ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (netdev->dcbnl_ops->setapp) {
5413d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		ret = netdev->dcbnl_ops->setapp(netdev, idtype, id, up);
5429ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	} else {
5439ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		struct dcb_app app;
5449ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.selector = idtype;
5459ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.protocol = id;
5469ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.priority = up;
5473d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		ret = dcb_setapp(netdev, &app);
5489ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
5499ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
5507be994138b188387691322921c08e19bddf6d3c5Thomas Graf	ret = nla_put_u8(skb, DCB_ATTR_APP, ret);
551081579840b4b2421e37bc67e3b089b7ca64ef040John Fastabend	dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SAPP, seq, 0);
5523d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
553579496865cf4ea429146382d62047ffdbaab0deeYi Zou	return ret;
554579496865cf4ea429146382d62047ffdbaab0deeYi Zou}
555579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5567be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
5577be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     struct nlattr **tb, struct sk_buff *skb, int dir)
5582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
5592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_nest, *param_nest, *data;
5602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
5612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
5622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 prio, pgid, tc_pct, up_map;
5633d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
5642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int getall = 0;
5652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
5662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
5673d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_PG_CFG])
5683d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
5693d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
5703d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->getpgtccfgtx ||
5712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgtccfgrx ||
5722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgbwgcfgtx ||
5732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgbwgcfgrx)
5743d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
5752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
5762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
5772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
5782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
5793d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
5802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
5817be994138b188387691322921c08e19bddf6d3c5Thomas Graf	pg_nest = nla_nest_start(skb, DCB_ATTR_PG_CFG);
5822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!pg_nest)
5833d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
5842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
5852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (pg_tb[DCB_PG_ATTR_TC_ALL])
5862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
5872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
5882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
5892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !pg_tb[i])
5902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
5912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
5922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (pg_tb[DCB_PG_ATTR_TC_ALL])
5932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data = pg_tb[DCB_PG_ATTR_TC_ALL];
5942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		else
5952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data = pg_tb[i];
5962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
5972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				       data, dcbnl_tc_param_nest);
5982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
5992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
6002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6017be994138b188387691322921c08e19bddf6d3c5Thomas Graf		param_nest = nla_nest_start(skb, i);
6022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!param_nest)
6032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
6042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		pgid = DCB_ATTR_VALUE_UNDEFINED;
6062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		prio = DCB_ATTR_VALUE_UNDEFINED;
6072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
6082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		up_map = DCB_ATTR_VALUE_UNDEFINED;
6092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
6112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
6122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgtccfgrx(netdev,
6132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						i - DCB_PG_ATTR_TC_0, &prio,
6142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						&pgid, &tc_pct, &up_map);
6152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
6162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
6172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgtccfgtx(netdev,
6182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						i - DCB_PG_ATTR_TC_0, &prio,
6192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						&pgid, &tc_pct, &up_map);
6202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
6212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_PGID] ||
6232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
6247be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb,
6252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_PGID, pgid);
6262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
6272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
6282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
6292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] ||
6302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
6317be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb,
6322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
6332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
6342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
6352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
6362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] ||
6372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
6387be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb,
6392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
6402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
6412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
6422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
6432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] ||
6442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
6457be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT,
6462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 tc_pct);
6472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
6482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
6492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
6507be994138b188387691322921c08e19bddf6d3c5Thomas Graf		nla_nest_end(skb, param_nest);
6512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
6522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (pg_tb[DCB_PG_ATTR_BW_ID_ALL])
6542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
6552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	else
6562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 0;
6572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
6592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !pg_tb[i])
6602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
6612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
6632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
6652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
6662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgbwgcfgrx(netdev,
6672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
6682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
6692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
6702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgbwgcfgtx(netdev,
6712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
6722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
6737be994138b188387691322921c08e19bddf6d3c5Thomas Graf		ret = nla_put_u8(skb, i, tc_pct);
6742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
6752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
6762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
6772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6787be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, pg_nest);
6792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
6812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_param:
6837be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_cancel(skb, param_nest);
6842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_pg:
6857be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_cancel(skb, pg_nest);
6863d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
6873d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	return -EMSGSIZE;
6882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
6892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6907be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
6917be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
6922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
6937be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 0);
6942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
6952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6967be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
6977be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
6982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
6997be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 1);
7002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
7012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7027be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setstate(struct net_device *netdev, struct nlmsghdr *nlh,
7037be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
7042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
7052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
7062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7073d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_STATE])
7087be994138b188387691322921c08e19bddf6d3c5Thomas Graf		return -EINVAL;
7092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7103d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setstate)
7113d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
7123d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
7132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	value = nla_get_u8(tb[DCB_ATTR_STATE]);
7142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7157be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_STATE,
7167be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  netdev->dcbnl_ops->setstate(netdev, value));
7172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
7182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7197be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setpfccfg(struct net_device *netdev, struct nlmsghdr *nlh,
7207be994138b188387691322921c08e19bddf6d3c5Thomas Graf			   u32 seq, struct nlattr **tb, struct sk_buff *skb)
7212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
7222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1];
7232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
7243d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
7252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
7262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7273d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_PFC_CFG])
7283d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
7293d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
7303d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setpfccfg)
7313d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
7322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
7342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PFC_CFG],
7352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       dcbnl_pfc_up_nest);
7362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
7373d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
7382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
7402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (data[i] == NULL)
7412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
7422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		value = nla_get_u8(data[i]);
7432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		netdev->dcbnl_ops->setpfccfg(netdev,
7442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data[i]->nla_type - DCB_PFC_UP_ATTR_0, value);
7452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
7462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7477be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_PFC_CFG, 0);
7482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
7492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7507be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setall(struct net_device *netdev, struct nlmsghdr *nlh,
7517be994138b188387691322921c08e19bddf6d3c5Thomas Graf			u32 seq, struct nlattr **tb, struct sk_buff *skb)
7522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
7533d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
7542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7553d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_SET_ALL])
7563d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
7573d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
7583d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setall)
7593d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
7602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7617be994138b188387691322921c08e19bddf6d3c5Thomas Graf	ret = nla_put_u8(skb, DCB_ATTR_SET_ALL,
7627be994138b188387691322921c08e19bddf6d3c5Thomas Graf			 netdev->dcbnl_ops->setall(netdev));
763081579840b4b2421e37bc67e3b089b7ca64ef040John Fastabend	dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SET_ALL, seq, 0);
7642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
7662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
7672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7687be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
7697be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb,
7707be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     int dir)
7712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
7722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
7732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
7743d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
7752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
7762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 pgid;
7772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 up_map;
7782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 prio;
7792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 tc_pct;
7802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7813d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_PG_CFG])
7823d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
7833d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
7843d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setpgtccfgtx ||
7852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgtccfgrx ||
7862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgbwgcfgtx ||
7872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgbwgcfgrx)
7883d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
7892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
7912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
7922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
7933d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
7942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
7962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!pg_tb[i])
7972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
7982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
8002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                       pg_tb[i], dcbnl_tc_param_nest);
8012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
8023d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return ret;
8032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		pgid = DCB_ATTR_VALUE_UNDEFINED;
8052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		prio = DCB_ATTR_VALUE_UNDEFINED;
8062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
8072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		up_map = DCB_ATTR_VALUE_UNDEFINED;
8082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO])
8102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			prio =
8112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			    nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]);
8122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_PGID])
8142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]);
8152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT])
8172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]);
8182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING])
8202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			up_map =
8212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			     nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]);
8222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		/* dir: Tx = 0, Rx = 1 */
8242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
8252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
8262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgtccfgrx(netdev,
8272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				i - DCB_PG_ATTR_TC_0,
8282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				prio, pgid, tc_pct, up_map);
8292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
8302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
8312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgtccfgtx(netdev,
8322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				i - DCB_PG_ATTR_TC_0,
8332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				prio, pgid, tc_pct, up_map);
8342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
8362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
8382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!pg_tb[i])
8392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
8402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = nla_get_u8(pg_tb[i]);
8422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		/* dir: Tx = 0, Rx = 1 */
8442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
8452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
8462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgbwgcfgrx(netdev,
8472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
8482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
8492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
8502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgbwgcfgtx(netdev,
8512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
8522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
8542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
855bb1dfefdc62fa68107c4c9f1374cb856743a9434John Fastabend	return nla_put_u8(skb, DCB_ATTR_PG_CFG, 0);
8562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8587be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
8597be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
8602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8617be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 0);
8622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8647be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
8657be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
8662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8677be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 1);
8682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8707be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
8717be994138b188387691322921c08e19bddf6d3c5Thomas Graf			    u32 seq, struct nlattr **tb, struct sk_buff *skb)
872859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck{
873859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *bcn_nest;
874859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1];
875859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u8 value_byte;
876859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u32 value_integer;
8773d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
878859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	bool getall = false;
879859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int i;
880859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
8813d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_BCN])
8823d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
8833d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
8843d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->getbcnrp ||
885859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	    !netdev->dcbnl_ops->getbcncfg)
8863d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
887859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
888859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX,
889859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       tb[DCB_ATTR_BCN], dcbnl_bcn_nest);
890859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
8913d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
892859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
8937be994138b188387691322921c08e19bddf6d3c5Thomas Graf	bcn_nest = nla_nest_start(skb, DCB_ATTR_BCN);
894859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!bcn_nest)
8953d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
896859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
897859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (bcn_tb[DCB_BCN_ATTR_ALL])
898859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		getall = true;
899859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
900859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
901859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (!getall && !bcn_tb[i])
902859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
903859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
904859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0,
905859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                            &value_byte);
9067be994138b188387691322921c08e19bddf6d3c5Thomas Graf		ret = nla_put_u8(skb, i, value_byte);
907859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (ret)
908859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			goto err_bcn;
909859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
910859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
911f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
912859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (!getall && !bcn_tb[i])
913859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
914859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
915859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->getbcncfg(netdev, i,
916859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                             &value_integer);
9177be994138b188387691322921c08e19bddf6d3c5Thomas Graf		ret = nla_put_u32(skb, i, value_integer);
918859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (ret)
919859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			goto err_bcn;
920859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
921859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
9227be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, bcn_nest);
923859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
924859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return 0;
925859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
926859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr_bcn:
9277be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_cancel(skb, bcn_nest);
928859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return ret;
929859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck}
930859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
9317be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
9327be994138b188387691322921c08e19bddf6d3c5Thomas Graf			    u32 seq, struct nlattr **tb, struct sk_buff *skb)
933859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck{
934859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *data[DCB_BCN_ATTR_MAX + 1];
935859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int i;
9363d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
937859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u8 value_byte;
938859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u32 value_int;
939859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
9403d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_BCN])
9413d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
9423d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
9433d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setbcncfg ||
944f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches	    !netdev->dcbnl_ops->setbcnrp)
9453d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
946859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
947859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX,
948859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       tb[DCB_ATTR_BCN],
949859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       dcbnl_pfc_up_nest);
950859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
9513d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
952859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
953859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
954859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (data[i] == NULL)
955859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
956859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		value_byte = nla_get_u8(data[i]);
957859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->setbcnrp(netdev,
958859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte);
959859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
960859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
961f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
962859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (data[i] == NULL)
963859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
964859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		value_int = nla_get_u32(data[i]);
965859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->setbcncfg(netdev,
966859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                                     i, value_int);
967859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
968859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
9693d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	return nla_put_u8(skb, DCB_ATTR_BCN, 0);
970859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck}
971859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
972dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravidstatic int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
973dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid				int app_nested_type, int app_info_type,
974dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid				int app_entry_type)
975eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid{
976eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	struct dcb_peer_app_info info;
977eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	struct dcb_app *table = NULL;
978eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
979eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	u16 app_count;
980eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	int err;
981eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
982eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
983eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	/**
984eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	 * retrieve the peer app configuration form the driver. If the driver
985eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	 * handlers fail exit without doing anything
986eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	 */
987eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	err = ops->peer_getappinfo(netdev, &info, &app_count);
988eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (!err && app_count) {
989eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		table = kmalloc(sizeof(struct dcb_app) * app_count, GFP_KERNEL);
990eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		if (!table)
991eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid			return -ENOMEM;
992eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
993eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = ops->peer_getapptable(netdev, table);
994eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
995eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
996eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (!err) {
997eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		u16 i;
998eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		struct nlattr *app;
999eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1000eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		/**
1001eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		 * build the message, from here on the only possible failure
1002eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		 * is due to the skb size
1003eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		 */
1004eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = -EMSGSIZE;
1005eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1006dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		app = nla_nest_start(skb, app_nested_type);
1007eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		if (!app)
1008eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid			goto nla_put_failure;
1009eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
10101eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (app_info_type &&
10111eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, app_info_type, sizeof(info), &info))
10121eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
1013eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
10141eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		for (i = 0; i < app_count; i++) {
10151eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			if (nla_put(skb, app_entry_type, sizeof(struct dcb_app),
10161eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				    &table[i]))
10171eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				goto nla_put_failure;
10181eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		}
1019eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		nla_nest_end(skb, app);
1020eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1021eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	err = 0;
1022eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1023eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravidnla_put_failure:
1024eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	kfree(table);
1025eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	return err;
1026eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid}
10273e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
10283e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend/* Handle IEEE 802.1Qaz GET commands. */
1029314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabendstatic int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
10303e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend{
10319ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct nlattr *ieee, *app;
10329ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
10333e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1034c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	int dcbx;
10353d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int err;
10363e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
10371eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller	if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name))
10383d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
10393d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
10403e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	ieee = nla_nest_start(skb, DCB_ATTR_IEEE);
10413e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (!ieee)
10423d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
10433e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
10443e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (ops->ieee_getets) {
10453e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		struct ieee_ets ets;
104629cd8ae0e1a39e239a3a7b67da1986add1199fc0Mathias Krause		memset(&ets, 0, sizeof(ets));
10473e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		err = ops->ieee_getets(netdev, &ets);
10481eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
10491eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets))
10503d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
10513e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	}
10523e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
105308f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	if (ops->ieee_getmaxrate) {
105408f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		struct ieee_maxrate maxrate;
105529cd8ae0e1a39e239a3a7b67da1986add1199fc0Mathias Krause		memset(&maxrate, 0, sizeof(maxrate));
105608f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		err = ops->ieee_getmaxrate(netdev, &maxrate);
105708f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		if (!err) {
105808f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai			err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE,
105908f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai				      sizeof(maxrate), &maxrate);
106008f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai			if (err)
10613d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf				return -EMSGSIZE;
106208f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		}
106308f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	}
106408f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai
10653e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (ops->ieee_getpfc) {
10663e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		struct ieee_pfc pfc;
106729cd8ae0e1a39e239a3a7b67da1986add1199fc0Mathias Krause		memset(&pfc, 0, sizeof(pfc));
10683e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		err = ops->ieee_getpfc(netdev, &pfc);
10691eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
10701eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc))
10713d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
10723e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	}
10733e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
10749ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE);
10759ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (!app)
10763d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
10779ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
10789ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
10799ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
1080e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		if (itr->ifindex == netdev->ifindex) {
108170bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app),
108270bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter					 &itr->app);
108370bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			if (err) {
108470bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter				spin_unlock(&dcb_lock);
10853d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf				return -EMSGSIZE;
108670bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			}
108770bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter		}
10889ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
1089c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend
1090c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	if (netdev->dcbnl_ops->getdcbx)
1091c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		dcbx = netdev->dcbnl_ops->getdcbx(netdev);
1092c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	else
1093c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		dcbx = -EOPNOTSUPP;
1094c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend
10959ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
10969ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	nla_nest_end(skb, app);
10979ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
1098eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	/* get peer info if available */
1099eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (ops->ieee_peer_getets) {
1100eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		struct ieee_ets ets;
110129cd8ae0e1a39e239a3a7b67da1986add1199fc0Mathias Krause		memset(&ets, 0, sizeof(ets));
1102eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = ops->ieee_peer_getets(netdev, &ets);
11031eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
11041eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets))
11053d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
1106eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1107eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1108eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (ops->ieee_peer_getpfc) {
1109eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		struct ieee_pfc pfc;
111029cd8ae0e1a39e239a3a7b67da1986add1199fc0Mathias Krause		memset(&pfc, 0, sizeof(pfc));
1111eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = ops->ieee_peer_getpfc(netdev, &pfc);
11121eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
11131eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc))
11143d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
1115eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1116eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1117eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (ops->peer_getappinfo && ops->peer_getapptable) {
1118dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		err = dcbnl_build_peer_app(netdev, skb,
1119dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid					   DCB_ATTR_IEEE_PEER_APP,
1120dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid					   DCB_ATTR_IEEE_APP_UNSPEC,
1121dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid					   DCB_ATTR_IEEE_APP);
1122eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		if (err)
11233d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
1124eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1125eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
11263e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	nla_nest_end(skb, ieee);
1127c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	if (dcbx >= 0) {
1128c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
1129c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		if (err)
11303d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
1131c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	}
11323e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
1133314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return 0;
11343e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend}
11353e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
11365b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidstatic int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
11375b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			     int dir)
11385b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
11395b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	u8 pgid, up_map, prio, tc_pct;
11405b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
11415b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	int i = dir ? DCB_ATTR_CEE_TX_PG : DCB_ATTR_CEE_RX_PG;
11425b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct nlattr *pg = nla_nest_start(skb, i);
11435b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11445b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (!pg)
11453d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
11465b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11475b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
11485b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct nlattr *tc_nest = nla_nest_start(skb, i);
11495b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11505b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!tc_nest)
11513d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
11525b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11535b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		pgid = DCB_ATTR_VALUE_UNDEFINED;
11545b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		prio = DCB_ATTR_VALUE_UNDEFINED;
11555b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
11565b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		up_map = DCB_ATTR_VALUE_UNDEFINED;
11575b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11585b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!dir)
11595b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgtccfgrx(dev, i - DCB_PG_ATTR_TC_0,
11605b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					  &prio, &pgid, &tc_pct, &up_map);
11615b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		else
11625b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgtccfgtx(dev, i - DCB_PG_ATTR_TC_0,
11635b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					  &prio, &pgid, &tc_pct, &up_map);
11645b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11651eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (nla_put_u8(skb, DCB_TC_ATTR_PARAM_PGID, pgid) ||
11661eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map) ||
11671eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio) ||
11681eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct))
11693d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
11705b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nla_nest_end(skb, tc_nest);
11715b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
11725b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11735b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
11745b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
11755b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11765b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!dir)
11775b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgbwgcfgrx(dev, i - DCB_PG_ATTR_BW_ID_0,
11785b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   &tc_pct);
11795b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		else
11805b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0,
11815b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   &tc_pct);
11821eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (nla_put_u8(skb, i, tc_pct))
11833d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
11845b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
11855b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nla_nest_end(skb, pg);
11865b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return 0;
11875b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
11885b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11895b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidstatic int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
11905b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
11915b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct nlattr *cee, *app;
11925b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct dcb_app_type *itr;
11935b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
11945b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	int dcbx, i, err = -EMSGSIZE;
11955b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	u8 value;
11965b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11971eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller	if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name))
11981eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		goto nla_put_failure;
11995b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	cee = nla_nest_start(skb, DCB_ATTR_CEE);
12005b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (!cee)
12015b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		goto nla_put_failure;
12025b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12035b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* local pg */
12045b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getpgtccfgtx && ops->getpgbwgcfgtx) {
12055b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_cee_pg_fill(skb, netdev, 1);
12065b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
12075b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
12085b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
12095b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12105b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getpgtccfgrx && ops->getpgbwgcfgrx) {
12115b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_cee_pg_fill(skb, netdev, 0);
12125b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
12135b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
12145b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
12155b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12165b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* local pfc */
12175b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getpfccfg) {
12185b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct nlattr *pfc_nest = nla_nest_start(skb, DCB_ATTR_CEE_PFC);
12195b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12205b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!pfc_nest)
12215b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
12225b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12235b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
12245b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value);
12251eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			if (nla_put_u8(skb, i, value))
12261eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				goto nla_put_failure;
12275b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		}
12285b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nla_nest_end(skb, pfc_nest);
12295b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
12305b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12315b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* local app */
12325b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	spin_lock(&dcb_lock);
12335b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE);
12345b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (!app)
123540f5d72a4fc098c47068e3888cfb055922f6519fDan Carpenter		goto dcb_unlock;
12365b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12375b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	list_for_each_entry(itr, &dcb_app_list, list) {
1238e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		if (itr->ifindex == netdev->ifindex) {
12395b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			struct nlattr *app_nest = nla_nest_start(skb,
12405b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid								 DCB_ATTR_APP);
12415b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (!app_nest)
12425b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
12435b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12445b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			err = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE,
12455b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					 itr->app.selector);
12465b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (err)
12475b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
12485b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12495b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			err = nla_put_u16(skb, DCB_APP_ATTR_ID,
12505b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					  itr->app.protocol);
12515b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (err)
12525b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
12535b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12545b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			err = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY,
12555b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					 itr->app.priority);
12565b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (err)
12575b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
12585b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12595b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			nla_nest_end(skb, app_nest);
12605b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		}
12615b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
12625b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nla_nest_end(skb, app);
12635b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12645b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (netdev->dcbnl_ops->getdcbx)
12655b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		dcbx = netdev->dcbnl_ops->getdcbx(netdev);
12665b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	else
12675b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		dcbx = -EOPNOTSUPP;
12685b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12695b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	spin_unlock(&dcb_lock);
12705b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12715b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* features flags */
12725b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getfeatcfg) {
12735b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct nlattr *feat = nla_nest_start(skb, DCB_ATTR_CEE_FEAT);
12745b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!feat)
12755b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
12765b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12775b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		for (i = DCB_FEATCFG_ATTR_ALL + 1; i <= DCB_FEATCFG_ATTR_MAX;
12785b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		     i++)
12791eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			if (!ops->getfeatcfg(netdev, i, &value) &&
12801eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			    nla_put_u8(skb, i, value))
12811eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				goto nla_put_failure;
12825b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12835b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nla_nest_end(skb, feat);
12845b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
12855b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12865b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* peer info if available */
12875b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->cee_peer_getpg) {
12885b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct cee_pg pg;
128929cd8ae0e1a39e239a3a7b67da1986add1199fc0Mathias Krause		memset(&pg, 0, sizeof(pg));
12905b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = ops->cee_peer_getpg(netdev, &pg);
12911eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
12921eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg))
12931eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
12945b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
12955b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12965b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->cee_peer_getpfc) {
12975b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct cee_pfc pfc;
129829cd8ae0e1a39e239a3a7b67da1986add1199fc0Mathias Krause		memset(&pfc, 0, sizeof(pfc));
12995b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = ops->cee_peer_getpfc(netdev, &pfc);
13001eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
13011eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc))
13021eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
13035b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
13045b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13055b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->peer_getappinfo && ops->peer_getapptable) {
13065b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_build_peer_app(netdev, skb,
13075b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   DCB_ATTR_CEE_PEER_APP_TABLE,
13085b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   DCB_ATTR_CEE_PEER_APP_INFO,
13095b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   DCB_ATTR_CEE_PEER_APP);
13105b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
13115b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
13125b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
13135b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nla_nest_end(skb, cee);
13145b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13155b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* DCBX state */
13165b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (dcbx >= 0) {
13175b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
13185b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
13195b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
13205b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
13215b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return 0;
13225b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13235b7f7626743e0912958981343b47ac0ab2206b1cShmulik Raviddcb_unlock:
13245b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	spin_unlock(&dcb_lock);
13255b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidnla_put_failure:
13265b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return err;
13275b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
13285b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13295b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidstatic int dcbnl_notify(struct net_device *dev, int event, int cmd,
133015e473046cb6e5d18a4d0057e61d76315230382bEric W. Biederman			u32 seq, u32 portid, int dcbx_ver)
1331314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend{
1332314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct net *net = dev_net(dev);
1333314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct sk_buff *skb;
1334314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct nlmsghdr *nlh;
1335314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
1336314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	int err;
1337314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1338314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!ops)
1339314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -EOPNOTSUPP;
1340314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
134115e473046cb6e5d18a4d0057e61d76315230382bEric W. Biederman	skb = dcbnl_newmsg(event, cmd, portid, seq, 0, &nlh);
1342314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!skb)
1343314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -ENOBUFS;
1344314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
13455b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (dcbx_ver == DCB_CAP_DCBX_VER_IEEE)
13465b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_ieee_fill(skb, dev);
13475b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	else
13485b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_cee_fill(skb, dev);
13495b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
1350314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (err < 0) {
1351314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		/* Report error to broadcast listeners */
1352ab6d470735682a6e1ba889a66f56eb1640242096Thomas Graf		nlmsg_free(skb);
1353314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		rtnl_set_sk_err(net, RTNLGRP_DCB, err);
1354314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	} else {
1355314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		/* End nlmsg and notify broadcast listeners */
1356314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nlmsg_end(skb, nlh);
1357314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		rtnl_notify(skb, net, 0, RTNLGRP_DCB, NULL, GFP_KERNEL);
1358314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1359314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1360314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return err;
1361314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend}
13625b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13635b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidint dcbnl_ieee_notify(struct net_device *dev, int event, int cmd,
136415e473046cb6e5d18a4d0057e61d76315230382bEric W. Biederman		      u32 seq, u32 portid)
13655b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
136615e473046cb6e5d18a4d0057e61d76315230382bEric W. Biederman	return dcbnl_notify(dev, event, cmd, seq, portid, DCB_CAP_DCBX_VER_IEEE);
13675b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
13685b7f7626743e0912958981343b47ac0ab2206b1cShmulik RavidEXPORT_SYMBOL(dcbnl_ieee_notify);
13695b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13705b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidint dcbnl_cee_notify(struct net_device *dev, int event, int cmd,
137115e473046cb6e5d18a4d0057e61d76315230382bEric W. Biederman		     u32 seq, u32 portid)
13725b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
137315e473046cb6e5d18a4d0057e61d76315230382bEric W. Biederman	return dcbnl_notify(dev, event, cmd, seq, portid, DCB_CAP_DCBX_VER_CEE);
13745b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
13755b7f7626743e0912958981343b47ac0ab2206b1cShmulik RavidEXPORT_SYMBOL(dcbnl_cee_notify);
1376314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1377314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
1378314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend * be completed the entire msg is aborted and error value is returned.
1379314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend * No attempt is made to reconcile the case where only part of the
1380314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend * cmd can be completed.
1381314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend */
13827be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh,
13837be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
1384314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend{
1385314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1386314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
13873d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int err;
1388314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1389314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!ops)
13903d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
1391314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
13924003b65871c101eb5ce8f37a325feac54aa5c681John Fastabend	if (!tb[DCB_ATTR_IEEE])
13934003b65871c101eb5ce8f37a325feac54aa5c681John Fastabend		return -EINVAL;
13944003b65871c101eb5ce8f37a325feac54aa5c681John Fastabend
1395314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1396314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1397314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (err)
1398314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return err;
1399314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1400314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
1401314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
1402314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		err = ops->ieee_setets(netdev, ets);
1403314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		if (err)
1404314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			goto err;
1405314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1406314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
140708f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	if (ieee[DCB_ATTR_IEEE_MAXRATE] && ops->ieee_setmaxrate) {
140808f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		struct ieee_maxrate *maxrate =
140908f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai			nla_data(ieee[DCB_ATTR_IEEE_MAXRATE]);
141008f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		err = ops->ieee_setmaxrate(netdev, maxrate);
141108f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		if (err)
141208f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai			goto err;
141308f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	}
141408f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai
1415314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
1416314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
1417314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		err = ops->ieee_setpfc(netdev, pfc);
1418314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		if (err)
1419314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			goto err;
1420314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1421314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1422314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1423314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		struct nlattr *attr;
1424314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		int rem;
1425314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1426314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1427314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			struct dcb_app *app_data;
1428314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1429314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend				continue;
1430314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			app_data = nla_data(attr);
1431314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			if (ops->ieee_setapp)
1432314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend				err = ops->ieee_setapp(netdev, app_data);
1433314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			else
1434b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend				err = dcb_ieee_setapp(netdev, app_data);
1435314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			if (err)
1436314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend				goto err;
1437314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		}
1438314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1439314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1440314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabenderr:
14417be994138b188387691322921c08e19bddf6d3c5Thomas Graf	err = nla_put_u8(skb, DCB_ATTR_IEEE, err);
14425b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0);
1443314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return err;
1444314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend}
1445314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
14467be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_ieee_get(struct net_device *netdev, struct nlmsghdr *nlh,
14477be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
1448314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend{
1449314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1450314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1451314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!ops)
1452314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -EOPNOTSUPP;
1453314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
14547be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return dcbnl_ieee_fill(skb, netdev);
1455314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend}
1456f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
14577be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_ieee_del(struct net_device *netdev, struct nlmsghdr *nlh,
14587be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
1459f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend{
1460f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1461f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
14623d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int err;
1463f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1464f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (!ops)
1465f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		return -EOPNOTSUPP;
1466f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1467f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (!tb[DCB_ATTR_IEEE])
1468f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		return -EINVAL;
1469f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1470f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1471f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1472f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (err)
1473f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		return err;
1474f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1475f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1476f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		struct nlattr *attr;
1477f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		int rem;
1478f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1479f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1480f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			struct dcb_app *app_data;
1481f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1482f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1483f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				continue;
1484f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			app_data = nla_data(attr);
1485f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			if (ops->ieee_delapp)
1486f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				err = ops->ieee_delapp(netdev, app_data);
1487f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			else
1488f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				err = dcb_ieee_delapp(netdev, app_data);
1489f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			if (err)
1490f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				goto err;
1491f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		}
1492f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	}
1493f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1494f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabenderr:
14957be994138b188387691322921c08e19bddf6d3c5Thomas Graf	err = nla_put_u8(skb, DCB_ATTR_IEEE, err);
14965b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0);
1497f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	return err;
1498f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend}
1499f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1500f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
15016241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid/* DCBX configuration */
15027be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getdcbx(struct net_device *netdev, struct nlmsghdr *nlh,
15037be994138b188387691322921c08e19bddf6d3c5Thomas Graf			 u32 seq, struct nlattr **tb, struct sk_buff *skb)
15046241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid{
15056241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	if (!netdev->dcbnl_ops->getdcbx)
15067f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
15076241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
15087be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_DCBX,
15097be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  netdev->dcbnl_ops->getdcbx(netdev));
15106241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid}
15116241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
15127be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setdcbx(struct net_device *netdev, struct nlmsghdr *nlh,
15137be994138b188387691322921c08e19bddf6d3c5Thomas Graf			 u32 seq, struct nlattr **tb, struct sk_buff *skb)
15146241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid{
15156241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	u8 value;
15166241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
15177f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->setdcbx)
15187f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
15197f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
15207f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_DCBX])
15217f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
15226241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
15236241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	value = nla_get_u8(tb[DCB_ATTR_DCBX]);
15246241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
15257be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_DCBX,
15267be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  netdev->dcbnl_ops->setdcbx(netdev, value));
15276241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid}
15286241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
15297be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh,
15307be994138b188387691322921c08e19bddf6d3c5Thomas Graf			    u32 seq, struct nlattr **tb, struct sk_buff *skb)
1531ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid{
1532ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest;
1533ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	u8 value;
15347f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret, i;
1535ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	int getall = 0;
1536ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15377f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->getfeatcfg)
15387f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
15397f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
15407f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_FEATCFG])
15417f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
1542ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1543ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1544ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			       dcbnl_featcfg_nest);
15457f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (ret)
15467be994138b188387691322921c08e19bddf6d3c5Thomas Graf		return ret;
1547ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15487be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nest = nla_nest_start(skb, DCB_ATTR_FEATCFG);
15497be994138b188387691322921c08e19bddf6d3c5Thomas Graf	if (!nest)
15507be994138b188387691322921c08e19bddf6d3c5Thomas Graf		return -EMSGSIZE;
1551ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1552ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	if (data[DCB_FEATCFG_ATTR_ALL])
1553ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		getall = 1;
1554ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1555ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1556ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (!getall && !data[i])
1557ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			continue;
1558ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1559ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value);
15607f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		if (!ret)
15617be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb, i, value);
1562ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15637f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		if (ret) {
15647be994138b188387691322921c08e19bddf6d3c5Thomas Graf			nla_nest_cancel(skb, nest);
15657f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid			goto nla_put_failure;
15667f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		}
1567ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
15687be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, nest);
1569ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15707f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravidnla_put_failure:
1571ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	return ret;
1572ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid}
1573ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15747be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh,
15757be994138b188387691322921c08e19bddf6d3c5Thomas Graf			    u32 seq, struct nlattr **tb, struct sk_buff *skb)
1576ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid{
1577ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1];
15787f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret, i;
1579ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	u8 value;
1580ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15817f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->setfeatcfg)
15827f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -ENOTSUPP;
15837f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
15847f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_FEATCFG])
15857f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
1586ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1587ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1588ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			       dcbnl_featcfg_nest);
1589ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15907f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (ret)
1591ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto err;
1592ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1593ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1594ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (data[i] == NULL)
1595ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			continue;
1596ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1597ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		value = nla_get_u8(data[i]);
1598ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1599ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = netdev->dcbnl_ops->setfeatcfg(netdev, i, value);
1600ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1601ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (ret)
16027f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid			goto err;
1603ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1604ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Raviderr:
16057be994138b188387691322921c08e19bddf6d3c5Thomas Graf	ret = nla_put_u8(skb, DCB_ATTR_FEATCFG, ret);
16067f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
1607ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	return ret;
1608ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid}
1609ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1610dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid/* Handle CEE DCBX GET commands. */
16117be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_cee_get(struct net_device *netdev, struct nlmsghdr *nlh,
16127be994138b188387691322921c08e19bddf6d3c5Thomas Graf			 u32 seq, struct nlattr **tb, struct sk_buff *skb)
1613dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid{
1614dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1615dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
1616dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	if (!ops)
1617dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		return -EOPNOTSUPP;
1618dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
16197be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return dcbnl_cee_fill(skb, netdev);
1620dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid}
1621dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
162233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Grafstruct reply_func {
162333a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	/* reply netlink message type */
162433a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	int	type;
162533a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
162633a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	/* function to fill message contents */
162733a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	int   (*cb)(struct net_device *, struct nlmsghdr *, u32,
162833a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		    struct nlattr **, struct sk_buff *);
162933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf};
163033a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
163133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Grafstatic const struct reply_func reply_funcs[DCB_CMD_MAX+1] = {
16327be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GSTATE]	= { RTM_GETDCB, dcbnl_getstate },
16337be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_SSTATE]	= { RTM_SETDCB, dcbnl_setstate },
16347be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PFC_GCFG]	= { RTM_GETDCB, dcbnl_getpfccfg },
16357be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PFC_SCFG]	= { RTM_SETDCB, dcbnl_setpfccfg },
16367be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GPERM_HWADDR]	= { RTM_GETDCB, dcbnl_getperm_hwaddr },
16377be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GCAP]		= { RTM_GETDCB, dcbnl_getcap },
16387be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GNUMTCS]	= { RTM_GETDCB, dcbnl_getnumtcs },
16397be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_SNUMTCS]	= { RTM_SETDCB, dcbnl_setnumtcs },
16407be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PFC_GSTATE]	= { RTM_GETDCB, dcbnl_getpfcstate },
16417be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PFC_SSTATE]	= { RTM_SETDCB, dcbnl_setpfcstate },
16427be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GAPP]		= { RTM_GETDCB, dcbnl_getapp },
16437be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_SAPP]		= { RTM_SETDCB, dcbnl_setapp },
16447be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PGTX_GCFG]	= { RTM_GETDCB, dcbnl_pgtx_getcfg },
16457be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PGTX_SCFG]	= { RTM_SETDCB, dcbnl_pgtx_setcfg },
16467be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PGRX_GCFG]	= { RTM_GETDCB, dcbnl_pgrx_getcfg },
16477be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PGRX_SCFG]	= { RTM_SETDCB, dcbnl_pgrx_setcfg },
16487be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_SET_ALL]	= { RTM_SETDCB, dcbnl_setall },
16497be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_BCN_GCFG]	= { RTM_GETDCB, dcbnl_bcn_getcfg },
16507be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_BCN_SCFG]	= { RTM_SETDCB, dcbnl_bcn_setcfg },
16517be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_IEEE_GET]	= { RTM_GETDCB, dcbnl_ieee_get },
16527be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_IEEE_SET]	= { RTM_SETDCB, dcbnl_ieee_set },
16537be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_IEEE_DEL]	= { RTM_SETDCB, dcbnl_ieee_del },
16547be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GDCBX]		= { RTM_GETDCB, dcbnl_getdcbx },
16557be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_SDCBX]		= { RTM_SETDCB, dcbnl_setdcbx },
16567be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GFEATCFG]	= { RTM_GETDCB, dcbnl_getfeatcfg },
16577be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_SFEATCFG]	= { RTM_SETDCB, dcbnl_setfeatcfg },
16587be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_CEE_GET]	= { RTM_GETDCB, dcbnl_cee_get },
165933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf};
166033a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
1661661d2967b3f1b34eeaa7e212e7b9bbe8ee072b59Thomas Grafstatic int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh)
16622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
16632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct net *net = sock_net(skb->sk);
16642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct net_device *netdev;
16657a282bc37f8a1e7b46907d78724177d20214b137Thomas Graf	struct dcbmsg *dcb = nlmsg_data(nlh);
16662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *tb[DCB_ATTR_MAX + 1];
166715e473046cb6e5d18a4d0057e61d76315230382bEric W. Biederman	u32 portid = skb ? NETLINK_CB(skb).portid : 0;
16682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
166933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	struct sk_buff *reply_skb;
167039912f9cf9603f0de085fb5ba916a7a88010ccd9Thomas Graf	struct nlmsghdr *reply_nlh = NULL;
167133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	const struct reply_func *fn;
16722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1673dfc47ef8639facd77210e74be831943c2fdd9c74Eric W. Biederman	if ((nlh->nlmsg_type == RTM_SETDCB) && !capable(CAP_NET_ADMIN))
1674dfc47ef8639facd77210e74be831943c2fdd9c74Eric W. Biederman		return -EPERM;
1675dfc47ef8639facd77210e74be831943c2fdd9c74Eric W. Biederman
16762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
16772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  dcbnl_rtnl_policy);
16782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret < 0)
16792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
16802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
168133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	if (dcb->cmd > DCB_CMD_MAX)
168233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		return -EINVAL;
168333a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
168433a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	/* check if a reply function has been defined for the command */
168533a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	fn = &reply_funcs[dcb->cmd];
168633a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	if (!fn->cb)
168733a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		return -EOPNOTSUPP;
168833a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
16892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_IFNAME])
16902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
16912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
16927c77ab24e30bad7598b5cfda93be6f32ed439c2fJohn Fastabend	netdev = dev_get_by_name(net, nla_data(tb[DCB_ATTR_IFNAME]));
16932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev)
16943d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -ENODEV;
16952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
16963d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops) {
16973d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		ret = -EOPNOTSUPP;
16983d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		goto out;
16993d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	}
17002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
170115e473046cb6e5d18a4d0057e61d76315230382bEric W. Biederman	reply_skb = dcbnl_newmsg(fn->type, dcb->cmd, portid, nlh->nlmsg_seq,
170233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf				 nlh->nlmsg_flags, &reply_nlh);
170333a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	if (!reply_skb) {
170433a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		ret = -ENOBUFS;
170533a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		goto out;
170633a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	}
170733a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
170833a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	ret = fn->cb(netdev, nlh, nlh->nlmsg_seq, tb, reply_skb);
170933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	if (ret < 0) {
171033a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		nlmsg_free(reply_skb);
171133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		goto out;
171233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	}
171333a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
171433a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	nlmsg_end(reply_skb, reply_nlh);
171533a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
17167c77ab24e30bad7598b5cfda93be6f32ed439c2fJohn Fastabend	ret = rtnl_unicast(reply_skb, net, portid);
17172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckout:
17182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dev_put(netdev);
17192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
17202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
17212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1722716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Grafstatic struct dcb_app_type *dcb_app_lookup(const struct dcb_app *app,
1723716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf					   int ifindex, int prio)
1724716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf{
1725716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	struct dcb_app_type *itr;
1726716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf
1727716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	list_for_each_entry(itr, &dcb_app_list, list) {
1728716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		if (itr->app.selector == app->selector &&
1729716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		    itr->app.protocol == app->protocol &&
1730716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		    itr->ifindex == ifindex &&
1731716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		    (!prio || itr->app.priority == prio))
1732716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf			return itr;
1733716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	}
1734716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf
1735716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	return NULL;
1736716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf}
1737716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf
17384e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Grafstatic int dcb_app_add(const struct dcb_app *app, int ifindex)
17394e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf{
17404e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	struct dcb_app_type *entry;
17414e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf
17424e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
17434e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	if (!entry)
17444e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf		return -ENOMEM;
17454e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf
17464e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	memcpy(&entry->app, app, sizeof(*app));
17474e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	entry->ifindex = ifindex;
17484e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	list_add(&entry->list, &dcb_app_list);
17494e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf
17504e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	return 0;
17514e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf}
17524e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf
17539ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend/**
17549ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * dcb_getapp - retrieve the DCBX application user priority
17559ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend *
17569ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * On success returns a non-zero 802.1p user priority bitmap
17579ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * otherwise returns 0 as the invalid user priority bitmap to
17589ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * indicate an error.
17599ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend */
17609ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendu8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
17619ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
17629ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
17639ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	u8 prio = 0;
17649ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
17659ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
1766716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
1767716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		prio = itr->app.priority;
17689ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
17699ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
17709ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	return prio;
17719ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
17729ab933ab2cc80f04690d6aa385b1110075c5e507John FastabendEXPORT_SYMBOL(dcb_getapp);
17739ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
17749ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend/**
1775b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * dcb_setapp - add CEE dcb application data to app list
17769ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend *
1777b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * Priority 0 is an invalid priority in CEE spec. This routine
1778b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * removes applications from the app list if the priority is
1779b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * set to zero.
17809ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend */
1781ab6baf980b095c70a56c5eb2f58166aef8a0edc8John Fastabendint dcb_setapp(struct net_device *dev, struct dcb_app *new)
17829ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
17839ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
17847ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	struct dcb_app_type event;
17854e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	int err = 0;
17867ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend
1787e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	event.ifindex = dev->ifindex;
17887ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	memcpy(&event.app, new, sizeof(event.app));
17896bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend	if (dev->dcbnl_ops->getdcbx)
17906bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
17919ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
17929ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
17939ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	/* Search for existing match and replace */
1794716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	if ((itr = dcb_app_lookup(new, dev->ifindex, 0))) {
1795716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		if (new->priority)
1796716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf			itr->app.priority = new->priority;
1797716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		else {
1798716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf			list_del(&itr->list);
1799716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf			kfree(itr);
18009ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		}
1801716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		goto out;
18029ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
18039ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	/* App type does not exist add new application type */
18044e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	if (new->priority)
18054e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf		err = dcb_app_add(new, dev->ifindex);
18069ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendout:
18079ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
18084e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	if (!err)
18094e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
18104e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	return err;
18119ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
18129ab933ab2cc80f04690d6aa385b1110075c5e507John FastabendEXPORT_SYMBOL(dcb_setapp);
18139ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
1814b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend/**
1815a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * dcb_ieee_getapp_mask - retrieve the IEEE DCB application priority
1816a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend *
1817a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * Helper routine which on success returns a non-zero 802.1Qaz user
1818a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * priority bitmap otherwise returns 0 to indicate the dcb_app was
1819a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * not found in APP list.
1820a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend */
1821a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabendu8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
1822a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend{
1823a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	struct dcb_app_type *itr;
1824a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	u8 prio = 0;
1825a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend
1826a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	spin_lock(&dcb_lock);
1827716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
1828716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		prio |= 1 << itr->app.priority;
1829a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	spin_unlock(&dcb_lock);
1830a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend
1831a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	return prio;
1832a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend}
1833a364c8cf80251849bab207be8c9e66253c8ca8f8John FastabendEXPORT_SYMBOL(dcb_ieee_getapp_mask);
1834a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend
1835a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend/**
1836b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * dcb_ieee_setapp - add IEEE dcb application data to app list
1837b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend *
1838b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * This adds Application data to the list. Multiple application
1839b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * entries may exists for the same selector and protocol as long
1840b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * as the priorities are different.
1841b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend */
1842b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabendint dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
1843b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend{
1844b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	struct dcb_app_type event;
1845b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	int err = 0;
1846b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
1847e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	event.ifindex = dev->ifindex;
1848b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	memcpy(&event.app, new, sizeof(event.app));
18496bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend	if (dev->dcbnl_ops->getdcbx)
18506bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
1851b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
1852b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	spin_lock(&dcb_lock);
1853b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	/* Search for existing match and abort if found */
1854716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	if (dcb_app_lookup(new, dev->ifindex, new->priority)) {
1855716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		err = -EEXIST;
1856716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		goto out;
1857b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	}
1858b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
18594e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	err = dcb_app_add(new, dev->ifindex);
1860b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabendout:
1861b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	spin_unlock(&dcb_lock);
1862b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	if (!err)
1863b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
1864b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	return err;
1865b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend}
1866b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John FastabendEXPORT_SYMBOL(dcb_ieee_setapp);
1867b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
1868f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend/**
1869f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend * dcb_ieee_delapp - delete IEEE dcb application data from list
1870f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend *
1871f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend * This removes a matching APP data from the APP list
1872f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend */
1873f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabendint dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
1874f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend{
1875f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	struct dcb_app_type *itr;
1876f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	struct dcb_app_type event;
1877f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	int err = -ENOENT;
1878f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1879e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	event.ifindex = dev->ifindex;
1880f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	memcpy(&event.app, del, sizeof(event.app));
18816bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend	if (dev->dcbnl_ops->getdcbx)
18826bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
1883f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1884f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	spin_lock(&dcb_lock);
1885f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	/* Search for existing match and remove it. */
1886716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	if ((itr = dcb_app_lookup(del, dev->ifindex, del->priority))) {
1887716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		list_del(&itr->list);
1888716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		kfree(itr);
1889716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		err = 0;
1890f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	}
1891f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1892f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	spin_unlock(&dcb_lock);
1893f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (!err)
1894f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
1895f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	return err;
1896f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend}
1897f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John FastabendEXPORT_SYMBOL(dcb_ieee_delapp);
1898f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
18997c14c3f10e6dcd7f70e49f77b6e1ae605c4861e6Shmulik Ravidstatic void dcb_flushapp(void)
19009ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
19019ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *app;
19022a8fe003741aa90b6b9453e90af4bbb7bc42918cDan Carpenter	struct dcb_app_type *tmp;
19039ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
19049ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
19052a8fe003741aa90b6b9453e90af4bbb7bc42918cDan Carpenter	list_for_each_entry_safe(app, tmp, &dcb_app_list, list) {
19069ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		list_del(&app->list);
19079ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		kfree(app);
19089ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
19099ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
19109ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
19119ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
19122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __init dcbnl_init(void)
19132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
19149ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	INIT_LIST_HEAD(&dcb_app_list);
19159ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
1916c7ac8679bec9397afe8918f788cbcef88c38da54Greg Rose	rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, NULL);
1917c7ac8679bec9397afe8918f788cbcef88c38da54Greg Rose	rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, NULL);
19182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
19202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
19212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_init(dcbnl_init);
19222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic void __exit dcbnl_exit(void)
19242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
19252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_unregister(PF_UNSPEC, RTM_GETDCB);
19262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_unregister(PF_UNSPEC, RTM_SETDCB);
19279ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	dcb_flushapp();
19282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
19292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_exit(dcbnl_exit);
1930