dcbnl.c revision 081579840b4b2421e37bc67e3b089b7ca64ef040
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},
18108f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	[DCB_ATTR_IEEE_MAXRATE]   = {.len = sizeof(struct ieee_maxrate)},
1823e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend};
1833e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
1843e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabendstatic const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = {
1853e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	[DCB_ATTR_IEEE_APP]	    = {.len = sizeof(struct dcb_app)},
1863e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend};
1873e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
188ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid/* DCB number of traffic classes nested attributes. */
189ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravidstatic const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = {
190ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_FEATCFG_ATTR_ALL]      = {.type = NLA_FLAG},
191ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_FEATCFG_ATTR_PG]       = {.type = NLA_U8},
192ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_FEATCFG_ATTR_PFC]      = {.type = NLA_U8},
193ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	[DCB_FEATCFG_ATTR_APP]      = {.type = NLA_U8},
194ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid};
195ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1969ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendstatic LIST_HEAD(dcb_app_list);
1979ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendstatic DEFINE_SPINLOCK(dcb_lock);
1989ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
1992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* standard netlink reply call */
2002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
2012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                       u32 seq, u16 flags)
2022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
2042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
2052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
2062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
2072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
2102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
2112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags);
2132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
2152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
2162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = cmd;
2172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_pad = 0;
2182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_put_u8(dcbnl_skb, attr, value);
2202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
2212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
2222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	/* end the message, assign the nlmsg_len. */
2242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
2252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
2262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
2277eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		return -EINVAL;
2282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
2302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
2312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
232858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
2332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
2342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getstate(struct net_device *netdev, struct nlattr **tb,
2372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                          u32 pid, u32 seq, u16 flags)
2382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
2402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	/* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */
2422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops->getstate)
2432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
2442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(netdev->dcbnl_ops->getstate(netdev), RTM_GETDCB,
2462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  DCB_CMD_GSTATE, DCB_ATTR_STATE, pid, seq, flags);
2472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
2492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb,
2522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                           u32 pid, u32 seq, u16 flags)
2532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
2552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
2562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
2572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest;
2582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
2592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
2602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
2612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int getall = 0;
2622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->getpfccfg)
2642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
2652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
2672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PFC_CFG],
2682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       dcbnl_pfc_up_nest);
2692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
2702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
2712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
2742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
2752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
2772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
2792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
2802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = DCB_CMD_PFC_GCFG;
2812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG);
2832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!nest)
2842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
2852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (data[DCB_PFC_UP_ATTR_ALL])
2872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
2882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
2902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !data[i])
2912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
2922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0,
2942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                             &value);
2952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_put_u8(dcbnl_skb, i, value);
2962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret) {
2982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			nla_nest_cancel(dcbnl_skb, nest);
2992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err;
3002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
3012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
3022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_end(dcbnl_skb, nest);
3032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
3052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
3072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
3087eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
3092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
3112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
3122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
313858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
3142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out:
3152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return -EINVAL;
3162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
3172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb,
3192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                                u32 pid, u32 seq, u16 flags)
3202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
3212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
3222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
3232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
3242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 perm_addr[MAX_ADDR_LEN];
3252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
3262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops->getpermhwaddr)
3282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
3292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
3322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
3332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
3352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
3372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
3382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = DCB_CMD_GPERM_HWADDR;
3392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
3412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr),
3432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	              perm_addr);
3442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
3462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
3482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
3497eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
3502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
3522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
354858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
3552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out:
3562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return -EINVAL;
3572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
3582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
35946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckstatic int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb,
36046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck                        u32 pid, u32 seq, u16 flags)
36146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck{
36246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct sk_buff *dcbnl_skb;
36346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct nlmsghdr *nlh;
36446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct dcbmsg *dcb;
36546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest;
36646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	u8 value;
36746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int ret = -EINVAL;
36846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int i;
36946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int getall = 0;
37046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
37146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap)
37246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		return ret;
37346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
37446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP],
37546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	                       dcbnl_cap_nest);
37646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (ret)
37746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto err_out;
37846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
37946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
38046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!dcbnl_skb)
38146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto err_out;
38246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
38346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
38446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
38546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcb = NLMSG_DATA(nlh);
38646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
38746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcb->cmd = DCB_CMD_GCAP;
38846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
38946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP);
39046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!nest)
39146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto err;
39246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
39346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (data[DCB_CAP_ATTR_ALL])
39446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		getall = 1;
39546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
39646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) {
39746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		if (!getall && !data[i])
39846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			continue;
39946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
40046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) {
40146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			ret = nla_put_u8(dcbnl_skb, i, value);
40246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
40346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			if (ret) {
40446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck				nla_nest_cancel(dcbnl_skb, nest);
40546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck				goto err;
40646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			}
40746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		}
40846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	}
40946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nla_nest_end(dcbnl_skb, nest);
41046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
41146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
41246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
41346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
41446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (ret)
4157eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
41646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
41746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	return 0;
41846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duycknlmsg_failure:
41946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckerr:
420858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
42146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckerr_out:
42246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	return -EINVAL;
42346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck}
42446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
42533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckstatic int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb,
42633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck                           u32 pid, u32 seq, u16 flags)
42733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{
42833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct sk_buff *dcbnl_skb;
42933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlmsghdr *nlh;
43033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct dcbmsg *dcb;
43133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest;
43233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	u8 value;
43333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int ret = -EINVAL;
43433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int i;
43533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int getall = 0;
43633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
43733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs)
43833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		return ret;
43933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
44033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
44133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                       dcbnl_numtcs_nest);
44233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (ret) {
44333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
44433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err_out;
44533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
44633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
44733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
44833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (!dcbnl_skb) {
44933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
45033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err_out;
45133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
45233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
45333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
45433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
45533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcb = NLMSG_DATA(nlh);
45633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
45733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcb->cmd = DCB_CMD_GNUMTCS;
45833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
45933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS);
46033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (!nest) {
46133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
46233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err;
46333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
46433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
46533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (data[DCB_NUMTCS_ATTR_ALL])
46633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		getall = 1;
46733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
46833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
46933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (!getall && !data[i])
47033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			continue;
47133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
47233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value);
47333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (!ret) {
47433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			ret = nla_put_u8(dcbnl_skb, i, value);
47533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
47633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			if (ret) {
47733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck				nla_nest_cancel(dcbnl_skb, nest);
47833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck				ret = -EINVAL;
47933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck				goto err;
48033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			}
48133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		} else {
48233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			goto err;
48333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		}
48433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
48533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nla_nest_end(dcbnl_skb, nest);
48633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
48733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
48833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
48933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
49033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (ret) {
49133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
4927eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
49333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
49433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
49533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return 0;
49633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duycknlmsg_failure:
49733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr:
498858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
49933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr_out:
50033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return ret;
50133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck}
50233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
50333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckstatic int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb,
50433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck                           u32 pid, u32 seq, u16 flags)
50533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{
50633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1];
50733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int ret = -EINVAL;
50833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	u8 value;
50933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int i;
51033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
5118b124a8e14c04378466ddfe63e41fc5035f957ebDon Skidmore	if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setnumtcs)
51233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		return ret;
51333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
51433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
51533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                       dcbnl_numtcs_nest);
51633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
51733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (ret) {
51833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
51933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err;
52033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
52133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
52233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
52333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (data[i] == NULL)
52433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			continue;
52533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
52633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		value = nla_get_u8(data[i]);
52733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
52833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value);
52933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
53033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (ret)
53133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			goto operr;
53233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
53333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
53433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckoperr:
53533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS,
53633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                  DCB_ATTR_NUMTCS, pid, seq, flags);
53733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
53833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr:
53933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return ret;
54033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck}
54133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
5420eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyckstatic int dcbnl_getpfcstate(struct net_device *netdev, struct nlattr **tb,
5430eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
5440eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{
5450eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	int ret = -EINVAL;
5460eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5470eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	if (!netdev->dcbnl_ops->getpfcstate)
5480eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		return ret;
5490eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5500eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	ret = dcbnl_reply(netdev->dcbnl_ops->getpfcstate(netdev), RTM_GETDCB,
5510eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	                  DCB_CMD_PFC_GSTATE, DCB_ATTR_PFC_STATE,
5520eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	                  pid, seq, flags);
5530eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5540eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	return ret;
5550eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck}
5560eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5570eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyckstatic int dcbnl_setpfcstate(struct net_device *netdev, struct nlattr **tb,
5580eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
5590eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{
5600eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	int ret = -EINVAL;
5610eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	u8 value;
5620eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5630eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	if (!tb[DCB_ATTR_PFC_STATE] || !netdev->dcbnl_ops->setpfcstate)
5640eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		return ret;
5650eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5660eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]);
5670eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5680eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	netdev->dcbnl_ops->setpfcstate(netdev, value);
5690eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5700eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SSTATE, DCB_ATTR_PFC_STATE,
5710eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	                  pid, seq, flags);
5720eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5730eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	return ret;
5740eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck}
5750eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
576579496865cf4ea429146382d62047ffdbaab0deeYi Zoustatic int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb,
577579496865cf4ea429146382d62047ffdbaab0deeYi Zou                        u32 pid, u32 seq, u16 flags)
578579496865cf4ea429146382d62047ffdbaab0deeYi Zou{
579579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct sk_buff *dcbnl_skb;
580579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlmsghdr *nlh;
581579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct dcbmsg *dcb;
582579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_nest;
583579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
584579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u16 id;
585579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u8 up, idtype;
586579496865cf4ea429146382d62047ffdbaab0deeYi Zou	int ret = -EINVAL;
587579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5883dce38a02d6370dca690cd923619d4b00024b723John Fastabend	if (!tb[DCB_ATTR_APP])
589579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
590579496865cf4ea429146382d62047ffdbaab0deeYi Zou
591579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
592579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                       dcbnl_app_nest);
593579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
594579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
595579496865cf4ea429146382d62047ffdbaab0deeYi Zou
596579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = -EINVAL;
597579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* all must be non-null */
598579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
599579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_ID]))
600579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
601579496865cf4ea429146382d62047ffdbaab0deeYi Zou
602579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* either by eth type or by socket number */
603579496865cf4ea429146382d62047ffdbaab0deeYi Zou	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
604579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
605579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (idtype != DCB_APP_IDTYPE_PORTNUM))
606579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
607579496865cf4ea429146382d62047ffdbaab0deeYi Zou
608579496865cf4ea429146382d62047ffdbaab0deeYi Zou	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
6093dce38a02d6370dca690cd923619d4b00024b723John Fastabend
6103dce38a02d6370dca690cd923619d4b00024b723John Fastabend	if (netdev->dcbnl_ops->getapp) {
6113dce38a02d6370dca690cd923619d4b00024b723John Fastabend		up = netdev->dcbnl_ops->getapp(netdev, idtype, id);
6123dce38a02d6370dca690cd923619d4b00024b723John Fastabend	} else {
6133dce38a02d6370dca690cd923619d4b00024b723John Fastabend		struct dcb_app app = {
6143dce38a02d6370dca690cd923619d4b00024b723John Fastabend					.selector = idtype,
6153dce38a02d6370dca690cd923619d4b00024b723John Fastabend					.protocol = id,
6163dce38a02d6370dca690cd923619d4b00024b723John Fastabend				     };
6173dce38a02d6370dca690cd923619d4b00024b723John Fastabend		up = dcb_getapp(netdev, &app);
6183dce38a02d6370dca690cd923619d4b00024b723John Fastabend	}
619579496865cf4ea429146382d62047ffdbaab0deeYi Zou
620579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* send this back */
621579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
622579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (!dcbnl_skb)
623579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
624579496865cf4ea429146382d62047ffdbaab0deeYi Zou
625579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
626579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcb = NLMSG_DATA(nlh);
627579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcb->dcb_family = AF_UNSPEC;
628579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcb->cmd = DCB_CMD_GAPP;
629579496865cf4ea429146382d62047ffdbaab0deeYi Zou
630579496865cf4ea429146382d62047ffdbaab0deeYi Zou	app_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_APP);
631d3337de52af7fb0ebe605b02b740be4ee7dee9ebJesper Juhl	if (!app_nest)
632d3337de52af7fb0ebe605b02b740be4ee7dee9ebJesper Juhl		goto out_cancel;
633d3337de52af7fb0ebe605b02b740be4ee7dee9ebJesper Juhl
634579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype);
635579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
636579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
637579496865cf4ea429146382d62047ffdbaab0deeYi Zou
638579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_put_u16(dcbnl_skb, DCB_APP_ATTR_ID, id);
639579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
640579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
641579496865cf4ea429146382d62047ffdbaab0deeYi Zou
642579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_PRIORITY, up);
643579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
644579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
645579496865cf4ea429146382d62047ffdbaab0deeYi Zou
646579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nla_nest_end(dcbnl_skb, app_nest);
647579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nlmsg_end(dcbnl_skb, nlh);
648579496865cf4ea429146382d62047ffdbaab0deeYi Zou
649579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
650579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
651579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto nlmsg_failure;
652579496865cf4ea429146382d62047ffdbaab0deeYi Zou
653579496865cf4ea429146382d62047ffdbaab0deeYi Zou	goto out;
654579496865cf4ea429146382d62047ffdbaab0deeYi Zou
655579496865cf4ea429146382d62047ffdbaab0deeYi Zouout_cancel:
656579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nla_nest_cancel(dcbnl_skb, app_nest);
657579496865cf4ea429146382d62047ffdbaab0deeYi Zounlmsg_failure:
658579496865cf4ea429146382d62047ffdbaab0deeYi Zou	kfree_skb(dcbnl_skb);
659579496865cf4ea429146382d62047ffdbaab0deeYi Zouout:
660579496865cf4ea429146382d62047ffdbaab0deeYi Zou	return ret;
661579496865cf4ea429146382d62047ffdbaab0deeYi Zou}
662579496865cf4ea429146382d62047ffdbaab0deeYi Zou
663579496865cf4ea429146382d62047ffdbaab0deeYi Zoustatic int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb,
664579496865cf4ea429146382d62047ffdbaab0deeYi Zou                        u32 pid, u32 seq, u16 flags)
665579496865cf4ea429146382d62047ffdbaab0deeYi Zou{
6669ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	int err, ret = -EINVAL;
667579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u16 id;
668579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u8 up, idtype;
669579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
670579496865cf4ea429146382d62047ffdbaab0deeYi Zou
6719ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (!tb[DCB_ATTR_APP])
672579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
673579496865cf4ea429146382d62047ffdbaab0deeYi Zou
674579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
675579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                       dcbnl_app_nest);
676579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
677579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
678579496865cf4ea429146382d62047ffdbaab0deeYi Zou
679579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = -EINVAL;
680579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* all must be non-null */
681579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
682579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_ID]) ||
683579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_PRIORITY]))
684579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
685579496865cf4ea429146382d62047ffdbaab0deeYi Zou
686579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* either by eth type or by socket number */
687579496865cf4ea429146382d62047ffdbaab0deeYi Zou	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
688579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
689579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (idtype != DCB_APP_IDTYPE_PORTNUM))
690579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
691579496865cf4ea429146382d62047ffdbaab0deeYi Zou
692579496865cf4ea429146382d62047ffdbaab0deeYi Zou	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
693579496865cf4ea429146382d62047ffdbaab0deeYi Zou	up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]);
694579496865cf4ea429146382d62047ffdbaab0deeYi Zou
6959ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (netdev->dcbnl_ops->setapp) {
6969ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		err = netdev->dcbnl_ops->setapp(netdev, idtype, id, up);
6979ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	} else {
6989ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		struct dcb_app app;
6999ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.selector = idtype;
7009ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.protocol = id;
7019ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.priority = up;
7029ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		err = dcb_setapp(netdev, &app);
7039ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
7049ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
7059ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	ret = dcbnl_reply(err, RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP,
7069ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			  pid, seq, flags);
707081579840b4b2421e37bc67e3b089b7ca64ef040John Fastabend	dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SAPP, seq, 0);
708579496865cf4ea429146382d62047ffdbaab0deeYi Zouout:
709579496865cf4ea429146382d62047ffdbaab0deeYi Zou	return ret;
710579496865cf4ea429146382d62047ffdbaab0deeYi Zou}
711579496865cf4ea429146382d62047ffdbaab0deeYi Zou
7122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb,
7132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags, int dir)
7142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
7152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
7162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
7172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
7182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_nest, *param_nest, *data;
7192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
7202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
7212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 prio, pgid, tc_pct, up_map;
7222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret  = -EINVAL;
7232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int getall = 0;
7242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
7252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PG_CFG] ||
7272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgtccfgtx ||
7282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgtccfgrx ||
7292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgbwgcfgtx ||
7302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgbwgcfgrx)
7312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
7322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
7342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
7352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
7372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
7382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
7412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
7422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
7442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
7462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
7472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = (dir) ? DCB_CMD_PGRX_GCFG : DCB_CMD_PGTX_GCFG;
7482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	pg_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PG_CFG);
7502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!pg_nest)
7512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
7522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (pg_tb[DCB_PG_ATTR_TC_ALL])
7542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
7552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
7572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !pg_tb[i])
7582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
7592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (pg_tb[DCB_PG_ATTR_TC_ALL])
7612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data = pg_tb[DCB_PG_ATTR_TC_ALL];
7622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		else
7632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data = pg_tb[i];
7642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
7652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				       data, dcbnl_tc_param_nest);
7662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
7672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
7682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		param_nest = nla_nest_start(dcbnl_skb, i);
7702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!param_nest)
7712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
7722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		pgid = DCB_ATTR_VALUE_UNDEFINED;
7742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		prio = DCB_ATTR_VALUE_UNDEFINED;
7752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
7762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		up_map = DCB_ATTR_VALUE_UNDEFINED;
7772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
7792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
7802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgtccfgrx(netdev,
7812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						i - DCB_PG_ATTR_TC_0, &prio,
7822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						&pgid, &tc_pct, &up_map);
7832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
7842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
7852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgtccfgtx(netdev,
7862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						i - DCB_PG_ATTR_TC_0, &prio,
7872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						&pgid, &tc_pct, &up_map);
7882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
7892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_PGID] ||
7912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb,
7932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_PGID, pgid);
7942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
7952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
7962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
7972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] ||
7982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb,
8002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
8012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
8022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
8032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] ||
8052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
8062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb,
8072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
8082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
8092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
8102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] ||
8122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
8132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_BW_PCT,
8142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 tc_pct);
8152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
8162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
8172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		nla_nest_end(dcbnl_skb, param_nest);
8192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
8202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (pg_tb[DCB_PG_ATTR_BW_ID_ALL])
8222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
8232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	else
8242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 0;
8252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
8272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !pg_tb[i])
8282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
8292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
8312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
8332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
8342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgbwgcfgrx(netdev,
8352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
8362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
8372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
8382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgbwgcfgtx(netdev,
8392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
8402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_put_u8(dcbnl_skb, i, tc_pct);
8422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
8442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
8452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
8462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_end(dcbnl_skb, pg_nest);
8482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
8502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
8522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
8537eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
8542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
8562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_param:
8582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_cancel(dcbnl_skb, param_nest);
8592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_pg:
8602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_cancel(dcbnl_skb, pg_nest);
8612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
8622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
863858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
8642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out:
8652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret  = -EINVAL;
8662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
8672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlattr **tb,
8702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
8712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 0);
8732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlattr **tb,
8762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
8772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 1);
8792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb,
8822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                          u32 pid, u32 seq, u16 flags)
8832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
8852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
8862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate)
8882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
8892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	value = nla_get_u8(tb[DCB_ATTR_STATE]);
8912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8921486a61ebcd2711532f8163d30babc40e11e7b40Don Skidmore	ret = dcbnl_reply(netdev->dcbnl_ops->setstate(netdev, value),
8931486a61ebcd2711532f8163d30babc40e11e7b40Don Skidmore	                  RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE,
8942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  pid, seq, flags);
8952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
8972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb,
9002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                           u32 pid, u32 seq, u16 flags)
9012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
9022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1];
9032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
9042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
9052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
9062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->setpfccfg)
9082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
9092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
9112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PFC_CFG],
9122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       dcbnl_pfc_up_nest);
9132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
9142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
9152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
9172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (data[i] == NULL)
9182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
9192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		value = nla_get_u8(data[i]);
9202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		netdev->dcbnl_ops->setpfccfg(netdev,
9212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data[i]->nla_type - DCB_PFC_UP_ATTR_0, value);
9222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
9232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SCFG, DCB_ATTR_PFC_CFG,
9252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  pid, seq, flags);
9262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
9272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
9282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
9292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setall(struct net_device *netdev, struct nlattr **tb,
9312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                        u32 pid, u32 seq, u16 flags)
9322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
9332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
9342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall)
9362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
9372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(netdev->dcbnl_ops->setall(netdev), RTM_SETDCB,
9392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  DCB_CMD_SET_ALL, DCB_ATTR_SET_ALL, pid, seq, flags);
940081579840b4b2421e37bc67e3b089b7ca64ef040John Fastabend	dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SET_ALL, seq, 0);
9412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
9432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
9442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb,
9462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags, int dir)
9472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
9482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
9492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
9502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
9512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
9522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 pgid;
9532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 up_map;
9542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 prio;
9552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 tc_pct;
9562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PG_CFG] ||
9582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgtccfgtx ||
9592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgtccfgrx ||
9602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgbwgcfgtx ||
9612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgbwgcfgrx)
9622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
9632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
9652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
9662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
9672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
9682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
9702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!pg_tb[i])
9712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
9722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
9742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                       pg_tb[i], dcbnl_tc_param_nest);
9752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
9762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err;
9772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		pgid = DCB_ATTR_VALUE_UNDEFINED;
9792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		prio = DCB_ATTR_VALUE_UNDEFINED;
9802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
9812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		up_map = DCB_ATTR_VALUE_UNDEFINED;
9822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO])
9842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			prio =
9852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			    nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]);
9862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_PGID])
9882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]);
9892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT])
9912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]);
9922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING])
9942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			up_map =
9952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			     nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]);
9962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		/* dir: Tx = 0, Rx = 1 */
9982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
9992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
10002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgtccfgrx(netdev,
10012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				i - DCB_PG_ATTR_TC_0,
10022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				prio, pgid, tc_pct, up_map);
10032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
10042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
10052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgtccfgtx(netdev,
10062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				i - DCB_PG_ATTR_TC_0,
10072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				prio, pgid, tc_pct, up_map);
10082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
10092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
10102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
10122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!pg_tb[i])
10132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
10142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = nla_get_u8(pg_tb[i]);
10162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		/* dir: Tx = 0, Rx = 1 */
10182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
10192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
10202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgbwgcfgrx(netdev,
10212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
10222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
10232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
10242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgbwgcfgtx(netdev,
10252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
10262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
10272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
10282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB,
10302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG),
10312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  DCB_ATTR_PG_CFG, pid, seq, flags);
10322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
10342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
10352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
10362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlattr **tb,
10382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
10392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
10402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 0);
10412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
10422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
10432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb,
10442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
10452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
10462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1);
10472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
10482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1049859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckstatic int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb,
1050859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck                            u32 pid, u32 seq, u16 flags)
1051859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck{
1052859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct sk_buff *dcbnl_skb;
1053859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlmsghdr *nlh;
1054859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct dcbmsg *dcb;
1055859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *bcn_nest;
1056859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1];
1057859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u8 value_byte;
1058859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u32 value_integer;
1059859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int ret  = -EINVAL;
1060859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	bool getall = false;
1061859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int i;
1062859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1063859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->getbcnrp ||
1064859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	    !netdev->dcbnl_ops->getbcncfg)
1065859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		return ret;
1066859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1067859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX,
1068859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       tb[DCB_ATTR_BCN], dcbnl_bcn_nest);
1069859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1070859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
1071859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err_out;
1072859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1073859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1074859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!dcbnl_skb)
1075859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err_out;
1076859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1077859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1078859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1079859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcb = NLMSG_DATA(nlh);
1080859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
1081859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcb->cmd = DCB_CMD_BCN_GCFG;
1082859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1083859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	bcn_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_BCN);
1084859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!bcn_nest)
1085859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err;
1086859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1087859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (bcn_tb[DCB_BCN_ATTR_ALL])
1088859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		getall = true;
1089859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1090859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
1091859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (!getall && !bcn_tb[i])
1092859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1093859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1094859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0,
1095859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                            &value_byte);
1096859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = nla_put_u8(dcbnl_skb, i, value_byte);
1097859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (ret)
1098859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			goto err_bcn;
1099859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1100859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1101f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
1102859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (!getall && !bcn_tb[i])
1103859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1104859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1105859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->getbcncfg(netdev, i,
1106859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                             &value_integer);
1107859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = nla_put_u32(dcbnl_skb, i, value_integer);
1108859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (ret)
1109859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			goto err_bcn;
1110859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1111859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1112859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nla_nest_end(dcbnl_skb, bcn_nest);
1113859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1114859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
1115859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1116859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
1117859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
11187eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
1119859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1120859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return 0;
1121859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1122859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr_bcn:
1123859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nla_nest_cancel(dcbnl_skb, bcn_nest);
1124859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duycknlmsg_failure:
1125859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr:
1126858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
1127859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr_out:
1128859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret  = -EINVAL;
1129859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return ret;
1130859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck}
1131859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1132859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckstatic int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlattr **tb,
1133859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck                            u32 pid, u32 seq, u16 flags)
1134859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck{
1135859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *data[DCB_BCN_ATTR_MAX + 1];
1136859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int i;
1137859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int ret = -EINVAL;
1138859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u8 value_byte;
1139859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u32 value_int;
1140859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1141f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches	if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg ||
1142f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches	    !netdev->dcbnl_ops->setbcnrp)
1143859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		return ret;
1144859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1145859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX,
1146859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       tb[DCB_ATTR_BCN],
1147859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       dcbnl_pfc_up_nest);
1148859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
1149859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err;
1150859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1151859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
1152859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (data[i] == NULL)
1153859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1154859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		value_byte = nla_get_u8(data[i]);
1155859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->setbcnrp(netdev,
1156859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte);
1157859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1158859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1159f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
1160859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (data[i] == NULL)
1161859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1162859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		value_int = nla_get_u32(data[i]);
1163859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->setbcncfg(netdev,
1164859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                                     i, value_int);
1165859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1166859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1167859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_BCN_SCFG, DCB_ATTR_BCN,
1168859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                  pid, seq, flags);
1169859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr:
1170859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return ret;
1171859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck}
1172859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1173dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravidstatic int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
1174dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid				int app_nested_type, int app_info_type,
1175dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid				int app_entry_type)
1176eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid{
1177eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	struct dcb_peer_app_info info;
1178eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	struct dcb_app *table = NULL;
1179eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1180eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	u16 app_count;
1181eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	int err;
1182eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1183eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1184eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	/**
1185eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	 * retrieve the peer app configuration form the driver. If the driver
1186eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	 * handlers fail exit without doing anything
1187eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	 */
1188eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	err = ops->peer_getappinfo(netdev, &info, &app_count);
1189eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (!err && app_count) {
1190eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		table = kmalloc(sizeof(struct dcb_app) * app_count, GFP_KERNEL);
1191eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		if (!table)
1192eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid			return -ENOMEM;
1193eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1194eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = ops->peer_getapptable(netdev, table);
1195eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1196eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1197eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (!err) {
1198eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		u16 i;
1199eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		struct nlattr *app;
1200eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1201eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		/**
1202eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		 * build the message, from here on the only possible failure
1203eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		 * is due to the skb size
1204eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		 */
1205eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = -EMSGSIZE;
1206eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1207dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		app = nla_nest_start(skb, app_nested_type);
1208eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		if (!app)
1209eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid			goto nla_put_failure;
1210eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
12111eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (app_info_type &&
12121eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, app_info_type, sizeof(info), &info))
12131eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
1214eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
12151eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		for (i = 0; i < app_count; i++) {
12161eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			if (nla_put(skb, app_entry_type, sizeof(struct dcb_app),
12171eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				    &table[i]))
12181eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				goto nla_put_failure;
12191eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		}
1220eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		nla_nest_end(skb, app);
1221eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1222eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	err = 0;
1223eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1224eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravidnla_put_failure:
1225eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	kfree(table);
1226eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	return err;
1227eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid}
12283e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12293e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend/* Handle IEEE 802.1Qaz GET commands. */
1230314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabendstatic int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
12313e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend{
12329ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct nlattr *ieee, *app;
12339ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
12343e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1235c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	int dcbx;
1236314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	int err = -EMSGSIZE;
12373e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12381eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller	if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name))
12391eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		goto nla_put_failure;
12403e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	ieee = nla_nest_start(skb, DCB_ATTR_IEEE);
12413e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (!ieee)
12423e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		goto nla_put_failure;
12433e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12443e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (ops->ieee_getets) {
12453e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		struct ieee_ets ets;
12463e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		err = ops->ieee_getets(netdev, &ets);
12471eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
12481eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets))
12491eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
12503e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	}
12513e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
125208f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	if (ops->ieee_getmaxrate) {
125308f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		struct ieee_maxrate maxrate;
125408f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		err = ops->ieee_getmaxrate(netdev, &maxrate);
125508f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		if (!err) {
125608f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai			err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE,
125708f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai				      sizeof(maxrate), &maxrate);
125808f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai			if (err)
125908f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai				goto nla_put_failure;
126008f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		}
126108f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	}
126208f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai
12633e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (ops->ieee_getpfc) {
12643e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		struct ieee_pfc pfc;
12653e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		err = ops->ieee_getpfc(netdev, &pfc);
12661eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
12671eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc))
12681eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
12693e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	}
12703e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
12719ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE);
12729ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (!app)
12739ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		goto nla_put_failure;
12749ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
12759ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
12769ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
1277e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		if (itr->ifindex == netdev->ifindex) {
127870bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app),
127970bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter					 &itr->app);
128070bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			if (err) {
128170bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter				spin_unlock(&dcb_lock);
128270bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter				goto nla_put_failure;
128370bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			}
128470bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter		}
12859ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
1286c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend
1287c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	if (netdev->dcbnl_ops->getdcbx)
1288c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		dcbx = netdev->dcbnl_ops->getdcbx(netdev);
1289c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	else
1290c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		dcbx = -EOPNOTSUPP;
1291c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend
12929ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
12939ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	nla_nest_end(skb, app);
12949ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
1295eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	/* get peer info if available */
1296eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (ops->ieee_peer_getets) {
1297eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		struct ieee_ets ets;
1298eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = ops->ieee_peer_getets(netdev, &ets);
12991eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
13001eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets))
13011eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
1302eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1303eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1304eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (ops->ieee_peer_getpfc) {
1305eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		struct ieee_pfc pfc;
1306eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = ops->ieee_peer_getpfc(netdev, &pfc);
13071eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
13081eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc))
13091eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
1310eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1311eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1312eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (ops->peer_getappinfo && ops->peer_getapptable) {
1313dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		err = dcbnl_build_peer_app(netdev, skb,
1314dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid					   DCB_ATTR_IEEE_PEER_APP,
1315dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid					   DCB_ATTR_IEEE_APP_UNSPEC,
1316dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid					   DCB_ATTR_IEEE_APP);
1317eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		if (err)
1318eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid			goto nla_put_failure;
1319eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1320eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
13213e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	nla_nest_end(skb, ieee);
1322c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	if (dcbx >= 0) {
1323c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
1324c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		if (err)
1325c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend			goto nla_put_failure;
1326c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	}
13273e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
1328314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return 0;
1329314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
13303e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabendnla_put_failure:
1331314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return err;
13323e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend}
13333e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
13345b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidstatic int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
13355b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			     int dir)
13365b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
13375b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	u8 pgid, up_map, prio, tc_pct;
13385b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
13395b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	int i = dir ? DCB_ATTR_CEE_TX_PG : DCB_ATTR_CEE_RX_PG;
13405b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct nlattr *pg = nla_nest_start(skb, i);
13415b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13425b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (!pg)
13435b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		goto nla_put_failure;
13445b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13455b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
13465b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct nlattr *tc_nest = nla_nest_start(skb, i);
13475b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13485b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!tc_nest)
13495b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
13505b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13515b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		pgid = DCB_ATTR_VALUE_UNDEFINED;
13525b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		prio = DCB_ATTR_VALUE_UNDEFINED;
13535b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
13545b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		up_map = DCB_ATTR_VALUE_UNDEFINED;
13555b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13565b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!dir)
13575b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgtccfgrx(dev, i - DCB_PG_ATTR_TC_0,
13585b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					  &prio, &pgid, &tc_pct, &up_map);
13595b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		else
13605b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgtccfgtx(dev, i - DCB_PG_ATTR_TC_0,
13615b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					  &prio, &pgid, &tc_pct, &up_map);
13625b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13631eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (nla_put_u8(skb, DCB_TC_ATTR_PARAM_PGID, pgid) ||
13641eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map) ||
13651eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio) ||
13661eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct))
13671eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
13685b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nla_nest_end(skb, tc_nest);
13695b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
13705b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13715b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
13725b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
13735b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13745b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!dir)
13755b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgbwgcfgrx(dev, i - DCB_PG_ATTR_BW_ID_0,
13765b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   &tc_pct);
13775b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		else
13785b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0,
13795b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   &tc_pct);
13801eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (nla_put_u8(skb, i, tc_pct))
13811eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
13825b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
13835b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nla_nest_end(skb, pg);
13845b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return 0;
13855b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13865b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidnla_put_failure:
13875b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return -EMSGSIZE;
13885b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
13895b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13905b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidstatic int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
13915b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
13925b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct nlattr *cee, *app;
13935b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct dcb_app_type *itr;
13945b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
13955b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	int dcbx, i, err = -EMSGSIZE;
13965b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	u8 value;
13975b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13981eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller	if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name))
13991eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		goto nla_put_failure;
14005b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	cee = nla_nest_start(skb, DCB_ATTR_CEE);
14015b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (!cee)
14025b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		goto nla_put_failure;
14035b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14045b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* local pg */
14055b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getpgtccfgtx && ops->getpgbwgcfgtx) {
14065b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_cee_pg_fill(skb, netdev, 1);
14075b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
14085b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
14095b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
14105b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14115b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getpgtccfgrx && ops->getpgbwgcfgrx) {
14125b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_cee_pg_fill(skb, netdev, 0);
14135b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
14145b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
14155b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
14165b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14175b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* local pfc */
14185b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getpfccfg) {
14195b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct nlattr *pfc_nest = nla_nest_start(skb, DCB_ATTR_CEE_PFC);
14205b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14215b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!pfc_nest)
14225b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
14235b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14245b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
14255b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value);
14261eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			if (nla_put_u8(skb, i, value))
14271eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				goto nla_put_failure;
14285b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		}
14295b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nla_nest_end(skb, pfc_nest);
14305b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
14315b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14325b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* local app */
14335b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	spin_lock(&dcb_lock);
14345b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE);
14355b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (!app)
143640f5d72a4fc098c47068e3888cfb055922f6519fDan Carpenter		goto dcb_unlock;
14375b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14385b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	list_for_each_entry(itr, &dcb_app_list, list) {
1439e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		if (itr->ifindex == netdev->ifindex) {
14405b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			struct nlattr *app_nest = nla_nest_start(skb,
14415b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid								 DCB_ATTR_APP);
14425b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (!app_nest)
14435b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
14445b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14455b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			err = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE,
14465b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					 itr->app.selector);
14475b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (err)
14485b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
14495b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14505b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			err = nla_put_u16(skb, DCB_APP_ATTR_ID,
14515b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					  itr->app.protocol);
14525b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (err)
14535b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
14545b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14555b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			err = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY,
14565b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					 itr->app.priority);
14575b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (err)
14585b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
14595b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14605b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			nla_nest_end(skb, app_nest);
14615b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		}
14625b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
14635b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nla_nest_end(skb, app);
14645b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14655b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (netdev->dcbnl_ops->getdcbx)
14665b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		dcbx = netdev->dcbnl_ops->getdcbx(netdev);
14675b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	else
14685b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		dcbx = -EOPNOTSUPP;
14695b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14705b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	spin_unlock(&dcb_lock);
14715b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14725b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* features flags */
14735b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getfeatcfg) {
14745b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct nlattr *feat = nla_nest_start(skb, DCB_ATTR_CEE_FEAT);
14755b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!feat)
14765b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
14775b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14785b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		for (i = DCB_FEATCFG_ATTR_ALL + 1; i <= DCB_FEATCFG_ATTR_MAX;
14795b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		     i++)
14801eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			if (!ops->getfeatcfg(netdev, i, &value) &&
14811eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			    nla_put_u8(skb, i, value))
14821eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				goto nla_put_failure;
14835b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14845b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nla_nest_end(skb, feat);
14855b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
14865b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14875b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* peer info if available */
14885b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->cee_peer_getpg) {
14895b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct cee_pg pg;
14905b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = ops->cee_peer_getpg(netdev, &pg);
14911eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
14921eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg))
14931eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
14945b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
14955b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
14965b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->cee_peer_getpfc) {
14975b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct cee_pfc pfc;
14985b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = ops->cee_peer_getpfc(netdev, &pfc);
14991eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
15001eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc))
15011eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
15025b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
15035b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
15045b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->peer_getappinfo && ops->peer_getapptable) {
15055b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_build_peer_app(netdev, skb,
15065b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   DCB_ATTR_CEE_PEER_APP_TABLE,
15075b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   DCB_ATTR_CEE_PEER_APP_INFO,
15085b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   DCB_ATTR_CEE_PEER_APP);
15095b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
15105b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
15115b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
15125b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nla_nest_end(skb, cee);
15135b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
15145b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* DCBX state */
15155b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (dcbx >= 0) {
15165b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
15175b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
15185b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
15195b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
15205b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return 0;
15215b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
15225b7f7626743e0912958981343b47ac0ab2206b1cShmulik Raviddcb_unlock:
15235b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	spin_unlock(&dcb_lock);
15245b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidnla_put_failure:
15255b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return err;
15265b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
15275b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
15285b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidstatic int dcbnl_notify(struct net_device *dev, int event, int cmd,
15295b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			u32 seq, u32 pid, int dcbx_ver)
1530314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend{
1531314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct net *net = dev_net(dev);
1532314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct sk_buff *skb;
1533314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct nlmsghdr *nlh;
1534314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct dcbmsg *dcb;
1535314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
1536314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	int err;
1537314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1538314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!ops)
1539314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -EOPNOTSUPP;
1540314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1541314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1542314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!skb)
1543314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -ENOBUFS;
1544314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1545314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	nlh = nlmsg_put(skb, pid, 0, event, sizeof(*dcb), 0);
1546314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (nlh == NULL) {
15474d054f2f1445aceedab3f9642692d55d2caa7ec6Dan Carpenter		nlmsg_free(skb);
1548314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -EMSGSIZE;
1549314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1550314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1551314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcb = NLMSG_DATA(nlh);
1552314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcb->dcb_family = AF_UNSPEC;
1553314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcb->cmd = cmd;
1554314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
15555b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (dcbx_ver == DCB_CAP_DCBX_VER_IEEE)
15565b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_ieee_fill(skb, dev);
15575b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	else
15585b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_cee_fill(skb, dev);
15595b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
1560314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (err < 0) {
1561314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		/* Report error to broadcast listeners */
1562314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nlmsg_cancel(skb, nlh);
1563314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		kfree_skb(skb);
1564314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		rtnl_set_sk_err(net, RTNLGRP_DCB, err);
1565314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	} else {
1566314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		/* End nlmsg and notify broadcast listeners */
1567314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nlmsg_end(skb, nlh);
1568314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		rtnl_notify(skb, net, 0, RTNLGRP_DCB, NULL, GFP_KERNEL);
1569314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1570314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1571314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return err;
1572314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend}
15735b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
15745b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidint dcbnl_ieee_notify(struct net_device *dev, int event, int cmd,
15755b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		      u32 seq, u32 pid)
15765b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
15775b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_IEEE);
15785b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
15795b7f7626743e0912958981343b47ac0ab2206b1cShmulik RavidEXPORT_SYMBOL(dcbnl_ieee_notify);
15805b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
15815b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidint dcbnl_cee_notify(struct net_device *dev, int event, int cmd,
15825b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		     u32 seq, u32 pid)
15835b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
15845b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_CEE);
15855b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
15865b7f7626743e0912958981343b47ac0ab2206b1cShmulik RavidEXPORT_SYMBOL(dcbnl_cee_notify);
1587314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1588314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
1589314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend * be completed the entire msg is aborted and error value is returned.
1590314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend * No attempt is made to reconcile the case where only part of the
1591314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend * cmd can be completed.
1592314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend */
1593314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabendstatic int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
1594314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			  u32 pid, u32 seq, u16 flags)
1595314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend{
1596314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1597314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
1598314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	int err = -EOPNOTSUPP;
1599314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1600314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!ops)
1601314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return err;
1602314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
16034003b65871c101eb5ce8f37a325feac54aa5c681John Fastabend	if (!tb[DCB_ATTR_IEEE])
16044003b65871c101eb5ce8f37a325feac54aa5c681John Fastabend		return -EINVAL;
16054003b65871c101eb5ce8f37a325feac54aa5c681John Fastabend
1606314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1607314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1608314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (err)
1609314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return err;
1610314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1611314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
1612314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
1613314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		err = ops->ieee_setets(netdev, ets);
1614314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		if (err)
1615314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			goto err;
1616314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1617314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
161808f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	if (ieee[DCB_ATTR_IEEE_MAXRATE] && ops->ieee_setmaxrate) {
161908f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		struct ieee_maxrate *maxrate =
162008f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai			nla_data(ieee[DCB_ATTR_IEEE_MAXRATE]);
162108f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		err = ops->ieee_setmaxrate(netdev, maxrate);
162208f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		if (err)
162308f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai			goto err;
162408f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	}
162508f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai
1626314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
1627314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
1628314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		err = ops->ieee_setpfc(netdev, pfc);
1629314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		if (err)
1630314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			goto err;
1631314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1632314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1633314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1634314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		struct nlattr *attr;
1635314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		int rem;
1636314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1637314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1638314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			struct dcb_app *app_data;
1639314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1640314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend				continue;
1641314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			app_data = nla_data(attr);
1642314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			if (ops->ieee_setapp)
1643314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend				err = ops->ieee_setapp(netdev, app_data);
1644314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			else
1645b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend				err = dcb_ieee_setapp(netdev, app_data);
1646314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			if (err)
1647314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend				goto err;
1648314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		}
1649314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1650314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1651314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabenderr:
1652314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
1653314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		    pid, seq, flags);
16545b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0);
1655314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return err;
1656314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend}
1657314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1658314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabendstatic int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
1659314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			  u32 pid, u32 seq, u16 flags)
1660314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend{
1661314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct net *net = dev_net(netdev);
1662314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct sk_buff *skb;
1663314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct nlmsghdr *nlh;
1664314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct dcbmsg *dcb;
1665314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1666314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	int err;
1667314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1668314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!ops)
1669314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -EOPNOTSUPP;
1670314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1671314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1672314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!skb)
1673314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -ENOBUFS;
1674314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1675314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1676314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (nlh == NULL) {
16774d054f2f1445aceedab3f9642692d55d2caa7ec6Dan Carpenter		nlmsg_free(skb);
1678314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -EMSGSIZE;
1679314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1680314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1681314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcb = NLMSG_DATA(nlh);
1682314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcb->dcb_family = AF_UNSPEC;
1683314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	dcb->cmd = DCB_CMD_IEEE_GET;
1684314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1685314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	err = dcbnl_ieee_fill(skb, netdev);
1686314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1687314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (err < 0) {
1688314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nlmsg_cancel(skb, nlh);
1689314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		kfree_skb(skb);
1690314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	} else {
1691314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nlmsg_end(skb, nlh);
1692314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		err = rtnl_unicast(skb, net, pid);
1693314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1694314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1695314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return err;
1696314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend}
1697f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1698f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabendstatic int dcbnl_ieee_del(struct net_device *netdev, struct nlattr **tb,
1699f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			  u32 pid, u32 seq, u16 flags)
1700f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend{
1701f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1702f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
1703f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	int err = -EOPNOTSUPP;
1704f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1705f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (!ops)
1706f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		return -EOPNOTSUPP;
1707f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1708f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (!tb[DCB_ATTR_IEEE])
1709f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		return -EINVAL;
1710f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1711f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1712f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1713f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (err)
1714f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		return err;
1715f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1716f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1717f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		struct nlattr *attr;
1718f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		int rem;
1719f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1720f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1721f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			struct dcb_app *app_data;
1722f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1723f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1724f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				continue;
1725f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			app_data = nla_data(attr);
1726f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			if (ops->ieee_delapp)
1727f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				err = ops->ieee_delapp(netdev, app_data);
1728f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			else
1729f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				err = dcb_ieee_delapp(netdev, app_data);
1730f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			if (err)
1731f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				goto err;
1732f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		}
1733f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	}
1734f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1735f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabenderr:
1736f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_DEL, DCB_ATTR_IEEE,
1737f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		    pid, seq, flags);
17385b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0);
1739f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	return err;
1740f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend}
1741f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1742f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
17436241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid/* DCBX configuration */
17446241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravidstatic int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
17456241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			 u32 pid, u32 seq, u16 flags)
17466241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid{
17477f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret;
17486241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17496241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	if (!netdev->dcbnl_ops->getdcbx)
17507f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
17516241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17526241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	ret = dcbnl_reply(netdev->dcbnl_ops->getdcbx(netdev), RTM_GETDCB,
17536241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			  DCB_CMD_GDCBX, DCB_ATTR_DCBX, pid, seq, flags);
17546241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17556241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	return ret;
17566241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid}
17576241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17586241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravidstatic int dcbnl_setdcbx(struct net_device *netdev, struct nlattr **tb,
17596241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			 u32 pid, u32 seq, u16 flags)
17606241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid{
17617f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret;
17626241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	u8 value;
17636241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17647f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->setdcbx)
17657f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
17667f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
17677f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_DCBX])
17687f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
17696241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17706241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	value = nla_get_u8(tb[DCB_ATTR_DCBX]);
17716241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17726241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	ret = dcbnl_reply(netdev->dcbnl_ops->setdcbx(netdev, value),
17736241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			  RTM_SETDCB, DCB_CMD_SDCBX, DCB_ATTR_DCBX,
17746241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid			  pid, seq, flags);
17756241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
17766241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	return ret;
17776241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid}
17786241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
1779ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravidstatic int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb,
1780ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			    u32 pid, u32 seq, u16 flags)
1781ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid{
1782ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct sk_buff *dcbnl_skb;
1783ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct nlmsghdr *nlh;
1784ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct dcbmsg *dcb;
1785ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest;
1786ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	u8 value;
17877f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret, i;
1788ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	int getall = 0;
1789ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
17907f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->getfeatcfg)
17917f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
17927f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
17937f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_FEATCFG])
17947f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
1795ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1796ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1797ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			       dcbnl_featcfg_nest);
17987f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (ret)
1799ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto err_out;
1800ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1801ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1802ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	if (!dcbnl_skb) {
18037f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		ret = -ENOBUFS;
1804ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto err_out;
1805ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1806ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1807ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1808ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1809ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	dcb = NLMSG_DATA(nlh);
1810ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	dcb->dcb_family = AF_UNSPEC;
1811ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	dcb->cmd = DCB_CMD_GFEATCFG;
1812ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1813ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_FEATCFG);
1814ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	if (!nest) {
18157f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		ret = -EMSGSIZE;
18167f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		goto nla_put_failure;
1817ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1818ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1819ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	if (data[DCB_FEATCFG_ATTR_ALL])
1820ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		getall = 1;
1821ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1822ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1823ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (!getall && !data[i])
1824ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			continue;
1825ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1826ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value);
18277f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		if (!ret)
1828ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			ret = nla_put_u8(dcbnl_skb, i, value);
1829ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
18307f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		if (ret) {
18317f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid			nla_nest_cancel(dcbnl_skb, nest);
18327f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid			goto nla_put_failure;
18337f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		}
1834ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1835ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	nla_nest_end(dcbnl_skb, nest);
1836ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1837ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	nlmsg_end(dcbnl_skb, nlh);
1838ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
18397f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	return rtnl_unicast(dcbnl_skb, &init_net, pid);
18407f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravidnla_put_failure:
18417f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	nlmsg_cancel(dcbnl_skb, nlh);
1842ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravidnlmsg_failure:
1843ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	kfree_skb(dcbnl_skb);
1844ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Raviderr_out:
1845ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	return ret;
1846ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid}
1847ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1848ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravidstatic int dcbnl_setfeatcfg(struct net_device *netdev, struct nlattr **tb,
1849ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			    u32 pid, u32 seq, u16 flags)
1850ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid{
1851ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1];
18527f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret, i;
1853ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	u8 value;
1854ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
18557f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->setfeatcfg)
18567f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -ENOTSUPP;
18577f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
18587f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_FEATCFG])
18597f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
1860ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1861ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1862ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			       dcbnl_featcfg_nest);
1863ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
18647f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (ret)
1865ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto err;
1866ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1867ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1868ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (data[i] == NULL)
1869ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			continue;
1870ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1871ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		value = nla_get_u8(data[i]);
1872ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1873ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = netdev->dcbnl_ops->setfeatcfg(netdev, i, value);
1874ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1875ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (ret)
18767f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid			goto err;
1877ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1878ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Raviderr:
18797f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	dcbnl_reply(ret, RTM_SETDCB, DCB_CMD_SFEATCFG, DCB_ATTR_FEATCFG,
18807f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		    pid, seq, flags);
18817f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
1882ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	return ret;
1883ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid}
1884ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1885dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid/* Handle CEE DCBX GET commands. */
1886dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravidstatic int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
1887dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid			 u32 pid, u32 seq, u16 flags)
1888dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid{
18895b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct net *net = dev_net(netdev);
1890dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	struct sk_buff *skb;
1891dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	struct nlmsghdr *nlh;
1892dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	struct dcbmsg *dcb;
1893dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
18945b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	int err;
1895dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
1896dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	if (!ops)
1897dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		return -EOPNOTSUPP;
1898dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
1899dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1900dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	if (!skb)
1901dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		return -ENOBUFS;
1902dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
19035b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
19045b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (nlh == NULL) {
19055b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nlmsg_free(skb);
19065b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		return -EMSGSIZE;
19075b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
1908dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
1909dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	dcb = NLMSG_DATA(nlh);
1910dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	dcb->dcb_family = AF_UNSPEC;
1911dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	dcb->cmd = DCB_CMD_CEE_GET;
1912dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
19135b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	err = dcbnl_cee_fill(skb, netdev);
191437cf4d1a9b0903b874a638d0f8649873ddde8a12Shmulik Ravid
19155b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (err < 0) {
19165b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nlmsg_cancel(skb, nlh);
19175b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nlmsg_free(skb);
19185b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	} else {
19195b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nlmsg_end(skb, nlh);
19205b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = rtnl_unicast(skb, net, pid);
192137cf4d1a9b0903b874a638d0f8649873ddde8a12Shmulik Ravid	}
192237cf4d1a9b0903b874a638d0f8649873ddde8a12Shmulik Ravid	return err;
1923dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid}
1924dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
19252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
19262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
19272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct net *net = sock_net(skb->sk);
19282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct net_device *netdev;
19292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg  *dcb = (struct dcbmsg *)NLMSG_DATA(nlh);
19302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *tb[DCB_ATTR_MAX + 1];
19312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u32 pid = skb ? NETLINK_CB(skb).pid : 0;
19322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
19332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
193409ad9bc752519cc167d0a573e1acf69b5c707c67Octavian Purdila	if (!net_eq(net, &init_net))
19352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
19362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
19382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  dcbnl_rtnl_policy);
19392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret < 0)
19402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
19412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_IFNAME])
19432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
19442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME]));
19462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev)
19472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
19482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops)
19502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto errout;
19512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	switch (dcb->cmd) {
19532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_GSTATE:
19542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq,
19552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                     nlh->nlmsg_flags);
19562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PFC_GCFG:
19582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
19592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                      nlh->nlmsg_flags);
19602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_GPERM_HWADDR:
19622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq,
19632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                           nlh->nlmsg_flags);
19642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGTX_GCFG:
19662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
19672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
19682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGRX_GCFG:
19702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
19712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
19722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
1973859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	case DCB_CMD_BCN_GCFG:
1974859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = dcbnl_bcn_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
1975859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                       nlh->nlmsg_flags);
1976859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto out;
19772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_SSTATE:
19782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq,
19792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                     nlh->nlmsg_flags);
19802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PFC_SCFG:
19822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
19832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                      nlh->nlmsg_flags);
19842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_SET_ALL:
19872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq,
19882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                   nlh->nlmsg_flags);
19892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGTX_SCFG:
19912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
19922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
19932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
19942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGRX_SCFG:
19952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
19962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
19972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
199846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	case DCB_CMD_GCAP:
199946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq,
200046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		                   nlh->nlmsg_flags);
200146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto out;
200233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	case DCB_CMD_GNUMTCS:
200333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
200433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		                      nlh->nlmsg_flags);
200533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto out;
200633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	case DCB_CMD_SNUMTCS:
200733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
200833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		                      nlh->nlmsg_flags);
200933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto out;
20100eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	case DCB_CMD_PFC_GSTATE:
20110eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		ret = dcbnl_getpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
20120eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		                        nlh->nlmsg_flags);
20130eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		goto out;
20140eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	case DCB_CMD_PFC_SSTATE:
20150eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
20160eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		                        nlh->nlmsg_flags);
20170eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		goto out;
2018859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	case DCB_CMD_BCN_SCFG:
2019859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
2020859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                       nlh->nlmsg_flags);
2021859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto out;
2022579496865cf4ea429146382d62047ffdbaab0deeYi Zou	case DCB_CMD_GAPP:
2023579496865cf4ea429146382d62047ffdbaab0deeYi Zou		ret = dcbnl_getapp(netdev, tb, pid, nlh->nlmsg_seq,
2024579496865cf4ea429146382d62047ffdbaab0deeYi Zou		                   nlh->nlmsg_flags);
2025579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
2026579496865cf4ea429146382d62047ffdbaab0deeYi Zou	case DCB_CMD_SAPP:
2027579496865cf4ea429146382d62047ffdbaab0deeYi Zou		ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq,
2028579496865cf4ea429146382d62047ffdbaab0deeYi Zou		                   nlh->nlmsg_flags);
2029579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
20303e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	case DCB_CMD_IEEE_SET:
20313e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq,
2032f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				     nlh->nlmsg_flags);
20333e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		goto out;
20343e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	case DCB_CMD_IEEE_GET:
20353e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq,
2036f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				     nlh->nlmsg_flags);
2037f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		goto out;
2038f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	case DCB_CMD_IEEE_DEL:
2039f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		ret = dcbnl_ieee_del(netdev, tb, pid, nlh->nlmsg_seq,
2040f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				     nlh->nlmsg_flags);
20413e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		goto out;
20426241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	case DCB_CMD_GDCBX:
20436241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid		ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq,
20446241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid				    nlh->nlmsg_flags);
20456241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid		goto out;
20466241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	case DCB_CMD_SDCBX:
20476241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid		ret = dcbnl_setdcbx(netdev, tb, pid, nlh->nlmsg_seq,
20486241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid				    nlh->nlmsg_flags);
20496241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid		goto out;
2050ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	case DCB_CMD_GFEATCFG:
2051ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = dcbnl_getfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
2052ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid				       nlh->nlmsg_flags);
2053ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto out;
2054ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	case DCB_CMD_SFEATCFG:
2055ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = dcbnl_setfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
2056ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid				       nlh->nlmsg_flags);
2057ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto out;
2058dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	case DCB_CMD_CEE_GET:
2059dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		ret = dcbnl_cee_get(netdev, tb, pid, nlh->nlmsg_seq,
2060dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid				    nlh->nlmsg_flags);
2061dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		goto out;
20622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	default:
20632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto errout;
20642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
20652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerrout:
20662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = -EINVAL;
20672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckout:
20682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dev_put(netdev);
20692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
20702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
20712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
20729ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend/**
20739ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * dcb_getapp - retrieve the DCBX application user priority
20749ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend *
20759ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * On success returns a non-zero 802.1p user priority bitmap
20769ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * otherwise returns 0 as the invalid user priority bitmap to
20779ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * indicate an error.
20789ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend */
20799ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendu8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
20809ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
20819ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
20829ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	u8 prio = 0;
20839ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
20849ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
20859ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
20869ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		if (itr->app.selector == app->selector &&
20879ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		    itr->app.protocol == app->protocol &&
2088e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		    itr->ifindex == dev->ifindex) {
20899ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			prio = itr->app.priority;
20909ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			break;
20919ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		}
20929ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
20939ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
20949ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
20959ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	return prio;
20969ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
20979ab933ab2cc80f04690d6aa385b1110075c5e507John FastabendEXPORT_SYMBOL(dcb_getapp);
20989ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
20999ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend/**
2100b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * dcb_setapp - add CEE dcb application data to app list
21019ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend *
2102b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * Priority 0 is an invalid priority in CEE spec. This routine
2103b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * removes applications from the app list if the priority is
2104b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * set to zero.
21059ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend */
2106ab6baf980b095c70a56c5eb2f58166aef8a0edc8John Fastabendint dcb_setapp(struct net_device *dev, struct dcb_app *new)
21079ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
21089ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
21097ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	struct dcb_app_type event;
21107ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend
2111e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	event.ifindex = dev->ifindex;
21127ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	memcpy(&event.app, new, sizeof(event.app));
21136bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend	if (dev->dcbnl_ops->getdcbx)
21146bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
21159ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
21169ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
21179ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	/* Search for existing match and replace */
21189ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
21199ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		if (itr->app.selector == new->selector &&
21209ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		    itr->app.protocol == new->protocol &&
2121e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		    itr->ifindex == dev->ifindex) {
21229ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			if (new->priority)
21239ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend				itr->app.priority = new->priority;
21249ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			else {
21259ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend				list_del(&itr->list);
21269ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend				kfree(itr);
21279ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			}
21289ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			goto out;
21299ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		}
21309ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
21319ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	/* App type does not exist add new application type */
21329ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (new->priority) {
21339ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		struct dcb_app_type *entry;
21349ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
21359ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		if (!entry) {
21369ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			spin_unlock(&dcb_lock);
21379ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend			return -ENOMEM;
21389ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		}
21399ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
21409ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		memcpy(&entry->app, new, sizeof(*new));
2141e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		entry->ifindex = dev->ifindex;
21429ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		list_add(&entry->list, &dcb_app_list);
21439ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
21449ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendout:
21459ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
21467ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	call_dcbevent_notifiers(DCB_APP_EVENT, &event);
21479ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	return 0;
21489ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
21499ab933ab2cc80f04690d6aa385b1110075c5e507John FastabendEXPORT_SYMBOL(dcb_setapp);
21509ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
2151b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend/**
2152a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * dcb_ieee_getapp_mask - retrieve the IEEE DCB application priority
2153a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend *
2154a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * Helper routine which on success returns a non-zero 802.1Qaz user
2155a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * priority bitmap otherwise returns 0 to indicate the dcb_app was
2156a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * not found in APP list.
2157a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend */
2158a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabendu8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
2159a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend{
2160a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	struct dcb_app_type *itr;
2161a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	u8 prio = 0;
2162a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend
2163a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	spin_lock(&dcb_lock);
2164a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
2165a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend		if (itr->app.selector == app->selector &&
2166a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend		    itr->app.protocol == app->protocol &&
2167e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		    itr->ifindex == dev->ifindex) {
2168a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend			prio |= 1 << itr->app.priority;
2169a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend		}
2170a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	}
2171a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	spin_unlock(&dcb_lock);
2172a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend
2173a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	return prio;
2174a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend}
2175a364c8cf80251849bab207be8c9e66253c8ca8f8John FastabendEXPORT_SYMBOL(dcb_ieee_getapp_mask);
2176a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend
2177a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend/**
2178b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * dcb_ieee_setapp - add IEEE dcb application data to app list
2179b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend *
2180b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * This adds Application data to the list. Multiple application
2181b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * entries may exists for the same selector and protocol as long
2182b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * as the priorities are different.
2183b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend */
2184b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabendint dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
2185b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend{
2186b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	struct dcb_app_type *itr, *entry;
2187b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	struct dcb_app_type event;
2188b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	int err = 0;
2189b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
2190e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	event.ifindex = dev->ifindex;
2191b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	memcpy(&event.app, new, sizeof(event.app));
21926bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend	if (dev->dcbnl_ops->getdcbx)
21936bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
2194b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
2195b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	spin_lock(&dcb_lock);
2196b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	/* Search for existing match and abort if found */
2197b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
2198b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		if (itr->app.selector == new->selector &&
2199b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		    itr->app.protocol == new->protocol &&
2200b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		    itr->app.priority == new->priority &&
2201e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		    itr->ifindex == dev->ifindex) {
2202b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend			err = -EEXIST;
2203b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend			goto out;
2204b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		}
2205b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	}
2206b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
2207b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	/* App entry does not exist add new entry */
2208b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
2209b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	if (!entry) {
2210b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		err = -ENOMEM;
2211b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		goto out;
2212b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	}
2213b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
2214b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	memcpy(&entry->app, new, sizeof(*new));
2215e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	entry->ifindex = dev->ifindex;
2216b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	list_add(&entry->list, &dcb_app_list);
2217b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabendout:
2218b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	spin_unlock(&dcb_lock);
2219b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	if (!err)
2220b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
2221b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	return err;
2222b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend}
2223b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John FastabendEXPORT_SYMBOL(dcb_ieee_setapp);
2224b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
2225f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend/**
2226f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend * dcb_ieee_delapp - delete IEEE dcb application data from list
2227f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend *
2228f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend * This removes a matching APP data from the APP list
2229f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend */
2230f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabendint dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
2231f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend{
2232f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	struct dcb_app_type *itr;
2233f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	struct dcb_app_type event;
2234f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	int err = -ENOENT;
2235f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
2236e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	event.ifindex = dev->ifindex;
2237f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	memcpy(&event.app, del, sizeof(event.app));
22386bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend	if (dev->dcbnl_ops->getdcbx)
22396bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
2240f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
2241f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	spin_lock(&dcb_lock);
2242f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	/* Search for existing match and remove it. */
2243f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
2244f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		if (itr->app.selector == del->selector &&
2245f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		    itr->app.protocol == del->protocol &&
2246f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		    itr->app.priority == del->priority &&
2247e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		    itr->ifindex == dev->ifindex) {
2248f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			list_del(&itr->list);
2249f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			kfree(itr);
2250f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			err = 0;
2251f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			goto out;
2252f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		}
2253f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	}
2254f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
2255f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabendout:
2256f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	spin_unlock(&dcb_lock);
2257f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (!err)
2258f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
2259f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	return err;
2260f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend}
2261f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John FastabendEXPORT_SYMBOL(dcb_ieee_delapp);
2262f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
22637c14c3f10e6dcd7f70e49f77b6e1ae605c4861e6Shmulik Ravidstatic void dcb_flushapp(void)
22649ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
22659ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *app;
22662a8fe003741aa90b6b9453e90af4bbb7bc42918cDan Carpenter	struct dcb_app_type *tmp;
22679ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
22689ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
22692a8fe003741aa90b6b9453e90af4bbb7bc42918cDan Carpenter	list_for_each_entry_safe(app, tmp, &dcb_app_list, list) {
22709ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		list_del(&app->list);
22719ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		kfree(app);
22729ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
22739ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
22749ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
22759ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
22762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __init dcbnl_init(void)
22772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
22789ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	INIT_LIST_HEAD(&dcb_app_list);
22799ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
2280c7ac8679bec9397afe8918f788cbcef88c38da54Greg Rose	rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, NULL);
2281c7ac8679bec9397afe8918f788cbcef88c38da54Greg Rose	rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, NULL);
22822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
22832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
22842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
22852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_init(dcbnl_init);
22862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
22872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic void __exit dcbnl_exit(void)
22882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
22892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_unregister(PF_UNSPEC, RTM_GETDCB);
22902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_unregister(PF_UNSPEC, RTM_SETDCB);
22919ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	dcb_flushapp();
22922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
22932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_exit(dcbnl_exit);
2294