dcbnl.c revision 1eb4c977778b5ab8e8fba9022687f0a5941d681a
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
312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/**
322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Data Center Bridging (DCB) is a collection of Ethernet enhancements
332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * intended to allow network traffic with differing requirements
342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * (highly reliable, no drops vs. best effort vs. low latency) to operate
352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * and co-exist on Ethernet.  Current DCB features are:
362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Enhanced Transmission Selection (aka Priority Grouping [PG]) - provides a
382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *   framework for assigning bandwidth guarantees to traffic classes.
392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Priority-based Flow Control (PFC) - provides a flow control mechanism which
412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *   can work independently for each 802.1p priority.
422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Congestion Notification - provides a mechanism for end-to-end congestion
442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *   control for protocols which do not have built-in congestion management.
452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * More information about the emerging standards for these Ethernet features
472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * can be found at: http://www.ieee802.org/1/pages/dcbridges.html
482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * This file implements an rtnetlink interface to allow configuration of DCB
502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * features for capable devices.
512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck */
522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander DuyckMODULE_AUTHOR("Lucy Liu, <lucy.liu@intel.com>");
547a6b6f515f77d1c62a2f383b6dce18cb0af0cf4fJeff KirsherMODULE_DESCRIPTION("Data Center Bridging netlink interface");
552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander DuyckMODULE_LICENSE("GPL");
562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/**************** DCB attribute policies *************************************/
582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB netlink attributes policy */
60b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = {
61859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_IFNAME]      = {.type = NLA_NUL_STRING, .len = IFNAMSIZ - 1},
62859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_STATE]       = {.type = NLA_U8},
63859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_PFC_CFG]     = {.type = NLA_NESTED},
64859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_PG_CFG]      = {.type = NLA_NESTED},
65859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_SET_ALL]     = {.type = NLA_U8},
662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG},
67859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_CAP]         = {.type = NLA_NESTED},
68859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_PFC_STATE]   = {.type = NLA_U8},
69859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_BCN]         = {.type = NLA_NESTED},
706fa382af61338908e5713234bcee598423f661c3Yi Zou	[DCB_ATTR_APP]         = {.type = NLA_NESTED},
713e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	[DCB_ATTR_IEEE]	       = {.type = NLA_NESTED},
726241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	[DCB_ATTR_DCBX]        = {.type = NLA_U8},
73ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_ATTR_FEATCFG]     = {.type = NLA_NESTED},
742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck};
752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB priority flow control to User Priority nested attributes */
77b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = {
782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_0]   = {.type = NLA_U8},
792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_1]   = {.type = NLA_U8},
802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_2]   = {.type = NLA_U8},
812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_3]   = {.type = NLA_U8},
822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_4]   = {.type = NLA_U8},
832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_5]   = {.type = NLA_U8},
842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_6]   = {.type = NLA_U8},
852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_7]   = {.type = NLA_U8},
862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_ALL] = {.type = NLA_FLAG},
872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck};
882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB priority grouping nested attributes */
90b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = {
912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_0]      = {.type = NLA_NESTED},
922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_1]      = {.type = NLA_NESTED},
932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_2]      = {.type = NLA_NESTED},
942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_3]      = {.type = NLA_NESTED},
952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_4]      = {.type = NLA_NESTED},
962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_5]      = {.type = NLA_NESTED},
972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_6]      = {.type = NLA_NESTED},
982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_7]      = {.type = NLA_NESTED},
992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_ALL]    = {.type = NLA_NESTED},
1002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_0]   = {.type = NLA_U8},
1012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_1]   = {.type = NLA_U8},
1022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_2]   = {.type = NLA_U8},
1032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_3]   = {.type = NLA_U8},
1042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_4]   = {.type = NLA_U8},
1052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_5]   = {.type = NLA_U8},
1062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_6]   = {.type = NLA_U8},
1072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_7]   = {.type = NLA_U8},
1082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_ALL] = {.type = NLA_FLAG},
1092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck};
1102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB traffic class nested attributes. */
112b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = {
1132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_PGID]            = {.type = NLA_U8},
1142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_UP_MAPPING]      = {.type = NLA_U8},
1152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_STRICT_PRIO]     = {.type = NLA_U8},
1162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_BW_PCT]          = {.type = NLA_U8},
1172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_ALL]             = {.type = NLA_FLAG},
1182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck};
1192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
12046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck/* DCB capabilities nested attributes. */
121b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = {
12246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_ALL]     = {.type = NLA_FLAG},
12346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_PG]      = {.type = NLA_U8},
12446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_PFC]     = {.type = NLA_U8},
12546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_UP2TC]   = {.type = NLA_U8},
12646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_PG_TCS]  = {.type = NLA_U8},
12746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8},
12846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_GSP]     = {.type = NLA_U8},
12946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_BCN]     = {.type = NLA_U8},
1306241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	[DCB_CAP_ATTR_DCBX]    = {.type = NLA_U8},
13146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck};
1322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
13333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck/* DCB capabilities nested attributes. */
134b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = {
13533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	[DCB_NUMTCS_ATTR_ALL]     = {.type = NLA_FLAG},
13633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	[DCB_NUMTCS_ATTR_PG]      = {.type = NLA_U8},
13733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	[DCB_NUMTCS_ATTR_PFC]     = {.type = NLA_U8},
13833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck};
13933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
140859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck/* DCB BCN nested attributes. */
141b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = {
142859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_0]         = {.type = NLA_U8},
143859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_1]         = {.type = NLA_U8},
144859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_2]         = {.type = NLA_U8},
145859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_3]         = {.type = NLA_U8},
146859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_4]         = {.type = NLA_U8},
147859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_5]         = {.type = NLA_U8},
148859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_6]         = {.type = NLA_U8},
149859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_7]         = {.type = NLA_U8},
150859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_ALL]       = {.type = NLA_FLAG},
151f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	[DCB_BCN_ATTR_BCNA_0]       = {.type = NLA_U32},
152f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	[DCB_BCN_ATTR_BCNA_1]       = {.type = NLA_U32},
153859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_ALPHA]        = {.type = NLA_U32},
154859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_BETA]         = {.type = NLA_U32},
155859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_GD]           = {.type = NLA_U32},
156859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_GI]           = {.type = NLA_U32},
157859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_TMAX]         = {.type = NLA_U32},
158859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_TD]           = {.type = NLA_U32},
159859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RMIN]         = {.type = NLA_U32},
160859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_W]            = {.type = NLA_U32},
161859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RD]           = {.type = NLA_U32},
162859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RU]           = {.type = NLA_U32},
163859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_WRTT]         = {.type = NLA_U32},
164859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RI]           = {.type = NLA_U32},
165859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_C]            = {.type = NLA_U32},
166859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_ALL]          = {.type = NLA_FLAG},
167859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck};
168859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1696fa382af61338908e5713234bcee598423f661c3Yi Zou/* DCB APP nested attributes. */
170b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = {
1716fa382af61338908e5713234bcee598423f661c3Yi Zou	[DCB_APP_ATTR_IDTYPE]       = {.type = NLA_U8},
1726fa382af61338908e5713234bcee598423f661c3Yi Zou	[DCB_APP_ATTR_ID]           = {.type = NLA_U16},
1736fa382af61338908e5713234bcee598423f661c3Yi Zou	[DCB_APP_ATTR_PRIORITY]     = {.type = NLA_U8},
1746fa382af61338908e5713234bcee598423f661c3Yi Zou};
1756fa382af61338908e5713234bcee598423f661c3Yi Zou
1763e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend/* IEEE 802.1Qaz nested attributes. */
1773e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabendstatic const struct nla_policy dcbnl_ieee_policy[DCB_ATTR_IEEE_MAX + 1] = {
1783e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	[DCB_ATTR_IEEE_ETS]	    = {.len = sizeof(struct ieee_ets)},
1793e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	[DCB_ATTR_IEEE_PFC]	    = {.len = sizeof(struct ieee_pfc)},
1803e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	[DCB_ATTR_IEEE_APP_TABLE]   = {.type = NLA_NESTED},
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
1982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* standard netlink reply call */
1992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
2002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                       u32 seq, u16 flags)
2012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
2032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
2042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
2052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
2062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
2092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
2102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags);
2122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
2142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
2152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = cmd;
2162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_pad = 0;
2172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_put_u8(dcbnl_skb, attr, value);
2192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
2202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
2212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	/* end the message, assign the nlmsg_len. */
2232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
2242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
2252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
2267eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		return -EINVAL;
2272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
2292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
2302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
231858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
2322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
2332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getstate(struct net_device *netdev, struct nlattr **tb,
2362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                          u32 pid, u32 seq, u16 flags)
2372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
2392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	/* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */
2412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops->getstate)
2422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
2432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(netdev->dcbnl_ops->getstate(netdev), RTM_GETDCB,
2452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  DCB_CMD_GSTATE, DCB_ATTR_STATE, pid, seq, flags);
2462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
2482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb,
2512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                           u32 pid, u32 seq, u16 flags)
2522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
2542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
2552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
2562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest;
2572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
2582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
2592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
2602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int getall = 0;
2612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->getpfccfg)
2632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
2642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
2662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PFC_CFG],
2672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       dcbnl_pfc_up_nest);
2682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
2692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
2702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
2732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
2742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
2762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
2782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
2792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = DCB_CMD_PFC_GCFG;
2802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG);
2822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!nest)
2832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
2842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (data[DCB_PFC_UP_ATTR_ALL])
2862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
2872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
2892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !data[i])
2902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
2912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0,
2932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                             &value);
2942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_put_u8(dcbnl_skb, i, value);
2952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret) {
2972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			nla_nest_cancel(dcbnl_skb, nest);
2982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err;
2992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
3002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
3012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_end(dcbnl_skb, nest);
3022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
3042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
3062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
3077eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
3082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
3102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
3112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
312858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
3132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out:
3142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return -EINVAL;
3152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
3162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb,
3182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                                u32 pid, u32 seq, u16 flags)
3192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
3202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
3212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
3222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
3232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 perm_addr[MAX_ADDR_LEN];
3242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
3252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops->getpermhwaddr)
3272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
3282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
3312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
3322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
3342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
3362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
3372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = DCB_CMD_GPERM_HWADDR;
3382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
3402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr),
3422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	              perm_addr);
3432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
3452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
3472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
3487eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
3492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
3512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
353858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
3542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out:
3552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return -EINVAL;
3562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
3572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
35846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckstatic int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb,
35946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck                        u32 pid, u32 seq, u16 flags)
36046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck{
36146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct sk_buff *dcbnl_skb;
36246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct nlmsghdr *nlh;
36346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct dcbmsg *dcb;
36446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest;
36546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	u8 value;
36646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int ret = -EINVAL;
36746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int i;
36846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int getall = 0;
36946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
37046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap)
37146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		return ret;
37246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
37346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP],
37446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	                       dcbnl_cap_nest);
37546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (ret)
37646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto err_out;
37746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
37846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
37946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!dcbnl_skb)
38046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto err_out;
38146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
38246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
38346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
38446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcb = NLMSG_DATA(nlh);
38546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
38646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcb->cmd = DCB_CMD_GCAP;
38746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
38846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP);
38946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!nest)
39046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto err;
39146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
39246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (data[DCB_CAP_ATTR_ALL])
39346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		getall = 1;
39446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
39546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) {
39646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		if (!getall && !data[i])
39746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			continue;
39846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
39946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) {
40046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			ret = nla_put_u8(dcbnl_skb, i, value);
40146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
40246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			if (ret) {
40346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck				nla_nest_cancel(dcbnl_skb, nest);
40446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck				goto err;
40546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			}
40646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		}
40746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	}
40846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nla_nest_end(dcbnl_skb, nest);
40946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
41046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
41146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
41246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
41346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (ret)
4147eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
41546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
41646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	return 0;
41746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duycknlmsg_failure:
41846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckerr:
419858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
42046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckerr_out:
42146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	return -EINVAL;
42246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck}
42346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
42433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckstatic int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb,
42533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck                           u32 pid, u32 seq, u16 flags)
42633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{
42733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct sk_buff *dcbnl_skb;
42833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlmsghdr *nlh;
42933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct dcbmsg *dcb;
43033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest;
43133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	u8 value;
43233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int ret = -EINVAL;
43333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int i;
43433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int getall = 0;
43533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
43633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs)
43733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		return ret;
43833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
43933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
44033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                       dcbnl_numtcs_nest);
44133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (ret) {
44233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
44333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err_out;
44433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
44533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
44633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
44733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (!dcbnl_skb) {
44833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
44933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err_out;
45033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
45133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
45233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
45333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
45433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcb = NLMSG_DATA(nlh);
45533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
45633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcb->cmd = DCB_CMD_GNUMTCS;
45733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
45833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS);
45933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (!nest) {
46033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
46133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err;
46233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
46333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
46433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (data[DCB_NUMTCS_ATTR_ALL])
46533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		getall = 1;
46633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
46733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
46833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (!getall && !data[i])
46933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			continue;
47033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
47133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value);
47233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (!ret) {
47333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			ret = nla_put_u8(dcbnl_skb, i, value);
47433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
47533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			if (ret) {
47633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck				nla_nest_cancel(dcbnl_skb, nest);
47733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck				ret = -EINVAL;
47833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck				goto err;
47933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			}
48033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		} else {
48133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			goto err;
48233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		}
48333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
48433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nla_nest_end(dcbnl_skb, nest);
48533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
48633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
48733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
48833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
48933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (ret) {
49033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
4917eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
49233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
49333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
49433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return 0;
49533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duycknlmsg_failure:
49633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr:
497858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
49833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr_out:
49933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return ret;
50033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck}
50133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
50233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckstatic int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb,
50333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck                           u32 pid, u32 seq, u16 flags)
50433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{
50533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1];
50633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int ret = -EINVAL;
50733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	u8 value;
50833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int i;
50933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
5108b124a8e14c04378466ddfe63e41fc5035f957ebDon Skidmore	if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setnumtcs)
51133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		return ret;
51233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
51333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
51433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                       dcbnl_numtcs_nest);
51533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
51633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (ret) {
51733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
51833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err;
51933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
52033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
52133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
52233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (data[i] == NULL)
52333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			continue;
52433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
52533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		value = nla_get_u8(data[i]);
52633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
52733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value);
52833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
52933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (ret)
53033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			goto operr;
53133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
53233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
53333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckoperr:
53433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS,
53533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                  DCB_ATTR_NUMTCS, pid, seq, flags);
53633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
53733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr:
53833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return ret;
53933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck}
54033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
5410eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyckstatic int dcbnl_getpfcstate(struct net_device *netdev, struct nlattr **tb,
5420eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
5430eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{
5440eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	int ret = -EINVAL;
5450eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5460eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	if (!netdev->dcbnl_ops->getpfcstate)
5470eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		return ret;
5480eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5490eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	ret = dcbnl_reply(netdev->dcbnl_ops->getpfcstate(netdev), RTM_GETDCB,
5500eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	                  DCB_CMD_PFC_GSTATE, DCB_ATTR_PFC_STATE,
5510eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	                  pid, seq, flags);
5520eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5530eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	return ret;
5540eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck}
5550eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5560eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyckstatic int dcbnl_setpfcstate(struct net_device *netdev, struct nlattr **tb,
5570eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
5580eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{
5590eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	int ret = -EINVAL;
5600eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	u8 value;
5610eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5620eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	if (!tb[DCB_ATTR_PFC_STATE] || !netdev->dcbnl_ops->setpfcstate)
5630eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		return ret;
5640eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5650eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]);
5660eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5670eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	netdev->dcbnl_ops->setpfcstate(netdev, value);
5680eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5690eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SSTATE, DCB_ATTR_PFC_STATE,
5700eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	                  pid, seq, flags);
5710eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5720eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	return ret;
5730eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck}
5740eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
575579496865cf4ea429146382d62047ffdbaab0deeYi Zoustatic int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb,
576579496865cf4ea429146382d62047ffdbaab0deeYi Zou                        u32 pid, u32 seq, u16 flags)
577579496865cf4ea429146382d62047ffdbaab0deeYi Zou{
578579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct sk_buff *dcbnl_skb;
579579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlmsghdr *nlh;
580579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct dcbmsg *dcb;
581579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_nest;
582579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
583579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u16 id;
584579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u8 up, idtype;
585579496865cf4ea429146382d62047ffdbaab0deeYi Zou	int ret = -EINVAL;
586579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5873dce38a02d6370dca690cd923619d4b00024b723John Fastabend	if (!tb[DCB_ATTR_APP])
588579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
589579496865cf4ea429146382d62047ffdbaab0deeYi Zou
590579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
591579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                       dcbnl_app_nest);
592579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
593579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
594579496865cf4ea429146382d62047ffdbaab0deeYi Zou
595579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = -EINVAL;
596579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* all must be non-null */
597579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
598579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_ID]))
599579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
600579496865cf4ea429146382d62047ffdbaab0deeYi Zou
601579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* either by eth type or by socket number */
602579496865cf4ea429146382d62047ffdbaab0deeYi Zou	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
603579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
604579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (idtype != DCB_APP_IDTYPE_PORTNUM))
605579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
606579496865cf4ea429146382d62047ffdbaab0deeYi Zou
607579496865cf4ea429146382d62047ffdbaab0deeYi Zou	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
6083dce38a02d6370dca690cd923619d4b00024b723John Fastabend
6093dce38a02d6370dca690cd923619d4b00024b723John Fastabend	if (netdev->dcbnl_ops->getapp) {
6103dce38a02d6370dca690cd923619d4b00024b723John Fastabend		up = netdev->dcbnl_ops->getapp(netdev, idtype, id);
6113dce38a02d6370dca690cd923619d4b00024b723John Fastabend	} else {
6123dce38a02d6370dca690cd923619d4b00024b723John Fastabend		struct dcb_app app = {
6133dce38a02d6370dca690cd923619d4b00024b723John Fastabend					.selector = idtype,
6143dce38a02d6370dca690cd923619d4b00024b723John Fastabend					.protocol = id,
6153dce38a02d6370dca690cd923619d4b00024b723John Fastabend				     };
6163dce38a02d6370dca690cd923619d4b00024b723John Fastabend		up = dcb_getapp(netdev, &app);
6173dce38a02d6370dca690cd923619d4b00024b723John Fastabend	}
618579496865cf4ea429146382d62047ffdbaab0deeYi Zou
619579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* send this back */
620579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
621579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (!dcbnl_skb)
622579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
623579496865cf4ea429146382d62047ffdbaab0deeYi Zou
624579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
625579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcb = NLMSG_DATA(nlh);
626579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcb->dcb_family = AF_UNSPEC;
627579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcb->cmd = DCB_CMD_GAPP;
628579496865cf4ea429146382d62047ffdbaab0deeYi Zou
629579496865cf4ea429146382d62047ffdbaab0deeYi Zou	app_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_APP);
630d3337de52af7fb0ebe605b02b740be4ee7dee9ebJesper Juhl	if (!app_nest)
631d3337de52af7fb0ebe605b02b740be4ee7dee9ebJesper Juhl		goto out_cancel;
632d3337de52af7fb0ebe605b02b740be4ee7dee9ebJesper Juhl
633579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype);
634579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
635579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
636579496865cf4ea429146382d62047ffdbaab0deeYi Zou
637579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_put_u16(dcbnl_skb, DCB_APP_ATTR_ID, id);
638579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
639579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
640579496865cf4ea429146382d62047ffdbaab0deeYi Zou
641579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_PRIORITY, up);
642579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
643579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
644579496865cf4ea429146382d62047ffdbaab0deeYi Zou
645579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nla_nest_end(dcbnl_skb, app_nest);
646579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nlmsg_end(dcbnl_skb, nlh);
647579496865cf4ea429146382d62047ffdbaab0deeYi Zou
648579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
649579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
650579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto nlmsg_failure;
651579496865cf4ea429146382d62047ffdbaab0deeYi Zou
652579496865cf4ea429146382d62047ffdbaab0deeYi Zou	goto out;
653579496865cf4ea429146382d62047ffdbaab0deeYi Zou
654579496865cf4ea429146382d62047ffdbaab0deeYi Zouout_cancel:
655579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nla_nest_cancel(dcbnl_skb, app_nest);
656579496865cf4ea429146382d62047ffdbaab0deeYi Zounlmsg_failure:
657579496865cf4ea429146382d62047ffdbaab0deeYi Zou	kfree_skb(dcbnl_skb);
658579496865cf4ea429146382d62047ffdbaab0deeYi Zouout:
659579496865cf4ea429146382d62047ffdbaab0deeYi Zou	return ret;
660579496865cf4ea429146382d62047ffdbaab0deeYi Zou}
661579496865cf4ea429146382d62047ffdbaab0deeYi Zou
662579496865cf4ea429146382d62047ffdbaab0deeYi Zoustatic int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb,
663579496865cf4ea429146382d62047ffdbaab0deeYi Zou                        u32 pid, u32 seq, u16 flags)
664579496865cf4ea429146382d62047ffdbaab0deeYi Zou{
6659ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	int err, ret = -EINVAL;
666579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u16 id;
667579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u8 up, idtype;
668579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
669579496865cf4ea429146382d62047ffdbaab0deeYi Zou
6709ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (!tb[DCB_ATTR_APP])
671579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
672579496865cf4ea429146382d62047ffdbaab0deeYi Zou
673579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
674579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                       dcbnl_app_nest);
675579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
676579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
677579496865cf4ea429146382d62047ffdbaab0deeYi Zou
678579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = -EINVAL;
679579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* all must be non-null */
680579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
681579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_ID]) ||
682579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_PRIORITY]))
683579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
684579496865cf4ea429146382d62047ffdbaab0deeYi Zou
685579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* either by eth type or by socket number */
686579496865cf4ea429146382d62047ffdbaab0deeYi Zou	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
687579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
688579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (idtype != DCB_APP_IDTYPE_PORTNUM))
689579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
690579496865cf4ea429146382d62047ffdbaab0deeYi Zou
691579496865cf4ea429146382d62047ffdbaab0deeYi Zou	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
692579496865cf4ea429146382d62047ffdbaab0deeYi Zou	up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]);
693579496865cf4ea429146382d62047ffdbaab0deeYi Zou
6949ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (netdev->dcbnl_ops->setapp) {
6959ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		err = netdev->dcbnl_ops->setapp(netdev, idtype, id, up);
6969ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	} else {
6979ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		struct dcb_app app;
6989ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.selector = idtype;
6999ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.protocol = id;
7009ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.priority = up;
7019ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		err = dcb_setapp(netdev, &app);
7029ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
7039ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
7049ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	ret = dcbnl_reply(err, RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP,
7059ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			  pid, seq, flags);
706579496865cf4ea429146382d62047ffdbaab0deeYi Zouout:
707579496865cf4ea429146382d62047ffdbaab0deeYi Zou	return ret;
708579496865cf4ea429146382d62047ffdbaab0deeYi Zou}
709579496865cf4ea429146382d62047ffdbaab0deeYi Zou
7102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb,
7112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags, int dir)
7122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
7132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
7142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
7152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
7162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_nest, *param_nest, *data;
7172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
7182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
7192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 prio, pgid, tc_pct, up_map;
7202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret  = -EINVAL;
7212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int getall = 0;
7222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
7232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PG_CFG] ||
7252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgtccfgtx ||
7262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgtccfgrx ||
7272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgbwgcfgtx ||
7282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgbwgcfgrx)
7292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
7302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
7322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
7332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
7352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
7362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
7392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
7402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
7422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
7442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
7452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = (dir) ? DCB_CMD_PGRX_GCFG : DCB_CMD_PGTX_GCFG;
7462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	pg_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PG_CFG);
7482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!pg_nest)
7492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
7502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (pg_tb[DCB_PG_ATTR_TC_ALL])
7522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
7532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
7552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !pg_tb[i])
7562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
7572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (pg_tb[DCB_PG_ATTR_TC_ALL])
7592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data = pg_tb[DCB_PG_ATTR_TC_ALL];
7602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		else
7612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data = pg_tb[i];
7622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
7632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				       data, dcbnl_tc_param_nest);
7642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
7652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
7662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		param_nest = nla_nest_start(dcbnl_skb, i);
7682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!param_nest)
7692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
7702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		pgid = DCB_ATTR_VALUE_UNDEFINED;
7722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		prio = DCB_ATTR_VALUE_UNDEFINED;
7732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
7742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		up_map = DCB_ATTR_VALUE_UNDEFINED;
7752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
7772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
7782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgtccfgrx(netdev,
7792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						i - DCB_PG_ATTR_TC_0, &prio,
7802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						&pgid, &tc_pct, &up_map);
7812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
7822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
7832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgtccfgtx(netdev,
7842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						i - DCB_PG_ATTR_TC_0, &prio,
7852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						&pgid, &tc_pct, &up_map);
7862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
7872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_PGID] ||
7892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb,
7912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_PGID, pgid);
7922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
7932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
7942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
7952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] ||
7962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb,
7982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
7992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
8002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
8012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] ||
8032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
8042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb,
8052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
8062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
8072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
8082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] ||
8102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
8112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_BW_PCT,
8122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 tc_pct);
8132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
8142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
8152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		nla_nest_end(dcbnl_skb, param_nest);
8172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
8182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (pg_tb[DCB_PG_ATTR_BW_ID_ALL])
8202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
8212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	else
8222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 0;
8232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
8252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !pg_tb[i])
8262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
8272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
8292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
8312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
8322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgbwgcfgrx(netdev,
8332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
8342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
8352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
8362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgbwgcfgtx(netdev,
8372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
8382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_put_u8(dcbnl_skb, i, tc_pct);
8402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
8422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
8432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
8442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_end(dcbnl_skb, pg_nest);
8462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
8482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
8502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
8517eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
8522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
8542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_param:
8562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_cancel(dcbnl_skb, param_nest);
8572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_pg:
8582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_cancel(dcbnl_skb, pg_nest);
8592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
8602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
861858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
8622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out:
8632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret  = -EINVAL;
8642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
8652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlattr **tb,
8682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
8692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 0);
8712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlattr **tb,
8742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
8752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 1);
8772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb,
8802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                          u32 pid, u32 seq, u16 flags)
8812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
8832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
8842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate)
8862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
8872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	value = nla_get_u8(tb[DCB_ATTR_STATE]);
8892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8901486a61ebcd2711532f8163d30babc40e11e7b40Don Skidmore	ret = dcbnl_reply(netdev->dcbnl_ops->setstate(netdev, value),
8911486a61ebcd2711532f8163d30babc40e11e7b40Don Skidmore	                  RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE,
8922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  pid, seq, flags);
8932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
8952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb,
8982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                           u32 pid, u32 seq, u16 flags)
8992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
9002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1];
9012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
9022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
9032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
9042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->setpfccfg)
9062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
9072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
9092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PFC_CFG],
9102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       dcbnl_pfc_up_nest);
9112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
9122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
9132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
9152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (data[i] == NULL)
9162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
9172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		value = nla_get_u8(data[i]);
9182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		netdev->dcbnl_ops->setpfccfg(netdev,
9192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data[i]->nla_type - DCB_PFC_UP_ATTR_0, value);
9202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
9212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SCFG, DCB_ATTR_PFC_CFG,
9232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  pid, seq, flags);
9242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
9252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
9262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
9272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setall(struct net_device *netdev, struct nlattr **tb,
9292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                        u32 pid, u32 seq, u16 flags)
9302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
9312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
9322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall)
9342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
9352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(netdev->dcbnl_ops->setall(netdev), RTM_SETDCB,
9372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  DCB_CMD_SET_ALL, DCB_ATTR_SET_ALL, pid, seq, flags);
9382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
9402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
9412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb,
9432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags, int dir)
9442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
9452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
9462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
9472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
9482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
9492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 pgid;
9502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 up_map;
9512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 prio;
9522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 tc_pct;
9532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PG_CFG] ||
9552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgtccfgtx ||
9562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgtccfgrx ||
9572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgbwgcfgtx ||
9582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgbwgcfgrx)
9592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
9602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
9622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
9632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
9642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
9652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
9672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!pg_tb[i])
9682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
9692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
9712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                       pg_tb[i], dcbnl_tc_param_nest);
9722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
9732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err;
9742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		pgid = DCB_ATTR_VALUE_UNDEFINED;
9762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		prio = DCB_ATTR_VALUE_UNDEFINED;
9772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
9782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		up_map = DCB_ATTR_VALUE_UNDEFINED;
9792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO])
9812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			prio =
9822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			    nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]);
9832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_PGID])
9852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]);
9862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT])
9882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]);
9892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING])
9912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			up_map =
9922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			     nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]);
9932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		/* dir: Tx = 0, Rx = 1 */
9952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
9962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
9972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgtccfgrx(netdev,
9982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				i - DCB_PG_ATTR_TC_0,
9992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				prio, pgid, tc_pct, up_map);
10002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
10012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
10022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgtccfgtx(netdev,
10032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				i - DCB_PG_ATTR_TC_0,
10042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				prio, pgid, tc_pct, up_map);
10052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
10062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
10072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
10092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!pg_tb[i])
10102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
10112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = nla_get_u8(pg_tb[i]);
10132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		/* dir: Tx = 0, Rx = 1 */
10152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
10162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
10172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgbwgcfgrx(netdev,
10182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
10192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
10202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
10212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgbwgcfgtx(netdev,
10222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
10232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
10242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
10252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB,
10272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG),
10282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  DCB_ATTR_PG_CFG, pid, seq, flags);
10292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
10312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
10322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
10332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlattr **tb,
10352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
10362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
10372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 0);
10382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
10392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb,
10412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
10422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
10432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1);
10442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
10452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1046859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckstatic int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb,
1047859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck                            u32 pid, u32 seq, u16 flags)
1048859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck{
1049859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct sk_buff *dcbnl_skb;
1050859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlmsghdr *nlh;
1051859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct dcbmsg *dcb;
1052859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *bcn_nest;
1053859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1];
1054859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u8 value_byte;
1055859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u32 value_integer;
1056859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int ret  = -EINVAL;
1057859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	bool getall = false;
1058859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int i;
1059859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1060859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->getbcnrp ||
1061859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	    !netdev->dcbnl_ops->getbcncfg)
1062859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		return ret;
1063859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1064859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX,
1065859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       tb[DCB_ATTR_BCN], dcbnl_bcn_nest);
1066859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1067859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
1068859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err_out;
1069859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1070859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1071859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!dcbnl_skb)
1072859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err_out;
1073859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1074859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1075859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1076859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcb = NLMSG_DATA(nlh);
1077859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
1078859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcb->cmd = DCB_CMD_BCN_GCFG;
1079859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1080859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	bcn_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_BCN);
1081859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!bcn_nest)
1082859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err;
1083859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1084859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (bcn_tb[DCB_BCN_ATTR_ALL])
1085859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		getall = true;
1086859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1087859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
1088859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (!getall && !bcn_tb[i])
1089859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1090859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1091859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0,
1092859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                            &value_byte);
1093859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = nla_put_u8(dcbnl_skb, i, value_byte);
1094859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (ret)
1095859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			goto err_bcn;
1096859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1097859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1098f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
1099859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (!getall && !bcn_tb[i])
1100859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1101859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1102859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->getbcncfg(netdev, i,
1103859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                             &value_integer);
1104859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = nla_put_u32(dcbnl_skb, i, value_integer);
1105859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (ret)
1106859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			goto err_bcn;
1107859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1108859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1109859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nla_nest_end(dcbnl_skb, bcn_nest);
1110859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1111859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
1112859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1113859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
1114859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
11157eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
1116859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1117859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return 0;
1118859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1119859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr_bcn:
1120859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nla_nest_cancel(dcbnl_skb, bcn_nest);
1121859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duycknlmsg_failure:
1122859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr:
1123858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
1124859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr_out:
1125859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret  = -EINVAL;
1126859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return ret;
1127859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck}
1128859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1129859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckstatic int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlattr **tb,
1130859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck                            u32 pid, u32 seq, u16 flags)
1131859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck{
1132859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *data[DCB_BCN_ATTR_MAX + 1];
1133859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int i;
1134859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int ret = -EINVAL;
1135859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u8 value_byte;
1136859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u32 value_int;
1137859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1138f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches	if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg ||
1139f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches	    !netdev->dcbnl_ops->setbcnrp)
1140859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		return ret;
1141859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1142859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX,
1143859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       tb[DCB_ATTR_BCN],
1144859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       dcbnl_pfc_up_nest);
1145859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
1146859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err;
1147859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1148859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
1149859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (data[i] == NULL)
1150859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1151859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		value_byte = nla_get_u8(data[i]);
1152859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->setbcnrp(netdev,
1153859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte);
1154859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1155859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1156f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
1157859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (data[i] == NULL)
1158859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1159859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		value_int = nla_get_u32(data[i]);
1160859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->setbcncfg(netdev,
1161859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                                     i, value_int);
1162859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1163859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1164859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_BCN_SCFG, DCB_ATTR_BCN,
1165859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                  pid, seq, flags);
1166859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr:
1167859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return ret;
1168859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck}
1169859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1170dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravidstatic int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
1171dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid				int app_nested_type, int app_info_type,
1172dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid				int app_entry_type)
1173eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid{
1174eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	struct dcb_peer_app_info info;
1175eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	struct dcb_app *table = NULL;
1176eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1177eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	u16 app_count;
1178eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	int err;
1179eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1180eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1181eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	/**
1182eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	 * retrieve the peer app configuration form the driver. If the driver
1183eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	 * handlers fail exit without doing anything
1184eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	 */
1185eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	err = ops->peer_getappinfo(netdev, &info, &app_count);
1186eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (!err && app_count) {
1187eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		table = kmalloc(sizeof(struct dcb_app) * app_count, GFP_KERNEL);
1188eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		if (!table)
1189eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid			return -ENOMEM;
1190eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1191eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = ops->peer_getapptable(netdev, table);
1192eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1193eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1194eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (!err) {
1195eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		u16 i;
1196eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		struct nlattr *app;
1197eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1198eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		/**
1199eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		 * build the message, from here on the only possible failure
1200eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		 * is due to the skb size
1201eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		 */
1202eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = -EMSGSIZE;
1203eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1204dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		app = nla_nest_start(skb, app_nested_type);
1205eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		if (!app)
1206eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid			goto nla_put_failure;
1207eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
12081eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (app_info_type &&
12091eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, app_info_type, sizeof(info), &info))
12101eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
1211eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
12121eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		for (i = 0; i < app_count; i++) {
12131eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			if (nla_put(skb, app_entry_type, sizeof(struct dcb_app),
12141eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				    &table[i]))
12151eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				goto nla_put_failure;
12161eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		}
1217eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		nla_nest_end(skb, app);
1218eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1219eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	err = 0;
1220eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1221eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravidnla_put_failure:
1222eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	kfree(table);
1223eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	return err;
1224eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid}
12253e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12263e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend/* Handle IEEE 802.1Qaz GET commands. */
1227314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabendstatic int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
12283e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend{
12299ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct nlattr *ieee, *app;
12309ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
12313e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1232c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	int dcbx;
1233314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	int err = -EMSGSIZE;
12343e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12351eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller	if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name))
12361eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		goto nla_put_failure;
12373e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	ieee = nla_nest_start(skb, DCB_ATTR_IEEE);
12383e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (!ieee)
12393e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		goto nla_put_failure;
12403e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12413e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (ops->ieee_getets) {
12423e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		struct ieee_ets ets;
12433e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		err = ops->ieee_getets(netdev, &ets);
12441eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
12451eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets))
12461eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
12473e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	}
12483e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12493e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (ops->ieee_getpfc) {
12503e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		struct ieee_pfc pfc;
12513e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		err = ops->ieee_getpfc(netdev, &pfc);
12521eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
12531eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc))
12541eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
12553e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	}
12563e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12579ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE);
12589ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (!app)
12599ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		goto nla_put_failure;
12609ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
12619ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
12629ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
1263e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		if (itr->ifindex == netdev->ifindex) {
126470bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app),
126570bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter					 &itr->app);
126670bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			if (err) {
126770bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter				spin_unlock(&dcb_lock);
126870bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter				goto nla_put_failure;
126970bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			}
127070bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter		}
12719ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
1272c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend
1273c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	if (netdev->dcbnl_ops->getdcbx)
1274c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		dcbx = netdev->dcbnl_ops->getdcbx(netdev);
1275c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	else
1276c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		dcbx = -EOPNOTSUPP;
1277c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend
12789ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
12799ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	nla_nest_end(skb, app);
12809ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
1281eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	/* get peer info if available */
1282eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (ops->ieee_peer_getets) {
1283eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		struct ieee_ets ets;
1284eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = ops->ieee_peer_getets(netdev, &ets);
12851eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
12861eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets))
12871eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
1288eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1289eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1290eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (ops->ieee_peer_getpfc) {
1291eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		struct ieee_pfc pfc;
1292eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = ops->ieee_peer_getpfc(netdev, &pfc);
12931eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
12941eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc))
12951eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
1296eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1297eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1298eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (ops->peer_getappinfo && ops->peer_getapptable) {
1299dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		err = dcbnl_build_peer_app(netdev, skb,
1300dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid					   DCB_ATTR_IEEE_PEER_APP,
1301dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid					   DCB_ATTR_IEEE_APP_UNSPEC,
1302dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid					   DCB_ATTR_IEEE_APP);
1303eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		if (err)
1304eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid			goto nla_put_failure;
1305eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1306eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
13073e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	nla_nest_end(skb, ieee);
1308c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	if (dcbx >= 0) {
1309c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
1310c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		if (err)
1311c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend			goto nla_put_failure;
1312c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	}
13133e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
1314314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return 0;
1315314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
13163e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabendnla_put_failure:
1317314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return err;
13183e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend}
13193e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
13205b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidstatic int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
13215b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			     int dir)
13225b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
13235b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	u8 pgid, up_map, prio, tc_pct;
13245b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
13255b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	int i = dir ? DCB_ATTR_CEE_TX_PG : DCB_ATTR_CEE_RX_PG;
13265b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct nlattr *pg = nla_nest_start(skb, i);
13275b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13285b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (!pg)
13295b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		goto nla_put_failure;
13305b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13315b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
13325b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct nlattr *tc_nest = nla_nest_start(skb, i);
13335b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13345b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!tc_nest)
13355b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
13365b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13375b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		pgid = DCB_ATTR_VALUE_UNDEFINED;
13385b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		prio = DCB_ATTR_VALUE_UNDEFINED;
13395b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
13405b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		up_map = DCB_ATTR_VALUE_UNDEFINED;
13415b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13425b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!dir)
13435b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgtccfgrx(dev, i - DCB_PG_ATTR_TC_0,
13445b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					  &prio, &pgid, &tc_pct, &up_map);
13455b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		else
13465b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgtccfgtx(dev, i - DCB_PG_ATTR_TC_0,
13475b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					  &prio, &pgid, &tc_pct, &up_map);
13485b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13491eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (nla_put_u8(skb, DCB_TC_ATTR_PARAM_PGID, pgid) ||
13501eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map) ||
13511eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio) ||
13521eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct))
13531eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
13545b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nla_nest_end(skb, tc_nest);
13555b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
13565b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13575b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
13585b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
13595b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13605b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!dir)
13615b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgbwgcfgrx(dev, i - DCB_PG_ATTR_BW_ID_0,
13625b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   &tc_pct);
13635b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		else
13645b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0,
13655b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   &tc_pct);
13661eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (nla_put_u8(skb, i, tc_pct))
13671eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
13685b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
13695b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nla_nest_end(skb, pg);
13705b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return 0;
13715b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13725b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidnla_put_failure:
13735b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return -EMSGSIZE;
13745b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
13755b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13765b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidstatic int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
13775b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
13785b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct nlattr *cee, *app;
13795b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct dcb_app_type *itr;
13805b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
13815b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	int dcbx, i, err = -EMSGSIZE;
13825b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	u8 value;
13835b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13841eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller	if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name))
13851eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		goto nla_put_failure;
13865b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	cee = nla_nest_start(skb, DCB_ATTR_CEE);
13875b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (!cee)
13885b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		goto nla_put_failure;
13895b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13905b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* local pg */
13915b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getpgtccfgtx && ops->getpgbwgcfgtx) {
13925b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_cee_pg_fill(skb, netdev, 1);
13935b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
13945b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
13955b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
13965b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13975b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getpgtccfgrx && ops->getpgbwgcfgrx) {
13985b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_cee_pg_fill(skb, netdev, 0);
13995b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
14005b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
14015b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
14025b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14035b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* local pfc */
14045b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getpfccfg) {
14055b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct nlattr *pfc_nest = nla_nest_start(skb, DCB_ATTR_CEE_PFC);
14065b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14075b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!pfc_nest)
14085b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
14095b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14105b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
14115b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value);
14121eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			if (nla_put_u8(skb, i, value))
14131eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				goto nla_put_failure;
14145b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		}
14155b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nla_nest_end(skb, pfc_nest);
14165b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
14175b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14185b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* local app */
14195b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	spin_lock(&dcb_lock);
14205b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE);
14215b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (!app)
142240f5d72a4fc098c47068e3888cfb055922f6519fDan Carpenter		goto dcb_unlock;
14235b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14245b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	list_for_each_entry(itr, &dcb_app_list, list) {
1425e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		if (itr->ifindex == netdev->ifindex) {
14265b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			struct nlattr *app_nest = nla_nest_start(skb,
14275b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid								 DCB_ATTR_APP);
14285b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (!app_nest)
14295b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
14305b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14315b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			err = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE,
14325b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					 itr->app.selector);
14335b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (err)
14345b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
14355b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14365b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			err = nla_put_u16(skb, DCB_APP_ATTR_ID,
14375b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					  itr->app.protocol);
14385b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (err)
14395b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
14405b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14415b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			err = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY,
14425b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					 itr->app.priority);
14435b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (err)
14445b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
14455b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14465b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			nla_nest_end(skb, app_nest);
14475b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		}
14485b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
14495b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nla_nest_end(skb, app);
14505b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14515b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (netdev->dcbnl_ops->getdcbx)
14525b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		dcbx = netdev->dcbnl_ops->getdcbx(netdev);
14535b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	else
14545b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		dcbx = -EOPNOTSUPP;
14555b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14565b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	spin_unlock(&dcb_lock);
14575b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14585b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* features flags */
14595b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getfeatcfg) {
14605b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct nlattr *feat = nla_nest_start(skb, DCB_ATTR_CEE_FEAT);
14615b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!feat)
14625b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
14635b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14645b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		for (i = DCB_FEATCFG_ATTR_ALL + 1; i <= DCB_FEATCFG_ATTR_MAX;
14655b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		     i++)
14661eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			if (!ops->getfeatcfg(netdev, i, &value) &&
14671eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			    nla_put_u8(skb, i, value))
14681eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				goto nla_put_failure;
14695b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14705b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nla_nest_end(skb, feat);
14715b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
14725b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14735b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* peer info if available */
14745b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->cee_peer_getpg) {
14755b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct cee_pg pg;
14765b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = ops->cee_peer_getpg(netdev, &pg);
14771eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
14781eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg))
14791eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
14805b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
14815b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14825b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->cee_peer_getpfc) {
14835b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct cee_pfc pfc;
14845b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = ops->cee_peer_getpfc(netdev, &pfc);
14851eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
14861eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc))
14871eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
14885b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
14895b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14905b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->peer_getappinfo && ops->peer_getapptable) {
14915b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_build_peer_app(netdev, skb,
14925b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   DCB_ATTR_CEE_PEER_APP_TABLE,
14935b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   DCB_ATTR_CEE_PEER_APP_INFO,
14945b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   DCB_ATTR_CEE_PEER_APP);
14955b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
14965b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
14975b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
14985b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nla_nest_end(skb, cee);
14995b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
15005b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* DCBX state */
15015b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (dcbx >= 0) {
15025b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
15035b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
15045b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
15055b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
15065b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return 0;
15075b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
15085b7f7626743e0912958981343b47ac0ab2206b1cShmulik Raviddcb_unlock:
15095b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	spin_unlock(&dcb_lock);
15105b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidnla_put_failure:
15115b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return err;
15125b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
15135b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
15145b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidstatic int dcbnl_notify(struct net_device *dev, int event, int cmd,
15155b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			u32 seq, u32 pid, int dcbx_ver)
1516314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend{
1517314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct net *net = dev_net(dev);
1518314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct sk_buff *skb;
1519314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct nlmsghdr *nlh;
1520314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct dcbmsg *dcb;
1521314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
1522314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	int err;
1523314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1524314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!ops)
1525314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -EOPNOTSUPP;
1526314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1527314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1528314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!skb)
1529314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -ENOBUFS;
1530314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1531314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	nlh = nlmsg_put(skb, pid, 0, event, sizeof(*dcb), 0);
1532314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (nlh == NULL) {
15334d054f2f1445aceedab3f9642692d55d2caa7ec6Dan Carpenter		nlmsg_free(skb);
1534314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -EMSGSIZE;
1535314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1536314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1537314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcb = NLMSG_DATA(nlh);
1538314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcb->dcb_family = AF_UNSPEC;
1539314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcb->cmd = cmd;
1540314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
15415b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (dcbx_ver == DCB_CAP_DCBX_VER_IEEE)
15425b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_ieee_fill(skb, dev);
15435b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	else
15445b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_cee_fill(skb, dev);
15455b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
1546314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (err < 0) {
1547314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		/* Report error to broadcast listeners */
1548314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nlmsg_cancel(skb, nlh);
1549314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		kfree_skb(skb);
1550314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		rtnl_set_sk_err(net, RTNLGRP_DCB, err);
1551314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	} else {
1552314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		/* End nlmsg and notify broadcast listeners */
1553314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nlmsg_end(skb, nlh);
1554314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		rtnl_notify(skb, net, 0, RTNLGRP_DCB, NULL, GFP_KERNEL);
1555314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1556314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1557314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return err;
1558314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend}
15595b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
15605b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidint dcbnl_ieee_notify(struct net_device *dev, int event, int cmd,
15615b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		      u32 seq, u32 pid)
15625b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
15635b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_IEEE);
15645b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
15655b7f7626743e0912958981343b47ac0ab2206b1cShmulik RavidEXPORT_SYMBOL(dcbnl_ieee_notify);
15665b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
15675b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidint dcbnl_cee_notify(struct net_device *dev, int event, int cmd,
15685b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		     u32 seq, u32 pid)
15695b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
15705b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_CEE);
15715b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
15725b7f7626743e0912958981343b47ac0ab2206b1cShmulik RavidEXPORT_SYMBOL(dcbnl_cee_notify);
1573314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1574314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
1575314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend * be completed the entire msg is aborted and error value is returned.
1576314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend * No attempt is made to reconcile the case where only part of the
1577314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend * cmd can be completed.
1578314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend */
1579314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabendstatic int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
1580314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			  u32 pid, u32 seq, u16 flags)
1581314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend{
1582314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1583314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
1584314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	int err = -EOPNOTSUPP;
1585314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1586314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!ops)
1587314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return err;
1588314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
15894003b65871c101eb5ce8f37a325feac54aa5c681John Fastabend	if (!tb[DCB_ATTR_IEEE])
15904003b65871c101eb5ce8f37a325feac54aa5c681John Fastabend		return -EINVAL;
15914003b65871c101eb5ce8f37a325feac54aa5c681John Fastabend
1592314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1593314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1594314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (err)
1595314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return err;
1596314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1597314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
1598314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
1599314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		err = ops->ieee_setets(netdev, ets);
1600314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		if (err)
1601314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			goto err;
1602314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1603314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1604314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
1605314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
1606314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		err = ops->ieee_setpfc(netdev, pfc);
1607314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		if (err)
1608314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			goto err;
1609314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1610314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1611314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1612314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		struct nlattr *attr;
1613314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		int rem;
1614314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1615314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1616314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			struct dcb_app *app_data;
1617314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1618314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend				continue;
1619314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			app_data = nla_data(attr);
1620314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			if (ops->ieee_setapp)
1621314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend				err = ops->ieee_setapp(netdev, app_data);
1622314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			else
1623b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend				err = dcb_ieee_setapp(netdev, app_data);
1624314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			if (err)
1625314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend				goto err;
1626314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		}
1627314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1628314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1629314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabenderr:
1630314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
1631314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		    pid, seq, flags);
16325b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0);
1633314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return err;
1634314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend}
1635314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1636314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabendstatic int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
1637314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			  u32 pid, u32 seq, u16 flags)
1638314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend{
1639314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct net *net = dev_net(netdev);
1640314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct sk_buff *skb;
1641314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct nlmsghdr *nlh;
1642314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct dcbmsg *dcb;
1643314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1644314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	int err;
1645314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1646314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!ops)
1647314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -EOPNOTSUPP;
1648314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1649314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1650314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!skb)
1651314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -ENOBUFS;
1652314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1653314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1654314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (nlh == NULL) {
16554d054f2f1445aceedab3f9642692d55d2caa7ec6Dan Carpenter		nlmsg_free(skb);
1656314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -EMSGSIZE;
1657314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1658314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1659314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcb = NLMSG_DATA(nlh);
1660314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcb->dcb_family = AF_UNSPEC;
1661314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcb->cmd = DCB_CMD_IEEE_GET;
1662314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1663314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	err = dcbnl_ieee_fill(skb, netdev);
1664314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1665314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (err < 0) {
1666314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nlmsg_cancel(skb, nlh);
1667314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		kfree_skb(skb);
1668314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	} else {
1669314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nlmsg_end(skb, nlh);
1670314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		err = rtnl_unicast(skb, net, pid);
1671314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1672314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1673314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return err;
1674314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend}
1675f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1676f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabendstatic int dcbnl_ieee_del(struct net_device *netdev, struct nlattr **tb,
1677f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			  u32 pid, u32 seq, u16 flags)
1678f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend{
1679f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1680f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
1681f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	int err = -EOPNOTSUPP;
1682f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1683f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (!ops)
1684f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		return -EOPNOTSUPP;
1685f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1686f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (!tb[DCB_ATTR_IEEE])
1687f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		return -EINVAL;
1688f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1689f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1690f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1691f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (err)
1692f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		return err;
1693f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1694f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1695f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		struct nlattr *attr;
1696f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		int rem;
1697f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1698f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1699f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			struct dcb_app *app_data;
1700f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1701f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1702f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				continue;
1703f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			app_data = nla_data(attr);
1704f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			if (ops->ieee_delapp)
1705f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				err = ops->ieee_delapp(netdev, app_data);
1706f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			else
1707f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				err = dcb_ieee_delapp(netdev, app_data);
1708f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			if (err)
1709f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				goto err;
1710f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		}
1711f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	}
1712f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1713f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabenderr:
1714f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_DEL, DCB_ATTR_IEEE,
1715f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		    pid, seq, flags);
17165b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0);
1717f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	return err;
1718f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend}
1719f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1720f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
17216241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid/* DCBX configuration */
17226241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravidstatic int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
17236241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			 u32 pid, u32 seq, u16 flags)
17246241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid{
17257f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret;
17266241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17276241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	if (!netdev->dcbnl_ops->getdcbx)
17287f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
17296241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17306241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	ret = dcbnl_reply(netdev->dcbnl_ops->getdcbx(netdev), RTM_GETDCB,
17316241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			  DCB_CMD_GDCBX, DCB_ATTR_DCBX, pid, seq, flags);
17326241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17336241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	return ret;
17346241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid}
17356241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17366241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravidstatic int dcbnl_setdcbx(struct net_device *netdev, struct nlattr **tb,
17376241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			 u32 pid, u32 seq, u16 flags)
17386241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid{
17397f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret;
17406241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	u8 value;
17416241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17427f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->setdcbx)
17437f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
17447f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
17457f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_DCBX])
17467f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
17476241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17486241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	value = nla_get_u8(tb[DCB_ATTR_DCBX]);
17496241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17506241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	ret = dcbnl_reply(netdev->dcbnl_ops->setdcbx(netdev, value),
17516241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			  RTM_SETDCB, DCB_CMD_SDCBX, DCB_ATTR_DCBX,
17526241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			  pid, seq, flags);
17536241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17546241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	return ret;
17556241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid}
17566241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
1757ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravidstatic int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb,
1758ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			    u32 pid, u32 seq, u16 flags)
1759ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid{
1760ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct sk_buff *dcbnl_skb;
1761ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct nlmsghdr *nlh;
1762ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct dcbmsg *dcb;
1763ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest;
1764ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	u8 value;
17657f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret, i;
1766ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	int getall = 0;
1767ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
17687f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->getfeatcfg)
17697f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
17707f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
17717f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_FEATCFG])
17727f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
1773ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1774ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1775ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			       dcbnl_featcfg_nest);
17767f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (ret)
1777ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto err_out;
1778ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1779ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1780ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	if (!dcbnl_skb) {
17817f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		ret = -ENOBUFS;
1782ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto err_out;
1783ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1784ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1785ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1786ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1787ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	dcb = NLMSG_DATA(nlh);
1788ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	dcb->dcb_family = AF_UNSPEC;
1789ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	dcb->cmd = DCB_CMD_GFEATCFG;
1790ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1791ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_FEATCFG);
1792ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	if (!nest) {
17937f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		ret = -EMSGSIZE;
17947f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		goto nla_put_failure;
1795ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1796ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1797ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	if (data[DCB_FEATCFG_ATTR_ALL])
1798ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		getall = 1;
1799ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1800ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1801ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (!getall && !data[i])
1802ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			continue;
1803ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1804ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value);
18057f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		if (!ret)
1806ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			ret = nla_put_u8(dcbnl_skb, i, value);
1807ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
18087f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		if (ret) {
18097f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid			nla_nest_cancel(dcbnl_skb, nest);
18107f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid			goto nla_put_failure;
18117f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		}
1812ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1813ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	nla_nest_end(dcbnl_skb, nest);
1814ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1815ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	nlmsg_end(dcbnl_skb, nlh);
1816ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
18177f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	return rtnl_unicast(dcbnl_skb, &init_net, pid);
18187f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravidnla_put_failure:
18197f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	nlmsg_cancel(dcbnl_skb, nlh);
1820ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravidnlmsg_failure:
1821ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	kfree_skb(dcbnl_skb);
1822ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Raviderr_out:
1823ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	return ret;
1824ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid}
1825ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1826ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravidstatic int dcbnl_setfeatcfg(struct net_device *netdev, struct nlattr **tb,
1827ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			    u32 pid, u32 seq, u16 flags)
1828ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid{
1829ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1];
18307f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret, i;
1831ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	u8 value;
1832ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
18337f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->setfeatcfg)
18347f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -ENOTSUPP;
18357f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
18367f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_FEATCFG])
18377f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
1838ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1839ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1840ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			       dcbnl_featcfg_nest);
1841ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
18427f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (ret)
1843ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto err;
1844ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1845ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1846ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (data[i] == NULL)
1847ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			continue;
1848ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1849ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		value = nla_get_u8(data[i]);
1850ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1851ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = netdev->dcbnl_ops->setfeatcfg(netdev, i, value);
1852ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1853ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (ret)
18547f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid			goto err;
1855ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1856ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Raviderr:
18577f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	dcbnl_reply(ret, RTM_SETDCB, DCB_CMD_SFEATCFG, DCB_ATTR_FEATCFG,
18587f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		    pid, seq, flags);
18597f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
1860ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	return ret;
1861ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid}
1862ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1863dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid/* Handle CEE DCBX GET commands. */
1864dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravidstatic int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
1865dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid			 u32 pid, u32 seq, u16 flags)
1866dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid{
18675b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct net *net = dev_net(netdev);
1868dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	struct sk_buff *skb;
1869dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	struct nlmsghdr *nlh;
1870dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	struct dcbmsg *dcb;
1871dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
18725b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	int err;
1873dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
1874dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	if (!ops)
1875dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		return -EOPNOTSUPP;
1876dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
1877dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1878dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	if (!skb)
1879dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		return -ENOBUFS;
1880dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
18815b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
18825b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (nlh == NULL) {
18835b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nlmsg_free(skb);
18845b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		return -EMSGSIZE;
18855b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
1886dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
1887dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	dcb = NLMSG_DATA(nlh);
1888dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	dcb->dcb_family = AF_UNSPEC;
1889dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	dcb->cmd = DCB_CMD_CEE_GET;
1890dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
18915b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	err = dcbnl_cee_fill(skb, netdev);
189237cf4d1a9b0903b874a638d0f8649873ddde8a12Shmulik Ravid
18935b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (err < 0) {
18945b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nlmsg_cancel(skb, nlh);
18955b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nlmsg_free(skb);
18965b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	} else {
18975b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nlmsg_end(skb, nlh);
18985b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = rtnl_unicast(skb, net, pid);
189937cf4d1a9b0903b874a638d0f8649873ddde8a12Shmulik Ravid	}
190037cf4d1a9b0903b874a638d0f8649873ddde8a12Shmulik Ravid	return err;
1901dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid}
1902dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
19032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
19042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
19052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct net *net = sock_net(skb->sk);
19062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct net_device *netdev;
19072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg  *dcb = (struct dcbmsg *)NLMSG_DATA(nlh);
19082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *tb[DCB_ATTR_MAX + 1];
19092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u32 pid = skb ? NETLINK_CB(skb).pid : 0;
19102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
19112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
191209ad9bc752519cc167d0a573e1acf69b5c707c67Octavian Purdila	if (!net_eq(net, &init_net))
19132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
19142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
19162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  dcbnl_rtnl_policy);
19172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret < 0)
19182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
19192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_IFNAME])
19212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
19222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME]));
19242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev)
19252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
19262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops)
19282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto errout;
19292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	switch (dcb->cmd) {
19312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_GSTATE:
19322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq,
19332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                     nlh->nlmsg_flags);
19342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PFC_GCFG:
19362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
19372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                      nlh->nlmsg_flags);
19382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_GPERM_HWADDR:
19402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq,
19412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                           nlh->nlmsg_flags);
19422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGTX_GCFG:
19442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
19452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
19462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGRX_GCFG:
19482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
19492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
19502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
1951859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	case DCB_CMD_BCN_GCFG:
1952859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = dcbnl_bcn_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
1953859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                       nlh->nlmsg_flags);
1954859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto out;
19552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_SSTATE:
19562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq,
19572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                     nlh->nlmsg_flags);
19582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PFC_SCFG:
19602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
19612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                      nlh->nlmsg_flags);
19622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_SET_ALL:
19652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq,
19662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                   nlh->nlmsg_flags);
19672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGTX_SCFG:
19692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
19702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
19712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGRX_SCFG:
19732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
19742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
19752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
197646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	case DCB_CMD_GCAP:
197746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq,
197846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		                   nlh->nlmsg_flags);
197946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto out;
198033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	case DCB_CMD_GNUMTCS:
198133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
198233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		                      nlh->nlmsg_flags);
198333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto out;
198433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	case DCB_CMD_SNUMTCS:
198533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
198633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		                      nlh->nlmsg_flags);
198733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto out;
19880eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	case DCB_CMD_PFC_GSTATE:
19890eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		ret = dcbnl_getpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
19900eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		                        nlh->nlmsg_flags);
19910eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		goto out;
19920eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	case DCB_CMD_PFC_SSTATE:
19930eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
19940eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		                        nlh->nlmsg_flags);
19950eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		goto out;
1996859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	case DCB_CMD_BCN_SCFG:
1997859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
1998859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                       nlh->nlmsg_flags);
1999859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto out;
2000579496865cf4ea429146382d62047ffdbaab0deeYi Zou	case DCB_CMD_GAPP:
2001579496865cf4ea429146382d62047ffdbaab0deeYi Zou		ret = dcbnl_getapp(netdev, tb, pid, nlh->nlmsg_seq,
2002579496865cf4ea429146382d62047ffdbaab0deeYi Zou		                   nlh->nlmsg_flags);
2003579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
2004579496865cf4ea429146382d62047ffdbaab0deeYi Zou	case DCB_CMD_SAPP:
2005579496865cf4ea429146382d62047ffdbaab0deeYi Zou		ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq,
2006579496865cf4ea429146382d62047ffdbaab0deeYi Zou		                   nlh->nlmsg_flags);
2007579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
20083e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	case DCB_CMD_IEEE_SET:
20093e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq,
2010f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				     nlh->nlmsg_flags);
20113e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		goto out;
20123e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	case DCB_CMD_IEEE_GET:
20133e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq,
2014f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				     nlh->nlmsg_flags);
2015f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		goto out;
2016f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	case DCB_CMD_IEEE_DEL:
2017f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		ret = dcbnl_ieee_del(netdev, tb, pid, nlh->nlmsg_seq,
2018f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				     nlh->nlmsg_flags);
20193e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		goto out;
20206241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	case DCB_CMD_GDCBX:
20216241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid		ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq,
20226241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid				    nlh->nlmsg_flags);
20236241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid		goto out;
20246241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	case DCB_CMD_SDCBX:
20256241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid		ret = dcbnl_setdcbx(netdev, tb, pid, nlh->nlmsg_seq,
20266241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid				    nlh->nlmsg_flags);
20276241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid		goto out;
2028ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	case DCB_CMD_GFEATCFG:
2029ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = dcbnl_getfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
2030ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid				       nlh->nlmsg_flags);
2031ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto out;
2032ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	case DCB_CMD_SFEATCFG:
2033ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = dcbnl_setfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
2034ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid				       nlh->nlmsg_flags);
2035ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto out;
2036dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	case DCB_CMD_CEE_GET:
2037dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		ret = dcbnl_cee_get(netdev, tb, pid, nlh->nlmsg_seq,
2038dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid				    nlh->nlmsg_flags);
2039dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		goto out;
20402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	default:
20412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto errout;
20422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
20432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerrout:
20442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = -EINVAL;
20452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckout:
20462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dev_put(netdev);
20472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
20482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
20492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
20509ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend/**
20519ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * dcb_getapp - retrieve the DCBX application user priority
20529ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend *
20539ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * On success returns a non-zero 802.1p user priority bitmap
20549ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * otherwise returns 0 as the invalid user priority bitmap to
20559ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * indicate an error.
20569ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend */
20579ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendu8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
20589ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
20599ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
20609ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	u8 prio = 0;
20619ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
20629ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
20639ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
20649ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		if (itr->app.selector == app->selector &&
20659ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		    itr->app.protocol == app->protocol &&
2066e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		    itr->ifindex == dev->ifindex) {
20679ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			prio = itr->app.priority;
20689ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			break;
20699ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		}
20709ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
20719ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
20729ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
20739ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	return prio;
20749ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
20759ab933ab2cc80f04690d6aa385b1110075c5e507John FastabendEXPORT_SYMBOL(dcb_getapp);
20769ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
20779ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend/**
2078b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * dcb_setapp - add CEE dcb application data to app list
20799ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend *
2080b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * Priority 0 is an invalid priority in CEE spec. This routine
2081b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * removes applications from the app list if the priority is
2082b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * set to zero.
20839ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend */
2084ab6baf980b095c70a56c5eb2f58166aef8a0edc8John Fastabendint dcb_setapp(struct net_device *dev, struct dcb_app *new)
20859ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
20869ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
20877ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	struct dcb_app_type event;
20887ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend
2089e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	event.ifindex = dev->ifindex;
20907ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	memcpy(&event.app, new, sizeof(event.app));
20916bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend	if (dev->dcbnl_ops->getdcbx)
20926bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
20939ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
20949ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
20959ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	/* Search for existing match and replace */
20969ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
20979ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		if (itr->app.selector == new->selector &&
20989ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		    itr->app.protocol == new->protocol &&
2099e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		    itr->ifindex == dev->ifindex) {
21009ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			if (new->priority)
21019ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend				itr->app.priority = new->priority;
21029ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			else {
21039ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend				list_del(&itr->list);
21049ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend				kfree(itr);
21059ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			}
21069ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			goto out;
21079ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		}
21089ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
21099ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	/* App type does not exist add new application type */
21109ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (new->priority) {
21119ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		struct dcb_app_type *entry;
21129ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
21139ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		if (!entry) {
21149ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			spin_unlock(&dcb_lock);
21159ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			return -ENOMEM;
21169ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		}
21179ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
21189ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		memcpy(&entry->app, new, sizeof(*new));
2119e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		entry->ifindex = dev->ifindex;
21209ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		list_add(&entry->list, &dcb_app_list);
21219ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
21229ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendout:
21239ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
21247ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	call_dcbevent_notifiers(DCB_APP_EVENT, &event);
21259ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	return 0;
21269ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
21279ab933ab2cc80f04690d6aa385b1110075c5e507John FastabendEXPORT_SYMBOL(dcb_setapp);
21289ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
2129b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend/**
2130a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * dcb_ieee_getapp_mask - retrieve the IEEE DCB application priority
2131a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend *
2132a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * Helper routine which on success returns a non-zero 802.1Qaz user
2133a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * priority bitmap otherwise returns 0 to indicate the dcb_app was
2134a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * not found in APP list.
2135a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend */
2136a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabendu8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
2137a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend{
2138a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	struct dcb_app_type *itr;
2139a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	u8 prio = 0;
2140a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend
2141a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	spin_lock(&dcb_lock);
2142a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
2143a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend		if (itr->app.selector == app->selector &&
2144a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend		    itr->app.protocol == app->protocol &&
2145e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		    itr->ifindex == dev->ifindex) {
2146a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend			prio |= 1 << itr->app.priority;
2147a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend		}
2148a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	}
2149a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	spin_unlock(&dcb_lock);
2150a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend
2151a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	return prio;
2152a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend}
2153a364c8cf80251849bab207be8c9e66253c8ca8f8John FastabendEXPORT_SYMBOL(dcb_ieee_getapp_mask);
2154a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend
2155a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend/**
2156b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * dcb_ieee_setapp - add IEEE dcb application data to app list
2157b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend *
2158b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * This adds Application data to the list. Multiple application
2159b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * entries may exists for the same selector and protocol as long
2160b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * as the priorities are different.
2161b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend */
2162b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabendint dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
2163b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend{
2164b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	struct dcb_app_type *itr, *entry;
2165b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	struct dcb_app_type event;
2166b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	int err = 0;
2167b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
2168e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	event.ifindex = dev->ifindex;
2169b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	memcpy(&event.app, new, sizeof(event.app));
21706bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend	if (dev->dcbnl_ops->getdcbx)
21716bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
2172b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
2173b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	spin_lock(&dcb_lock);
2174b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	/* Search for existing match and abort if found */
2175b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
2176b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		if (itr->app.selector == new->selector &&
2177b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		    itr->app.protocol == new->protocol &&
2178b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		    itr->app.priority == new->priority &&
2179e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		    itr->ifindex == dev->ifindex) {
2180b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend			err = -EEXIST;
2181b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend			goto out;
2182b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		}
2183b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	}
2184b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
2185b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	/* App entry does not exist add new entry */
2186b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
2187b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	if (!entry) {
2188b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		err = -ENOMEM;
2189b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		goto out;
2190b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	}
2191b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
2192b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	memcpy(&entry->app, new, sizeof(*new));
2193e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	entry->ifindex = dev->ifindex;
2194b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	list_add(&entry->list, &dcb_app_list);
2195b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabendout:
2196b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	spin_unlock(&dcb_lock);
2197b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	if (!err)
2198b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
2199b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	return err;
2200b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend}
2201b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John FastabendEXPORT_SYMBOL(dcb_ieee_setapp);
2202b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
2203f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend/**
2204f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend * dcb_ieee_delapp - delete IEEE dcb application data from list
2205f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend *
2206f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend * This removes a matching APP data from the APP list
2207f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend */
2208f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabendint dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
2209f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend{
2210f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	struct dcb_app_type *itr;
2211f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	struct dcb_app_type event;
2212f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	int err = -ENOENT;
2213f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
2214e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	event.ifindex = dev->ifindex;
2215f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	memcpy(&event.app, del, sizeof(event.app));
22166bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend	if (dev->dcbnl_ops->getdcbx)
22176bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
2218f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
2219f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	spin_lock(&dcb_lock);
2220f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	/* Search for existing match and remove it. */
2221f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
2222f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		if (itr->app.selector == del->selector &&
2223f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		    itr->app.protocol == del->protocol &&
2224f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		    itr->app.priority == del->priority &&
2225e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		    itr->ifindex == dev->ifindex) {
2226f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			list_del(&itr->list);
2227f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			kfree(itr);
2228f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			err = 0;
2229f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			goto out;
2230f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		}
2231f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	}
2232f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
2233f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabendout:
2234f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	spin_unlock(&dcb_lock);
2235f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (!err)
2236f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
2237f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	return err;
2238f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend}
2239f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John FastabendEXPORT_SYMBOL(dcb_ieee_delapp);
2240f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
22417c14c3f10e6dcd7f70e49f77b6e1ae605c4861e6Shmulik Ravidstatic void dcb_flushapp(void)
22429ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
22439ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *app;
22442a8fe003741aa90b6b9453e90af4bbb7bc42918cDan Carpenter	struct dcb_app_type *tmp;
22459ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
22469ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
22472a8fe003741aa90b6b9453e90af4bbb7bc42918cDan Carpenter	list_for_each_entry_safe(app, tmp, &dcb_app_list, list) {
22489ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		list_del(&app->list);
22499ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		kfree(app);
22509ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
22519ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
22529ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
22539ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
22542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __init dcbnl_init(void)
22552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
22569ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	INIT_LIST_HEAD(&dcb_app_list);
22579ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
2258c7ac8679bec9397afe8918f788cbcef88c38da54Greg Rose	rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, NULL);
2259c7ac8679bec9397afe8918f788cbcef88c38da54Greg Rose	rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, NULL);
22602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
22612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
22622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
22632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_init(dcbnl_init);
22642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
22652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic void __exit dcbnl_exit(void)
22662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
22672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_unregister(PF_UNSPEC, RTM_GETDCB);
22682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_unregister(PF_UNSPEC, RTM_SETDCB);
22699ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	dcb_flushapp();
22702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
22712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_exit(dcbnl_exit);
2272