12f90b865SAlexander Duyck /* 22f90b865SAlexander Duyck * Copyright (c) 2008, Intel Corporation. 32f90b865SAlexander Duyck * 42f90b865SAlexander Duyck * This program is free software; you can redistribute it and/or modify it 52f90b865SAlexander Duyck * under the terms and conditions of the GNU General Public License, 62f90b865SAlexander Duyck * version 2, as published by the Free Software Foundation. 72f90b865SAlexander Duyck * 82f90b865SAlexander Duyck * This program is distributed in the hope it will be useful, but WITHOUT 92f90b865SAlexander Duyck * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 102f90b865SAlexander Duyck * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 112f90b865SAlexander Duyck * more details. 122f90b865SAlexander Duyck * 132f90b865SAlexander Duyck * You should have received a copy of the GNU General Public License along with 142f90b865SAlexander Duyck * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 152f90b865SAlexander Duyck * Place - Suite 330, Boston, MA 02111-1307 USA. 162f90b865SAlexander Duyck * 172f90b865SAlexander Duyck * Author: Lucy Liu <lucy.liu@intel.com> 182f90b865SAlexander Duyck */ 192f90b865SAlexander Duyck 202f90b865SAlexander Duyck #include <linux/netdevice.h> 212f90b865SAlexander Duyck #include <linux/netlink.h> 225a0e3ad6STejun Heo #include <linux/slab.h> 232f90b865SAlexander Duyck #include <net/netlink.h> 242f90b865SAlexander Duyck #include <net/rtnetlink.h> 252f90b865SAlexander Duyck #include <linux/dcbnl.h> 262f90b865SAlexander Duyck #include <linux/rtnetlink.h> 272f90b865SAlexander Duyck #include <net/sock.h> 282f90b865SAlexander Duyck 292f90b865SAlexander Duyck /** 302f90b865SAlexander Duyck * Data Center Bridging (DCB) is a collection of Ethernet enhancements 312f90b865SAlexander Duyck * intended to allow network traffic with differing requirements 322f90b865SAlexander Duyck * (highly reliable, no drops vs. best effort vs. low latency) to operate 332f90b865SAlexander Duyck * and co-exist on Ethernet. Current DCB features are: 342f90b865SAlexander Duyck * 352f90b865SAlexander Duyck * Enhanced Transmission Selection (aka Priority Grouping [PG]) - provides a 362f90b865SAlexander Duyck * framework for assigning bandwidth guarantees to traffic classes. 372f90b865SAlexander Duyck * 382f90b865SAlexander Duyck * Priority-based Flow Control (PFC) - provides a flow control mechanism which 392f90b865SAlexander Duyck * can work independently for each 802.1p priority. 402f90b865SAlexander Duyck * 412f90b865SAlexander Duyck * Congestion Notification - provides a mechanism for end-to-end congestion 422f90b865SAlexander Duyck * control for protocols which do not have built-in congestion management. 432f90b865SAlexander Duyck * 442f90b865SAlexander Duyck * More information about the emerging standards for these Ethernet features 452f90b865SAlexander Duyck * can be found at: http://www.ieee802.org/1/pages/dcbridges.html 462f90b865SAlexander Duyck * 472f90b865SAlexander Duyck * This file implements an rtnetlink interface to allow configuration of DCB 482f90b865SAlexander Duyck * features for capable devices. 492f90b865SAlexander Duyck */ 502f90b865SAlexander Duyck 512f90b865SAlexander Duyck MODULE_AUTHOR("Lucy Liu, <lucy.liu@intel.com>"); 527a6b6f51SJeff Kirsher MODULE_DESCRIPTION("Data Center Bridging netlink interface"); 532f90b865SAlexander Duyck MODULE_LICENSE("GPL"); 542f90b865SAlexander Duyck 552f90b865SAlexander Duyck /**************** DCB attribute policies *************************************/ 562f90b865SAlexander Duyck 572f90b865SAlexander Duyck /* DCB netlink attributes policy */ 58b54452b0SAlexey Dobriyan static const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { 59859ee3c4SAlexander Duyck [DCB_ATTR_IFNAME] = {.type = NLA_NUL_STRING, .len = IFNAMSIZ - 1}, 602f90b865SAlexander Duyck [DCB_ATTR_STATE] = {.type = NLA_U8}, 612f90b865SAlexander Duyck [DCB_ATTR_PFC_CFG] = {.type = NLA_NESTED}, 622f90b865SAlexander Duyck [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED}, 632f90b865SAlexander Duyck [DCB_ATTR_SET_ALL] = {.type = NLA_U8}, 642f90b865SAlexander Duyck [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG}, 6546132188SAlexander Duyck [DCB_ATTR_CAP] = {.type = NLA_NESTED}, 660eb3aa9bSAlexander Duyck [DCB_ATTR_PFC_STATE] = {.type = NLA_U8}, 67859ee3c4SAlexander Duyck [DCB_ATTR_BCN] = {.type = NLA_NESTED}, 686fa382afSYi Zou [DCB_ATTR_APP] = {.type = NLA_NESTED}, 693e29027aSJohn Fastabend [DCB_ATTR_IEEE] = {.type = NLA_NESTED}, 702f90b865SAlexander Duyck }; 712f90b865SAlexander Duyck 722f90b865SAlexander Duyck /* DCB priority flow control to User Priority nested attributes */ 73b54452b0SAlexey Dobriyan static const struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = { 742f90b865SAlexander Duyck [DCB_PFC_UP_ATTR_0] = {.type = NLA_U8}, 752f90b865SAlexander Duyck [DCB_PFC_UP_ATTR_1] = {.type = NLA_U8}, 762f90b865SAlexander Duyck [DCB_PFC_UP_ATTR_2] = {.type = NLA_U8}, 772f90b865SAlexander Duyck [DCB_PFC_UP_ATTR_3] = {.type = NLA_U8}, 782f90b865SAlexander Duyck [DCB_PFC_UP_ATTR_4] = {.type = NLA_U8}, 792f90b865SAlexander Duyck [DCB_PFC_UP_ATTR_5] = {.type = NLA_U8}, 802f90b865SAlexander Duyck [DCB_PFC_UP_ATTR_6] = {.type = NLA_U8}, 812f90b865SAlexander Duyck [DCB_PFC_UP_ATTR_7] = {.type = NLA_U8}, 822f90b865SAlexander Duyck [DCB_PFC_UP_ATTR_ALL] = {.type = NLA_FLAG}, 832f90b865SAlexander Duyck }; 842f90b865SAlexander Duyck 852f90b865SAlexander Duyck /* DCB priority grouping nested attributes */ 86b54452b0SAlexey Dobriyan static const struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = { 872f90b865SAlexander Duyck [DCB_PG_ATTR_TC_0] = {.type = NLA_NESTED}, 882f90b865SAlexander Duyck [DCB_PG_ATTR_TC_1] = {.type = NLA_NESTED}, 892f90b865SAlexander Duyck [DCB_PG_ATTR_TC_2] = {.type = NLA_NESTED}, 902f90b865SAlexander Duyck [DCB_PG_ATTR_TC_3] = {.type = NLA_NESTED}, 912f90b865SAlexander Duyck [DCB_PG_ATTR_TC_4] = {.type = NLA_NESTED}, 922f90b865SAlexander Duyck [DCB_PG_ATTR_TC_5] = {.type = NLA_NESTED}, 932f90b865SAlexander Duyck [DCB_PG_ATTR_TC_6] = {.type = NLA_NESTED}, 942f90b865SAlexander Duyck [DCB_PG_ATTR_TC_7] = {.type = NLA_NESTED}, 952f90b865SAlexander Duyck [DCB_PG_ATTR_TC_ALL] = {.type = NLA_NESTED}, 962f90b865SAlexander Duyck [DCB_PG_ATTR_BW_ID_0] = {.type = NLA_U8}, 972f90b865SAlexander Duyck [DCB_PG_ATTR_BW_ID_1] = {.type = NLA_U8}, 982f90b865SAlexander Duyck [DCB_PG_ATTR_BW_ID_2] = {.type = NLA_U8}, 992f90b865SAlexander Duyck [DCB_PG_ATTR_BW_ID_3] = {.type = NLA_U8}, 1002f90b865SAlexander Duyck [DCB_PG_ATTR_BW_ID_4] = {.type = NLA_U8}, 1012f90b865SAlexander Duyck [DCB_PG_ATTR_BW_ID_5] = {.type = NLA_U8}, 1022f90b865SAlexander Duyck [DCB_PG_ATTR_BW_ID_6] = {.type = NLA_U8}, 1032f90b865SAlexander Duyck [DCB_PG_ATTR_BW_ID_7] = {.type = NLA_U8}, 1042f90b865SAlexander Duyck [DCB_PG_ATTR_BW_ID_ALL] = {.type = NLA_FLAG}, 1052f90b865SAlexander Duyck }; 1062f90b865SAlexander Duyck 1072f90b865SAlexander Duyck /* DCB traffic class nested attributes. */ 108b54452b0SAlexey Dobriyan static const struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = { 1092f90b865SAlexander Duyck [DCB_TC_ATTR_PARAM_PGID] = {.type = NLA_U8}, 1102f90b865SAlexander Duyck [DCB_TC_ATTR_PARAM_UP_MAPPING] = {.type = NLA_U8}, 1112f90b865SAlexander Duyck [DCB_TC_ATTR_PARAM_STRICT_PRIO] = {.type = NLA_U8}, 1122f90b865SAlexander Duyck [DCB_TC_ATTR_PARAM_BW_PCT] = {.type = NLA_U8}, 1132f90b865SAlexander Duyck [DCB_TC_ATTR_PARAM_ALL] = {.type = NLA_FLAG}, 1142f90b865SAlexander Duyck }; 1152f90b865SAlexander Duyck 11646132188SAlexander Duyck /* DCB capabilities nested attributes. */ 117b54452b0SAlexey Dobriyan static const struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = { 11846132188SAlexander Duyck [DCB_CAP_ATTR_ALL] = {.type = NLA_FLAG}, 11946132188SAlexander Duyck [DCB_CAP_ATTR_PG] = {.type = NLA_U8}, 12046132188SAlexander Duyck [DCB_CAP_ATTR_PFC] = {.type = NLA_U8}, 12146132188SAlexander Duyck [DCB_CAP_ATTR_UP2TC] = {.type = NLA_U8}, 12246132188SAlexander Duyck [DCB_CAP_ATTR_PG_TCS] = {.type = NLA_U8}, 12346132188SAlexander Duyck [DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8}, 12446132188SAlexander Duyck [DCB_CAP_ATTR_GSP] = {.type = NLA_U8}, 12546132188SAlexander Duyck [DCB_CAP_ATTR_BCN] = {.type = NLA_U8}, 12646132188SAlexander Duyck }; 1272f90b865SAlexander Duyck 12833dbabc4SAlexander Duyck /* DCB capabilities nested attributes. */ 129b54452b0SAlexey Dobriyan static const struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = { 13033dbabc4SAlexander Duyck [DCB_NUMTCS_ATTR_ALL] = {.type = NLA_FLAG}, 13133dbabc4SAlexander Duyck [DCB_NUMTCS_ATTR_PG] = {.type = NLA_U8}, 13233dbabc4SAlexander Duyck [DCB_NUMTCS_ATTR_PFC] = {.type = NLA_U8}, 13333dbabc4SAlexander Duyck }; 13433dbabc4SAlexander Duyck 135859ee3c4SAlexander Duyck /* DCB BCN nested attributes. */ 136b54452b0SAlexey Dobriyan static const struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = { 137859ee3c4SAlexander Duyck [DCB_BCN_ATTR_RP_0] = {.type = NLA_U8}, 138859ee3c4SAlexander Duyck [DCB_BCN_ATTR_RP_1] = {.type = NLA_U8}, 139859ee3c4SAlexander Duyck [DCB_BCN_ATTR_RP_2] = {.type = NLA_U8}, 140859ee3c4SAlexander Duyck [DCB_BCN_ATTR_RP_3] = {.type = NLA_U8}, 141859ee3c4SAlexander Duyck [DCB_BCN_ATTR_RP_4] = {.type = NLA_U8}, 142859ee3c4SAlexander Duyck [DCB_BCN_ATTR_RP_5] = {.type = NLA_U8}, 143859ee3c4SAlexander Duyck [DCB_BCN_ATTR_RP_6] = {.type = NLA_U8}, 144859ee3c4SAlexander Duyck [DCB_BCN_ATTR_RP_7] = {.type = NLA_U8}, 145859ee3c4SAlexander Duyck [DCB_BCN_ATTR_RP_ALL] = {.type = NLA_FLAG}, 146f4314e81SDon Skidmore [DCB_BCN_ATTR_BCNA_0] = {.type = NLA_U32}, 147f4314e81SDon Skidmore [DCB_BCN_ATTR_BCNA_1] = {.type = NLA_U32}, 148859ee3c4SAlexander Duyck [DCB_BCN_ATTR_ALPHA] = {.type = NLA_U32}, 149859ee3c4SAlexander Duyck [DCB_BCN_ATTR_BETA] = {.type = NLA_U32}, 150859ee3c4SAlexander Duyck [DCB_BCN_ATTR_GD] = {.type = NLA_U32}, 151859ee3c4SAlexander Duyck [DCB_BCN_ATTR_GI] = {.type = NLA_U32}, 152859ee3c4SAlexander Duyck [DCB_BCN_ATTR_TMAX] = {.type = NLA_U32}, 153859ee3c4SAlexander Duyck [DCB_BCN_ATTR_TD] = {.type = NLA_U32}, 154859ee3c4SAlexander Duyck [DCB_BCN_ATTR_RMIN] = {.type = NLA_U32}, 155859ee3c4SAlexander Duyck [DCB_BCN_ATTR_W] = {.type = NLA_U32}, 156859ee3c4SAlexander Duyck [DCB_BCN_ATTR_RD] = {.type = NLA_U32}, 157859ee3c4SAlexander Duyck [DCB_BCN_ATTR_RU] = {.type = NLA_U32}, 158859ee3c4SAlexander Duyck [DCB_BCN_ATTR_WRTT] = {.type = NLA_U32}, 159859ee3c4SAlexander Duyck [DCB_BCN_ATTR_RI] = {.type = NLA_U32}, 160859ee3c4SAlexander Duyck [DCB_BCN_ATTR_C] = {.type = NLA_U32}, 161859ee3c4SAlexander Duyck [DCB_BCN_ATTR_ALL] = {.type = NLA_FLAG}, 162859ee3c4SAlexander Duyck }; 163859ee3c4SAlexander Duyck 1646fa382afSYi Zou /* DCB APP nested attributes. */ 165b54452b0SAlexey Dobriyan static const struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = { 1666fa382afSYi Zou [DCB_APP_ATTR_IDTYPE] = {.type = NLA_U8}, 1676fa382afSYi Zou [DCB_APP_ATTR_ID] = {.type = NLA_U16}, 1686fa382afSYi Zou [DCB_APP_ATTR_PRIORITY] = {.type = NLA_U8}, 1696fa382afSYi Zou }; 1706fa382afSYi Zou 1713e29027aSJohn Fastabend /* IEEE 802.1Qaz nested attributes. */ 1723e29027aSJohn Fastabend static const struct nla_policy dcbnl_ieee_policy[DCB_ATTR_IEEE_MAX + 1] = { 1733e29027aSJohn Fastabend [DCB_ATTR_IEEE_ETS] = {.len = sizeof(struct ieee_ets)}, 1743e29027aSJohn Fastabend [DCB_ATTR_IEEE_PFC] = {.len = sizeof(struct ieee_pfc)}, 1753e29027aSJohn Fastabend [DCB_ATTR_IEEE_APP_TABLE] = {.type = NLA_NESTED}, 1763e29027aSJohn Fastabend }; 1773e29027aSJohn Fastabend 1783e29027aSJohn Fastabend static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = { 1793e29027aSJohn Fastabend [DCB_ATTR_IEEE_APP] = {.len = sizeof(struct dcb_app)}, 1803e29027aSJohn Fastabend }; 1813e29027aSJohn Fastabend 1822f90b865SAlexander Duyck /* standard netlink reply call */ 1832f90b865SAlexander Duyck static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, 1842f90b865SAlexander Duyck u32 seq, u16 flags) 1852f90b865SAlexander Duyck { 1862f90b865SAlexander Duyck struct sk_buff *dcbnl_skb; 1872f90b865SAlexander Duyck struct dcbmsg *dcb; 1882f90b865SAlexander Duyck struct nlmsghdr *nlh; 1892f90b865SAlexander Duyck int ret = -EINVAL; 1902f90b865SAlexander Duyck 1912f90b865SAlexander Duyck dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1922f90b865SAlexander Duyck if (!dcbnl_skb) 1932f90b865SAlexander Duyck return ret; 1942f90b865SAlexander Duyck 1952f90b865SAlexander Duyck nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags); 1962f90b865SAlexander Duyck 1972f90b865SAlexander Duyck dcb = NLMSG_DATA(nlh); 1982f90b865SAlexander Duyck dcb->dcb_family = AF_UNSPEC; 1992f90b865SAlexander Duyck dcb->cmd = cmd; 2002f90b865SAlexander Duyck dcb->dcb_pad = 0; 2012f90b865SAlexander Duyck 2022f90b865SAlexander Duyck ret = nla_put_u8(dcbnl_skb, attr, value); 2032f90b865SAlexander Duyck if (ret) 2042f90b865SAlexander Duyck goto err; 2052f90b865SAlexander Duyck 2062f90b865SAlexander Duyck /* end the message, assign the nlmsg_len. */ 2072f90b865SAlexander Duyck nlmsg_end(dcbnl_skb, nlh); 2082f90b865SAlexander Duyck ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 2092f90b865SAlexander Duyck if (ret) 2107eaf5077SJohn Fastabend return -EINVAL; 2112f90b865SAlexander Duyck 2122f90b865SAlexander Duyck return 0; 2132f90b865SAlexander Duyck nlmsg_failure: 2142f90b865SAlexander Duyck err: 215858eb711SRoel Kluin kfree_skb(dcbnl_skb); 2162f90b865SAlexander Duyck return ret; 2172f90b865SAlexander Duyck } 2182f90b865SAlexander Duyck 2192f90b865SAlexander Duyck static int dcbnl_getstate(struct net_device *netdev, struct nlattr **tb, 2202f90b865SAlexander Duyck u32 pid, u32 seq, u16 flags) 2212f90b865SAlexander Duyck { 2222f90b865SAlexander Duyck int ret = -EINVAL; 2232f90b865SAlexander Duyck 2242f90b865SAlexander Duyck /* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */ 2252f90b865SAlexander Duyck if (!netdev->dcbnl_ops->getstate) 2262f90b865SAlexander Duyck return ret; 2272f90b865SAlexander Duyck 2282f90b865SAlexander Duyck ret = dcbnl_reply(netdev->dcbnl_ops->getstate(netdev), RTM_GETDCB, 2292f90b865SAlexander Duyck DCB_CMD_GSTATE, DCB_ATTR_STATE, pid, seq, flags); 2302f90b865SAlexander Duyck 2312f90b865SAlexander Duyck return ret; 2322f90b865SAlexander Duyck } 2332f90b865SAlexander Duyck 2342f90b865SAlexander Duyck static int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb, 2352f90b865SAlexander Duyck u32 pid, u32 seq, u16 flags) 2362f90b865SAlexander Duyck { 2372f90b865SAlexander Duyck struct sk_buff *dcbnl_skb; 2382f90b865SAlexander Duyck struct nlmsghdr *nlh; 2392f90b865SAlexander Duyck struct dcbmsg *dcb; 2402f90b865SAlexander Duyck struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest; 2412f90b865SAlexander Duyck u8 value; 2422f90b865SAlexander Duyck int ret = -EINVAL; 2432f90b865SAlexander Duyck int i; 2442f90b865SAlexander Duyck int getall = 0; 2452f90b865SAlexander Duyck 2462f90b865SAlexander Duyck if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->getpfccfg) 2472f90b865SAlexander Duyck return ret; 2482f90b865SAlexander Duyck 2492f90b865SAlexander Duyck ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, 2502f90b865SAlexander Duyck tb[DCB_ATTR_PFC_CFG], 2512f90b865SAlexander Duyck dcbnl_pfc_up_nest); 2522f90b865SAlexander Duyck if (ret) 2532f90b865SAlexander Duyck goto err_out; 2542f90b865SAlexander Duyck 2552f90b865SAlexander Duyck dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2562f90b865SAlexander Duyck if (!dcbnl_skb) 2572f90b865SAlexander Duyck goto err_out; 2582f90b865SAlexander Duyck 2592f90b865SAlexander Duyck nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 2602f90b865SAlexander Duyck 2612f90b865SAlexander Duyck dcb = NLMSG_DATA(nlh); 2622f90b865SAlexander Duyck dcb->dcb_family = AF_UNSPEC; 2632f90b865SAlexander Duyck dcb->cmd = DCB_CMD_PFC_GCFG; 2642f90b865SAlexander Duyck 2652f90b865SAlexander Duyck nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG); 2662f90b865SAlexander Duyck if (!nest) 2672f90b865SAlexander Duyck goto err; 2682f90b865SAlexander Duyck 2692f90b865SAlexander Duyck if (data[DCB_PFC_UP_ATTR_ALL]) 2702f90b865SAlexander Duyck getall = 1; 2712f90b865SAlexander Duyck 2722f90b865SAlexander Duyck for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { 2732f90b865SAlexander Duyck if (!getall && !data[i]) 2742f90b865SAlexander Duyck continue; 2752f90b865SAlexander Duyck 2762f90b865SAlexander Duyck netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, 2772f90b865SAlexander Duyck &value); 2782f90b865SAlexander Duyck ret = nla_put_u8(dcbnl_skb, i, value); 2792f90b865SAlexander Duyck 2802f90b865SAlexander Duyck if (ret) { 2812f90b865SAlexander Duyck nla_nest_cancel(dcbnl_skb, nest); 2822f90b865SAlexander Duyck goto err; 2832f90b865SAlexander Duyck } 2842f90b865SAlexander Duyck } 2852f90b865SAlexander Duyck nla_nest_end(dcbnl_skb, nest); 2862f90b865SAlexander Duyck 2872f90b865SAlexander Duyck nlmsg_end(dcbnl_skb, nlh); 2882f90b865SAlexander Duyck 2892f90b865SAlexander Duyck ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 2902f90b865SAlexander Duyck if (ret) 2917eaf5077SJohn Fastabend goto err_out; 2922f90b865SAlexander Duyck 2932f90b865SAlexander Duyck return 0; 2942f90b865SAlexander Duyck nlmsg_failure: 2952f90b865SAlexander Duyck err: 296858eb711SRoel Kluin kfree_skb(dcbnl_skb); 2972f90b865SAlexander Duyck err_out: 2982f90b865SAlexander Duyck return -EINVAL; 2992f90b865SAlexander Duyck } 3002f90b865SAlexander Duyck 3012f90b865SAlexander Duyck static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb, 3022f90b865SAlexander Duyck u32 pid, u32 seq, u16 flags) 3032f90b865SAlexander Duyck { 3042f90b865SAlexander Duyck struct sk_buff *dcbnl_skb; 3052f90b865SAlexander Duyck struct nlmsghdr *nlh; 3062f90b865SAlexander Duyck struct dcbmsg *dcb; 3072f90b865SAlexander Duyck u8 perm_addr[MAX_ADDR_LEN]; 3082f90b865SAlexander Duyck int ret = -EINVAL; 3092f90b865SAlexander Duyck 3102f90b865SAlexander Duyck if (!netdev->dcbnl_ops->getpermhwaddr) 3112f90b865SAlexander Duyck return ret; 3122f90b865SAlexander Duyck 3132f90b865SAlexander Duyck dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3142f90b865SAlexander Duyck if (!dcbnl_skb) 3152f90b865SAlexander Duyck goto err_out; 3162f90b865SAlexander Duyck 3172f90b865SAlexander Duyck nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 3182f90b865SAlexander Duyck 3192f90b865SAlexander Duyck dcb = NLMSG_DATA(nlh); 3202f90b865SAlexander Duyck dcb->dcb_family = AF_UNSPEC; 3212f90b865SAlexander Duyck dcb->cmd = DCB_CMD_GPERM_HWADDR; 3222f90b865SAlexander Duyck 3232f90b865SAlexander Duyck netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr); 3242f90b865SAlexander Duyck 3252f90b865SAlexander Duyck ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), 3262f90b865SAlexander Duyck perm_addr); 3272f90b865SAlexander Duyck 3282f90b865SAlexander Duyck nlmsg_end(dcbnl_skb, nlh); 3292f90b865SAlexander Duyck 3302f90b865SAlexander Duyck ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 3312f90b865SAlexander Duyck if (ret) 3327eaf5077SJohn Fastabend goto err_out; 3332f90b865SAlexander Duyck 3342f90b865SAlexander Duyck return 0; 3352f90b865SAlexander Duyck 3362f90b865SAlexander Duyck nlmsg_failure: 337858eb711SRoel Kluin kfree_skb(dcbnl_skb); 3382f90b865SAlexander Duyck err_out: 3392f90b865SAlexander Duyck return -EINVAL; 3402f90b865SAlexander Duyck } 3412f90b865SAlexander Duyck 34246132188SAlexander Duyck static int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb, 34346132188SAlexander Duyck u32 pid, u32 seq, u16 flags) 34446132188SAlexander Duyck { 34546132188SAlexander Duyck struct sk_buff *dcbnl_skb; 34646132188SAlexander Duyck struct nlmsghdr *nlh; 34746132188SAlexander Duyck struct dcbmsg *dcb; 34846132188SAlexander Duyck struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest; 34946132188SAlexander Duyck u8 value; 35046132188SAlexander Duyck int ret = -EINVAL; 35146132188SAlexander Duyck int i; 35246132188SAlexander Duyck int getall = 0; 35346132188SAlexander Duyck 35446132188SAlexander Duyck if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap) 35546132188SAlexander Duyck return ret; 35646132188SAlexander Duyck 35746132188SAlexander Duyck ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP], 35846132188SAlexander Duyck dcbnl_cap_nest); 35946132188SAlexander Duyck if (ret) 36046132188SAlexander Duyck goto err_out; 36146132188SAlexander Duyck 36246132188SAlexander Duyck dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 36346132188SAlexander Duyck if (!dcbnl_skb) 36446132188SAlexander Duyck goto err_out; 36546132188SAlexander Duyck 36646132188SAlexander Duyck nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 36746132188SAlexander Duyck 36846132188SAlexander Duyck dcb = NLMSG_DATA(nlh); 36946132188SAlexander Duyck dcb->dcb_family = AF_UNSPEC; 37046132188SAlexander Duyck dcb->cmd = DCB_CMD_GCAP; 37146132188SAlexander Duyck 37246132188SAlexander Duyck nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP); 37346132188SAlexander Duyck if (!nest) 37446132188SAlexander Duyck goto err; 37546132188SAlexander Duyck 37646132188SAlexander Duyck if (data[DCB_CAP_ATTR_ALL]) 37746132188SAlexander Duyck getall = 1; 37846132188SAlexander Duyck 37946132188SAlexander Duyck for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) { 38046132188SAlexander Duyck if (!getall && !data[i]) 38146132188SAlexander Duyck continue; 38246132188SAlexander Duyck 38346132188SAlexander Duyck if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) { 38446132188SAlexander Duyck ret = nla_put_u8(dcbnl_skb, i, value); 38546132188SAlexander Duyck 38646132188SAlexander Duyck if (ret) { 38746132188SAlexander Duyck nla_nest_cancel(dcbnl_skb, nest); 38846132188SAlexander Duyck goto err; 38946132188SAlexander Duyck } 39046132188SAlexander Duyck } 39146132188SAlexander Duyck } 39246132188SAlexander Duyck nla_nest_end(dcbnl_skb, nest); 39346132188SAlexander Duyck 39446132188SAlexander Duyck nlmsg_end(dcbnl_skb, nlh); 39546132188SAlexander Duyck 39646132188SAlexander Duyck ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 39746132188SAlexander Duyck if (ret) 3987eaf5077SJohn Fastabend goto err_out; 39946132188SAlexander Duyck 40046132188SAlexander Duyck return 0; 40146132188SAlexander Duyck nlmsg_failure: 40246132188SAlexander Duyck err: 403858eb711SRoel Kluin kfree_skb(dcbnl_skb); 40446132188SAlexander Duyck err_out: 40546132188SAlexander Duyck return -EINVAL; 40646132188SAlexander Duyck } 40746132188SAlexander Duyck 40833dbabc4SAlexander Duyck static int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb, 40933dbabc4SAlexander Duyck u32 pid, u32 seq, u16 flags) 41033dbabc4SAlexander Duyck { 41133dbabc4SAlexander Duyck struct sk_buff *dcbnl_skb; 41233dbabc4SAlexander Duyck struct nlmsghdr *nlh; 41333dbabc4SAlexander Duyck struct dcbmsg *dcb; 41433dbabc4SAlexander Duyck struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest; 41533dbabc4SAlexander Duyck u8 value; 41633dbabc4SAlexander Duyck int ret = -EINVAL; 41733dbabc4SAlexander Duyck int i; 41833dbabc4SAlexander Duyck int getall = 0; 41933dbabc4SAlexander Duyck 42033dbabc4SAlexander Duyck if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs) 42133dbabc4SAlexander Duyck return ret; 42233dbabc4SAlexander Duyck 42333dbabc4SAlexander Duyck ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], 42433dbabc4SAlexander Duyck dcbnl_numtcs_nest); 42533dbabc4SAlexander Duyck if (ret) { 42633dbabc4SAlexander Duyck ret = -EINVAL; 42733dbabc4SAlexander Duyck goto err_out; 42833dbabc4SAlexander Duyck } 42933dbabc4SAlexander Duyck 43033dbabc4SAlexander Duyck dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 43133dbabc4SAlexander Duyck if (!dcbnl_skb) { 43233dbabc4SAlexander Duyck ret = -EINVAL; 43333dbabc4SAlexander Duyck goto err_out; 43433dbabc4SAlexander Duyck } 43533dbabc4SAlexander Duyck 43633dbabc4SAlexander Duyck nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 43733dbabc4SAlexander Duyck 43833dbabc4SAlexander Duyck dcb = NLMSG_DATA(nlh); 43933dbabc4SAlexander Duyck dcb->dcb_family = AF_UNSPEC; 44033dbabc4SAlexander Duyck dcb->cmd = DCB_CMD_GNUMTCS; 44133dbabc4SAlexander Duyck 44233dbabc4SAlexander Duyck nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS); 44333dbabc4SAlexander Duyck if (!nest) { 44433dbabc4SAlexander Duyck ret = -EINVAL; 44533dbabc4SAlexander Duyck goto err; 44633dbabc4SAlexander Duyck } 44733dbabc4SAlexander Duyck 44833dbabc4SAlexander Duyck if (data[DCB_NUMTCS_ATTR_ALL]) 44933dbabc4SAlexander Duyck getall = 1; 45033dbabc4SAlexander Duyck 45133dbabc4SAlexander Duyck for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { 45233dbabc4SAlexander Duyck if (!getall && !data[i]) 45333dbabc4SAlexander Duyck continue; 45433dbabc4SAlexander Duyck 45533dbabc4SAlexander Duyck ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value); 45633dbabc4SAlexander Duyck if (!ret) { 45733dbabc4SAlexander Duyck ret = nla_put_u8(dcbnl_skb, i, value); 45833dbabc4SAlexander Duyck 45933dbabc4SAlexander Duyck if (ret) { 46033dbabc4SAlexander Duyck nla_nest_cancel(dcbnl_skb, nest); 46133dbabc4SAlexander Duyck ret = -EINVAL; 46233dbabc4SAlexander Duyck goto err; 46333dbabc4SAlexander Duyck } 46433dbabc4SAlexander Duyck } else { 46533dbabc4SAlexander Duyck goto err; 46633dbabc4SAlexander Duyck } 46733dbabc4SAlexander Duyck } 46833dbabc4SAlexander Duyck nla_nest_end(dcbnl_skb, nest); 46933dbabc4SAlexander Duyck 47033dbabc4SAlexander Duyck nlmsg_end(dcbnl_skb, nlh); 47133dbabc4SAlexander Duyck 47233dbabc4SAlexander Duyck ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 47333dbabc4SAlexander Duyck if (ret) { 47433dbabc4SAlexander Duyck ret = -EINVAL; 4757eaf5077SJohn Fastabend goto err_out; 47633dbabc4SAlexander Duyck } 47733dbabc4SAlexander Duyck 47833dbabc4SAlexander Duyck return 0; 47933dbabc4SAlexander Duyck nlmsg_failure: 48033dbabc4SAlexander Duyck err: 481858eb711SRoel Kluin kfree_skb(dcbnl_skb); 48233dbabc4SAlexander Duyck err_out: 48333dbabc4SAlexander Duyck return ret; 48433dbabc4SAlexander Duyck } 48533dbabc4SAlexander Duyck 48633dbabc4SAlexander Duyck static int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb, 48733dbabc4SAlexander Duyck u32 pid, u32 seq, u16 flags) 48833dbabc4SAlexander Duyck { 48933dbabc4SAlexander Duyck struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1]; 49033dbabc4SAlexander Duyck int ret = -EINVAL; 49133dbabc4SAlexander Duyck u8 value; 49233dbabc4SAlexander Duyck int i; 49333dbabc4SAlexander Duyck 4948b124a8eSDon Skidmore if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setnumtcs) 49533dbabc4SAlexander Duyck return ret; 49633dbabc4SAlexander Duyck 49733dbabc4SAlexander Duyck ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], 49833dbabc4SAlexander Duyck dcbnl_numtcs_nest); 49933dbabc4SAlexander Duyck 50033dbabc4SAlexander Duyck if (ret) { 50133dbabc4SAlexander Duyck ret = -EINVAL; 50233dbabc4SAlexander Duyck goto err; 50333dbabc4SAlexander Duyck } 50433dbabc4SAlexander Duyck 50533dbabc4SAlexander Duyck for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { 50633dbabc4SAlexander Duyck if (data[i] == NULL) 50733dbabc4SAlexander Duyck continue; 50833dbabc4SAlexander Duyck 50933dbabc4SAlexander Duyck value = nla_get_u8(data[i]); 51033dbabc4SAlexander Duyck 51133dbabc4SAlexander Duyck ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value); 51233dbabc4SAlexander Duyck 51333dbabc4SAlexander Duyck if (ret) 51433dbabc4SAlexander Duyck goto operr; 51533dbabc4SAlexander Duyck } 51633dbabc4SAlexander Duyck 51733dbabc4SAlexander Duyck operr: 51833dbabc4SAlexander Duyck ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS, 51933dbabc4SAlexander Duyck DCB_ATTR_NUMTCS, pid, seq, flags); 52033dbabc4SAlexander Duyck 52133dbabc4SAlexander Duyck err: 52233dbabc4SAlexander Duyck return ret; 52333dbabc4SAlexander Duyck } 52433dbabc4SAlexander Duyck 5250eb3aa9bSAlexander Duyck static int dcbnl_getpfcstate(struct net_device *netdev, struct nlattr **tb, 5260eb3aa9bSAlexander Duyck u32 pid, u32 seq, u16 flags) 5270eb3aa9bSAlexander Duyck { 5280eb3aa9bSAlexander Duyck int ret = -EINVAL; 5290eb3aa9bSAlexander Duyck 5300eb3aa9bSAlexander Duyck if (!netdev->dcbnl_ops->getpfcstate) 5310eb3aa9bSAlexander Duyck return ret; 5320eb3aa9bSAlexander Duyck 5330eb3aa9bSAlexander Duyck ret = dcbnl_reply(netdev->dcbnl_ops->getpfcstate(netdev), RTM_GETDCB, 5340eb3aa9bSAlexander Duyck DCB_CMD_PFC_GSTATE, DCB_ATTR_PFC_STATE, 5350eb3aa9bSAlexander Duyck pid, seq, flags); 5360eb3aa9bSAlexander Duyck 5370eb3aa9bSAlexander Duyck return ret; 5380eb3aa9bSAlexander Duyck } 5390eb3aa9bSAlexander Duyck 5400eb3aa9bSAlexander Duyck static int dcbnl_setpfcstate(struct net_device *netdev, struct nlattr **tb, 5410eb3aa9bSAlexander Duyck u32 pid, u32 seq, u16 flags) 5420eb3aa9bSAlexander Duyck { 5430eb3aa9bSAlexander Duyck int ret = -EINVAL; 5440eb3aa9bSAlexander Duyck u8 value; 5450eb3aa9bSAlexander Duyck 5460eb3aa9bSAlexander Duyck if (!tb[DCB_ATTR_PFC_STATE] || !netdev->dcbnl_ops->setpfcstate) 5470eb3aa9bSAlexander Duyck return ret; 5480eb3aa9bSAlexander Duyck 5490eb3aa9bSAlexander Duyck value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]); 5500eb3aa9bSAlexander Duyck 5510eb3aa9bSAlexander Duyck netdev->dcbnl_ops->setpfcstate(netdev, value); 5520eb3aa9bSAlexander Duyck 5530eb3aa9bSAlexander Duyck ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SSTATE, DCB_ATTR_PFC_STATE, 5540eb3aa9bSAlexander Duyck pid, seq, flags); 5550eb3aa9bSAlexander Duyck 5560eb3aa9bSAlexander Duyck return ret; 5570eb3aa9bSAlexander Duyck } 5580eb3aa9bSAlexander Duyck 55957949686SYi Zou static int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb, 56057949686SYi Zou u32 pid, u32 seq, u16 flags) 56157949686SYi Zou { 56257949686SYi Zou struct sk_buff *dcbnl_skb; 56357949686SYi Zou struct nlmsghdr *nlh; 56457949686SYi Zou struct dcbmsg *dcb; 56557949686SYi Zou struct nlattr *app_nest; 56657949686SYi Zou struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; 56757949686SYi Zou u16 id; 56857949686SYi Zou u8 up, idtype; 56957949686SYi Zou int ret = -EINVAL; 57057949686SYi Zou 57157949686SYi Zou if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->getapp) 57257949686SYi Zou goto out; 57357949686SYi Zou 57457949686SYi Zou ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], 57557949686SYi Zou dcbnl_app_nest); 57657949686SYi Zou if (ret) 57757949686SYi Zou goto out; 57857949686SYi Zou 57957949686SYi Zou ret = -EINVAL; 58057949686SYi Zou /* all must be non-null */ 58157949686SYi Zou if ((!app_tb[DCB_APP_ATTR_IDTYPE]) || 58257949686SYi Zou (!app_tb[DCB_APP_ATTR_ID])) 58357949686SYi Zou goto out; 58457949686SYi Zou 58557949686SYi Zou /* either by eth type or by socket number */ 58657949686SYi Zou idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]); 58757949686SYi Zou if ((idtype != DCB_APP_IDTYPE_ETHTYPE) && 58857949686SYi Zou (idtype != DCB_APP_IDTYPE_PORTNUM)) 58957949686SYi Zou goto out; 59057949686SYi Zou 59157949686SYi Zou id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); 59257949686SYi Zou up = netdev->dcbnl_ops->getapp(netdev, idtype, id); 59357949686SYi Zou 59457949686SYi Zou /* send this back */ 59557949686SYi Zou dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 59657949686SYi Zou if (!dcbnl_skb) 59757949686SYi Zou goto out; 59857949686SYi Zou 59957949686SYi Zou nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 60057949686SYi Zou dcb = NLMSG_DATA(nlh); 60157949686SYi Zou dcb->dcb_family = AF_UNSPEC; 60257949686SYi Zou dcb->cmd = DCB_CMD_GAPP; 60357949686SYi Zou 60457949686SYi Zou app_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_APP); 60557949686SYi Zou ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype); 60657949686SYi Zou if (ret) 60757949686SYi Zou goto out_cancel; 60857949686SYi Zou 60957949686SYi Zou ret = nla_put_u16(dcbnl_skb, DCB_APP_ATTR_ID, id); 61057949686SYi Zou if (ret) 61157949686SYi Zou goto out_cancel; 61257949686SYi Zou 61357949686SYi Zou ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_PRIORITY, up); 61457949686SYi Zou if (ret) 61557949686SYi Zou goto out_cancel; 61657949686SYi Zou 61757949686SYi Zou nla_nest_end(dcbnl_skb, app_nest); 61857949686SYi Zou nlmsg_end(dcbnl_skb, nlh); 61957949686SYi Zou 62057949686SYi Zou ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 62157949686SYi Zou if (ret) 62257949686SYi Zou goto nlmsg_failure; 62357949686SYi Zou 62457949686SYi Zou goto out; 62557949686SYi Zou 62657949686SYi Zou out_cancel: 62757949686SYi Zou nla_nest_cancel(dcbnl_skb, app_nest); 62857949686SYi Zou nlmsg_failure: 62957949686SYi Zou kfree_skb(dcbnl_skb); 63057949686SYi Zou out: 63157949686SYi Zou return ret; 63257949686SYi Zou } 63357949686SYi Zou 63457949686SYi Zou static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb, 63557949686SYi Zou u32 pid, u32 seq, u16 flags) 63657949686SYi Zou { 63757949686SYi Zou int ret = -EINVAL; 63857949686SYi Zou u16 id; 63957949686SYi Zou u8 up, idtype; 64057949686SYi Zou struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; 64157949686SYi Zou 64257949686SYi Zou if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->setapp) 64357949686SYi Zou goto out; 64457949686SYi Zou 64557949686SYi Zou ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], 64657949686SYi Zou dcbnl_app_nest); 64757949686SYi Zou if (ret) 64857949686SYi Zou goto out; 64957949686SYi Zou 65057949686SYi Zou ret = -EINVAL; 65157949686SYi Zou /* all must be non-null */ 65257949686SYi Zou if ((!app_tb[DCB_APP_ATTR_IDTYPE]) || 65357949686SYi Zou (!app_tb[DCB_APP_ATTR_ID]) || 65457949686SYi Zou (!app_tb[DCB_APP_ATTR_PRIORITY])) 65557949686SYi Zou goto out; 65657949686SYi Zou 65757949686SYi Zou /* either by eth type or by socket number */ 65857949686SYi Zou idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]); 65957949686SYi Zou if ((idtype != DCB_APP_IDTYPE_ETHTYPE) && 66057949686SYi Zou (idtype != DCB_APP_IDTYPE_PORTNUM)) 66157949686SYi Zou goto out; 66257949686SYi Zou 66357949686SYi Zou id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); 66457949686SYi Zou up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]); 66557949686SYi Zou 66657949686SYi Zou ret = dcbnl_reply(netdev->dcbnl_ops->setapp(netdev, idtype, id, up), 66757949686SYi Zou RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP, 66857949686SYi Zou pid, seq, flags); 66957949686SYi Zou out: 67057949686SYi Zou return ret; 67157949686SYi Zou } 67257949686SYi Zou 6732f90b865SAlexander Duyck static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, 6742f90b865SAlexander Duyck u32 pid, u32 seq, u16 flags, int dir) 6752f90b865SAlexander Duyck { 6762f90b865SAlexander Duyck struct sk_buff *dcbnl_skb; 6772f90b865SAlexander Duyck struct nlmsghdr *nlh; 6782f90b865SAlexander Duyck struct dcbmsg *dcb; 6792f90b865SAlexander Duyck struct nlattr *pg_nest, *param_nest, *data; 6802f90b865SAlexander Duyck struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; 6812f90b865SAlexander Duyck struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; 6822f90b865SAlexander Duyck u8 prio, pgid, tc_pct, up_map; 6832f90b865SAlexander Duyck int ret = -EINVAL; 6842f90b865SAlexander Duyck int getall = 0; 6852f90b865SAlexander Duyck int i; 6862f90b865SAlexander Duyck 6872f90b865SAlexander Duyck if (!tb[DCB_ATTR_PG_CFG] || 6882f90b865SAlexander Duyck !netdev->dcbnl_ops->getpgtccfgtx || 6892f90b865SAlexander Duyck !netdev->dcbnl_ops->getpgtccfgrx || 6902f90b865SAlexander Duyck !netdev->dcbnl_ops->getpgbwgcfgtx || 6912f90b865SAlexander Duyck !netdev->dcbnl_ops->getpgbwgcfgrx) 6922f90b865SAlexander Duyck return ret; 6932f90b865SAlexander Duyck 6942f90b865SAlexander Duyck ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, 6952f90b865SAlexander Duyck tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest); 6962f90b865SAlexander Duyck 6972f90b865SAlexander Duyck if (ret) 6982f90b865SAlexander Duyck goto err_out; 6992f90b865SAlexander Duyck 7002f90b865SAlexander Duyck dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 7012f90b865SAlexander Duyck if (!dcbnl_skb) 7022f90b865SAlexander Duyck goto err_out; 7032f90b865SAlexander Duyck 7042f90b865SAlexander Duyck nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 7052f90b865SAlexander Duyck 7062f90b865SAlexander Duyck dcb = NLMSG_DATA(nlh); 7072f90b865SAlexander Duyck dcb->dcb_family = AF_UNSPEC; 7082f90b865SAlexander Duyck dcb->cmd = (dir) ? DCB_CMD_PGRX_GCFG : DCB_CMD_PGTX_GCFG; 7092f90b865SAlexander Duyck 7102f90b865SAlexander Duyck pg_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PG_CFG); 7112f90b865SAlexander Duyck if (!pg_nest) 7122f90b865SAlexander Duyck goto err; 7132f90b865SAlexander Duyck 7142f90b865SAlexander Duyck if (pg_tb[DCB_PG_ATTR_TC_ALL]) 7152f90b865SAlexander Duyck getall = 1; 7162f90b865SAlexander Duyck 7172f90b865SAlexander Duyck for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { 7182f90b865SAlexander Duyck if (!getall && !pg_tb[i]) 7192f90b865SAlexander Duyck continue; 7202f90b865SAlexander Duyck 7212f90b865SAlexander Duyck if (pg_tb[DCB_PG_ATTR_TC_ALL]) 7222f90b865SAlexander Duyck data = pg_tb[DCB_PG_ATTR_TC_ALL]; 7232f90b865SAlexander Duyck else 7242f90b865SAlexander Duyck data = pg_tb[i]; 7252f90b865SAlexander Duyck ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX, 7262f90b865SAlexander Duyck data, dcbnl_tc_param_nest); 7272f90b865SAlexander Duyck if (ret) 7282f90b865SAlexander Duyck goto err_pg; 7292f90b865SAlexander Duyck 7302f90b865SAlexander Duyck param_nest = nla_nest_start(dcbnl_skb, i); 7312f90b865SAlexander Duyck if (!param_nest) 7322f90b865SAlexander Duyck goto err_pg; 7332f90b865SAlexander Duyck 7342f90b865SAlexander Duyck pgid = DCB_ATTR_VALUE_UNDEFINED; 7352f90b865SAlexander Duyck prio = DCB_ATTR_VALUE_UNDEFINED; 7362f90b865SAlexander Duyck tc_pct = DCB_ATTR_VALUE_UNDEFINED; 7372f90b865SAlexander Duyck up_map = DCB_ATTR_VALUE_UNDEFINED; 7382f90b865SAlexander Duyck 7392f90b865SAlexander Duyck if (dir) { 7402f90b865SAlexander Duyck /* Rx */ 7412f90b865SAlexander Duyck netdev->dcbnl_ops->getpgtccfgrx(netdev, 7422f90b865SAlexander Duyck i - DCB_PG_ATTR_TC_0, &prio, 7432f90b865SAlexander Duyck &pgid, &tc_pct, &up_map); 7442f90b865SAlexander Duyck } else { 7452f90b865SAlexander Duyck /* Tx */ 7462f90b865SAlexander Duyck netdev->dcbnl_ops->getpgtccfgtx(netdev, 7472f90b865SAlexander Duyck i - DCB_PG_ATTR_TC_0, &prio, 7482f90b865SAlexander Duyck &pgid, &tc_pct, &up_map); 7492f90b865SAlexander Duyck } 7502f90b865SAlexander Duyck 7512f90b865SAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_PGID] || 7522f90b865SAlexander Duyck param_tb[DCB_TC_ATTR_PARAM_ALL]) { 7532f90b865SAlexander Duyck ret = nla_put_u8(dcbnl_skb, 7542f90b865SAlexander Duyck DCB_TC_ATTR_PARAM_PGID, pgid); 7552f90b865SAlexander Duyck if (ret) 7562f90b865SAlexander Duyck goto err_param; 7572f90b865SAlexander Duyck } 7582f90b865SAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] || 7592f90b865SAlexander Duyck param_tb[DCB_TC_ATTR_PARAM_ALL]) { 7602f90b865SAlexander Duyck ret = nla_put_u8(dcbnl_skb, 7612f90b865SAlexander Duyck DCB_TC_ATTR_PARAM_UP_MAPPING, up_map); 7622f90b865SAlexander Duyck if (ret) 7632f90b865SAlexander Duyck goto err_param; 7642f90b865SAlexander Duyck } 7652f90b865SAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] || 7662f90b865SAlexander Duyck param_tb[DCB_TC_ATTR_PARAM_ALL]) { 7672f90b865SAlexander Duyck ret = nla_put_u8(dcbnl_skb, 7682f90b865SAlexander Duyck DCB_TC_ATTR_PARAM_STRICT_PRIO, prio); 7692f90b865SAlexander Duyck if (ret) 7702f90b865SAlexander Duyck goto err_param; 7712f90b865SAlexander Duyck } 7722f90b865SAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] || 7732f90b865SAlexander Duyck param_tb[DCB_TC_ATTR_PARAM_ALL]) { 7742f90b865SAlexander Duyck ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_BW_PCT, 7752f90b865SAlexander Duyck tc_pct); 7762f90b865SAlexander Duyck if (ret) 7772f90b865SAlexander Duyck goto err_param; 7782f90b865SAlexander Duyck } 7792f90b865SAlexander Duyck nla_nest_end(dcbnl_skb, param_nest); 7802f90b865SAlexander Duyck } 7812f90b865SAlexander Duyck 7822f90b865SAlexander Duyck if (pg_tb[DCB_PG_ATTR_BW_ID_ALL]) 7832f90b865SAlexander Duyck getall = 1; 7842f90b865SAlexander Duyck else 7852f90b865SAlexander Duyck getall = 0; 7862f90b865SAlexander Duyck 7872f90b865SAlexander Duyck for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) { 7882f90b865SAlexander Duyck if (!getall && !pg_tb[i]) 7892f90b865SAlexander Duyck continue; 7902f90b865SAlexander Duyck 7912f90b865SAlexander Duyck tc_pct = DCB_ATTR_VALUE_UNDEFINED; 7922f90b865SAlexander Duyck 7932f90b865SAlexander Duyck if (dir) { 7942f90b865SAlexander Duyck /* Rx */ 7952f90b865SAlexander Duyck netdev->dcbnl_ops->getpgbwgcfgrx(netdev, 7962f90b865SAlexander Duyck i - DCB_PG_ATTR_BW_ID_0, &tc_pct); 7972f90b865SAlexander Duyck } else { 7982f90b865SAlexander Duyck /* Tx */ 7992f90b865SAlexander Duyck netdev->dcbnl_ops->getpgbwgcfgtx(netdev, 8002f90b865SAlexander Duyck i - DCB_PG_ATTR_BW_ID_0, &tc_pct); 8012f90b865SAlexander Duyck } 8022f90b865SAlexander Duyck ret = nla_put_u8(dcbnl_skb, i, tc_pct); 8032f90b865SAlexander Duyck 8042f90b865SAlexander Duyck if (ret) 8052f90b865SAlexander Duyck goto err_pg; 8062f90b865SAlexander Duyck } 8072f90b865SAlexander Duyck 8082f90b865SAlexander Duyck nla_nest_end(dcbnl_skb, pg_nest); 8092f90b865SAlexander Duyck 8102f90b865SAlexander Duyck nlmsg_end(dcbnl_skb, nlh); 8112f90b865SAlexander Duyck 8122f90b865SAlexander Duyck ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 8132f90b865SAlexander Duyck if (ret) 8147eaf5077SJohn Fastabend goto err_out; 8152f90b865SAlexander Duyck 8162f90b865SAlexander Duyck return 0; 8172f90b865SAlexander Duyck 8182f90b865SAlexander Duyck err_param: 8192f90b865SAlexander Duyck nla_nest_cancel(dcbnl_skb, param_nest); 8202f90b865SAlexander Duyck err_pg: 8212f90b865SAlexander Duyck nla_nest_cancel(dcbnl_skb, pg_nest); 8222f90b865SAlexander Duyck nlmsg_failure: 8232f90b865SAlexander Duyck err: 824858eb711SRoel Kluin kfree_skb(dcbnl_skb); 8252f90b865SAlexander Duyck err_out: 8262f90b865SAlexander Duyck ret = -EINVAL; 8272f90b865SAlexander Duyck return ret; 8282f90b865SAlexander Duyck } 8292f90b865SAlexander Duyck 8302f90b865SAlexander Duyck static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlattr **tb, 8312f90b865SAlexander Duyck u32 pid, u32 seq, u16 flags) 8322f90b865SAlexander Duyck { 8332f90b865SAlexander Duyck return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 0); 8342f90b865SAlexander Duyck } 8352f90b865SAlexander Duyck 8362f90b865SAlexander Duyck static int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlattr **tb, 8372f90b865SAlexander Duyck u32 pid, u32 seq, u16 flags) 8382f90b865SAlexander Duyck { 8392f90b865SAlexander Duyck return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 1); 8402f90b865SAlexander Duyck } 8412f90b865SAlexander Duyck 8422f90b865SAlexander Duyck static int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb, 8432f90b865SAlexander Duyck u32 pid, u32 seq, u16 flags) 8442f90b865SAlexander Duyck { 8452f90b865SAlexander Duyck int ret = -EINVAL; 8462f90b865SAlexander Duyck u8 value; 8472f90b865SAlexander Duyck 8482f90b865SAlexander Duyck if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate) 8492f90b865SAlexander Duyck return ret; 8502f90b865SAlexander Duyck 8512f90b865SAlexander Duyck value = nla_get_u8(tb[DCB_ATTR_STATE]); 8522f90b865SAlexander Duyck 8531486a61eSDon Skidmore ret = dcbnl_reply(netdev->dcbnl_ops->setstate(netdev, value), 8541486a61eSDon Skidmore RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE, 8552f90b865SAlexander Duyck pid, seq, flags); 8562f90b865SAlexander Duyck 8572f90b865SAlexander Duyck return ret; 8582f90b865SAlexander Duyck } 8592f90b865SAlexander Duyck 8602f90b865SAlexander Duyck static int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb, 8612f90b865SAlexander Duyck u32 pid, u32 seq, u16 flags) 8622f90b865SAlexander Duyck { 8632f90b865SAlexander Duyck struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1]; 8642f90b865SAlexander Duyck int i; 8652f90b865SAlexander Duyck int ret = -EINVAL; 8662f90b865SAlexander Duyck u8 value; 8672f90b865SAlexander Duyck 8682f90b865SAlexander Duyck if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->setpfccfg) 8692f90b865SAlexander Duyck return ret; 8702f90b865SAlexander Duyck 8712f90b865SAlexander Duyck ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, 8722f90b865SAlexander Duyck tb[DCB_ATTR_PFC_CFG], 8732f90b865SAlexander Duyck dcbnl_pfc_up_nest); 8742f90b865SAlexander Duyck if (ret) 8752f90b865SAlexander Duyck goto err; 8762f90b865SAlexander Duyck 8772f90b865SAlexander Duyck for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { 8782f90b865SAlexander Duyck if (data[i] == NULL) 8792f90b865SAlexander Duyck continue; 8802f90b865SAlexander Duyck value = nla_get_u8(data[i]); 8812f90b865SAlexander Duyck netdev->dcbnl_ops->setpfccfg(netdev, 8822f90b865SAlexander Duyck data[i]->nla_type - DCB_PFC_UP_ATTR_0, value); 8832f90b865SAlexander Duyck } 8842f90b865SAlexander Duyck 8852f90b865SAlexander Duyck ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SCFG, DCB_ATTR_PFC_CFG, 8862f90b865SAlexander Duyck pid, seq, flags); 8872f90b865SAlexander Duyck err: 8882f90b865SAlexander Duyck return ret; 8892f90b865SAlexander Duyck } 8902f90b865SAlexander Duyck 8912f90b865SAlexander Duyck static int dcbnl_setall(struct net_device *netdev, struct nlattr **tb, 8922f90b865SAlexander Duyck u32 pid, u32 seq, u16 flags) 8932f90b865SAlexander Duyck { 8942f90b865SAlexander Duyck int ret = -EINVAL; 8952f90b865SAlexander Duyck 8962f90b865SAlexander Duyck if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall) 8972f90b865SAlexander Duyck return ret; 8982f90b865SAlexander Duyck 8992f90b865SAlexander Duyck ret = dcbnl_reply(netdev->dcbnl_ops->setall(netdev), RTM_SETDCB, 9002f90b865SAlexander Duyck DCB_CMD_SET_ALL, DCB_ATTR_SET_ALL, pid, seq, flags); 9012f90b865SAlexander Duyck 9022f90b865SAlexander Duyck return ret; 9032f90b865SAlexander Duyck } 9042f90b865SAlexander Duyck 9052f90b865SAlexander Duyck static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb, 9062f90b865SAlexander Duyck u32 pid, u32 seq, u16 flags, int dir) 9072f90b865SAlexander Duyck { 9082f90b865SAlexander Duyck struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; 9092f90b865SAlexander Duyck struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; 9102f90b865SAlexander Duyck int ret = -EINVAL; 9112f90b865SAlexander Duyck int i; 9122f90b865SAlexander Duyck u8 pgid; 9132f90b865SAlexander Duyck u8 up_map; 9142f90b865SAlexander Duyck u8 prio; 9152f90b865SAlexander Duyck u8 tc_pct; 9162f90b865SAlexander Duyck 9172f90b865SAlexander Duyck if (!tb[DCB_ATTR_PG_CFG] || 9182f90b865SAlexander Duyck !netdev->dcbnl_ops->setpgtccfgtx || 9192f90b865SAlexander Duyck !netdev->dcbnl_ops->setpgtccfgrx || 9202f90b865SAlexander Duyck !netdev->dcbnl_ops->setpgbwgcfgtx || 9212f90b865SAlexander Duyck !netdev->dcbnl_ops->setpgbwgcfgrx) 9222f90b865SAlexander Duyck return ret; 9232f90b865SAlexander Duyck 9242f90b865SAlexander Duyck ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, 9252f90b865SAlexander Duyck tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest); 9262f90b865SAlexander Duyck if (ret) 9272f90b865SAlexander Duyck goto err; 9282f90b865SAlexander Duyck 9292f90b865SAlexander Duyck for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { 9302f90b865SAlexander Duyck if (!pg_tb[i]) 9312f90b865SAlexander Duyck continue; 9322f90b865SAlexander Duyck 9332f90b865SAlexander Duyck ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX, 9342f90b865SAlexander Duyck pg_tb[i], dcbnl_tc_param_nest); 9352f90b865SAlexander Duyck if (ret) 9362f90b865SAlexander Duyck goto err; 9372f90b865SAlexander Duyck 9382f90b865SAlexander Duyck pgid = DCB_ATTR_VALUE_UNDEFINED; 9392f90b865SAlexander Duyck prio = DCB_ATTR_VALUE_UNDEFINED; 9402f90b865SAlexander Duyck tc_pct = DCB_ATTR_VALUE_UNDEFINED; 9412f90b865SAlexander Duyck up_map = DCB_ATTR_VALUE_UNDEFINED; 9422f90b865SAlexander Duyck 9432f90b865SAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]) 9442f90b865SAlexander Duyck prio = 9452f90b865SAlexander Duyck nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]); 9462f90b865SAlexander Duyck 9472f90b865SAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_PGID]) 9482f90b865SAlexander Duyck pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]); 9492f90b865SAlexander Duyck 9502f90b865SAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT]) 9512f90b865SAlexander Duyck tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]); 9522f90b865SAlexander Duyck 9532f90b865SAlexander Duyck if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]) 9542f90b865SAlexander Duyck up_map = 9552f90b865SAlexander Duyck nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]); 9562f90b865SAlexander Duyck 9572f90b865SAlexander Duyck /* dir: Tx = 0, Rx = 1 */ 9582f90b865SAlexander Duyck if (dir) { 9592f90b865SAlexander Duyck /* Rx */ 9602f90b865SAlexander Duyck netdev->dcbnl_ops->setpgtccfgrx(netdev, 9612f90b865SAlexander Duyck i - DCB_PG_ATTR_TC_0, 9622f90b865SAlexander Duyck prio, pgid, tc_pct, up_map); 9632f90b865SAlexander Duyck } else { 9642f90b865SAlexander Duyck /* Tx */ 9652f90b865SAlexander Duyck netdev->dcbnl_ops->setpgtccfgtx(netdev, 9662f90b865SAlexander Duyck i - DCB_PG_ATTR_TC_0, 9672f90b865SAlexander Duyck prio, pgid, tc_pct, up_map); 9682f90b865SAlexander Duyck } 9692f90b865SAlexander Duyck } 9702f90b865SAlexander Duyck 9712f90b865SAlexander Duyck for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) { 9722f90b865SAlexander Duyck if (!pg_tb[i]) 9732f90b865SAlexander Duyck continue; 9742f90b865SAlexander Duyck 9752f90b865SAlexander Duyck tc_pct = nla_get_u8(pg_tb[i]); 9762f90b865SAlexander Duyck 9772f90b865SAlexander Duyck /* dir: Tx = 0, Rx = 1 */ 9782f90b865SAlexander Duyck if (dir) { 9792f90b865SAlexander Duyck /* Rx */ 9802f90b865SAlexander Duyck netdev->dcbnl_ops->setpgbwgcfgrx(netdev, 9812f90b865SAlexander Duyck i - DCB_PG_ATTR_BW_ID_0, tc_pct); 9822f90b865SAlexander Duyck } else { 9832f90b865SAlexander Duyck /* Tx */ 9842f90b865SAlexander Duyck netdev->dcbnl_ops->setpgbwgcfgtx(netdev, 9852f90b865SAlexander Duyck i - DCB_PG_ATTR_BW_ID_0, tc_pct); 9862f90b865SAlexander Duyck } 9872f90b865SAlexander Duyck } 9882f90b865SAlexander Duyck 9892f90b865SAlexander Duyck ret = dcbnl_reply(0, RTM_SETDCB, 9902f90b865SAlexander Duyck (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG), 9912f90b865SAlexander Duyck DCB_ATTR_PG_CFG, pid, seq, flags); 9922f90b865SAlexander Duyck 9932f90b865SAlexander Duyck err: 9942f90b865SAlexander Duyck return ret; 9952f90b865SAlexander Duyck } 9962f90b865SAlexander Duyck 9972f90b865SAlexander Duyck static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlattr **tb, 9982f90b865SAlexander Duyck u32 pid, u32 seq, u16 flags) 9992f90b865SAlexander Duyck { 10002f90b865SAlexander Duyck return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 0); 10012f90b865SAlexander Duyck } 10022f90b865SAlexander Duyck 10032f90b865SAlexander Duyck static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb, 10042f90b865SAlexander Duyck u32 pid, u32 seq, u16 flags) 10052f90b865SAlexander Duyck { 10062f90b865SAlexander Duyck return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1); 10072f90b865SAlexander Duyck } 10082f90b865SAlexander Duyck 1009859ee3c4SAlexander Duyck static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb, 1010859ee3c4SAlexander Duyck u32 pid, u32 seq, u16 flags) 1011859ee3c4SAlexander Duyck { 1012859ee3c4SAlexander Duyck struct sk_buff *dcbnl_skb; 1013859ee3c4SAlexander Duyck struct nlmsghdr *nlh; 1014859ee3c4SAlexander Duyck struct dcbmsg *dcb; 1015859ee3c4SAlexander Duyck struct nlattr *bcn_nest; 1016859ee3c4SAlexander Duyck struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1]; 1017859ee3c4SAlexander Duyck u8 value_byte; 1018859ee3c4SAlexander Duyck u32 value_integer; 1019859ee3c4SAlexander Duyck int ret = -EINVAL; 1020859ee3c4SAlexander Duyck bool getall = false; 1021859ee3c4SAlexander Duyck int i; 1022859ee3c4SAlexander Duyck 1023859ee3c4SAlexander Duyck if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->getbcnrp || 1024859ee3c4SAlexander Duyck !netdev->dcbnl_ops->getbcncfg) 1025859ee3c4SAlexander Duyck return ret; 1026859ee3c4SAlexander Duyck 1027859ee3c4SAlexander Duyck ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX, 1028859ee3c4SAlexander Duyck tb[DCB_ATTR_BCN], dcbnl_bcn_nest); 1029859ee3c4SAlexander Duyck 1030859ee3c4SAlexander Duyck if (ret) 1031859ee3c4SAlexander Duyck goto err_out; 1032859ee3c4SAlexander Duyck 1033859ee3c4SAlexander Duyck dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1034859ee3c4SAlexander Duyck if (!dcbnl_skb) 1035859ee3c4SAlexander Duyck goto err_out; 1036859ee3c4SAlexander Duyck 1037859ee3c4SAlexander Duyck nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 1038859ee3c4SAlexander Duyck 1039859ee3c4SAlexander Duyck dcb = NLMSG_DATA(nlh); 1040859ee3c4SAlexander Duyck dcb->dcb_family = AF_UNSPEC; 1041859ee3c4SAlexander Duyck dcb->cmd = DCB_CMD_BCN_GCFG; 1042859ee3c4SAlexander Duyck 1043859ee3c4SAlexander Duyck bcn_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_BCN); 1044859ee3c4SAlexander Duyck if (!bcn_nest) 1045859ee3c4SAlexander Duyck goto err; 1046859ee3c4SAlexander Duyck 1047859ee3c4SAlexander Duyck if (bcn_tb[DCB_BCN_ATTR_ALL]) 1048859ee3c4SAlexander Duyck getall = true; 1049859ee3c4SAlexander Duyck 1050859ee3c4SAlexander Duyck for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) { 1051859ee3c4SAlexander Duyck if (!getall && !bcn_tb[i]) 1052859ee3c4SAlexander Duyck continue; 1053859ee3c4SAlexander Duyck 1054859ee3c4SAlexander Duyck netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0, 1055859ee3c4SAlexander Duyck &value_byte); 1056859ee3c4SAlexander Duyck ret = nla_put_u8(dcbnl_skb, i, value_byte); 1057859ee3c4SAlexander Duyck if (ret) 1058859ee3c4SAlexander Duyck goto err_bcn; 1059859ee3c4SAlexander Duyck } 1060859ee3c4SAlexander Duyck 1061f4314e81SDon Skidmore for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) { 1062859ee3c4SAlexander Duyck if (!getall && !bcn_tb[i]) 1063859ee3c4SAlexander Duyck continue; 1064859ee3c4SAlexander Duyck 1065859ee3c4SAlexander Duyck netdev->dcbnl_ops->getbcncfg(netdev, i, 1066859ee3c4SAlexander Duyck &value_integer); 1067859ee3c4SAlexander Duyck ret = nla_put_u32(dcbnl_skb, i, value_integer); 1068859ee3c4SAlexander Duyck if (ret) 1069859ee3c4SAlexander Duyck goto err_bcn; 1070859ee3c4SAlexander Duyck } 1071859ee3c4SAlexander Duyck 1072859ee3c4SAlexander Duyck nla_nest_end(dcbnl_skb, bcn_nest); 1073859ee3c4SAlexander Duyck 1074859ee3c4SAlexander Duyck nlmsg_end(dcbnl_skb, nlh); 1075859ee3c4SAlexander Duyck 1076859ee3c4SAlexander Duyck ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 1077859ee3c4SAlexander Duyck if (ret) 10787eaf5077SJohn Fastabend goto err_out; 1079859ee3c4SAlexander Duyck 1080859ee3c4SAlexander Duyck return 0; 1081859ee3c4SAlexander Duyck 1082859ee3c4SAlexander Duyck err_bcn: 1083859ee3c4SAlexander Duyck nla_nest_cancel(dcbnl_skb, bcn_nest); 1084859ee3c4SAlexander Duyck nlmsg_failure: 1085859ee3c4SAlexander Duyck err: 1086858eb711SRoel Kluin kfree_skb(dcbnl_skb); 1087859ee3c4SAlexander Duyck err_out: 1088859ee3c4SAlexander Duyck ret = -EINVAL; 1089859ee3c4SAlexander Duyck return ret; 1090859ee3c4SAlexander Duyck } 1091859ee3c4SAlexander Duyck 1092859ee3c4SAlexander Duyck static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlattr **tb, 1093859ee3c4SAlexander Duyck u32 pid, u32 seq, u16 flags) 1094859ee3c4SAlexander Duyck { 1095859ee3c4SAlexander Duyck struct nlattr *data[DCB_BCN_ATTR_MAX + 1]; 1096859ee3c4SAlexander Duyck int i; 1097859ee3c4SAlexander Duyck int ret = -EINVAL; 1098859ee3c4SAlexander Duyck u8 value_byte; 1099859ee3c4SAlexander Duyck u32 value_int; 1100859ee3c4SAlexander Duyck 1101f64f9e71SJoe Perches if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg || 1102f64f9e71SJoe Perches !netdev->dcbnl_ops->setbcnrp) 1103859ee3c4SAlexander Duyck return ret; 1104859ee3c4SAlexander Duyck 1105859ee3c4SAlexander Duyck ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX, 1106859ee3c4SAlexander Duyck tb[DCB_ATTR_BCN], 1107859ee3c4SAlexander Duyck dcbnl_pfc_up_nest); 1108859ee3c4SAlexander Duyck if (ret) 1109859ee3c4SAlexander Duyck goto err; 1110859ee3c4SAlexander Duyck 1111859ee3c4SAlexander Duyck for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) { 1112859ee3c4SAlexander Duyck if (data[i] == NULL) 1113859ee3c4SAlexander Duyck continue; 1114859ee3c4SAlexander Duyck value_byte = nla_get_u8(data[i]); 1115859ee3c4SAlexander Duyck netdev->dcbnl_ops->setbcnrp(netdev, 1116859ee3c4SAlexander Duyck data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte); 1117859ee3c4SAlexander Duyck } 1118859ee3c4SAlexander Duyck 1119f4314e81SDon Skidmore for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) { 1120859ee3c4SAlexander Duyck if (data[i] == NULL) 1121859ee3c4SAlexander Duyck continue; 1122859ee3c4SAlexander Duyck value_int = nla_get_u32(data[i]); 1123859ee3c4SAlexander Duyck netdev->dcbnl_ops->setbcncfg(netdev, 1124859ee3c4SAlexander Duyck i, value_int); 1125859ee3c4SAlexander Duyck } 1126859ee3c4SAlexander Duyck 1127859ee3c4SAlexander Duyck ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_BCN_SCFG, DCB_ATTR_BCN, 1128859ee3c4SAlexander Duyck pid, seq, flags); 1129859ee3c4SAlexander Duyck err: 1130859ee3c4SAlexander Duyck return ret; 1131859ee3c4SAlexander Duyck } 1132859ee3c4SAlexander Duyck 11333e29027aSJohn Fastabend /* Handle IEEE 802.1Qaz SET commands. If any requested operation can not 11343e29027aSJohn Fastabend * be completed the entire msg is aborted and error value is returned. 11353e29027aSJohn Fastabend * No attempt is made to reconcile the case where only part of the 11363e29027aSJohn Fastabend * cmd can be completed. 11373e29027aSJohn Fastabend */ 11383e29027aSJohn Fastabend static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb, 11393e29027aSJohn Fastabend u32 pid, u32 seq, u16 flags) 11403e29027aSJohn Fastabend { 11413e29027aSJohn Fastabend const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 11423e29027aSJohn Fastabend struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1]; 11433e29027aSJohn Fastabend int err = -EOPNOTSUPP; 11443e29027aSJohn Fastabend 11453e29027aSJohn Fastabend if (!ops) 11463e29027aSJohn Fastabend goto err; 11473e29027aSJohn Fastabend 11483e29027aSJohn Fastabend err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX, 11493e29027aSJohn Fastabend tb[DCB_ATTR_IEEE], dcbnl_ieee_policy); 11503e29027aSJohn Fastabend if (err) 11513e29027aSJohn Fastabend goto err; 11523e29027aSJohn Fastabend 11533e29027aSJohn Fastabend if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) { 11543e29027aSJohn Fastabend struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]); 11553e29027aSJohn Fastabend err = ops->ieee_setets(netdev, ets); 11563e29027aSJohn Fastabend if (err) 11573e29027aSJohn Fastabend goto err; 11583e29027aSJohn Fastabend } 11593e29027aSJohn Fastabend 11603e29027aSJohn Fastabend if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setets) { 11613e29027aSJohn Fastabend struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]); 11623e29027aSJohn Fastabend err = ops->ieee_setpfc(netdev, pfc); 11633e29027aSJohn Fastabend if (err) 11643e29027aSJohn Fastabend goto err; 11653e29027aSJohn Fastabend } 11663e29027aSJohn Fastabend 11673e29027aSJohn Fastabend if (ieee[DCB_ATTR_IEEE_APP_TABLE] && ops->ieee_setapp) { 11683e29027aSJohn Fastabend struct nlattr *attr; 11693e29027aSJohn Fastabend int rem; 11703e29027aSJohn Fastabend 11713e29027aSJohn Fastabend nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) { 11723e29027aSJohn Fastabend struct dcb_app *app_data; 11733e29027aSJohn Fastabend if (nla_type(attr) != DCB_ATTR_IEEE_APP) 11743e29027aSJohn Fastabend continue; 11753e29027aSJohn Fastabend app_data = nla_data(attr); 11763e29027aSJohn Fastabend err = ops->ieee_setapp(netdev, app_data); 11773e29027aSJohn Fastabend if (err) 11783e29027aSJohn Fastabend goto err; 11793e29027aSJohn Fastabend } 11803e29027aSJohn Fastabend } 11813e29027aSJohn Fastabend 11823e29027aSJohn Fastabend err: 11833e29027aSJohn Fastabend dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE, 11843e29027aSJohn Fastabend pid, seq, flags); 11853e29027aSJohn Fastabend return err; 11863e29027aSJohn Fastabend } 11873e29027aSJohn Fastabend 11883e29027aSJohn Fastabend 11893e29027aSJohn Fastabend /* Handle IEEE 802.1Qaz GET commands. */ 11903e29027aSJohn Fastabend static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, 11913e29027aSJohn Fastabend u32 pid, u32 seq, u16 flags) 11923e29027aSJohn Fastabend { 11933e29027aSJohn Fastabend struct sk_buff *skb; 11943e29027aSJohn Fastabend struct nlmsghdr *nlh; 11953e29027aSJohn Fastabend struct dcbmsg *dcb; 11963e29027aSJohn Fastabend struct nlattr *ieee; 11973e29027aSJohn Fastabend const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 11983e29027aSJohn Fastabend int err; 11993e29027aSJohn Fastabend 12003e29027aSJohn Fastabend if (!ops) 12013e29027aSJohn Fastabend return -EOPNOTSUPP; 12023e29027aSJohn Fastabend 12033e29027aSJohn Fastabend skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 12043e29027aSJohn Fastabend if (!skb) 12053e29027aSJohn Fastabend return -ENOBUFS; 12063e29027aSJohn Fastabend 12073e29027aSJohn Fastabend nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 12083e29027aSJohn Fastabend 12093e29027aSJohn Fastabend dcb = NLMSG_DATA(nlh); 12103e29027aSJohn Fastabend dcb->dcb_family = AF_UNSPEC; 12113e29027aSJohn Fastabend dcb->cmd = DCB_CMD_IEEE_GET; 12123e29027aSJohn Fastabend 12133e29027aSJohn Fastabend NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name); 12143e29027aSJohn Fastabend 12153e29027aSJohn Fastabend ieee = nla_nest_start(skb, DCB_ATTR_IEEE); 12163e29027aSJohn Fastabend if (!ieee) 12173e29027aSJohn Fastabend goto nla_put_failure; 12183e29027aSJohn Fastabend 12193e29027aSJohn Fastabend if (ops->ieee_getets) { 12203e29027aSJohn Fastabend struct ieee_ets ets; 12213e29027aSJohn Fastabend err = ops->ieee_getets(netdev, &ets); 12223e29027aSJohn Fastabend if (!err) 12233e29027aSJohn Fastabend NLA_PUT(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets); 12243e29027aSJohn Fastabend } 12253e29027aSJohn Fastabend 12263e29027aSJohn Fastabend if (ops->ieee_getpfc) { 12273e29027aSJohn Fastabend struct ieee_pfc pfc; 12283e29027aSJohn Fastabend err = ops->ieee_getpfc(netdev, &pfc); 12293e29027aSJohn Fastabend if (!err) 12303e29027aSJohn Fastabend NLA_PUT(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc); 12313e29027aSJohn Fastabend } 12323e29027aSJohn Fastabend 12333e29027aSJohn Fastabend nla_nest_end(skb, ieee); 12343e29027aSJohn Fastabend nlmsg_end(skb, nlh); 12353e29027aSJohn Fastabend 12363e29027aSJohn Fastabend return rtnl_unicast(skb, &init_net, pid); 12373e29027aSJohn Fastabend nla_put_failure: 12383e29027aSJohn Fastabend nlmsg_cancel(skb, nlh); 12393e29027aSJohn Fastabend nlmsg_failure: 12403e29027aSJohn Fastabend kfree_skb(skb); 12413e29027aSJohn Fastabend return -1; 12423e29027aSJohn Fastabend } 12433e29027aSJohn Fastabend 12442f90b865SAlexander Duyck static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 12452f90b865SAlexander Duyck { 12462f90b865SAlexander Duyck struct net *net = sock_net(skb->sk); 12472f90b865SAlexander Duyck struct net_device *netdev; 12482f90b865SAlexander Duyck struct dcbmsg *dcb = (struct dcbmsg *)NLMSG_DATA(nlh); 12492f90b865SAlexander Duyck struct nlattr *tb[DCB_ATTR_MAX + 1]; 12502f90b865SAlexander Duyck u32 pid = skb ? NETLINK_CB(skb).pid : 0; 12512f90b865SAlexander Duyck int ret = -EINVAL; 12522f90b865SAlexander Duyck 125309ad9bc7SOctavian Purdila if (!net_eq(net, &init_net)) 12542f90b865SAlexander Duyck return -EINVAL; 12552f90b865SAlexander Duyck 12562f90b865SAlexander Duyck ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX, 12572f90b865SAlexander Duyck dcbnl_rtnl_policy); 12582f90b865SAlexander Duyck if (ret < 0) 12592f90b865SAlexander Duyck return ret; 12602f90b865SAlexander Duyck 12612f90b865SAlexander Duyck if (!tb[DCB_ATTR_IFNAME]) 12622f90b865SAlexander Duyck return -EINVAL; 12632f90b865SAlexander Duyck 12642f90b865SAlexander Duyck netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME])); 12652f90b865SAlexander Duyck if (!netdev) 12662f90b865SAlexander Duyck return -EINVAL; 12672f90b865SAlexander Duyck 12682f90b865SAlexander Duyck if (!netdev->dcbnl_ops) 12692f90b865SAlexander Duyck goto errout; 12702f90b865SAlexander Duyck 12712f90b865SAlexander Duyck switch (dcb->cmd) { 12722f90b865SAlexander Duyck case DCB_CMD_GSTATE: 12732f90b865SAlexander Duyck ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq, 12742f90b865SAlexander Duyck nlh->nlmsg_flags); 12752f90b865SAlexander Duyck goto out; 12762f90b865SAlexander Duyck case DCB_CMD_PFC_GCFG: 12772f90b865SAlexander Duyck ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq, 12782f90b865SAlexander Duyck nlh->nlmsg_flags); 12792f90b865SAlexander Duyck goto out; 12802f90b865SAlexander Duyck case DCB_CMD_GPERM_HWADDR: 12812f90b865SAlexander Duyck ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq, 12822f90b865SAlexander Duyck nlh->nlmsg_flags); 12832f90b865SAlexander Duyck goto out; 12842f90b865SAlexander Duyck case DCB_CMD_PGTX_GCFG: 12852f90b865SAlexander Duyck ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq, 12862f90b865SAlexander Duyck nlh->nlmsg_flags); 12872f90b865SAlexander Duyck goto out; 12882f90b865SAlexander Duyck case DCB_CMD_PGRX_GCFG: 12892f90b865SAlexander Duyck ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq, 12902f90b865SAlexander Duyck nlh->nlmsg_flags); 12912f90b865SAlexander Duyck goto out; 1292859ee3c4SAlexander Duyck case DCB_CMD_BCN_GCFG: 1293859ee3c4SAlexander Duyck ret = dcbnl_bcn_getcfg(netdev, tb, pid, nlh->nlmsg_seq, 1294859ee3c4SAlexander Duyck nlh->nlmsg_flags); 1295859ee3c4SAlexander Duyck goto out; 12962f90b865SAlexander Duyck case DCB_CMD_SSTATE: 12972f90b865SAlexander Duyck ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq, 12982f90b865SAlexander Duyck nlh->nlmsg_flags); 12992f90b865SAlexander Duyck goto out; 13002f90b865SAlexander Duyck case DCB_CMD_PFC_SCFG: 13012f90b865SAlexander Duyck ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq, 13022f90b865SAlexander Duyck nlh->nlmsg_flags); 13032f90b865SAlexander Duyck goto out; 13042f90b865SAlexander Duyck 13052f90b865SAlexander Duyck case DCB_CMD_SET_ALL: 13062f90b865SAlexander Duyck ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq, 13072f90b865SAlexander Duyck nlh->nlmsg_flags); 13082f90b865SAlexander Duyck goto out; 13092f90b865SAlexander Duyck case DCB_CMD_PGTX_SCFG: 13102f90b865SAlexander Duyck ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, 13112f90b865SAlexander Duyck nlh->nlmsg_flags); 13122f90b865SAlexander Duyck goto out; 13132f90b865SAlexander Duyck case DCB_CMD_PGRX_SCFG: 13142f90b865SAlexander Duyck ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, 13152f90b865SAlexander Duyck nlh->nlmsg_flags); 13162f90b865SAlexander Duyck goto out; 131746132188SAlexander Duyck case DCB_CMD_GCAP: 131846132188SAlexander Duyck ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq, 131946132188SAlexander Duyck nlh->nlmsg_flags); 132046132188SAlexander Duyck goto out; 132133dbabc4SAlexander Duyck case DCB_CMD_GNUMTCS: 132233dbabc4SAlexander Duyck ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq, 132333dbabc4SAlexander Duyck nlh->nlmsg_flags); 132433dbabc4SAlexander Duyck goto out; 132533dbabc4SAlexander Duyck case DCB_CMD_SNUMTCS: 132633dbabc4SAlexander Duyck ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq, 132733dbabc4SAlexander Duyck nlh->nlmsg_flags); 132833dbabc4SAlexander Duyck goto out; 13290eb3aa9bSAlexander Duyck case DCB_CMD_PFC_GSTATE: 13300eb3aa9bSAlexander Duyck ret = dcbnl_getpfcstate(netdev, tb, pid, nlh->nlmsg_seq, 13310eb3aa9bSAlexander Duyck nlh->nlmsg_flags); 13320eb3aa9bSAlexander Duyck goto out; 13330eb3aa9bSAlexander Duyck case DCB_CMD_PFC_SSTATE: 13340eb3aa9bSAlexander Duyck ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq, 13350eb3aa9bSAlexander Duyck nlh->nlmsg_flags); 13360eb3aa9bSAlexander Duyck goto out; 1337859ee3c4SAlexander Duyck case DCB_CMD_BCN_SCFG: 1338859ee3c4SAlexander Duyck ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq, 1339859ee3c4SAlexander Duyck nlh->nlmsg_flags); 1340859ee3c4SAlexander Duyck goto out; 134157949686SYi Zou case DCB_CMD_GAPP: 134257949686SYi Zou ret = dcbnl_getapp(netdev, tb, pid, nlh->nlmsg_seq, 134357949686SYi Zou nlh->nlmsg_flags); 134457949686SYi Zou goto out; 134557949686SYi Zou case DCB_CMD_SAPP: 134657949686SYi Zou ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq, 134757949686SYi Zou nlh->nlmsg_flags); 134857949686SYi Zou goto out; 13493e29027aSJohn Fastabend case DCB_CMD_IEEE_SET: 13503e29027aSJohn Fastabend ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq, 13513e29027aSJohn Fastabend nlh->nlmsg_flags); 13523e29027aSJohn Fastabend goto out; 13533e29027aSJohn Fastabend case DCB_CMD_IEEE_GET: 13543e29027aSJohn Fastabend ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq, 13553e29027aSJohn Fastabend nlh->nlmsg_flags); 13563e29027aSJohn Fastabend goto out; 13572f90b865SAlexander Duyck default: 13582f90b865SAlexander Duyck goto errout; 13592f90b865SAlexander Duyck } 13602f90b865SAlexander Duyck errout: 13612f90b865SAlexander Duyck ret = -EINVAL; 13622f90b865SAlexander Duyck out: 13632f90b865SAlexander Duyck dev_put(netdev); 13642f90b865SAlexander Duyck return ret; 13652f90b865SAlexander Duyck } 13662f90b865SAlexander Duyck 13672f90b865SAlexander Duyck static int __init dcbnl_init(void) 13682f90b865SAlexander Duyck { 13692f90b865SAlexander Duyck rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL); 13702f90b865SAlexander Duyck rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL); 13712f90b865SAlexander Duyck 13722f90b865SAlexander Duyck return 0; 13732f90b865SAlexander Duyck } 13742f90b865SAlexander Duyck module_init(dcbnl_init); 13752f90b865SAlexander Duyck 13762f90b865SAlexander Duyck static void __exit dcbnl_exit(void) 13772f90b865SAlexander Duyck { 13782f90b865SAlexander Duyck rtnl_unregister(PF_UNSPEC, RTM_GETDCB); 13792f90b865SAlexander Duyck rtnl_unregister(PF_UNSPEC, RTM_SETDCB); 13802f90b865SAlexander Duyck } 13812f90b865SAlexander Duyck module_exit(dcbnl_exit); 13822f90b865SAlexander Duyck 13832f90b865SAlexander Duyck 1384