dcbnl.c revision 39912f9cf9603f0de085fb5ba916a7a88010ccd9
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
19933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Grafstatic struct sk_buff *dcbnl_newmsg(int type, u8 cmd, u32 port, u32 seq,
20033a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf				    u32 flags, struct nlmsghdr **nlhp)
20133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf{
20233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	struct sk_buff *skb;
20333a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	struct dcbmsg *dcb;
20433a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	struct nlmsghdr *nlh;
20533a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
20633a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
20733a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	if (!skb)
20833a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		return NULL;
20933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
21033a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	nlh = nlmsg_put(skb, port, seq, type, sizeof(*dcb), flags);
21133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	if (!nlh) {
21233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		/* header should always fit, allocation must be buggy */
21333a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		BUG();
21433a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	}
21533a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
21633a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	dcb = nlmsg_data(nlh);
21733a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	dcb->dcb_family = AF_UNSPEC;
21833a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	dcb->cmd = cmd;
21933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	dcb->dcb_pad = 0;
22033a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
22133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	if (nlhp)
22233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		*nlhp = nlh;
22333a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
22433a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	return skb;
22533a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf}
22633a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
2277be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getstate(struct net_device *netdev, struct nlmsghdr *nlh,
2287be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
2292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	/* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */
2312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops->getstate)
2323d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
2332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2347be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_STATE,
2357be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  netdev->dcbnl_ops->getstate(netdev));
2362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2387be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getpfccfg(struct net_device *netdev, struct nlmsghdr *nlh,
2397be994138b188387691322921c08e19bddf6d3c5Thomas Graf			   u32 seq, struct nlattr **tb, struct sk_buff *skb)
2402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest;
2422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
2433d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
2442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
2452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int getall = 0;
2462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2473d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_PFC_CFG])
2483d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
2493d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
2503d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->getpfccfg)
2513d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
2522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
2542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PFC_CFG],
2552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       dcbnl_pfc_up_nest);
2562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
2573d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
2582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2597be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nest = nla_nest_start(skb, DCB_ATTR_PFC_CFG);
2602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!nest)
2613d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
2622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (data[DCB_PFC_UP_ATTR_ALL])
2642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
2652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
2672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !data[i])
2682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
2692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0,
2712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                             &value);
2727be994138b188387691322921c08e19bddf6d3c5Thomas Graf		ret = nla_put_u8(skb, i, value);
2732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret) {
2747be994138b188387691322921c08e19bddf6d3c5Thomas Graf			nla_nest_cancel(skb, nest);
2753d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return ret;
2762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
2772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
2787be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, nest);
2792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
2812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2837be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlmsghdr *nlh,
2847be994138b188387691322921c08e19bddf6d3c5Thomas Graf				u32 seq, struct nlattr **tb, struct sk_buff *skb)
2852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 perm_addr[MAX_ADDR_LEN];
2872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops->getpermhwaddr)
2893d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
2902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
2922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2937be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put(skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), perm_addr);
2942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2967be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getcap(struct net_device *netdev, struct nlmsghdr *nlh,
2977be994138b188387691322921c08e19bddf6d3c5Thomas Graf			u32 seq, struct nlattr **tb, struct sk_buff *skb)
29846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck{
29946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest;
30046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	u8 value;
3013d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
30246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int i;
30346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int getall = 0;
30446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
3053d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_CAP])
3063d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
3073d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
3083d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->getcap)
3093d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
31046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
31146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP],
31246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	                       dcbnl_cap_nest);
31346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (ret)
3143d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
31546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
3167be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nest = nla_nest_start(skb, DCB_ATTR_CAP);
31746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!nest)
3183d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
31946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
32046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (data[DCB_CAP_ATTR_ALL])
32146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		getall = 1;
32246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
32346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) {
32446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		if (!getall && !data[i])
32546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			continue;
32646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
32746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) {
3287be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb, i, value);
32946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			if (ret) {
3307be994138b188387691322921c08e19bddf6d3c5Thomas Graf				nla_nest_cancel(skb, nest);
3313d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf				return ret;
33246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			}
33346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		}
33446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	}
3357be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, nest);
33646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
33746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	return 0;
33846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck}
33946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
3407be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getnumtcs(struct net_device *netdev, struct nlmsghdr *nlh,
3417be994138b188387691322921c08e19bddf6d3c5Thomas Graf			   u32 seq, struct nlattr **tb, struct sk_buff *skb)
34233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{
34333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest;
34433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	u8 value;
3453d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
34633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int i;
34733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int getall = 0;
34833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
3493d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_NUMTCS])
3503d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
3513d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
3523d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->getnumtcs)
3533d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
35433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
35533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
35633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                       dcbnl_numtcs_nest);
3573d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (ret)
3583d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
35933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
3607be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nest = nla_nest_start(skb, DCB_ATTR_NUMTCS);
3613d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!nest)
3623d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
36333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
36433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (data[DCB_NUMTCS_ATTR_ALL])
36533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		getall = 1;
36633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
36733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
36833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (!getall && !data[i])
36933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			continue;
37033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
37133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value);
37233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (!ret) {
3737be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb, i, value);
37433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			if (ret) {
3757be994138b188387691322921c08e19bddf6d3c5Thomas Graf				nla_nest_cancel(skb, nest);
3763d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf				return ret;
37733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			}
3783d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		} else
3793d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EINVAL;
38033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
3817be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, nest);
38233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
38333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return 0;
38433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck}
38533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
3867be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setnumtcs(struct net_device *netdev, struct nlmsghdr *nlh,
3877be994138b188387691322921c08e19bddf6d3c5Thomas Graf			   u32 seq, struct nlattr **tb, struct sk_buff *skb)
38833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{
38933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1];
3903d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
39133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	u8 value;
39233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int i;
39333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
3943d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_NUMTCS])
3953d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
3963d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
3973d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setnumtcs)
3983d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
39933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
40033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
40133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                       dcbnl_numtcs_nest);
4027be994138b188387691322921c08e19bddf6d3c5Thomas Graf	if (ret)
4033d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
40433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
40533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
40633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (data[i] == NULL)
40733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			continue;
40833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
40933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		value = nla_get_u8(data[i]);
41033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
41133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value);
41233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (ret)
4137be994138b188387691322921c08e19bddf6d3c5Thomas Graf			break;
41433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
41533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
4167be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_NUMTCS, !!ret);
41733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck}
41833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
4197be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getpfcstate(struct net_device *netdev, struct nlmsghdr *nlh,
4207be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
4210eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{
4220eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	if (!netdev->dcbnl_ops->getpfcstate)
4233d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
4240eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4257be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_PFC_STATE,
4267be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  netdev->dcbnl_ops->getpfcstate(netdev));
4270eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck}
4280eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4297be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setpfcstate(struct net_device *netdev, struct nlmsghdr *nlh,
4307be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
4310eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{
4320eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	u8 value;
4330eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4343d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_PFC_STATE])
4357be994138b188387691322921c08e19bddf6d3c5Thomas Graf		return -EINVAL;
4360eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4373d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setpfcstate)
4383d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
4393d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
4400eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]);
4410eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4420eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	netdev->dcbnl_ops->setpfcstate(netdev, value);
4430eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4447be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_PFC_STATE, 0);
4450eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck}
4460eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
4477be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getapp(struct net_device *netdev, struct nlmsghdr *nlh,
4487be994138b188387691322921c08e19bddf6d3c5Thomas Graf			u32 seq, struct nlattr **tb, struct sk_buff *skb)
449579496865cf4ea429146382d62047ffdbaab0deeYi Zou{
450579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_nest;
451579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
452579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u16 id;
453579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u8 up, idtype;
4543d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
455579496865cf4ea429146382d62047ffdbaab0deeYi Zou
4563dce38a02d6370dca690cd923619d4b00024b723John Fastabend	if (!tb[DCB_ATTR_APP])
4573d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
458579496865cf4ea429146382d62047ffdbaab0deeYi Zou
459579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
460579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                       dcbnl_app_nest);
461579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
4623d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
463579496865cf4ea429146382d62047ffdbaab0deeYi Zou
464579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* all must be non-null */
465579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
466579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_ID]))
4673d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
468579496865cf4ea429146382d62047ffdbaab0deeYi Zou
469579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* either by eth type or by socket number */
470579496865cf4ea429146382d62047ffdbaab0deeYi Zou	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
471579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
472579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (idtype != DCB_APP_IDTYPE_PORTNUM))
4733d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
474579496865cf4ea429146382d62047ffdbaab0deeYi Zou
475579496865cf4ea429146382d62047ffdbaab0deeYi Zou	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
4763dce38a02d6370dca690cd923619d4b00024b723John Fastabend
4773dce38a02d6370dca690cd923619d4b00024b723John Fastabend	if (netdev->dcbnl_ops->getapp) {
4783dce38a02d6370dca690cd923619d4b00024b723John Fastabend		up = netdev->dcbnl_ops->getapp(netdev, idtype, id);
4793dce38a02d6370dca690cd923619d4b00024b723John Fastabend	} else {
4803dce38a02d6370dca690cd923619d4b00024b723John Fastabend		struct dcb_app app = {
4813dce38a02d6370dca690cd923619d4b00024b723John Fastabend					.selector = idtype,
4823dce38a02d6370dca690cd923619d4b00024b723John Fastabend					.protocol = id,
4833dce38a02d6370dca690cd923619d4b00024b723John Fastabend				     };
4843dce38a02d6370dca690cd923619d4b00024b723John Fastabend		up = dcb_getapp(netdev, &app);
4853dce38a02d6370dca690cd923619d4b00024b723John Fastabend	}
486579496865cf4ea429146382d62047ffdbaab0deeYi Zou
4877be994138b188387691322921c08e19bddf6d3c5Thomas Graf	app_nest = nla_nest_start(skb, DCB_ATTR_APP);
488d3337de52af7fb0ebe605b02b740be4ee7dee9ebJesper Juhl	if (!app_nest)
4893d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
490d3337de52af7fb0ebe605b02b740be4ee7dee9ebJesper Juhl
4917be994138b188387691322921c08e19bddf6d3c5Thomas Graf	ret = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE, idtype);
492579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
493579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
494579496865cf4ea429146382d62047ffdbaab0deeYi Zou
4957be994138b188387691322921c08e19bddf6d3c5Thomas Graf	ret = nla_put_u16(skb, DCB_APP_ATTR_ID, id);
496579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
497579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
498579496865cf4ea429146382d62047ffdbaab0deeYi Zou
4997be994138b188387691322921c08e19bddf6d3c5Thomas Graf	ret = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY, up);
500579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
501579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
502579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5037be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, app_nest);
504579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5053d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	return 0;
506579496865cf4ea429146382d62047ffdbaab0deeYi Zou
507579496865cf4ea429146382d62047ffdbaab0deeYi Zouout_cancel:
5087be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_cancel(skb, app_nest);
509579496865cf4ea429146382d62047ffdbaab0deeYi Zou	return ret;
510579496865cf4ea429146382d62047ffdbaab0deeYi Zou}
511579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5127be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setapp(struct net_device *netdev, struct nlmsghdr *nlh,
5137be994138b188387691322921c08e19bddf6d3c5Thomas Graf			u32 seq, struct nlattr **tb, struct sk_buff *skb)
514579496865cf4ea429146382d62047ffdbaab0deeYi Zou{
5153d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
516579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u16 id;
517579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u8 up, idtype;
518579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
519579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5209ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (!tb[DCB_ATTR_APP])
5213d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
522579496865cf4ea429146382d62047ffdbaab0deeYi Zou
523579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
524579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                       dcbnl_app_nest);
525579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
5263d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
527579496865cf4ea429146382d62047ffdbaab0deeYi Zou
528579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* all must be non-null */
529579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
530579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_ID]) ||
531579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_PRIORITY]))
5323d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
533579496865cf4ea429146382d62047ffdbaab0deeYi Zou
534579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* either by eth type or by socket number */
535579496865cf4ea429146382d62047ffdbaab0deeYi Zou	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
536579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
537579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (idtype != DCB_APP_IDTYPE_PORTNUM))
5383d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
539579496865cf4ea429146382d62047ffdbaab0deeYi Zou
540579496865cf4ea429146382d62047ffdbaab0deeYi Zou	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
541579496865cf4ea429146382d62047ffdbaab0deeYi Zou	up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]);
542579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5439ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (netdev->dcbnl_ops->setapp) {
5443d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		ret = netdev->dcbnl_ops->setapp(netdev, idtype, id, up);
5459ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	} else {
5469ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		struct dcb_app app;
5479ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.selector = idtype;
5489ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.protocol = id;
5499ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		app.priority = up;
5503d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		ret = dcb_setapp(netdev, &app);
5519ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
5529ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
5537be994138b188387691322921c08e19bddf6d3c5Thomas Graf	ret = nla_put_u8(skb, DCB_ATTR_APP, ret);
554081579840b4b2421e37bc67e3b089b7ca64ef040John Fastabend	dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SAPP, seq, 0);
5553d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
556579496865cf4ea429146382d62047ffdbaab0deeYi Zou	return ret;
557579496865cf4ea429146382d62047ffdbaab0deeYi Zou}
558579496865cf4ea429146382d62047ffdbaab0deeYi Zou
5597be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
5607be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     struct nlattr **tb, struct sk_buff *skb, int dir)
5612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
5622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_nest, *param_nest, *data;
5632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
5642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
5652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 prio, pgid, tc_pct, up_map;
5663d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
5672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int getall = 0;
5682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
5692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
5703d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_PG_CFG])
5713d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
5723d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
5733d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->getpgtccfgtx ||
5742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgtccfgrx ||
5752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgbwgcfgtx ||
5762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgbwgcfgrx)
5773d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
5782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
5792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
5802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
5812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
5823d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
5832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
5847be994138b188387691322921c08e19bddf6d3c5Thomas Graf	pg_nest = nla_nest_start(skb, DCB_ATTR_PG_CFG);
5852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!pg_nest)
5863d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
5872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
5882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (pg_tb[DCB_PG_ATTR_TC_ALL])
5892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
5902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
5912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
5922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !pg_tb[i])
5932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
5942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
5952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (pg_tb[DCB_PG_ATTR_TC_ALL])
5962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data = pg_tb[DCB_PG_ATTR_TC_ALL];
5972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		else
5982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data = pg_tb[i];
5992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
6002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				       data, dcbnl_tc_param_nest);
6012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
6022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
6032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6047be994138b188387691322921c08e19bddf6d3c5Thomas Graf		param_nest = nla_nest_start(skb, i);
6052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!param_nest)
6062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
6072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		pgid = DCB_ATTR_VALUE_UNDEFINED;
6092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		prio = DCB_ATTR_VALUE_UNDEFINED;
6102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
6112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		up_map = DCB_ATTR_VALUE_UNDEFINED;
6122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
6142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
6152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgtccfgrx(netdev,
6162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						i - DCB_PG_ATTR_TC_0, &prio,
6172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						&pgid, &tc_pct, &up_map);
6182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
6192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
6202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgtccfgtx(netdev,
6212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						i - DCB_PG_ATTR_TC_0, &prio,
6222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						&pgid, &tc_pct, &up_map);
6232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
6242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_PGID] ||
6262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
6277be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb,
6282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_PGID, pgid);
6292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
6302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
6312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
6322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] ||
6332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
6347be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb,
6352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
6362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
6372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
6382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
6392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] ||
6402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
6417be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb,
6422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
6432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
6442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
6452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
6462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] ||
6472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
6487be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT,
6492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 tc_pct);
6502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
6512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
6522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
6537be994138b188387691322921c08e19bddf6d3c5Thomas Graf		nla_nest_end(skb, param_nest);
6542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
6552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (pg_tb[DCB_PG_ATTR_BW_ID_ALL])
6572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
6582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	else
6592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 0;
6602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
6622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !pg_tb[i])
6632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
6642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
6662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
6682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
6692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgbwgcfgrx(netdev,
6702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
6712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
6722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
6732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgbwgcfgtx(netdev,
6742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
6752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
6767be994138b188387691322921c08e19bddf6d3c5Thomas Graf		ret = nla_put_u8(skb, i, tc_pct);
6772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
6782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
6792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
6802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6817be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, pg_nest);
6822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
6842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_param:
6867be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_cancel(skb, param_nest);
6872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_pg:
6887be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_cancel(skb, pg_nest);
6893d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
6903d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	return -EMSGSIZE;
6912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
6922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6937be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
6947be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
6952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
6967be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 0);
6972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
6982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6997be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
7007be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
7012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
7027be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 1);
7032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
7042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7057be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setstate(struct net_device *netdev, struct nlmsghdr *nlh,
7067be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
7072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
7082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
7092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7103d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_STATE])
7117be994138b188387691322921c08e19bddf6d3c5Thomas Graf		return -EINVAL;
7122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7133d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setstate)
7143d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
7153d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
7162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	value = nla_get_u8(tb[DCB_ATTR_STATE]);
7172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7187be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_STATE,
7197be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  netdev->dcbnl_ops->setstate(netdev, value));
7202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
7212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7227be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setpfccfg(struct net_device *netdev, struct nlmsghdr *nlh,
7237be994138b188387691322921c08e19bddf6d3c5Thomas Graf			   u32 seq, struct nlattr **tb, struct sk_buff *skb)
7242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
7252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1];
7262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
7273d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
7282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
7292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7303d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_PFC_CFG])
7313d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
7323d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
7333d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setpfccfg)
7343d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
7352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
7372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PFC_CFG],
7382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       dcbnl_pfc_up_nest);
7392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
7403d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
7412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
7432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (data[i] == NULL)
7442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
7452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		value = nla_get_u8(data[i]);
7462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		netdev->dcbnl_ops->setpfccfg(netdev,
7472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data[i]->nla_type - DCB_PFC_UP_ATTR_0, value);
7482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
7492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7507be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_PFC_CFG, 0);
7512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
7522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7537be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setall(struct net_device *netdev, struct nlmsghdr *nlh,
7547be994138b188387691322921c08e19bddf6d3c5Thomas Graf			u32 seq, struct nlattr **tb, struct sk_buff *skb)
7552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
7563d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
7572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7583d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_SET_ALL])
7593d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
7603d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
7613d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setall)
7623d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
7632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7647be994138b188387691322921c08e19bddf6d3c5Thomas Graf	ret = nla_put_u8(skb, DCB_ATTR_SET_ALL,
7657be994138b188387691322921c08e19bddf6d3c5Thomas Graf			 netdev->dcbnl_ops->setall(netdev));
766081579840b4b2421e37bc67e3b089b7ca64ef040John Fastabend	dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SET_ALL, seq, 0);
7672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
7692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
7702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7717be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
7727be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb,
7737be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     int dir)
7742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
7752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
7762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
7773d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
7782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
7792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 pgid;
7802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 up_map;
7812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 prio;
7822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 tc_pct;
7832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7843d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_PG_CFG])
7853d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
7863d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
7873d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setpgtccfgtx ||
7882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgtccfgrx ||
7892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgbwgcfgtx ||
7902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgbwgcfgrx)
7913d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
7922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
7942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
7952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
7963d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
7972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
7992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!pg_tb[i])
8002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
8012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
8032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                       pg_tb[i], dcbnl_tc_param_nest);
8042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
8053d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return ret;
8062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		pgid = DCB_ATTR_VALUE_UNDEFINED;
8082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		prio = DCB_ATTR_VALUE_UNDEFINED;
8092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
8102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		up_map = DCB_ATTR_VALUE_UNDEFINED;
8112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO])
8132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			prio =
8142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			    nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]);
8152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_PGID])
8172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]);
8182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT])
8202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]);
8212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING])
8232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			up_map =
8242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			     nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]);
8252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		/* dir: Tx = 0, Rx = 1 */
8272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
8282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
8292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgtccfgrx(netdev,
8302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				i - DCB_PG_ATTR_TC_0,
8312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				prio, pgid, tc_pct, up_map);
8322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
8332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
8342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgtccfgtx(netdev,
8352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				i - DCB_PG_ATTR_TC_0,
8362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				prio, pgid, tc_pct, up_map);
8372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
8392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
8412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!pg_tb[i])
8422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
8432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = nla_get_u8(pg_tb[i]);
8452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		/* dir: Tx = 0, Rx = 1 */
8472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
8482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
8492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgbwgcfgrx(netdev,
8502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
8512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
8522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
8532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgbwgcfgtx(netdev,
8542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
8552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
8562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
8572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8583d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	return nla_put_u8(skb,
8593d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			  (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG), 0);
8602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8627be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
8637be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
8642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8657be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 0);
8662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8687be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
8697be994138b188387691322921c08e19bddf6d3c5Thomas Graf			     u32 seq, struct nlattr **tb, struct sk_buff *skb)
8702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8717be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 1);
8722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8747be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
8757be994138b188387691322921c08e19bddf6d3c5Thomas Graf			    u32 seq, struct nlattr **tb, struct sk_buff *skb)
876859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck{
877859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *bcn_nest;
878859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1];
879859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u8 value_byte;
880859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u32 value_integer;
8813d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
882859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	bool getall = false;
883859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int i;
884859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
8853d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_BCN])
8863d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
8873d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
8883d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->getbcnrp ||
889859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	    !netdev->dcbnl_ops->getbcncfg)
8903d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
891859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
892859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX,
893859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       tb[DCB_ATTR_BCN], dcbnl_bcn_nest);
894859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
8953d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
896859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
8977be994138b188387691322921c08e19bddf6d3c5Thomas Graf	bcn_nest = nla_nest_start(skb, DCB_ATTR_BCN);
898859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!bcn_nest)
8993d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
900859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
901859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (bcn_tb[DCB_BCN_ATTR_ALL])
902859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		getall = true;
903859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
904859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
905859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (!getall && !bcn_tb[i])
906859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
907859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
908859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0,
909859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                            &value_byte);
9107be994138b188387691322921c08e19bddf6d3c5Thomas Graf		ret = nla_put_u8(skb, i, value_byte);
911859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (ret)
912859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			goto err_bcn;
913859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
914859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
915f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
916859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (!getall && !bcn_tb[i])
917859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
918859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
919859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->getbcncfg(netdev, i,
920859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                             &value_integer);
9217be994138b188387691322921c08e19bddf6d3c5Thomas Graf		ret = nla_put_u32(skb, i, value_integer);
922859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (ret)
923859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			goto err_bcn;
924859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
925859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
9267be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, bcn_nest);
927859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
928859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return 0;
929859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
930859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr_bcn:
9317be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_cancel(skb, bcn_nest);
932859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return ret;
933859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck}
934859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
9357be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
9367be994138b188387691322921c08e19bddf6d3c5Thomas Graf			    u32 seq, struct nlattr **tb, struct sk_buff *skb)
937859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck{
938859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *data[DCB_BCN_ATTR_MAX + 1];
939859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int i;
9403d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int ret;
941859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u8 value_byte;
942859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u32 value_int;
943859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
9443d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!tb[DCB_ATTR_BCN])
9453d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EINVAL;
9463d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
9473d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops->setbcncfg ||
948f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches	    !netdev->dcbnl_ops->setbcnrp)
9493d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
950859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
951859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX,
952859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       tb[DCB_ATTR_BCN],
953859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       dcbnl_pfc_up_nest);
954859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
9553d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return ret;
956859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
957859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
958859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (data[i] == NULL)
959859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
960859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		value_byte = nla_get_u8(data[i]);
961859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->setbcnrp(netdev,
962859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte);
963859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
964859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
965f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
966859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (data[i] == NULL)
967859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
968859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		value_int = nla_get_u32(data[i]);
969859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->setbcncfg(netdev,
970859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                                     i, value_int);
971859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
972859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
9733d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	return nla_put_u8(skb, DCB_ATTR_BCN, 0);
974859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck}
975859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
976dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravidstatic int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
977dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid				int app_nested_type, int app_info_type,
978dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid				int app_entry_type)
979eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid{
980eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	struct dcb_peer_app_info info;
981eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	struct dcb_app *table = NULL;
982eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
983eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	u16 app_count;
984eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	int err;
985eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
986eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
987eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	/**
988eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	 * retrieve the peer app configuration form the driver. If the driver
989eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	 * handlers fail exit without doing anything
990eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	 */
991eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	err = ops->peer_getappinfo(netdev, &info, &app_count);
992eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (!err && app_count) {
993eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		table = kmalloc(sizeof(struct dcb_app) * app_count, GFP_KERNEL);
994eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		if (!table)
995eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid			return -ENOMEM;
996eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
997eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = ops->peer_getapptable(netdev, table);
998eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
999eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1000eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (!err) {
1001eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		u16 i;
1002eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		struct nlattr *app;
1003eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1004eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		/**
1005eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		 * build the message, from here on the only possible failure
1006eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		 * is due to the skb size
1007eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		 */
1008eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = -EMSGSIZE;
1009eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1010dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		app = nla_nest_start(skb, app_nested_type);
1011eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		if (!app)
1012eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid			goto nla_put_failure;
1013eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
10141eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (app_info_type &&
10151eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, app_info_type, sizeof(info), &info))
10161eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
1017eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
10181eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		for (i = 0; i < app_count; i++) {
10191eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			if (nla_put(skb, app_entry_type, sizeof(struct dcb_app),
10201eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				    &table[i]))
10211eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				goto nla_put_failure;
10221eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		}
1023eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		nla_nest_end(skb, app);
1024eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1025eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	err = 0;
1026eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1027eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravidnla_put_failure:
1028eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	kfree(table);
1029eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	return err;
1030eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid}
10313e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
10323e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend/* Handle IEEE 802.1Qaz GET commands. */
1033314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabendstatic int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
10343e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend{
10359ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct nlattr *ieee, *app;
10369ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
10373e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1038c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	int dcbx;
10393d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int err;
10403e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
10411eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller	if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name))
10423d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
10433d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf
10443e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	ieee = nla_nest_start(skb, DCB_ATTR_IEEE);
10453e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (!ieee)
10463d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
10473e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
10483e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (ops->ieee_getets) {
10493e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		struct ieee_ets ets;
10503e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		err = ops->ieee_getets(netdev, &ets);
10511eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
10521eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets))
10533d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
10543e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	}
10553e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
105608f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	if (ops->ieee_getmaxrate) {
105708f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		struct ieee_maxrate maxrate;
105808f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		err = ops->ieee_getmaxrate(netdev, &maxrate);
105908f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		if (!err) {
106008f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai			err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE,
106108f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai				      sizeof(maxrate), &maxrate);
106208f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai			if (err)
10633d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf				return -EMSGSIZE;
106408f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		}
106508f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	}
106608f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai
10673e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	if (ops->ieee_getpfc) {
10683e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		struct ieee_pfc pfc;
10693e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend		err = ops->ieee_getpfc(netdev, &pfc);
10701eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
10711eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc))
10723d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
10733e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	}
10743e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
10759ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE);
10769ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	if (!app)
10773d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
10789ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
10799ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
10809ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	list_for_each_entry(itr, &dcb_app_list, list) {
1081e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		if (itr->ifindex == netdev->ifindex) {
108270bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app),
108370bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter					 &itr->app);
108470bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			if (err) {
108570bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter				spin_unlock(&dcb_lock);
10863d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf				return -EMSGSIZE;
108770bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter			}
108870bfa2d2e1bfd90ef26758b5e2749f043a940037Dan Carpenter		}
10899ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
1090c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend
1091c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	if (netdev->dcbnl_ops->getdcbx)
1092c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		dcbx = netdev->dcbnl_ops->getdcbx(netdev);
1093c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	else
1094c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		dcbx = -EOPNOTSUPP;
1095c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend
10969ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
10979ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	nla_nest_end(skb, app);
10989ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
1099eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	/* get peer info if available */
1100eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (ops->ieee_peer_getets) {
1101eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		struct ieee_ets ets;
1102eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = ops->ieee_peer_getets(netdev, &ets);
11031eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
11041eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets))
11053d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
1106eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1107eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1108eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (ops->ieee_peer_getpfc) {
1109eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		struct ieee_pfc pfc;
1110eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		err = ops->ieee_peer_getpfc(netdev, &pfc);
11111eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
11121eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc))
11133d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
1114eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1115eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
1116eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	if (ops->peer_getappinfo && ops->peer_getapptable) {
1117dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		err = dcbnl_build_peer_app(netdev, skb,
1118dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid					   DCB_ATTR_IEEE_PEER_APP,
1119dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid					   DCB_ATTR_IEEE_APP_UNSPEC,
1120dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid					   DCB_ATTR_IEEE_APP);
1121eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid		if (err)
11223d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
1123eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid	}
1124eed84713bc47ce2f7d675914f297ad9b6227a587Shmulik Ravid
11253e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend	nla_nest_end(skb, ieee);
1126c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	if (dcbx >= 0) {
1127c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
1128c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend		if (err)
11293d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
1130c7797baf9f3900996ca800ab6298f95957bb4606John Fastabend	}
11313e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
1132314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return 0;
11333e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend}
11343e29027af43728c2a91fe3f735ab2822edaf54a8John Fastabend
11355b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidstatic int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
11365b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			     int dir)
11375b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
11385b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	u8 pgid, up_map, prio, tc_pct;
11395b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
11405b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	int i = dir ? DCB_ATTR_CEE_TX_PG : DCB_ATTR_CEE_RX_PG;
11415b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct nlattr *pg = nla_nest_start(skb, i);
11425b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11435b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (!pg)
11443d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EMSGSIZE;
11455b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11465b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
11475b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct nlattr *tc_nest = nla_nest_start(skb, i);
11485b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11495b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!tc_nest)
11503d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
11515b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11525b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		pgid = DCB_ATTR_VALUE_UNDEFINED;
11535b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		prio = DCB_ATTR_VALUE_UNDEFINED;
11545b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
11555b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		up_map = DCB_ATTR_VALUE_UNDEFINED;
11565b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11575b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!dir)
11585b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgtccfgrx(dev, i - DCB_PG_ATTR_TC_0,
11595b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					  &prio, &pgid, &tc_pct, &up_map);
11605b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		else
11615b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgtccfgtx(dev, i - DCB_PG_ATTR_TC_0,
11625b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					  &prio, &pgid, &tc_pct, &up_map);
11635b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11641eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (nla_put_u8(skb, DCB_TC_ATTR_PARAM_PGID, pgid) ||
11651eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map) ||
11661eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio) ||
11671eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct))
11683d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
11695b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nla_nest_end(skb, tc_nest);
11705b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
11715b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11725b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
11735b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
11745b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11755b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!dir)
11765b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgbwgcfgrx(dev, i - DCB_PG_ATTR_BW_ID_0,
11775b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   &tc_pct);
11785b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		else
11795b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0,
11805b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   &tc_pct);
11811eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (nla_put_u8(skb, i, tc_pct))
11823d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf			return -EMSGSIZE;
11835b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
11845b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nla_nest_end(skb, pg);
11855b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return 0;
11865b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
11875b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11885b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidstatic int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
11895b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
11905b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct nlattr *cee, *app;
11915b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	struct dcb_app_type *itr;
11925b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
11935b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	int dcbx, i, err = -EMSGSIZE;
11945b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	u8 value;
11955b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
11961eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller	if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name))
11971eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		goto nla_put_failure;
11985b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	cee = nla_nest_start(skb, DCB_ATTR_CEE);
11995b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (!cee)
12005b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		goto nla_put_failure;
12015b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12025b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* local pg */
12035b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getpgtccfgtx && ops->getpgbwgcfgtx) {
12045b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_cee_pg_fill(skb, netdev, 1);
12055b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
12065b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
12075b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
12085b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12095b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getpgtccfgrx && ops->getpgbwgcfgrx) {
12105b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_cee_pg_fill(skb, netdev, 0);
12115b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
12125b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
12135b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
12145b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12155b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* local pfc */
12165b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getpfccfg) {
12175b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct nlattr *pfc_nest = nla_nest_start(skb, DCB_ATTR_CEE_PFC);
12185b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12195b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!pfc_nest)
12205b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
12215b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12225b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
12235b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value);
12241eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			if (nla_put_u8(skb, i, value))
12251eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				goto nla_put_failure;
12265b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		}
12275b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nla_nest_end(skb, pfc_nest);
12285b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
12295b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12305b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* local app */
12315b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	spin_lock(&dcb_lock);
12325b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE);
12335b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (!app)
123440f5d72a4fc098c47068e3888cfb055922f6519fDan Carpenter		goto dcb_unlock;
12355b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12365b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	list_for_each_entry(itr, &dcb_app_list, list) {
1237e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad		if (itr->ifindex == netdev->ifindex) {
12385b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			struct nlattr *app_nest = nla_nest_start(skb,
12395b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid								 DCB_ATTR_APP);
12405b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (!app_nest)
12415b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
12425b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12435b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			err = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE,
12445b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					 itr->app.selector);
12455b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (err)
12465b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
12475b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12485b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			err = nla_put_u16(skb, DCB_APP_ATTR_ID,
12495b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					  itr->app.protocol);
12505b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (err)
12515b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
12525b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12535b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			err = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY,
12545b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					 itr->app.priority);
12555b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			if (err)
12565b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid				goto dcb_unlock;
12575b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12585b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			nla_nest_end(skb, app_nest);
12595b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		}
12605b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
12615b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nla_nest_end(skb, app);
12625b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12635b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (netdev->dcbnl_ops->getdcbx)
12645b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		dcbx = netdev->dcbnl_ops->getdcbx(netdev);
12655b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	else
12665b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		dcbx = -EOPNOTSUPP;
12675b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12685b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	spin_unlock(&dcb_lock);
12695b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12705b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* features flags */
12715b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->getfeatcfg) {
12725b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct nlattr *feat = nla_nest_start(skb, DCB_ATTR_CEE_FEAT);
12735b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (!feat)
12745b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
12755b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12765b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		for (i = DCB_FEATCFG_ATTR_ALL + 1; i <= DCB_FEATCFG_ATTR_MAX;
12775b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		     i++)
12781eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			if (!ops->getfeatcfg(netdev, i, &value) &&
12791eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			    nla_put_u8(skb, i, value))
12801eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller				goto nla_put_failure;
12815b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12825b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		nla_nest_end(skb, feat);
12835b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
12845b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12855b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* peer info if available */
12865b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->cee_peer_getpg) {
12875b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct cee_pg pg;
12885b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = ops->cee_peer_getpg(netdev, &pg);
12891eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
12901eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg))
12911eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
12925b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
12935b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
12945b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->cee_peer_getpfc) {
12955b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		struct cee_pfc pfc;
12965b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = ops->cee_peer_getpfc(netdev, &pfc);
12971eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		if (!err &&
12981eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller		    nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc))
12991eb4c977778b5ab8e8fba9022687f0a5941d681aDavid S. Miller			goto nla_put_failure;
13005b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
13015b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13025b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (ops->peer_getappinfo && ops->peer_getapptable) {
13035b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_build_peer_app(netdev, skb,
13045b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   DCB_ATTR_CEE_PEER_APP_TABLE,
13055b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   DCB_ATTR_CEE_PEER_APP_INFO,
13065b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid					   DCB_ATTR_CEE_PEER_APP);
13075b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
13085b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
13095b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
13105b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	nla_nest_end(skb, cee);
13115b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13125b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	/* DCBX state */
13135b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (dcbx >= 0) {
13145b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
13155b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		if (err)
13165b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			goto nla_put_failure;
13175b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	}
13185b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return 0;
13195b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13205b7f7626743e0912958981343b47ac0ab2206b1cShmulik Raviddcb_unlock:
13215b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	spin_unlock(&dcb_lock);
13225b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidnla_put_failure:
13235b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return err;
13245b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
13255b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13265b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidstatic int dcbnl_notify(struct net_device *dev, int event, int cmd,
13275b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid			u32 seq, u32 pid, int dcbx_ver)
1328314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend{
1329314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct net *net = dev_net(dev);
1330314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct sk_buff *skb;
1331314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct nlmsghdr *nlh;
1332314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
1333314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	int err;
1334314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1335314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!ops)
1336314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -EOPNOTSUPP;
1337314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1338ab6d470735682a6e1ba889a66f56eb1640242096Thomas Graf	skb = dcbnl_newmsg(event, cmd, pid, seq, 0, &nlh);
1339314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!skb)
1340314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -ENOBUFS;
1341314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
13425b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	if (dcbx_ver == DCB_CAP_DCBX_VER_IEEE)
13435b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_ieee_fill(skb, dev);
13445b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	else
13455b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		err = dcbnl_cee_fill(skb, dev);
13465b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
1347314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (err < 0) {
1348314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		/* Report error to broadcast listeners */
1349ab6d470735682a6e1ba889a66f56eb1640242096Thomas Graf		nlmsg_free(skb);
1350314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		rtnl_set_sk_err(net, RTNLGRP_DCB, err);
1351314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	} else {
1352314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		/* End nlmsg and notify broadcast listeners */
1353314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nlmsg_end(skb, nlh);
1354314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		rtnl_notify(skb, net, 0, RTNLGRP_DCB, NULL, GFP_KERNEL);
1355314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1356314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1357314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return err;
1358314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend}
13595b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13605b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidint dcbnl_ieee_notify(struct net_device *dev, int event, int cmd,
13615b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		      u32 seq, u32 pid)
13625b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
13635b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_IEEE);
13645b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
13655b7f7626743e0912958981343b47ac0ab2206b1cShmulik RavidEXPORT_SYMBOL(dcbnl_ieee_notify);
13665b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid
13675b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravidint dcbnl_cee_notify(struct net_device *dev, int event, int cmd,
13685b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid		     u32 seq, u32 pid)
13695b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid{
13705b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_CEE);
13715b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid}
13725b7f7626743e0912958981343b47ac0ab2206b1cShmulik RavidEXPORT_SYMBOL(dcbnl_cee_notify);
1373314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1374314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
1375314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend * be completed the entire msg is aborted and error value is returned.
1376314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend * No attempt is made to reconcile the case where only part of the
1377314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend * cmd can be completed.
1378314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend */
13797be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh,
13807be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
1381314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend{
1382314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1383314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
13843d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int err;
1385314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1386314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!ops)
13873d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -EOPNOTSUPP;
1388314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
13894003b65871c101eb5ce8f37a325feac54aa5c681John Fastabend	if (!tb[DCB_ATTR_IEEE])
13904003b65871c101eb5ce8f37a325feac54aa5c681John Fastabend		return -EINVAL;
13914003b65871c101eb5ce8f37a325feac54aa5c681John Fastabend
1392314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1393314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1394314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (err)
1395314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return err;
1396314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1397314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
1398314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
1399314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		err = ops->ieee_setets(netdev, ets);
1400314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		if (err)
1401314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			goto err;
1402314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1403314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
140408f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	if (ieee[DCB_ATTR_IEEE_MAXRATE] && ops->ieee_setmaxrate) {
140508f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		struct ieee_maxrate *maxrate =
140608f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai			nla_data(ieee[DCB_ATTR_IEEE_MAXRATE]);
140708f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		err = ops->ieee_setmaxrate(netdev, maxrate);
140808f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai		if (err)
140908f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai			goto err;
141008f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai	}
141108f10affe45051e18e0d8291c0a53aecef1b8a14Amir Vadai
1412314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
1413314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
1414314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		err = ops->ieee_setpfc(netdev, pfc);
1415314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		if (err)
1416314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			goto err;
1417314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1418314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1419314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1420314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		struct nlattr *attr;
1421314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		int rem;
1422314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1423314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1424314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			struct dcb_app *app_data;
1425314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1426314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend				continue;
1427314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			app_data = nla_data(attr);
1428314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			if (ops->ieee_setapp)
1429314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend				err = ops->ieee_setapp(netdev, app_data);
1430314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			else
1431b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend				err = dcb_ieee_setapp(netdev, app_data);
1432314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend			if (err)
1433314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend				goto err;
1434314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		}
1435314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	}
1436314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1437314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabenderr:
14387be994138b188387691322921c08e19bddf6d3c5Thomas Graf	err = nla_put_u8(skb, DCB_ATTR_IEEE, err);
14395b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0);
1440314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	return err;
1441314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend}
1442314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
14437be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_ieee_get(struct net_device *netdev, struct nlmsghdr *nlh,
14447be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
1445314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend{
1446314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1447314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
1448314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend	if (!ops)
1449314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend		return -EOPNOTSUPP;
1450314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend
14517be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return dcbnl_ieee_fill(skb, netdev);
1452314b4778ed579f29b6d46ba90dbf31314c13805fJohn Fastabend}
1453f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
14547be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_ieee_del(struct net_device *netdev, struct nlmsghdr *nlh,
14557be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  u32 seq, struct nlattr **tb, struct sk_buff *skb)
1456f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend{
1457f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1458f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
14593d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	int err;
1460f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1461f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (!ops)
1462f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		return -EOPNOTSUPP;
1463f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1464f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (!tb[DCB_ATTR_IEEE])
1465f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		return -EINVAL;
1466f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1467f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1468f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1469f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (err)
1470f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		return err;
1471f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1472f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1473f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		struct nlattr *attr;
1474f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		int rem;
1475f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1476f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1477f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			struct dcb_app *app_data;
1478f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1479f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1480f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				continue;
1481f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			app_data = nla_data(attr);
1482f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			if (ops->ieee_delapp)
1483f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				err = ops->ieee_delapp(netdev, app_data);
1484f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			else
1485f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				err = dcb_ieee_delapp(netdev, app_data);
1486f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend			if (err)
1487f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend				goto err;
1488f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		}
1489f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	}
1490f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1491f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabenderr:
14927be994138b188387691322921c08e19bddf6d3c5Thomas Graf	err = nla_put_u8(skb, DCB_ATTR_IEEE, err);
14935b7f7626743e0912958981343b47ac0ab2206b1cShmulik Ravid	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0);
1494f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	return err;
1495f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend}
1496f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1497f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
14986241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid/* DCBX configuration */
14997be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getdcbx(struct net_device *netdev, struct nlmsghdr *nlh,
15007be994138b188387691322921c08e19bddf6d3c5Thomas Graf			 u32 seq, struct nlattr **tb, struct sk_buff *skb)
15016241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid{
15026241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	if (!netdev->dcbnl_ops->getdcbx)
15037f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
15046241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
15057be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_DCBX,
15067be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  netdev->dcbnl_ops->getdcbx(netdev));
15076241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid}
15086241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
15097be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setdcbx(struct net_device *netdev, struct nlmsghdr *nlh,
15107be994138b188387691322921c08e19bddf6d3c5Thomas Graf			 u32 seq, struct nlattr **tb, struct sk_buff *skb)
15116241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid{
15126241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	u8 value;
15136241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
15147f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->setdcbx)
15157f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
15167f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
15177f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_DCBX])
15187f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
15196241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
15206241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid	value = nla_get_u8(tb[DCB_ATTR_DCBX]);
15216241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
15227be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return nla_put_u8(skb, DCB_ATTR_DCBX,
15237be994138b188387691322921c08e19bddf6d3c5Thomas Graf			  netdev->dcbnl_ops->setdcbx(netdev, value));
15246241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid}
15256241b6259b16aa390ff4bf50f520685b3801200bShmulik Ravid
15267be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_getfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh,
15277be994138b188387691322921c08e19bddf6d3c5Thomas Graf			    u32 seq, struct nlattr **tb, struct sk_buff *skb)
1528ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid{
1529ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest;
1530ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	u8 value;
15317f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret, i;
1532ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	int getall = 0;
1533ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15347f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->getfeatcfg)
15357f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EOPNOTSUPP;
15367f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
15377f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_FEATCFG])
15387f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
1539ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1540ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1541ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			       dcbnl_featcfg_nest);
15427f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (ret)
15437be994138b188387691322921c08e19bddf6d3c5Thomas Graf		return ret;
1544ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15457be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nest = nla_nest_start(skb, DCB_ATTR_FEATCFG);
15467be994138b188387691322921c08e19bddf6d3c5Thomas Graf	if (!nest)
15477be994138b188387691322921c08e19bddf6d3c5Thomas Graf		return -EMSGSIZE;
1548ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1549ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	if (data[DCB_FEATCFG_ATTR_ALL])
1550ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		getall = 1;
1551ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1552ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1553ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (!getall && !data[i])
1554ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			continue;
1555ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1556ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value);
15577f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		if (!ret)
15587be994138b188387691322921c08e19bddf6d3c5Thomas Graf			ret = nla_put_u8(skb, i, value);
1559ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15607f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		if (ret) {
15617be994138b188387691322921c08e19bddf6d3c5Thomas Graf			nla_nest_cancel(skb, nest);
15627f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid			goto nla_put_failure;
15637f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		}
1564ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
15657be994138b188387691322921c08e19bddf6d3c5Thomas Graf	nla_nest_end(skb, nest);
1566ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15677f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravidnla_put_failure:
1568ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	return ret;
1569ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid}
1570ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15717be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_setfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh,
15727be994138b188387691322921c08e19bddf6d3c5Thomas Graf			    u32 seq, struct nlattr **tb, struct sk_buff *skb)
1573ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid{
1574ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1];
15757f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	int ret, i;
1576ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	u8 value;
1577ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15787f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!netdev->dcbnl_ops->setfeatcfg)
15797f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -ENOTSUPP;
15807f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
15817f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (!tb[DCB_ATTR_FEATCFG])
15827f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid		return -EINVAL;
1583ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1584ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1585ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			       dcbnl_featcfg_nest);
1586ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
15877f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid	if (ret)
1588ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		goto err;
1589ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1590ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1591ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (data[i] == NULL)
1592ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid			continue;
1593ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1594ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		value = nla_get_u8(data[i]);
1595ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1596ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		ret = netdev->dcbnl_ops->setfeatcfg(netdev, i, value);
1597ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1598ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid		if (ret)
15997f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid			goto err;
1600ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	}
1601ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Raviderr:
16027be994138b188387691322921c08e19bddf6d3c5Thomas Graf	ret = nla_put_u8(skb, DCB_ATTR_FEATCFG, ret);
16037f891cf1fc0d5d5c5b359caec77e5383e1d55986Shmulik Ravid
1604ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid	return ret;
1605ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid}
1606ea45fe4e176a42d2396878f530cfdc8265bef37bShmulik Ravid
1607dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid/* Handle CEE DCBX GET commands. */
16087be994138b188387691322921c08e19bddf6d3c5Thomas Grafstatic int dcbnl_cee_get(struct net_device *netdev, struct nlmsghdr *nlh,
16097be994138b188387691322921c08e19bddf6d3c5Thomas Graf			 u32 seq, struct nlattr **tb, struct sk_buff *skb)
1610dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid{
1611dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1612dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
1613dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid	if (!ops)
1614dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid		return -EOPNOTSUPP;
1615dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
16167be994138b188387691322921c08e19bddf6d3c5Thomas Graf	return dcbnl_cee_fill(skb, netdev);
1617dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid}
1618dc6ed1df5a5f84e45e77e2acb6fd99b995414956Shmulik Ravid
161933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Grafstruct reply_func {
162033a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	/* reply netlink message type */
162133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	int	type;
162233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
162333a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	/* function to fill message contents */
162433a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	int   (*cb)(struct net_device *, struct nlmsghdr *, u32,
162533a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		    struct nlattr **, struct sk_buff *);
162633a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf};
162733a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
162833a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Grafstatic const struct reply_func reply_funcs[DCB_CMD_MAX+1] = {
16297be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GSTATE]	= { RTM_GETDCB, dcbnl_getstate },
16307be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_SSTATE]	= { RTM_SETDCB, dcbnl_setstate },
16317be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PFC_GCFG]	= { RTM_GETDCB, dcbnl_getpfccfg },
16327be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PFC_SCFG]	= { RTM_SETDCB, dcbnl_setpfccfg },
16337be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GPERM_HWADDR]	= { RTM_GETDCB, dcbnl_getperm_hwaddr },
16347be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GCAP]		= { RTM_GETDCB, dcbnl_getcap },
16357be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GNUMTCS]	= { RTM_GETDCB, dcbnl_getnumtcs },
16367be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_SNUMTCS]	= { RTM_SETDCB, dcbnl_setnumtcs },
16377be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PFC_GSTATE]	= { RTM_GETDCB, dcbnl_getpfcstate },
16387be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PFC_SSTATE]	= { RTM_SETDCB, dcbnl_setpfcstate },
16397be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GAPP]		= { RTM_GETDCB, dcbnl_getapp },
16407be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_SAPP]		= { RTM_SETDCB, dcbnl_setapp },
16417be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PGTX_GCFG]	= { RTM_GETDCB, dcbnl_pgtx_getcfg },
16427be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PGTX_SCFG]	= { RTM_SETDCB, dcbnl_pgtx_setcfg },
16437be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PGRX_GCFG]	= { RTM_GETDCB, dcbnl_pgrx_getcfg },
16447be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_PGRX_SCFG]	= { RTM_SETDCB, dcbnl_pgrx_setcfg },
16457be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_SET_ALL]	= { RTM_SETDCB, dcbnl_setall },
16467be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_BCN_GCFG]	= { RTM_GETDCB, dcbnl_bcn_getcfg },
16477be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_BCN_SCFG]	= { RTM_SETDCB, dcbnl_bcn_setcfg },
16487be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_IEEE_GET]	= { RTM_GETDCB, dcbnl_ieee_get },
16497be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_IEEE_SET]	= { RTM_SETDCB, dcbnl_ieee_set },
16507be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_IEEE_DEL]	= { RTM_SETDCB, dcbnl_ieee_del },
16517be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GDCBX]		= { RTM_GETDCB, dcbnl_getdcbx },
16527be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_SDCBX]		= { RTM_SETDCB, dcbnl_setdcbx },
16537be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_GFEATCFG]	= { RTM_GETDCB, dcbnl_getfeatcfg },
16547be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_SFEATCFG]	= { RTM_SETDCB, dcbnl_setfeatcfg },
16557be994138b188387691322921c08e19bddf6d3c5Thomas Graf	[DCB_CMD_CEE_GET]	= { RTM_GETDCB, dcbnl_cee_get },
165633a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf};
165733a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
16582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
16592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
16602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct net *net = sock_net(skb->sk);
16612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct net_device *netdev;
16627a282bc37f8a1e7b46907d78724177d20214b137Thomas Graf	struct dcbmsg *dcb = nlmsg_data(nlh);
16632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *tb[DCB_ATTR_MAX + 1];
16642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u32 pid = skb ? NETLINK_CB(skb).pid : 0;
16652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
166633a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	struct sk_buff *reply_skb;
166739912f9cf9603f0de085fb5ba916a7a88010ccd9Thomas Graf	struct nlmsghdr *reply_nlh = NULL;
166833a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	const struct reply_func *fn;
16692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
167009ad9bc752519cc167d0a573e1acf69b5c707c67Octavian Purdila	if (!net_eq(net, &init_net))
16712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
16722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
16732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
16742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  dcbnl_rtnl_policy);
16752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret < 0)
16762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
16772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
167833a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	if (dcb->cmd > DCB_CMD_MAX)
167933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		return -EINVAL;
168033a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
168133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	/* check if a reply function has been defined for the command */
168233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	fn = &reply_funcs[dcb->cmd];
168333a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	if (!fn->cb)
168433a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		return -EOPNOTSUPP;
168533a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
16862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_IFNAME])
16872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
16882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
16892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME]));
16902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev)
16913d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		return -ENODEV;
16922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
16933d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	if (!netdev->dcbnl_ops) {
16943d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		ret = -EOPNOTSUPP;
16953d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf		goto out;
16963d1f486952b750f1cca53cf22d4f769db5aba4f0Thomas Graf	}
16972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
169833a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	reply_skb = dcbnl_newmsg(fn->type, dcb->cmd, pid, nlh->nlmsg_seq,
169933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf				 nlh->nlmsg_flags, &reply_nlh);
170033a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	if (!reply_skb) {
170133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		ret = -ENOBUFS;
170233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		goto out;
170333a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	}
170433a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
170533a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	ret = fn->cb(netdev, nlh, nlh->nlmsg_seq, tb, reply_skb);
170633a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	if (ret < 0) {
170733a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		nlmsg_free(reply_skb);
170833a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf		goto out;
170933a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	}
171033a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
171133a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	nlmsg_end(reply_skb, reply_nlh);
171233a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf
171333a03aadb52fa05d28aba6d8f0c03c7b3b905897Thomas Graf	ret = rtnl_unicast(reply_skb, &init_net, pid);
17142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckout:
17152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dev_put(netdev);
17162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
17172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
17182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1719716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Grafstatic struct dcb_app_type *dcb_app_lookup(const struct dcb_app *app,
1720716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf					   int ifindex, int prio)
1721716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf{
1722716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	struct dcb_app_type *itr;
1723716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf
1724716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	list_for_each_entry(itr, &dcb_app_list, list) {
1725716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		if (itr->app.selector == app->selector &&
1726716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		    itr->app.protocol == app->protocol &&
1727716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		    itr->ifindex == ifindex &&
1728716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		    (!prio || itr->app.priority == prio))
1729716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf			return itr;
1730716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	}
1731716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf
1732716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	return NULL;
1733716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf}
1734716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf
17354e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Grafstatic int dcb_app_add(const struct dcb_app *app, int ifindex)
17364e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf{
17374e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	struct dcb_app_type *entry;
17384e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf
17394e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
17404e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	if (!entry)
17414e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf		return -ENOMEM;
17424e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf
17434e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	memcpy(&entry->app, app, sizeof(*app));
17444e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	entry->ifindex = ifindex;
17454e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	list_add(&entry->list, &dcb_app_list);
17464e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf
17474e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	return 0;
17484e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf}
17494e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf
17509ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend/**
17519ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * dcb_getapp - retrieve the DCBX application user priority
17529ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend *
17539ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * On success returns a non-zero 802.1p user priority bitmap
17549ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * otherwise returns 0 as the invalid user priority bitmap to
17559ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend * indicate an error.
17569ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend */
17579ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendu8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
17589ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
17599ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
17609ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	u8 prio = 0;
17619ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
17629ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
1763716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
1764716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		prio = itr->app.priority;
17659ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
17669ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
17679ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	return prio;
17689ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
17699ab933ab2cc80f04690d6aa385b1110075c5e507John FastabendEXPORT_SYMBOL(dcb_getapp);
17709ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
17719ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend/**
1772b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * dcb_setapp - add CEE dcb application data to app list
17739ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend *
1774b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * Priority 0 is an invalid priority in CEE spec. This routine
1775b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * removes applications from the app list if the priority is
1776b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * set to zero.
17779ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend */
1778ab6baf980b095c70a56c5eb2f58166aef8a0edc8John Fastabendint dcb_setapp(struct net_device *dev, struct dcb_app *new)
17799ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
17809ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *itr;
17817ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	struct dcb_app_type event;
17824e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	int err = 0;
17837ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend
1784e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	event.ifindex = dev->ifindex;
17857ec79270d7de0c8ca602c47cb25a9652ec28f37fJohn Fastabend	memcpy(&event.app, new, sizeof(event.app));
17866bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend	if (dev->dcbnl_ops->getdcbx)
17876bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
17889ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
17899ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
17909ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	/* Search for existing match and replace */
1791716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	if ((itr = dcb_app_lookup(new, dev->ifindex, 0))) {
1792716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		if (new->priority)
1793716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf			itr->app.priority = new->priority;
1794716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		else {
1795716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf			list_del(&itr->list);
1796716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf			kfree(itr);
17979ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		}
1798716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		goto out;
17999ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
18009ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	/* App type does not exist add new application type */
18014e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	if (new->priority)
18024e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf		err = dcb_app_add(new, dev->ifindex);
18039ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabendout:
18049ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
18054e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	if (!err)
18064e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
18074e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	return err;
18089ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
18099ab933ab2cc80f04690d6aa385b1110075c5e507John FastabendEXPORT_SYMBOL(dcb_setapp);
18109ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
1811b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend/**
1812a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * dcb_ieee_getapp_mask - retrieve the IEEE DCB application priority
1813a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend *
1814a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * Helper routine which on success returns a non-zero 802.1Qaz user
1815a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * priority bitmap otherwise returns 0 to indicate the dcb_app was
1816a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend * not found in APP list.
1817a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend */
1818a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabendu8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
1819a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend{
1820a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	struct dcb_app_type *itr;
1821a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	u8 prio = 0;
1822a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend
1823a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	spin_lock(&dcb_lock);
1824716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
1825716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		prio |= 1 << itr->app.priority;
1826a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	spin_unlock(&dcb_lock);
1827a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend
1828a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend	return prio;
1829a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend}
1830a364c8cf80251849bab207be8c9e66253c8ca8f8John FastabendEXPORT_SYMBOL(dcb_ieee_getapp_mask);
1831a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend
1832a364c8cf80251849bab207be8c9e66253c8ca8f8John Fastabend/**
1833b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * dcb_ieee_setapp - add IEEE dcb application data to app list
1834b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend *
1835b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * This adds Application data to the list. Multiple application
1836b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * entries may exists for the same selector and protocol as long
1837b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend * as the priorities are different.
1838b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend */
1839b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabendint dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
1840b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend{
1841b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	struct dcb_app_type event;
1842b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	int err = 0;
1843b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
1844e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	event.ifindex = dev->ifindex;
1845b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	memcpy(&event.app, new, sizeof(event.app));
18466bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend	if (dev->dcbnl_ops->getdcbx)
18476bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
1848b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
1849b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	spin_lock(&dcb_lock);
1850b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	/* Search for existing match and abort if found */
1851716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	if (dcb_app_lookup(new, dev->ifindex, new->priority)) {
1852716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		err = -EEXIST;
1853716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		goto out;
1854b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	}
1855b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
18564e4f2f69704be0ae218d91fb827e5a6987fe262fThomas Graf	err = dcb_app_add(new, dev->ifindex);
1857b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabendout:
1858b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	spin_unlock(&dcb_lock);
1859b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	if (!err)
1860b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
1861b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend	return err;
1862b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend}
1863b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John FastabendEXPORT_SYMBOL(dcb_ieee_setapp);
1864b6db2174c59ef1e72f7bd63e0f105b1a2d7f18d3John Fastabend
1865f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend/**
1866f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend * dcb_ieee_delapp - delete IEEE dcb application data from list
1867f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend *
1868f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend * This removes a matching APP data from the APP list
1869f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend */
1870f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabendint dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
1871f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend{
1872f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	struct dcb_app_type *itr;
1873f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	struct dcb_app_type event;
1874f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	int err = -ENOENT;
1875f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1876e290ed81307ca7d92675f0d9c683add693c2f377Mark Rustad	event.ifindex = dev->ifindex;
1877f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	memcpy(&event.app, del, sizeof(event.app));
18786bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend	if (dev->dcbnl_ops->getdcbx)
18796bd0e1cb10b6d14dda4a8806d0a2f4f0bbf01931John Fastabend		event.dcbx = dev->dcbnl_ops->getdcbx(dev);
1880f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1881f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	spin_lock(&dcb_lock);
1882f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	/* Search for existing match and remove it. */
1883716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf	if ((itr = dcb_app_lookup(del, dev->ifindex, del->priority))) {
1884716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		list_del(&itr->list);
1885716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		kfree(itr);
1886716b31abbd39baab307c0a7b38dce9a20c16c62dThomas Graf		err = 0;
1887f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	}
1888f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
1889f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	spin_unlock(&dcb_lock);
1890f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	if (!err)
1891f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
1892f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend	return err;
1893f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend}
1894f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John FastabendEXPORT_SYMBOL(dcb_ieee_delapp);
1895f9ae7e4b515c4d56baf6e0e84ebee2e03ae57a25John Fastabend
18967c14c3f10e6dcd7f70e49f77b6e1ae605c4861e6Shmulik Ravidstatic void dcb_flushapp(void)
18979ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend{
18989ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	struct dcb_app_type *app;
18992a8fe003741aa90b6b9453e90af4bbb7bc42918cDan Carpenter	struct dcb_app_type *tmp;
19009ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
19019ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_lock(&dcb_lock);
19022a8fe003741aa90b6b9453e90af4bbb7bc42918cDan Carpenter	list_for_each_entry_safe(app, tmp, &dcb_app_list, list) {
19039ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		list_del(&app->list);
19049ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend		kfree(app);
19059ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	}
19069ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	spin_unlock(&dcb_lock);
19079ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend}
19089ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
19092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __init dcbnl_init(void)
19102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
19119ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	INIT_LIST_HEAD(&dcb_app_list);
19129ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend
1913c7ac8679bec9397afe8918f788cbcef88c38da54Greg Rose	rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, NULL);
1914c7ac8679bec9397afe8918f788cbcef88c38da54Greg Rose	rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, NULL);
19152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
19172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
19182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_init(dcbnl_init);
19192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
19202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic void __exit dcbnl_exit(void)
19212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
19222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_unregister(PF_UNSPEC, RTM_GETDCB);
19232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_unregister(PF_UNSPEC, RTM_SETDCB);
19249ab933ab2cc80f04690d6aa385b1110075c5e507John Fastabend	dcb_flushapp();
19252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
19262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_exit(dcbnl_exit);
1927