dcbnl.c revision b54452b07a7b1b8cc1385edba3ef2ef6d4679d5a
12f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/*
22f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Copyright (c) 2008, Intel Corporation.
32f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
42f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * This program is free software; you can redistribute it and/or modify it
52f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * under the terms and conditions of the GNU General Public License,
62f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * version 2, as published by the Free Software Foundation.
72f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
82f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * This program is distributed in the hope it will be useful, but WITHOUT
92f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * more details.
122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * You should have received a copy of the GNU General Public License along with
142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Place - Suite 330, Boston, MA 02111-1307 USA.
162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Author: Lucy Liu <lucy.liu@intel.com>
182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck */
192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <linux/netdevice.h>
212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <linux/netlink.h>
222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <net/netlink.h>
232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <net/rtnetlink.h>
242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <linux/dcbnl.h>
252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <linux/rtnetlink.h>
262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck#include <net/sock.h>
272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/**
292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Data Center Bridging (DCB) is a collection of Ethernet enhancements
302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * intended to allow network traffic with differing requirements
312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * (highly reliable, no drops vs. best effort vs. low latency) to operate
322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * and co-exist on Ethernet.  Current DCB features are:
332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Enhanced Transmission Selection (aka Priority Grouping [PG]) - provides a
352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *   framework for assigning bandwidth guarantees to traffic classes.
362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Priority-based Flow Control (PFC) - provides a flow control mechanism which
382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *   can work independently for each 802.1p priority.
392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * Congestion Notification - provides a mechanism for end-to-end congestion
412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *   control for protocols which do not have built-in congestion management.
422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * More information about the emerging standards for these Ethernet features
442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * can be found at: http://www.ieee802.org/1/pages/dcbridges.html
452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck *
462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * This file implements an rtnetlink interface to allow configuration of DCB
472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck * features for capable devices.
482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck */
492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander DuyckMODULE_AUTHOR("Lucy Liu, <lucy.liu@intel.com>");
517a6b6f515f77d1c62a2f383b6dce18cb0af0cf4fJeff KirsherMODULE_DESCRIPTION("Data Center Bridging netlink interface");
522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander DuyckMODULE_LICENSE("GPL");
532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/**************** DCB attribute policies *************************************/
552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB netlink attributes policy */
57b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = {
58859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_IFNAME]      = {.type = NLA_NUL_STRING, .len = IFNAMSIZ - 1},
59859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_STATE]       = {.type = NLA_U8},
60859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_PFC_CFG]     = {.type = NLA_NESTED},
61859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_PG_CFG]      = {.type = NLA_NESTED},
62859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_SET_ALL]     = {.type = NLA_U8},
632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG},
64859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_CAP]         = {.type = NLA_NESTED},
65859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_PFC_STATE]   = {.type = NLA_U8},
66859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_ATTR_BCN]         = {.type = NLA_NESTED},
676fa382af61338908e5713234bcee598423f661c3Yi Zou	[DCB_ATTR_APP]         = {.type = NLA_NESTED},
682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck};
692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB priority flow control to User Priority nested attributes */
71b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = {
722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_0]   = {.type = NLA_U8},
732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_1]   = {.type = NLA_U8},
742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_2]   = {.type = NLA_U8},
752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_3]   = {.type = NLA_U8},
762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_4]   = {.type = NLA_U8},
772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_5]   = {.type = NLA_U8},
782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_6]   = {.type = NLA_U8},
792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_7]   = {.type = NLA_U8},
802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PFC_UP_ATTR_ALL] = {.type = NLA_FLAG},
812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck};
822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB priority grouping nested attributes */
84b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = {
852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_0]      = {.type = NLA_NESTED},
862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_1]      = {.type = NLA_NESTED},
872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_2]      = {.type = NLA_NESTED},
882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_3]      = {.type = NLA_NESTED},
892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_4]      = {.type = NLA_NESTED},
902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_5]      = {.type = NLA_NESTED},
912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_6]      = {.type = NLA_NESTED},
922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_7]      = {.type = NLA_NESTED},
932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_TC_ALL]    = {.type = NLA_NESTED},
942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_0]   = {.type = NLA_U8},
952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_1]   = {.type = NLA_U8},
962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_2]   = {.type = NLA_U8},
972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_3]   = {.type = NLA_U8},
982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_4]   = {.type = NLA_U8},
992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_5]   = {.type = NLA_U8},
1002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_6]   = {.type = NLA_U8},
1012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_7]   = {.type = NLA_U8},
1022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_PG_ATTR_BW_ID_ALL] = {.type = NLA_FLAG},
1032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck};
1042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB traffic class nested attributes. */
106b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = {
1072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_PGID]            = {.type = NLA_U8},
1082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_UP_MAPPING]      = {.type = NLA_U8},
1092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_STRICT_PRIO]     = {.type = NLA_U8},
1102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_BW_PCT]          = {.type = NLA_U8},
1112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	[DCB_TC_ATTR_PARAM_ALL]             = {.type = NLA_FLAG},
1122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck};
1132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
11446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck/* DCB capabilities nested attributes. */
115b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = {
11646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_ALL]     = {.type = NLA_FLAG},
11746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_PG]      = {.type = NLA_U8},
11846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_PFC]     = {.type = NLA_U8},
11946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_UP2TC]   = {.type = NLA_U8},
12046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_PG_TCS]  = {.type = NLA_U8},
12146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8},
12246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_GSP]     = {.type = NLA_U8},
12346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	[DCB_CAP_ATTR_BCN]     = {.type = NLA_U8},
12446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck};
1252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
12633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck/* DCB capabilities nested attributes. */
127b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = {
12833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	[DCB_NUMTCS_ATTR_ALL]     = {.type = NLA_FLAG},
12933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	[DCB_NUMTCS_ATTR_PG]      = {.type = NLA_U8},
13033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	[DCB_NUMTCS_ATTR_PFC]     = {.type = NLA_U8},
13133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck};
13233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
133859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck/* DCB BCN nested attributes. */
134b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = {
135859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_0]         = {.type = NLA_U8},
136859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_1]         = {.type = NLA_U8},
137859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_2]         = {.type = NLA_U8},
138859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_3]         = {.type = NLA_U8},
139859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_4]         = {.type = NLA_U8},
140859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_5]         = {.type = NLA_U8},
141859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_6]         = {.type = NLA_U8},
142859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_7]         = {.type = NLA_U8},
143859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RP_ALL]       = {.type = NLA_FLAG},
144f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	[DCB_BCN_ATTR_BCNA_0]       = {.type = NLA_U32},
145f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	[DCB_BCN_ATTR_BCNA_1]       = {.type = NLA_U32},
146859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_ALPHA]        = {.type = NLA_U32},
147859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_BETA]         = {.type = NLA_U32},
148859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_GD]           = {.type = NLA_U32},
149859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_GI]           = {.type = NLA_U32},
150859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_TMAX]         = {.type = NLA_U32},
151859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_TD]           = {.type = NLA_U32},
152859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RMIN]         = {.type = NLA_U32},
153859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_W]            = {.type = NLA_U32},
154859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RD]           = {.type = NLA_U32},
155859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RU]           = {.type = NLA_U32},
156859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_WRTT]         = {.type = NLA_U32},
157859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_RI]           = {.type = NLA_U32},
158859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_C]            = {.type = NLA_U32},
159859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	[DCB_BCN_ATTR_ALL]          = {.type = NLA_FLAG},
160859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck};
161859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1626fa382af61338908e5713234bcee598423f661c3Yi Zou/* DCB APP nested attributes. */
163b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = {
1646fa382af61338908e5713234bcee598423f661c3Yi Zou	[DCB_APP_ATTR_IDTYPE]       = {.type = NLA_U8},
1656fa382af61338908e5713234bcee598423f661c3Yi Zou	[DCB_APP_ATTR_ID]           = {.type = NLA_U16},
1666fa382af61338908e5713234bcee598423f661c3Yi Zou	[DCB_APP_ATTR_PRIORITY]     = {.type = NLA_U8},
1676fa382af61338908e5713234bcee598423f661c3Yi Zou};
1686fa382af61338908e5713234bcee598423f661c3Yi Zou
1692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* standard netlink reply call */
1702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
1712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                       u32 seq, u16 flags)
1722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
1732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
1742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
1752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
1762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
1772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
1802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
1812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags);
1832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
1852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
1862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = cmd;
1872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_pad = 0;
1882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_put_u8(dcbnl_skb, attr, value);
1902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
1912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
1922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	/* end the message, assign the nlmsg_len. */
1942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
1952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
1962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
1977eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		return -EINVAL;
1982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
2002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
2012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
202858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
2032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
2042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getstate(struct net_device *netdev, struct nlattr **tb,
2072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                          u32 pid, u32 seq, u16 flags)
2082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
2102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	/* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */
2122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops->getstate)
2132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
2142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(netdev->dcbnl_ops->getstate(netdev), RTM_GETDCB,
2162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  DCB_CMD_GSTATE, DCB_ATTR_STATE, pid, seq, flags);
2172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
2192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb,
2222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                           u32 pid, u32 seq, u16 flags)
2232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
2252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
2262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
2272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest;
2282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
2292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
2302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
2312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int getall = 0;
2322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->getpfccfg)
2342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
2352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
2372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PFC_CFG],
2382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       dcbnl_pfc_up_nest);
2392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
2402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
2412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
2442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
2452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
2472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
2492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
2502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = DCB_CMD_PFC_GCFG;
2512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG);
2532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!nest)
2542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
2552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (data[DCB_PFC_UP_ATTR_ALL])
2572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
2582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
2602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !data[i])
2612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
2622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0,
2642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                             &value);
2652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_put_u8(dcbnl_skb, i, value);
2662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret) {
2682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			nla_nest_cancel(dcbnl_skb, nest);
2692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err;
2702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
2712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
2722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_end(dcbnl_skb, nest);
2732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
2752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
2772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
2787eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
2792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
2812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
2822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
283858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
2842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out:
2852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return -EINVAL;
2862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
2872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb,
2892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                                u32 pid, u32 seq, u16 flags)
2902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
2912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
2922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
2932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
2942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 perm_addr[MAX_ADDR_LEN];
2952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
2962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
2972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops->getpermhwaddr)
2982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
2992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
3022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
3032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
3052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
3072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
3082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = DCB_CMD_GPERM_HWADDR;
3092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
3112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr),
3132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	              perm_addr);
3142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
3162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
3182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
3197eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
3202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
3222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
3232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
324858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
3252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out:
3262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return -EINVAL;
3272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
3282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
32946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckstatic int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb,
33046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck                        u32 pid, u32 seq, u16 flags)
33146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck{
33246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct sk_buff *dcbnl_skb;
33346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct nlmsghdr *nlh;
33446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct dcbmsg *dcb;
33546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest;
33646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	u8 value;
33746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int ret = -EINVAL;
33846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int i;
33946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	int getall = 0;
34046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
34146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap)
34246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		return ret;
34346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
34446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP],
34546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	                       dcbnl_cap_nest);
34646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (ret)
34746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto err_out;
34846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
34946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
35046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!dcbnl_skb)
35146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto err_out;
35246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
35346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
35446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
35546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcb = NLMSG_DATA(nlh);
35646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
35746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	dcb->cmd = DCB_CMD_GCAP;
35846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
35946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP);
36046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (!nest)
36146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto err;
36246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
36346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (data[DCB_CAP_ATTR_ALL])
36446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		getall = 1;
36546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
36646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) {
36746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		if (!getall && !data[i])
36846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			continue;
36946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
37046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) {
37146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			ret = nla_put_u8(dcbnl_skb, i, value);
37246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
37346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			if (ret) {
37446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck				nla_nest_cancel(dcbnl_skb, nest);
37546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck				goto err;
37646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck			}
37746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		}
37846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	}
37946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nla_nest_end(dcbnl_skb, nest);
38046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
38146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
38246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
38346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
38446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	if (ret)
3857eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
38646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
38746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	return 0;
38846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duycknlmsg_failure:
38946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckerr:
390858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
39146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckerr_out:
39246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	return -EINVAL;
39346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck}
39446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck
39533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckstatic int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb,
39633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck                           u32 pid, u32 seq, u16 flags)
39733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{
39833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct sk_buff *dcbnl_skb;
39933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlmsghdr *nlh;
40033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct dcbmsg *dcb;
40133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest;
40233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	u8 value;
40333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int ret = -EINVAL;
40433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int i;
40533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int getall = 0;
40633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
40733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs)
40833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		return ret;
40933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
41033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
41133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                       dcbnl_numtcs_nest);
41233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (ret) {
41333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
41433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err_out;
41533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
41633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
41733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
41833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (!dcbnl_skb) {
41933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
42033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err_out;
42133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
42233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
42333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
42433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
42533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcb = NLMSG_DATA(nlh);
42633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
42733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	dcb->cmd = DCB_CMD_GNUMTCS;
42833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
42933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS);
43033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (!nest) {
43133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
43233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err;
43333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
43433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
43533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (data[DCB_NUMTCS_ATTR_ALL])
43633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		getall = 1;
43733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
43833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
43933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (!getall && !data[i])
44033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			continue;
44133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
44233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value);
44333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (!ret) {
44433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			ret = nla_put_u8(dcbnl_skb, i, value);
44533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
44633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			if (ret) {
44733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck				nla_nest_cancel(dcbnl_skb, nest);
44833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck				ret = -EINVAL;
44933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck				goto err;
45033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			}
45133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		} else {
45233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			goto err;
45333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		}
45433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
45533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nla_nest_end(dcbnl_skb, nest);
45633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
45733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
45833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
45933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
46033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (ret) {
46133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
4627eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
46333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
46433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
46533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return 0;
46633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duycknlmsg_failure:
46733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr:
468858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
46933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr_out:
47033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return ret;
47133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck}
47233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
47333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckstatic int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb,
47433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck                           u32 pid, u32 seq, u16 flags)
47533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{
47633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1];
47733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int ret = -EINVAL;
47833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	u8 value;
47933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	int i;
48033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
4818b124a8e14c04378466ddfe63e41fc5035f957ebDon Skidmore	if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setnumtcs)
48233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		return ret;
48333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
48433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
48533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                       dcbnl_numtcs_nest);
48633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
48733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	if (ret) {
48833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = -EINVAL;
48933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto err;
49033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
49133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
49233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
49333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (data[i] == NULL)
49433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			continue;
49533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
49633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		value = nla_get_u8(data[i]);
49733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
49833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value);
49933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
50033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		if (ret)
50133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck			goto operr;
50233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	}
50333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
50433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckoperr:
50533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS,
50633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	                  DCB_ATTR_NUMTCS, pid, seq, flags);
50733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
50833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr:
50933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	return ret;
51033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck}
51133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck
5120eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyckstatic int dcbnl_getpfcstate(struct net_device *netdev, struct nlattr **tb,
5130eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
5140eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{
5150eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	int ret = -EINVAL;
5160eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5170eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	if (!netdev->dcbnl_ops->getpfcstate)
5180eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		return ret;
5190eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5200eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	ret = dcbnl_reply(netdev->dcbnl_ops->getpfcstate(netdev), RTM_GETDCB,
5210eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	                  DCB_CMD_PFC_GSTATE, DCB_ATTR_PFC_STATE,
5220eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	                  pid, seq, flags);
5230eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5240eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	return ret;
5250eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck}
5260eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5270eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyckstatic int dcbnl_setpfcstate(struct net_device *netdev, struct nlattr **tb,
5280eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
5290eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{
5300eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	int ret = -EINVAL;
5310eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	u8 value;
5320eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5330eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	if (!tb[DCB_ATTR_PFC_STATE] || !netdev->dcbnl_ops->setpfcstate)
5340eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		return ret;
5350eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5360eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]);
5370eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5380eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	netdev->dcbnl_ops->setpfcstate(netdev, value);
5390eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5400eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SSTATE, DCB_ATTR_PFC_STATE,
5410eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	                  pid, seq, flags);
5420eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
5430eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	return ret;
5440eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck}
5450eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck
546579496865cf4ea429146382d62047ffdbaab0deeYi Zoustatic int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb,
547579496865cf4ea429146382d62047ffdbaab0deeYi Zou                        u32 pid, u32 seq, u16 flags)
548579496865cf4ea429146382d62047ffdbaab0deeYi Zou{
549579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct sk_buff *dcbnl_skb;
550579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlmsghdr *nlh;
551579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct dcbmsg *dcb;
552579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_nest;
553579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
554579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u16 id;
555579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u8 up, idtype;
556579496865cf4ea429146382d62047ffdbaab0deeYi Zou	int ret = -EINVAL;
557579496865cf4ea429146382d62047ffdbaab0deeYi Zou
558579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->getapp)
559579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
560579496865cf4ea429146382d62047ffdbaab0deeYi Zou
561579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
562579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                       dcbnl_app_nest);
563579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
564579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
565579496865cf4ea429146382d62047ffdbaab0deeYi Zou
566579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = -EINVAL;
567579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* all must be non-null */
568579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
569579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_ID]))
570579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
571579496865cf4ea429146382d62047ffdbaab0deeYi Zou
572579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* either by eth type or by socket number */
573579496865cf4ea429146382d62047ffdbaab0deeYi Zou	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
574579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
575579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (idtype != DCB_APP_IDTYPE_PORTNUM))
576579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
577579496865cf4ea429146382d62047ffdbaab0deeYi Zou
578579496865cf4ea429146382d62047ffdbaab0deeYi Zou	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
579579496865cf4ea429146382d62047ffdbaab0deeYi Zou	up = netdev->dcbnl_ops->getapp(netdev, idtype, id);
580579496865cf4ea429146382d62047ffdbaab0deeYi Zou
581579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* send this back */
582579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
583579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (!dcbnl_skb)
584579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
585579496865cf4ea429146382d62047ffdbaab0deeYi Zou
586579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
587579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcb = NLMSG_DATA(nlh);
588579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcb->dcb_family = AF_UNSPEC;
589579496865cf4ea429146382d62047ffdbaab0deeYi Zou	dcb->cmd = DCB_CMD_GAPP;
590579496865cf4ea429146382d62047ffdbaab0deeYi Zou
591579496865cf4ea429146382d62047ffdbaab0deeYi Zou	app_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_APP);
592579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype);
593579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
594579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
595579496865cf4ea429146382d62047ffdbaab0deeYi Zou
596579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_put_u16(dcbnl_skb, DCB_APP_ATTR_ID, id);
597579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
598579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
599579496865cf4ea429146382d62047ffdbaab0deeYi Zou
600579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_PRIORITY, up);
601579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
602579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out_cancel;
603579496865cf4ea429146382d62047ffdbaab0deeYi Zou
604579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nla_nest_end(dcbnl_skb, app_nest);
605579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nlmsg_end(dcbnl_skb, nlh);
606579496865cf4ea429146382d62047ffdbaab0deeYi Zou
607579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
608579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
609579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto nlmsg_failure;
610579496865cf4ea429146382d62047ffdbaab0deeYi Zou
611579496865cf4ea429146382d62047ffdbaab0deeYi Zou	goto out;
612579496865cf4ea429146382d62047ffdbaab0deeYi Zou
613579496865cf4ea429146382d62047ffdbaab0deeYi Zouout_cancel:
614579496865cf4ea429146382d62047ffdbaab0deeYi Zou	nla_nest_cancel(dcbnl_skb, app_nest);
615579496865cf4ea429146382d62047ffdbaab0deeYi Zounlmsg_failure:
616579496865cf4ea429146382d62047ffdbaab0deeYi Zou	kfree_skb(dcbnl_skb);
617579496865cf4ea429146382d62047ffdbaab0deeYi Zouout:
618579496865cf4ea429146382d62047ffdbaab0deeYi Zou	return ret;
619579496865cf4ea429146382d62047ffdbaab0deeYi Zou}
620579496865cf4ea429146382d62047ffdbaab0deeYi Zou
621579496865cf4ea429146382d62047ffdbaab0deeYi Zoustatic int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb,
622579496865cf4ea429146382d62047ffdbaab0deeYi Zou                        u32 pid, u32 seq, u16 flags)
623579496865cf4ea429146382d62047ffdbaab0deeYi Zou{
624579496865cf4ea429146382d62047ffdbaab0deeYi Zou	int ret = -EINVAL;
625579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u16 id;
626579496865cf4ea429146382d62047ffdbaab0deeYi Zou	u8 up, idtype;
627579496865cf4ea429146382d62047ffdbaab0deeYi Zou	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
628579496865cf4ea429146382d62047ffdbaab0deeYi Zou
629579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->setapp)
630579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
631579496865cf4ea429146382d62047ffdbaab0deeYi Zou
632579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
633579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                       dcbnl_app_nest);
634579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if (ret)
635579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
636579496865cf4ea429146382d62047ffdbaab0deeYi Zou
637579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = -EINVAL;
638579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* all must be non-null */
639579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
640579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_ID]) ||
641579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (!app_tb[DCB_APP_ATTR_PRIORITY]))
642579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
643579496865cf4ea429146382d62047ffdbaab0deeYi Zou
644579496865cf4ea429146382d62047ffdbaab0deeYi Zou	/* either by eth type or by socket number */
645579496865cf4ea429146382d62047ffdbaab0deeYi Zou	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
646579496865cf4ea429146382d62047ffdbaab0deeYi Zou	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
647579496865cf4ea429146382d62047ffdbaab0deeYi Zou	    (idtype != DCB_APP_IDTYPE_PORTNUM))
648579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
649579496865cf4ea429146382d62047ffdbaab0deeYi Zou
650579496865cf4ea429146382d62047ffdbaab0deeYi Zou	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
651579496865cf4ea429146382d62047ffdbaab0deeYi Zou	up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]);
652579496865cf4ea429146382d62047ffdbaab0deeYi Zou
653579496865cf4ea429146382d62047ffdbaab0deeYi Zou	ret = dcbnl_reply(netdev->dcbnl_ops->setapp(netdev, idtype, id, up),
654579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                  RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP,
655579496865cf4ea429146382d62047ffdbaab0deeYi Zou	                  pid, seq, flags);
656579496865cf4ea429146382d62047ffdbaab0deeYi Zouout:
657579496865cf4ea429146382d62047ffdbaab0deeYi Zou	return ret;
658579496865cf4ea429146382d62047ffdbaab0deeYi Zou}
659579496865cf4ea429146382d62047ffdbaab0deeYi Zou
6602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb,
6612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags, int dir)
6622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
6632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct sk_buff *dcbnl_skb;
6642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlmsghdr *nlh;
6652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg *dcb;
6662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_nest, *param_nest, *data;
6672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
6682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
6692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 prio, pgid, tc_pct, up_map;
6702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret  = -EINVAL;
6712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int getall = 0;
6722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
6732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PG_CFG] ||
6752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgtccfgtx ||
6762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgtccfgrx ||
6772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgbwgcfgtx ||
6782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->getpgbwgcfgrx)
6792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
6802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
6822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
6832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
6852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
6862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!dcbnl_skb)
6892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err_out;
6902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
6922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb = NLMSG_DATA(nlh);
6942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
6952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dcb->cmd = (dir) ? DCB_CMD_PGRX_GCFG : DCB_CMD_PGTX_GCFG;
6962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
6972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	pg_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PG_CFG);
6982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!pg_nest)
6992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
7002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (pg_tb[DCB_PG_ATTR_TC_ALL])
7022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
7032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
7052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !pg_tb[i])
7062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
7072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (pg_tb[DCB_PG_ATTR_TC_ALL])
7092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data = pg_tb[DCB_PG_ATTR_TC_ALL];
7102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		else
7112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data = pg_tb[i];
7122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
7132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				       data, dcbnl_tc_param_nest);
7142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
7152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
7162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		param_nest = nla_nest_start(dcbnl_skb, i);
7182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!param_nest)
7192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
7202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		pgid = DCB_ATTR_VALUE_UNDEFINED;
7222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		prio = DCB_ATTR_VALUE_UNDEFINED;
7232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
7242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		up_map = DCB_ATTR_VALUE_UNDEFINED;
7252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
7272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
7282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgtccfgrx(netdev,
7292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						i - DCB_PG_ATTR_TC_0, &prio,
7302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						&pgid, &tc_pct, &up_map);
7312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
7322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
7332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgtccfgtx(netdev,
7342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						i - DCB_PG_ATTR_TC_0, &prio,
7352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck						&pgid, &tc_pct, &up_map);
7362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
7372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_PGID] ||
7392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb,
7412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_PGID, pgid);
7422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
7432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
7442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
7452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] ||
7462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb,
7482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
7492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
7502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
7512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
7522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] ||
7532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb,
7552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
7562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
7572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
7582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
7592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] ||
7602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		    param_tb[DCB_TC_ATTR_PARAM_ALL]) {
7612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_BW_PCT,
7622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			                 tc_pct);
7632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			if (ret)
7642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				goto err_param;
7652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
7662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		nla_nest_end(dcbnl_skb, param_nest);
7672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
7682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (pg_tb[DCB_PG_ATTR_BW_ID_ALL])
7702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 1;
7712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	else
7722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		getall = 0;
7732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
7752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!getall && !pg_tb[i])
7762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
7772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
7792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
7812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
7822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgbwgcfgrx(netdev,
7832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
7842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
7852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
7862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->getpgbwgcfgtx(netdev,
7872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
7882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
7892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_put_u8(dcbnl_skb, i, tc_pct);
7902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
7922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err_pg;
7932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
7942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_end(dcbnl_skb, pg_nest);
7962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
7982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
7992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
8002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
8017eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
8022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
8042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_param:
8062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_cancel(dcbnl_skb, param_nest);
8072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_pg:
8082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	nla_nest_cancel(dcbnl_skb, pg_nest);
8092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure:
8102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
811858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
8122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out:
8132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret  = -EINVAL;
8142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
8152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlattr **tb,
8182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
8192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 0);
8212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlattr **tb,
8242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
8252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 1);
8272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb,
8302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                          u32 pid, u32 seq, u16 flags)
8312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
8332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
8342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate)
8362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
8372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	value = nla_get_u8(tb[DCB_ATTR_STATE]);
8392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8401486a61ebcd2711532f8163d30babc40e11e7b40Don Skidmore	ret = dcbnl_reply(netdev->dcbnl_ops->setstate(netdev, value),
8411486a61ebcd2711532f8163d30babc40e11e7b40Don Skidmore	                  RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE,
8422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  pid, seq, flags);
8432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
8452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb,
8482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                           u32 pid, u32 seq, u16 flags)
8492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1];
8512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
8522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
8532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 value;
8542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->setpfccfg)
8562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
8572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
8592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PFC_CFG],
8602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       dcbnl_pfc_up_nest);
8612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
8622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
8632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
8652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (data[i] == NULL)
8662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
8672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		value = nla_get_u8(data[i]);
8682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		netdev->dcbnl_ops->setpfccfg(netdev,
8692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			data[i]->nla_type - DCB_PFC_UP_ATTR_0, value);
8702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
8712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SCFG, DCB_ATTR_PFC_CFG,
8732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  pid, seq, flags);
8742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
8752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
8762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setall(struct net_device *netdev, struct nlattr **tb,
8792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                        u32 pid, u32 seq, u16 flags)
8802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
8822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall)
8842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
8852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(netdev->dcbnl_ops->setall(netdev), RTM_SETDCB,
8872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                  DCB_CMD_SET_ALL, DCB_ATTR_SET_ALL, pid, seq, flags);
8882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
8902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
8912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
8922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb,
8932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags, int dir)
8942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
8952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
8962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
8972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
8982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int i;
8992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 pgid;
9002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 up_map;
9012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 prio;
9022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u8 tc_pct;
9032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_PG_CFG] ||
9052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgtccfgtx ||
9062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgtccfgrx ||
9072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgbwgcfgtx ||
9082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	    !netdev->dcbnl_ops->setpgbwgcfgrx)
9092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
9102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
9122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	                       tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
9132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret)
9142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto err;
9152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
9172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!pg_tb[i])
9182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
9192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
9212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                       pg_tb[i], dcbnl_tc_param_nest);
9222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (ret)
9232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			goto err;
9242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		pgid = DCB_ATTR_VALUE_UNDEFINED;
9262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		prio = DCB_ATTR_VALUE_UNDEFINED;
9272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
9282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		up_map = DCB_ATTR_VALUE_UNDEFINED;
9292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO])
9312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			prio =
9322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			    nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]);
9332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_PGID])
9352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]);
9362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT])
9382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]);
9392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING])
9412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			up_map =
9422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			     nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]);
9432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		/* dir: Tx = 0, Rx = 1 */
9452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
9462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
9472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgtccfgrx(netdev,
9482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				i - DCB_PG_ATTR_TC_0,
9492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				prio, pgid, tc_pct, up_map);
9502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
9512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
9522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgtccfgtx(netdev,
9532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				i - DCB_PG_ATTR_TC_0,
9542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck				prio, pgid, tc_pct, up_map);
9552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
9562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
9572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
9592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (!pg_tb[i])
9602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			continue;
9612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		tc_pct = nla_get_u8(pg_tb[i]);
9632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		/* dir: Tx = 0, Rx = 1 */
9652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		if (dir) {
9662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Rx */
9672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgbwgcfgrx(netdev,
9682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
9692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		} else {
9702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			/* Tx */
9712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			netdev->dcbnl_ops->setpgbwgcfgtx(netdev,
9722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck					 i - DCB_PG_ATTR_BW_ID_0, tc_pct);
9732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		}
9742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
9752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB,
9772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG),
9782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  DCB_ATTR_PG_CFG, pid, seq, flags);
9792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr:
9812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
9822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
9832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlattr **tb,
9852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
9862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
9872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 0);
9882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
9892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
9902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb,
9912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck                             u32 pid, u32 seq, u16 flags)
9922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
9932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1);
9942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
9952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
996859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckstatic int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb,
997859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck                            u32 pid, u32 seq, u16 flags)
998859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck{
999859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct sk_buff *dcbnl_skb;
1000859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlmsghdr *nlh;
1001859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct dcbmsg *dcb;
1002859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *bcn_nest;
1003859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1];
1004859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u8 value_byte;
1005859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u32 value_integer;
1006859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int ret  = -EINVAL;
1007859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	bool getall = false;
1008859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int i;
1009859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1010859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->getbcnrp ||
1011859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	    !netdev->dcbnl_ops->getbcncfg)
1012859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		return ret;
1013859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1014859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX,
1015859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       tb[DCB_ATTR_BCN], dcbnl_bcn_nest);
1016859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1017859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
1018859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err_out;
1019859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1020859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1021859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!dcbnl_skb)
1022859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err_out;
1023859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1024859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1025859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1026859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcb = NLMSG_DATA(nlh);
1027859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcb->dcb_family = AF_UNSPEC;
1028859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	dcb->cmd = DCB_CMD_BCN_GCFG;
1029859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1030859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	bcn_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_BCN);
1031859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (!bcn_nest)
1032859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err;
1033859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1034859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (bcn_tb[DCB_BCN_ATTR_ALL])
1035859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		getall = true;
1036859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1037859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
1038859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (!getall && !bcn_tb[i])
1039859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1040859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1041859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0,
1042859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                            &value_byte);
1043859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = nla_put_u8(dcbnl_skb, i, value_byte);
1044859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (ret)
1045859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			goto err_bcn;
1046859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1047859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1048f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
1049859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (!getall && !bcn_tb[i])
1050859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1051859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1052859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->getbcncfg(netdev, i,
1053859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                             &value_integer);
1054859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = nla_put_u32(dcbnl_skb, i, value_integer);
1055859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (ret)
1056859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			goto err_bcn;
1057859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1058859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1059859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nla_nest_end(dcbnl_skb, bcn_nest);
1060859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1061859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nlmsg_end(dcbnl_skb, nlh);
1062859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1063859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
1064859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
10657eaf5077b37bb33dbd44e569ff88566d6fe286e9John Fastabend		goto err_out;
1066859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1067859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return 0;
1068859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1069859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr_bcn:
1070859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	nla_nest_cancel(dcbnl_skb, bcn_nest);
1071859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duycknlmsg_failure:
1072859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr:
1073858eb711ba64f8a001d7003295b8078bcab33b6dRoel Kluin	kfree_skb(dcbnl_skb);
1074859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr_out:
1075859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret  = -EINVAL;
1076859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return ret;
1077859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck}
1078859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1079859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckstatic int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlattr **tb,
1080859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck                            u32 pid, u32 seq, u16 flags)
1081859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck{
1082859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	struct nlattr *data[DCB_BCN_ATTR_MAX + 1];
1083859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int i;
1084859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	int ret = -EINVAL;
1085859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u8 value_byte;
1086859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	u32 value_int;
1087859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1088f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches	if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg ||
1089f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches	    !netdev->dcbnl_ops->setbcnrp)
1090859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		return ret;
1091859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1092859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX,
1093859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       tb[DCB_ATTR_BCN],
1094859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                       dcbnl_pfc_up_nest);
1095859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	if (ret)
1096859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto err;
1097859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1098859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
1099859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (data[i] == NULL)
1100859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1101859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		value_byte = nla_get_u8(data[i]);
1102859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->setbcnrp(netdev,
1103859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte);
1104859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1105859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1106f4314e815e87b4ab1c9b1115dd5853cd20ca999cDon Skidmore	for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
1107859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		if (data[i] == NULL)
1108859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck			continue;
1109859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		value_int = nla_get_u32(data[i]);
1110859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		netdev->dcbnl_ops->setbcncfg(netdev,
1111859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                                     i, value_int);
1112859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	}
1113859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
1114859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_BCN_SCFG, DCB_ATTR_BCN,
1115859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	                  pid, seq, flags);
1116859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyckerr:
1117859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	return ret;
1118859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck}
1119859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck
11202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
11212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
11222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct net *net = sock_net(skb->sk);
11232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct net_device *netdev;
11242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct dcbmsg  *dcb = (struct dcbmsg *)NLMSG_DATA(nlh);
11252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	struct nlattr *tb[DCB_ATTR_MAX + 1];
11262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	u32 pid = skb ? NETLINK_CB(skb).pid : 0;
11272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	int ret = -EINVAL;
11282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
112909ad9bc752519cc167d0a573e1acf69b5c707c67Octavian Purdila	if (!net_eq(net, &init_net))
11302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
11312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
11322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
11332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck			  dcbnl_rtnl_policy);
11342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (ret < 0)
11352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return ret;
11362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
11372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!tb[DCB_ATTR_IFNAME])
11382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
11392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
11402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME]));
11412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev)
11422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		return -EINVAL;
11432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
11442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	if (!netdev->dcbnl_ops)
11452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto errout;
11462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
11472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	switch (dcb->cmd) {
11482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_GSTATE:
11492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq,
11502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                     nlh->nlmsg_flags);
11512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
11522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PFC_GCFG:
11532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
11542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                      nlh->nlmsg_flags);
11552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
11562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_GPERM_HWADDR:
11572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq,
11582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                           nlh->nlmsg_flags);
11592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
11602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGTX_GCFG:
11612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
11622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
11632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
11642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGRX_GCFG:
11652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
11662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
11672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
1168859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	case DCB_CMD_BCN_GCFG:
1169859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = dcbnl_bcn_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
1170859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                       nlh->nlmsg_flags);
1171859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto out;
11722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_SSTATE:
11732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq,
11742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                     nlh->nlmsg_flags);
11752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
11762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PFC_SCFG:
11772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
11782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                      nlh->nlmsg_flags);
11792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
11802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
11812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_SET_ALL:
11822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq,
11832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                   nlh->nlmsg_flags);
11842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
11852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGTX_SCFG:
11862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
11872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
11882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
11892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	case DCB_CMD_PGRX_SCFG:
11902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
11912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		                        nlh->nlmsg_flags);
11922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto out;
119346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck	case DCB_CMD_GCAP:
119446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq,
119546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		                   nlh->nlmsg_flags);
119646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck		goto out;
119733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	case DCB_CMD_GNUMTCS:
119833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
119933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		                      nlh->nlmsg_flags);
120033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto out;
120133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck	case DCB_CMD_SNUMTCS:
120233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
120333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		                      nlh->nlmsg_flags);
120433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck		goto out;
12050eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	case DCB_CMD_PFC_GSTATE:
12060eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		ret = dcbnl_getpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
12070eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		                        nlh->nlmsg_flags);
12080eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		goto out;
12090eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck	case DCB_CMD_PFC_SSTATE:
12100eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
12110eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		                        nlh->nlmsg_flags);
12120eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck		goto out;
1213859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck	case DCB_CMD_BCN_SCFG:
1214859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
1215859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		                       nlh->nlmsg_flags);
1216859ee3c43812051e21816c6d6d4cc04fb7ce9b2eAlexander Duyck		goto out;
1217579496865cf4ea429146382d62047ffdbaab0deeYi Zou	case DCB_CMD_GAPP:
1218579496865cf4ea429146382d62047ffdbaab0deeYi Zou		ret = dcbnl_getapp(netdev, tb, pid, nlh->nlmsg_seq,
1219579496865cf4ea429146382d62047ffdbaab0deeYi Zou		                   nlh->nlmsg_flags);
1220579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
1221579496865cf4ea429146382d62047ffdbaab0deeYi Zou	case DCB_CMD_SAPP:
1222579496865cf4ea429146382d62047ffdbaab0deeYi Zou		ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq,
1223579496865cf4ea429146382d62047ffdbaab0deeYi Zou		                   nlh->nlmsg_flags);
1224579496865cf4ea429146382d62047ffdbaab0deeYi Zou		goto out;
12252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	default:
12262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck		goto errout;
12272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	}
12282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerrout:
12292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	ret = -EINVAL;
12302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckout:
12312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	dev_put(netdev);
12322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return ret;
12332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
12342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
12352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __init dcbnl_init(void)
12362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
12372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL);
12382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL);
12392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
12402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	return 0;
12412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
12422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_init(dcbnl_init);
12432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
12442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic void __exit dcbnl_exit(void)
12452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{
12462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_unregister(PF_UNSPEC, RTM_GETDCB);
12472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck	rtnl_unregister(PF_UNSPEC, RTM_SETDCB);
12482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}
12492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_exit(dcbnl_exit);
12502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
12512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck
1252