dcbnl.c revision 0eb3aa9bab20217fb42244ccdcb5bf8a002f504c
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>"); 512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander DuyckMODULE_DESCRIPTION("Data Center Bridging generic netlink interface"); 522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander DuyckMODULE_LICENSE("GPL"); 532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/**************** DCB attribute policies *************************************/ 552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB netlink attributes policy */ 572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { 582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_ATTR_IFNAME] = {.type = NLA_STRING, .len = IFNAMSIZ - 1}, 592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_ATTR_STATE] = {.type = NLA_U8}, 602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_ATTR_PFC_CFG] = {.type = NLA_NESTED}, 612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED}, 622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_ATTR_SET_ALL] = {.type = NLA_U8}, 632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG}, 6446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck [DCB_ATTR_CAP] = {.type = NLA_NESTED}, 650eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck [DCB_ATTR_PFC_STATE] = {.type = NLA_U8}, 662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}; 672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB priority flow control to User Priority nested attributes */ 692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = { 702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PFC_UP_ATTR_0] = {.type = NLA_U8}, 712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PFC_UP_ATTR_1] = {.type = NLA_U8}, 722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PFC_UP_ATTR_2] = {.type = NLA_U8}, 732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PFC_UP_ATTR_3] = {.type = NLA_U8}, 742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PFC_UP_ATTR_4] = {.type = NLA_U8}, 752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PFC_UP_ATTR_5] = {.type = NLA_U8}, 762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PFC_UP_ATTR_6] = {.type = NLA_U8}, 772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PFC_UP_ATTR_7] = {.type = NLA_U8}, 782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PFC_UP_ATTR_ALL] = {.type = NLA_FLAG}, 792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}; 802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB priority grouping nested attributes */ 822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = { 832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_TC_0] = {.type = NLA_NESTED}, 842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_TC_1] = {.type = NLA_NESTED}, 852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_TC_2] = {.type = NLA_NESTED}, 862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_TC_3] = {.type = NLA_NESTED}, 872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_TC_4] = {.type = NLA_NESTED}, 882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_TC_5] = {.type = NLA_NESTED}, 892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_TC_6] = {.type = NLA_NESTED}, 902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_TC_7] = {.type = NLA_NESTED}, 912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_TC_ALL] = {.type = NLA_NESTED}, 922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_BW_ID_0] = {.type = NLA_U8}, 932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_BW_ID_1] = {.type = NLA_U8}, 942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_BW_ID_2] = {.type = NLA_U8}, 952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_BW_ID_3] = {.type = NLA_U8}, 962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_BW_ID_4] = {.type = NLA_U8}, 972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_BW_ID_5] = {.type = NLA_U8}, 982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_BW_ID_6] = {.type = NLA_U8}, 992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_BW_ID_7] = {.type = NLA_U8}, 1002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_PG_ATTR_BW_ID_ALL] = {.type = NLA_FLAG}, 1012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}; 1022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* DCB traffic class nested attributes. */ 1042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = { 1052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_TC_ATTR_PARAM_PGID] = {.type = NLA_U8}, 1062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_TC_ATTR_PARAM_UP_MAPPING] = {.type = NLA_U8}, 1072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_TC_ATTR_PARAM_STRICT_PRIO] = {.type = NLA_U8}, 1082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_TC_ATTR_PARAM_BW_PCT] = {.type = NLA_U8}, 1092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck [DCB_TC_ATTR_PARAM_ALL] = {.type = NLA_FLAG}, 1102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck}; 1112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 11246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck/* DCB capabilities nested attributes. */ 11346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckstatic struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = { 11446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck [DCB_CAP_ATTR_ALL] = {.type = NLA_FLAG}, 11546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck [DCB_CAP_ATTR_PG] = {.type = NLA_U8}, 11646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck [DCB_CAP_ATTR_PFC] = {.type = NLA_U8}, 11746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck [DCB_CAP_ATTR_UP2TC] = {.type = NLA_U8}, 11846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck [DCB_CAP_ATTR_PG_TCS] = {.type = NLA_U8}, 11946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck [DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8}, 12046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck [DCB_CAP_ATTR_GSP] = {.type = NLA_U8}, 12146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck [DCB_CAP_ATTR_BCN] = {.type = NLA_U8}, 12246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck}; 1232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 12433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck/* DCB capabilities nested attributes. */ 12533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckstatic struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = { 12633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck [DCB_NUMTCS_ATTR_ALL] = {.type = NLA_FLAG}, 12733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck [DCB_NUMTCS_ATTR_PG] = {.type = NLA_U8}, 12833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck [DCB_NUMTCS_ATTR_PFC] = {.type = NLA_U8}, 12933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck}; 13033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 1312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck/* standard netlink reply call */ 1322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, 1332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 seq, u16 flags) 1342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 1352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct sk_buff *dcbnl_skb; 1362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct dcbmsg *dcb; 1372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct nlmsghdr *nlh; 1382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int ret = -EINVAL; 1392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!dcbnl_skb) 1422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 1432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags); 1452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcb = NLMSG_DATA(nlh); 1472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcb->dcb_family = AF_UNSPEC; 1482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcb->cmd = cmd; 1492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcb->dcb_pad = 0; 1502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_put_u8(dcbnl_skb, attr, value); 1522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 1532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err; 1542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck /* end the message, assign the nlmsg_len. */ 1562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlmsg_end(dcbnl_skb, nlh); 1572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 1582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 1592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err; 1602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return 0; 1622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure: 1632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr: 1642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck kfree(dcbnl_skb); 1652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 1662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 1672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getstate(struct net_device *netdev, struct nlattr **tb, 1692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 pid, u32 seq, u16 flags) 1702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 1712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int ret = -EINVAL; 1722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck /* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */ 1742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!netdev->dcbnl_ops->getstate) 1752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 1762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_reply(netdev->dcbnl_ops->getstate(netdev), RTM_GETDCB, 1782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck DCB_CMD_GSTATE, DCB_ATTR_STATE, pid, seq, flags); 1792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 1812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 1822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb, 1842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 pid, u32 seq, u16 flags) 1852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 1862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct sk_buff *dcbnl_skb; 1872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct nlmsghdr *nlh; 1882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct dcbmsg *dcb; 1892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest; 1902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u8 value; 1912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int ret = -EINVAL; 1922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int i; 1932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int getall = 0; 1942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->getpfccfg) 1962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 1972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 1982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, 1992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck tb[DCB_ATTR_PFC_CFG], 2002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcbnl_pfc_up_nest); 2012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 2022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err_out; 2032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!dcbnl_skb) 2062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err_out; 2072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 2092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcb = NLMSG_DATA(nlh); 2112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcb->dcb_family = AF_UNSPEC; 2122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcb->cmd = DCB_CMD_PFC_GCFG; 2132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG); 2152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!nest) 2162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err; 2172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (data[DCB_PFC_UP_ATTR_ALL]) 2192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck getall = 1; 2202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { 2222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!getall && !data[i]) 2232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck continue; 2242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, 2262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck &value); 2272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_put_u8(dcbnl_skb, i, value); 2282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) { 2302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nla_nest_cancel(dcbnl_skb, nest); 2312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err; 2322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 2332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 2342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nla_nest_end(dcbnl_skb, nest); 2352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlmsg_end(dcbnl_skb, nlh); 2372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 2392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 2402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err; 2412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return 0; 2432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure: 2442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr: 2452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck kfree(dcbnl_skb); 2462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out: 2472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return -EINVAL; 2482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 2492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb, 2512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 pid, u32 seq, u16 flags) 2522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 2532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct sk_buff *dcbnl_skb; 2542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct nlmsghdr *nlh; 2552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct dcbmsg *dcb; 2562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u8 perm_addr[MAX_ADDR_LEN]; 2572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int ret = -EINVAL; 2582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!netdev->dcbnl_ops->getpermhwaddr) 2602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 2612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!dcbnl_skb) 2642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err_out; 2652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 2672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcb = NLMSG_DATA(nlh); 2692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcb->dcb_family = AF_UNSPEC; 2702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcb->cmd = DCB_CMD_GPERM_HWADDR; 2712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr); 2732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), 2752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck perm_addr); 2762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlmsg_end(dcbnl_skb, nlh); 2782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 2802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 2812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err; 2822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return 0; 2842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 2852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure: 2862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr: 2872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck kfree(dcbnl_skb); 2882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out: 2892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return -EINVAL; 2902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 2912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 29246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckstatic int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb, 29346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck u32 pid, u32 seq, u16 flags) 29446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck{ 29546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck struct sk_buff *dcbnl_skb; 29646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck struct nlmsghdr *nlh; 29746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck struct dcbmsg *dcb; 29846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest; 29946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck u8 value; 30046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck int ret = -EINVAL; 30146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck int i; 30246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck int getall = 0; 30346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 30446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap) 30546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck return ret; 30646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 30746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP], 30846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck dcbnl_cap_nest); 30946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck if (ret) 31046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck goto err_out; 31146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 31246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 31346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck if (!dcbnl_skb) 31446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck goto err_out; 31546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 31646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 31746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 31846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck dcb = NLMSG_DATA(nlh); 31946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck dcb->dcb_family = AF_UNSPEC; 32046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck dcb->cmd = DCB_CMD_GCAP; 32146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 32246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP); 32346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck if (!nest) 32446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck goto err; 32546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 32646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck if (data[DCB_CAP_ATTR_ALL]) 32746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck getall = 1; 32846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 32946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) { 33046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck if (!getall && !data[i]) 33146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck continue; 33246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 33346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) { 33446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck ret = nla_put_u8(dcbnl_skb, i, value); 33546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 33646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck if (ret) { 33746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck nla_nest_cancel(dcbnl_skb, nest); 33846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck goto err; 33946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck } 34046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck } 34146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck } 34246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck nla_nest_end(dcbnl_skb, nest); 34346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 34446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck nlmsg_end(dcbnl_skb, nlh); 34546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 34646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 34746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck if (ret) 34846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck goto err; 34946132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 35046132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck return 0; 35146132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duycknlmsg_failure: 35246132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckerr: 35346132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck kfree(dcbnl_skb); 35446132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyckerr_out: 35546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck return -EINVAL; 35646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck} 35746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck 35833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckstatic int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb, 35933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck u32 pid, u32 seq, u16 flags) 36033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{ 36133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck struct sk_buff *dcbnl_skb; 36233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck struct nlmsghdr *nlh; 36333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck struct dcbmsg *dcb; 36433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest; 36533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck u8 value; 36633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck int ret = -EINVAL; 36733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck int i; 36833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck int getall = 0; 36933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 37033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs) 37133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck return ret; 37233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 37333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], 37433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck dcbnl_numtcs_nest); 37533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck if (ret) { 37633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = -EINVAL; 37733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck goto err_out; 37833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck } 37933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 38033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 38133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck if (!dcbnl_skb) { 38233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = -EINVAL; 38333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck goto err_out; 38433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck } 38533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 38633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 38733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 38833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck dcb = NLMSG_DATA(nlh); 38933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck dcb->dcb_family = AF_UNSPEC; 39033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck dcb->cmd = DCB_CMD_GNUMTCS; 39133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 39233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS); 39333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck if (!nest) { 39433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = -EINVAL; 39533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck goto err; 39633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck } 39733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 39833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck if (data[DCB_NUMTCS_ATTR_ALL]) 39933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck getall = 1; 40033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 40133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { 40233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck if (!getall && !data[i]) 40333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck continue; 40433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 40533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value); 40633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck if (!ret) { 40733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = nla_put_u8(dcbnl_skb, i, value); 40833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 40933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck if (ret) { 41033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck nla_nest_cancel(dcbnl_skb, nest); 41133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = -EINVAL; 41233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck goto err; 41333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck } 41433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck } else { 41533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck goto err; 41633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck } 41733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck } 41833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck nla_nest_end(dcbnl_skb, nest); 41933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 42033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck nlmsg_end(dcbnl_skb, nlh); 42133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 42233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 42333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck if (ret) { 42433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = -EINVAL; 42533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck goto err; 42633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck } 42733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 42833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck return 0; 42933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duycknlmsg_failure: 43033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr: 43133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck kfree(dcbnl_skb); 43233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr_out: 43333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck return ret; 43433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck} 43533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 43633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckstatic int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb, 43733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck u32 pid, u32 seq, u16 flags) 43833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck{ 43933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1]; 44033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck int ret = -EINVAL; 44133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck u8 value; 44233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck int i; 44333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 44433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setstate) 44533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck return ret; 44633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 44733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], 44833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck dcbnl_numtcs_nest); 44933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 45033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck if (ret) { 45133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = -EINVAL; 45233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck goto err; 45333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck } 45433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 45533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { 45633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck if (data[i] == NULL) 45733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck continue; 45833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 45933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck value = nla_get_u8(data[i]); 46033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 46133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value); 46233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 46333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck if (ret) 46433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck goto operr; 46533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck } 46633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 46733dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckoperr: 46833dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS, 46933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck DCB_ATTR_NUMTCS, pid, seq, flags); 47033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 47133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyckerr: 47233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck return ret; 47333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck} 47433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck 4750eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyckstatic int dcbnl_getpfcstate(struct net_device *netdev, struct nlattr **tb, 4760eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck u32 pid, u32 seq, u16 flags) 4770eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{ 4780eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck int ret = -EINVAL; 4790eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck 4800eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck if (!netdev->dcbnl_ops->getpfcstate) 4810eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck return ret; 4820eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck 4830eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck ret = dcbnl_reply(netdev->dcbnl_ops->getpfcstate(netdev), RTM_GETDCB, 4840eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck DCB_CMD_PFC_GSTATE, DCB_ATTR_PFC_STATE, 4850eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck pid, seq, flags); 4860eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck 4870eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck return ret; 4880eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck} 4890eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck 4900eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyckstatic int dcbnl_setpfcstate(struct net_device *netdev, struct nlattr **tb, 4910eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck u32 pid, u32 seq, u16 flags) 4920eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck{ 4930eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck int ret = -EINVAL; 4940eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck u8 value; 4950eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck 4960eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck if (!tb[DCB_ATTR_PFC_STATE] || !netdev->dcbnl_ops->setpfcstate) 4970eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck return ret; 4980eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck 4990eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]); 5000eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck 5010eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck netdev->dcbnl_ops->setpfcstate(netdev, value); 5020eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck 5030eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SSTATE, DCB_ATTR_PFC_STATE, 5040eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck pid, seq, flags); 5050eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck 5060eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck return ret; 5070eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck} 5080eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck 5092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, 5102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 pid, u32 seq, u16 flags, int dir) 5112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 5122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct sk_buff *dcbnl_skb; 5132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct nlmsghdr *nlh; 5142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct dcbmsg *dcb; 5152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct nlattr *pg_nest, *param_nest, *data; 5162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; 5172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; 5182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u8 prio, pgid, tc_pct, up_map; 5192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int ret = -EINVAL; 5202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int getall = 0; 5212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int i; 5222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!tb[DCB_ATTR_PG_CFG] || 5242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck !netdev->dcbnl_ops->getpgtccfgtx || 5252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck !netdev->dcbnl_ops->getpgtccfgrx || 5262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck !netdev->dcbnl_ops->getpgbwgcfgtx || 5272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck !netdev->dcbnl_ops->getpgbwgcfgrx) 5282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 5292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, 5312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest); 5322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 5342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err_out; 5352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 5372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!dcbnl_skb) 5382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err_out; 5392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 5412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcb = NLMSG_DATA(nlh); 5432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcb->dcb_family = AF_UNSPEC; 5442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcb->cmd = (dir) ? DCB_CMD_PGRX_GCFG : DCB_CMD_PGTX_GCFG; 5452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck pg_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PG_CFG); 5472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!pg_nest) 5482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err; 5492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (pg_tb[DCB_PG_ATTR_TC_ALL]) 5512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck getall = 1; 5522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { 5542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!getall && !pg_tb[i]) 5552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck continue; 5562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (pg_tb[DCB_PG_ATTR_TC_ALL]) 5582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck data = pg_tb[DCB_PG_ATTR_TC_ALL]; 5592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck else 5602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck data = pg_tb[i]; 5612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX, 5622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck data, dcbnl_tc_param_nest); 5632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 5642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err_pg; 5652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck param_nest = nla_nest_start(dcbnl_skb, i); 5672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!param_nest) 5682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err_pg; 5692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck pgid = DCB_ATTR_VALUE_UNDEFINED; 5712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck prio = DCB_ATTR_VALUE_UNDEFINED; 5722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck tc_pct = DCB_ATTR_VALUE_UNDEFINED; 5732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck up_map = DCB_ATTR_VALUE_UNDEFINED; 5742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (dir) { 5762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck /* Rx */ 5772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck netdev->dcbnl_ops->getpgtccfgrx(netdev, 5782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck i - DCB_PG_ATTR_TC_0, &prio, 5792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck &pgid, &tc_pct, &up_map); 5802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } else { 5812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck /* Tx */ 5822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck netdev->dcbnl_ops->getpgtccfgtx(netdev, 5832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck i - DCB_PG_ATTR_TC_0, &prio, 5842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck &pgid, &tc_pct, &up_map); 5852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 5862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 5872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_PGID] || 5882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck param_tb[DCB_TC_ATTR_PARAM_ALL]) { 5892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_put_u8(dcbnl_skb, 5902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck DCB_TC_ATTR_PARAM_PGID, pgid); 5912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 5922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err_param; 5932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 5942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] || 5952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck param_tb[DCB_TC_ATTR_PARAM_ALL]) { 5962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_put_u8(dcbnl_skb, 5972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck DCB_TC_ATTR_PARAM_UP_MAPPING, up_map); 5982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 5992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err_param; 6002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 6012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] || 6022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck param_tb[DCB_TC_ATTR_PARAM_ALL]) { 6032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_put_u8(dcbnl_skb, 6042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck DCB_TC_ATTR_PARAM_STRICT_PRIO, prio); 6052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 6062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err_param; 6072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 6082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] || 6092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck param_tb[DCB_TC_ATTR_PARAM_ALL]) { 6102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_BW_PCT, 6112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck tc_pct); 6122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 6132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err_param; 6142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 6152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nla_nest_end(dcbnl_skb, param_nest); 6162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 6172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (pg_tb[DCB_PG_ATTR_BW_ID_ALL]) 6192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck getall = 1; 6202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck else 6212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck getall = 0; 6222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) { 6242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!getall && !pg_tb[i]) 6252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck continue; 6262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck tc_pct = DCB_ATTR_VALUE_UNDEFINED; 6282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (dir) { 6302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck /* Rx */ 6312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck netdev->dcbnl_ops->getpgbwgcfgrx(netdev, 6322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck i - DCB_PG_ATTR_BW_ID_0, &tc_pct); 6332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } else { 6342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck /* Tx */ 6352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck netdev->dcbnl_ops->getpgbwgcfgtx(netdev, 6362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck i - DCB_PG_ATTR_BW_ID_0, &tc_pct); 6372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 6382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_put_u8(dcbnl_skb, i, tc_pct); 6392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 6412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err_pg; 6422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 6432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nla_nest_end(dcbnl_skb, pg_nest); 6452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlmsg_end(dcbnl_skb, nlh); 6472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 6492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 6502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err; 6512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return 0; 6532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_param: 6552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nla_nest_cancel(dcbnl_skb, param_nest); 6562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_pg: 6572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nla_nest_cancel(dcbnl_skb, pg_nest); 6582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duycknlmsg_failure: 6592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr: 6602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck kfree(dcbnl_skb); 6612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr_out: 6622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = -EINVAL; 6632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 6642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 6652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlattr **tb, 6672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 pid, u32 seq, u16 flags) 6682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 6692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 0); 6702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 6712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlattr **tb, 6732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 pid, u32 seq, u16 flags) 6742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 6752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 1); 6762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 6772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb, 6792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 pid, u32 seq, u16 flags) 6802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 6812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int ret = -EINVAL; 6822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u8 value; 6832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate) 6852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 6862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck value = nla_get_u8(tb[DCB_ATTR_STATE]); 6882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck netdev->dcbnl_ops->setstate(netdev, value); 6902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE, 6922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck pid, seq, flags); 6932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 6952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 6962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 6972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb, 6982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 pid, u32 seq, u16 flags) 6992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 7002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1]; 7012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int i; 7022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int ret = -EINVAL; 7032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u8 value; 7042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->setpfccfg) 7062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 7072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, 7092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck tb[DCB_ATTR_PFC_CFG], 7102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcbnl_pfc_up_nest); 7112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 7122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err; 7132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { 7152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (data[i] == NULL) 7162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck continue; 7172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck value = nla_get_u8(data[i]); 7182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck netdev->dcbnl_ops->setpfccfg(netdev, 7192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck data[i]->nla_type - DCB_PFC_UP_ATTR_0, value); 7202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 7212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SCFG, DCB_ATTR_PFC_CFG, 7232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck pid, seq, flags); 7242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr: 7252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 7262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 7272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_setall(struct net_device *netdev, struct nlattr **tb, 7292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 pid, u32 seq, u16 flags) 7302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 7312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int ret = -EINVAL; 7322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall) 7342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 7352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_reply(netdev->dcbnl_ops->setall(netdev), RTM_SETDCB, 7372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck DCB_CMD_SET_ALL, DCB_ATTR_SET_ALL, pid, seq, flags); 7382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 7402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 7412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb, 7432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 pid, u32 seq, u16 flags, int dir) 7442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 7452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; 7462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; 7472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int ret = -EINVAL; 7482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int i; 7492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u8 pgid; 7502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u8 up_map; 7512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u8 prio; 7522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u8 tc_pct; 7532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!tb[DCB_ATTR_PG_CFG] || 7552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck !netdev->dcbnl_ops->setpgtccfgtx || 7562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck !netdev->dcbnl_ops->setpgtccfgrx || 7572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck !netdev->dcbnl_ops->setpgbwgcfgtx || 7582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck !netdev->dcbnl_ops->setpgbwgcfgrx) 7592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 7602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, 7622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest); 7632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 7642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err; 7652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { 7672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!pg_tb[i]) 7682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck continue; 7692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX, 7712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck pg_tb[i], dcbnl_tc_param_nest); 7722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret) 7732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto err; 7742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck pgid = DCB_ATTR_VALUE_UNDEFINED; 7762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck prio = DCB_ATTR_VALUE_UNDEFINED; 7772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck tc_pct = DCB_ATTR_VALUE_UNDEFINED; 7782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck up_map = DCB_ATTR_VALUE_UNDEFINED; 7792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]) 7812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck prio = 7822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]); 7832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_PGID]) 7852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]); 7862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT]) 7882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]); 7892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]) 7912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck up_map = 7922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]); 7932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 7942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck /* dir: Tx = 0, Rx = 1 */ 7952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (dir) { 7962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck /* Rx */ 7972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck netdev->dcbnl_ops->setpgtccfgrx(netdev, 7982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck i - DCB_PG_ATTR_TC_0, 7992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck prio, pgid, tc_pct, up_map); 8002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } else { 8012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck /* Tx */ 8022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck netdev->dcbnl_ops->setpgtccfgtx(netdev, 8032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck i - DCB_PG_ATTR_TC_0, 8042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck prio, pgid, tc_pct, up_map); 8052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 8062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 8072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) { 8092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!pg_tb[i]) 8102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck continue; 8112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck tc_pct = nla_get_u8(pg_tb[i]); 8132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck /* dir: Tx = 0, Rx = 1 */ 8152f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (dir) { 8162f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck /* Rx */ 8172f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck netdev->dcbnl_ops->setpgbwgcfgrx(netdev, 8182f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck i - DCB_PG_ATTR_BW_ID_0, tc_pct); 8192f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } else { 8202f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck /* Tx */ 8212f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck netdev->dcbnl_ops->setpgbwgcfgtx(netdev, 8222f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck i - DCB_PG_ATTR_BW_ID_0, tc_pct); 8232f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 8242f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 8252f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8262f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_reply(0, RTM_SETDCB, 8272f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG), 8282f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck DCB_ATTR_PG_CFG, pid, seq, flags); 8292f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8302f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerr: 8312f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 8322f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 8332f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8342f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlattr **tb, 8352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 pid, u32 seq, u16 flags) 8362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 8372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 0); 8382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 8392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb, 8412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 pid, u32 seq, u16 flags) 8422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 8432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1); 8442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 8452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 8472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 8482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct net *net = sock_net(skb->sk); 8492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct net_device *netdev; 8502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct dcbmsg *dcb = (struct dcbmsg *)NLMSG_DATA(nlh); 8512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck struct nlattr *tb[DCB_ATTR_MAX + 1]; 8522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck u32 pid = skb ? NETLINK_CB(skb).pid : 0; 8532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck int ret = -EINVAL; 8542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (net != &init_net) 8562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return -EINVAL; 8572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX, 8592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dcbnl_rtnl_policy); 8602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (ret < 0) 8612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 8622f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8632f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!tb[DCB_ATTR_IFNAME]) 8642f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return -EINVAL; 8652f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8662f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME])); 8672f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!netdev) 8682f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return -EINVAL; 8692f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8702f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck if (!netdev->dcbnl_ops) 8712f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto errout; 8722f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 8732f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck switch (dcb->cmd) { 8742f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck case DCB_CMD_GSTATE: 8752f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq, 8762f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh->nlmsg_flags); 8772f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto out; 8782f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck case DCB_CMD_PFC_GCFG: 8792f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq, 8802f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh->nlmsg_flags); 8812f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto out; 8822f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck case DCB_CMD_GPERM_HWADDR: 8832f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq, 8842f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh->nlmsg_flags); 8852f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto out; 8862f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck case DCB_CMD_PGTX_GCFG: 8872f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq, 8882f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh->nlmsg_flags); 8892f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto out; 8902f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck case DCB_CMD_PGRX_GCFG: 8912f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq, 8922f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh->nlmsg_flags); 8932f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto out; 8942f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck case DCB_CMD_SSTATE: 8952f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq, 8962f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh->nlmsg_flags); 8972f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto out; 8982f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck case DCB_CMD_PFC_SCFG: 8992f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq, 9002f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh->nlmsg_flags); 9012f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto out; 9022f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 9032f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck case DCB_CMD_SET_ALL: 9042f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq, 9052f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh->nlmsg_flags); 9062f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto out; 9072f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck case DCB_CMD_PGTX_SCFG: 9082f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, 9092f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh->nlmsg_flags); 9102f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto out; 9112f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck case DCB_CMD_PGRX_SCFG: 9122f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, 9132f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck nlh->nlmsg_flags); 9142f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto out; 91546132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck case DCB_CMD_GCAP: 91646132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq, 91746132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck nlh->nlmsg_flags); 91846132188bf72e22ef097f16ed5c969ee8cea1e8bAlexander Duyck goto out; 91933dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck case DCB_CMD_GNUMTCS: 92033dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq, 92133dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck nlh->nlmsg_flags); 92233dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck goto out; 92333dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck case DCB_CMD_SNUMTCS: 92433dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq, 92533dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck nlh->nlmsg_flags); 92633dbabc4a7f7bd72313c73a3c199f31f3900336fAlexander Duyck goto out; 9270eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck case DCB_CMD_PFC_GSTATE: 9280eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck ret = dcbnl_getpfcstate(netdev, tb, pid, nlh->nlmsg_seq, 9290eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck nlh->nlmsg_flags); 9300eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck goto out; 9310eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck case DCB_CMD_PFC_SSTATE: 9320eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq, 9330eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck nlh->nlmsg_flags); 9340eb3aa9bab20217fb42244ccdcb5bf8a002f504cAlexander Duyck goto out; 9352f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck default: 9362f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck goto errout; 9372f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck } 9382f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckerrout: 9392f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck ret = -EINVAL; 9402f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckout: 9412f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck dev_put(netdev); 9422f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return ret; 9432f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 9442f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 9452f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic int __init dcbnl_init(void) 9462f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 9472f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL); 9482f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL); 9492f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 9502f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck return 0; 9512f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 9522f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_init(dcbnl_init); 9532f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 9542f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckstatic void __exit dcbnl_exit(void) 9552f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck{ 9562f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck rtnl_unregister(PF_UNSPEC, RTM_GETDCB); 9572f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck rtnl_unregister(PF_UNSPEC, RTM_SETDCB); 9582f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck} 9592f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyckmodule_exit(dcbnl_exit); 9602f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 9612f90b8657ec942d1880f720e0177ee71df7c8e3cAlexander Duyck 962