1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2008-2011, Intel Corporation. 4 * 5 * Description: Data Center Bridging netlink interface 6 * Author: Lucy Liu <lucy.liu@intel.com> 7 */ 8 9 #include <linux/netdevice.h> 10 #include <linux/netlink.h> 11 #include <linux/slab.h> 12 #include <net/netlink.h> 13 #include <net/rtnetlink.h> 14 #include <linux/dcbnl.h> 15 #include <net/dcbevent.h> 16 #include <linux/rtnetlink.h> 17 #include <linux/init.h> 18 #include <net/sock.h> 19 20 /* Data Center Bridging (DCB) is a collection of Ethernet enhancements 21 * intended to allow network traffic with differing requirements 22 * (highly reliable, no drops vs. best effort vs. low latency) to operate 23 * and co-exist on Ethernet. Current DCB features are: 24 * 25 * Enhanced Transmission Selection (aka Priority Grouping [PG]) - provides a 26 * framework for assigning bandwidth guarantees to traffic classes. 27 * 28 * Priority-based Flow Control (PFC) - provides a flow control mechanism which 29 * can work independently for each 802.1p priority. 30 * See Documentation/networking/flow_control.rst for a high level description 31 * of the user space interface for Priority-based Flow Control (PFC). 32 * 33 * Congestion Notification - provides a mechanism for end-to-end congestion 34 * control for protocols which do not have built-in congestion management. 35 * 36 * More information about the emerging standards for these Ethernet features 37 * can be found at: http://www.ieee802.org/1/pages/dcbridges.html 38 * 39 * This file implements an rtnetlink interface to allow configuration of DCB 40 * features for capable devices. 41 */ 42 43 /**************** DCB attribute policies *************************************/ 44 45 /* DCB netlink attributes policy */ 46 static const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { 47 [DCB_ATTR_IFNAME] = {.type = NLA_NUL_STRING, .len = IFNAMSIZ - 1}, 48 [DCB_ATTR_STATE] = {.type = NLA_U8}, 49 [DCB_ATTR_PFC_CFG] = {.type = NLA_NESTED}, 50 [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED}, 51 [DCB_ATTR_SET_ALL] = {.type = NLA_U8}, 52 [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG}, 53 [DCB_ATTR_CAP] = {.type = NLA_NESTED}, 54 [DCB_ATTR_PFC_STATE] = {.type = NLA_U8}, 55 [DCB_ATTR_BCN] = {.type = NLA_NESTED}, 56 [DCB_ATTR_APP] = {.type = NLA_NESTED}, 57 [DCB_ATTR_IEEE] = {.type = NLA_NESTED}, 58 [DCB_ATTR_DCBX] = {.type = NLA_U8}, 59 [DCB_ATTR_FEATCFG] = {.type = NLA_NESTED}, 60 }; 61 62 /* DCB priority flow control to User Priority nested attributes */ 63 static const struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = { 64 [DCB_PFC_UP_ATTR_0] = {.type = NLA_U8}, 65 [DCB_PFC_UP_ATTR_1] = {.type = NLA_U8}, 66 [DCB_PFC_UP_ATTR_2] = {.type = NLA_U8}, 67 [DCB_PFC_UP_ATTR_3] = {.type = NLA_U8}, 68 [DCB_PFC_UP_ATTR_4] = {.type = NLA_U8}, 69 [DCB_PFC_UP_ATTR_5] = {.type = NLA_U8}, 70 [DCB_PFC_UP_ATTR_6] = {.type = NLA_U8}, 71 [DCB_PFC_UP_ATTR_7] = {.type = NLA_U8}, 72 [DCB_PFC_UP_ATTR_ALL] = {.type = NLA_FLAG}, 73 }; 74 75 /* DCB priority grouping nested attributes */ 76 static const struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = { 77 [DCB_PG_ATTR_TC_0] = {.type = NLA_NESTED}, 78 [DCB_PG_ATTR_TC_1] = {.type = NLA_NESTED}, 79 [DCB_PG_ATTR_TC_2] = {.type = NLA_NESTED}, 80 [DCB_PG_ATTR_TC_3] = {.type = NLA_NESTED}, 81 [DCB_PG_ATTR_TC_4] = {.type = NLA_NESTED}, 82 [DCB_PG_ATTR_TC_5] = {.type = NLA_NESTED}, 83 [DCB_PG_ATTR_TC_6] = {.type = NLA_NESTED}, 84 [DCB_PG_ATTR_TC_7] = {.type = NLA_NESTED}, 85 [DCB_PG_ATTR_TC_ALL] = {.type = NLA_NESTED}, 86 [DCB_PG_ATTR_BW_ID_0] = {.type = NLA_U8}, 87 [DCB_PG_ATTR_BW_ID_1] = {.type = NLA_U8}, 88 [DCB_PG_ATTR_BW_ID_2] = {.type = NLA_U8}, 89 [DCB_PG_ATTR_BW_ID_3] = {.type = NLA_U8}, 90 [DCB_PG_ATTR_BW_ID_4] = {.type = NLA_U8}, 91 [DCB_PG_ATTR_BW_ID_5] = {.type = NLA_U8}, 92 [DCB_PG_ATTR_BW_ID_6] = {.type = NLA_U8}, 93 [DCB_PG_ATTR_BW_ID_7] = {.type = NLA_U8}, 94 [DCB_PG_ATTR_BW_ID_ALL] = {.type = NLA_FLAG}, 95 }; 96 97 /* DCB traffic class nested attributes. */ 98 static const struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = { 99 [DCB_TC_ATTR_PARAM_PGID] = {.type = NLA_U8}, 100 [DCB_TC_ATTR_PARAM_UP_MAPPING] = {.type = NLA_U8}, 101 [DCB_TC_ATTR_PARAM_STRICT_PRIO] = {.type = NLA_U8}, 102 [DCB_TC_ATTR_PARAM_BW_PCT] = {.type = NLA_U8}, 103 [DCB_TC_ATTR_PARAM_ALL] = {.type = NLA_FLAG}, 104 }; 105 106 /* DCB capabilities nested attributes. */ 107 static const struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = { 108 [DCB_CAP_ATTR_ALL] = {.type = NLA_FLAG}, 109 [DCB_CAP_ATTR_PG] = {.type = NLA_U8}, 110 [DCB_CAP_ATTR_PFC] = {.type = NLA_U8}, 111 [DCB_CAP_ATTR_UP2TC] = {.type = NLA_U8}, 112 [DCB_CAP_ATTR_PG_TCS] = {.type = NLA_U8}, 113 [DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8}, 114 [DCB_CAP_ATTR_GSP] = {.type = NLA_U8}, 115 [DCB_CAP_ATTR_BCN] = {.type = NLA_U8}, 116 [DCB_CAP_ATTR_DCBX] = {.type = NLA_U8}, 117 }; 118 119 /* DCB capabilities nested attributes. */ 120 static const struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = { 121 [DCB_NUMTCS_ATTR_ALL] = {.type = NLA_FLAG}, 122 [DCB_NUMTCS_ATTR_PG] = {.type = NLA_U8}, 123 [DCB_NUMTCS_ATTR_PFC] = {.type = NLA_U8}, 124 }; 125 126 /* DCB BCN nested attributes. */ 127 static const struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = { 128 [DCB_BCN_ATTR_RP_0] = {.type = NLA_U8}, 129 [DCB_BCN_ATTR_RP_1] = {.type = NLA_U8}, 130 [DCB_BCN_ATTR_RP_2] = {.type = NLA_U8}, 131 [DCB_BCN_ATTR_RP_3] = {.type = NLA_U8}, 132 [DCB_BCN_ATTR_RP_4] = {.type = NLA_U8}, 133 [DCB_BCN_ATTR_RP_5] = {.type = NLA_U8}, 134 [DCB_BCN_ATTR_RP_6] = {.type = NLA_U8}, 135 [DCB_BCN_ATTR_RP_7] = {.type = NLA_U8}, 136 [DCB_BCN_ATTR_RP_ALL] = {.type = NLA_FLAG}, 137 [DCB_BCN_ATTR_BCNA_0] = {.type = NLA_U32}, 138 [DCB_BCN_ATTR_BCNA_1] = {.type = NLA_U32}, 139 [DCB_BCN_ATTR_ALPHA] = {.type = NLA_U32}, 140 [DCB_BCN_ATTR_BETA] = {.type = NLA_U32}, 141 [DCB_BCN_ATTR_GD] = {.type = NLA_U32}, 142 [DCB_BCN_ATTR_GI] = {.type = NLA_U32}, 143 [DCB_BCN_ATTR_TMAX] = {.type = NLA_U32}, 144 [DCB_BCN_ATTR_TD] = {.type = NLA_U32}, 145 [DCB_BCN_ATTR_RMIN] = {.type = NLA_U32}, 146 [DCB_BCN_ATTR_W] = {.type = NLA_U32}, 147 [DCB_BCN_ATTR_RD] = {.type = NLA_U32}, 148 [DCB_BCN_ATTR_RU] = {.type = NLA_U32}, 149 [DCB_BCN_ATTR_WRTT] = {.type = NLA_U32}, 150 [DCB_BCN_ATTR_RI] = {.type = NLA_U32}, 151 [DCB_BCN_ATTR_C] = {.type = NLA_U32}, 152 [DCB_BCN_ATTR_ALL] = {.type = NLA_FLAG}, 153 }; 154 155 /* DCB APP nested attributes. */ 156 static const struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = { 157 [DCB_APP_ATTR_IDTYPE] = {.type = NLA_U8}, 158 [DCB_APP_ATTR_ID] = {.type = NLA_U16}, 159 [DCB_APP_ATTR_PRIORITY] = {.type = NLA_U8}, 160 }; 161 162 /* IEEE 802.1Qaz nested attributes. */ 163 static const struct nla_policy dcbnl_ieee_policy[DCB_ATTR_IEEE_MAX + 1] = { 164 [DCB_ATTR_IEEE_ETS] = {.len = sizeof(struct ieee_ets)}, 165 [DCB_ATTR_IEEE_PFC] = {.len = sizeof(struct ieee_pfc)}, 166 [DCB_ATTR_IEEE_APP_TABLE] = {.type = NLA_NESTED}, 167 [DCB_ATTR_IEEE_MAXRATE] = {.len = sizeof(struct ieee_maxrate)}, 168 [DCB_ATTR_IEEE_QCN] = {.len = sizeof(struct ieee_qcn)}, 169 [DCB_ATTR_IEEE_QCN_STATS] = {.len = sizeof(struct ieee_qcn_stats)}, 170 [DCB_ATTR_DCB_BUFFER] = {.len = sizeof(struct dcbnl_buffer)}, 171 [DCB_ATTR_DCB_APP_TRUST_TABLE] = {.type = NLA_NESTED}, 172 }; 173 174 /* DCB number of traffic classes nested attributes. */ 175 static const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = { 176 [DCB_FEATCFG_ATTR_ALL] = {.type = NLA_FLAG}, 177 [DCB_FEATCFG_ATTR_PG] = {.type = NLA_U8}, 178 [DCB_FEATCFG_ATTR_PFC] = {.type = NLA_U8}, 179 [DCB_FEATCFG_ATTR_APP] = {.type = NLA_U8}, 180 }; 181 182 static LIST_HEAD(dcb_app_list); 183 static LIST_HEAD(dcb_rewr_list); 184 static DEFINE_SPINLOCK(dcb_lock); 185 186 static enum ieee_attrs_app dcbnl_app_attr_type_get(u8 selector) 187 { 188 switch (selector) { 189 case IEEE_8021QAZ_APP_SEL_ETHERTYPE: 190 case IEEE_8021QAZ_APP_SEL_STREAM: 191 case IEEE_8021QAZ_APP_SEL_DGRAM: 192 case IEEE_8021QAZ_APP_SEL_ANY: 193 case IEEE_8021QAZ_APP_SEL_DSCP: 194 return DCB_ATTR_IEEE_APP; 195 case DCB_APP_SEL_PCP: 196 return DCB_ATTR_DCB_APP; 197 default: 198 return DCB_ATTR_IEEE_APP_UNSPEC; 199 } 200 } 201 202 static bool dcbnl_app_attr_type_validate(enum ieee_attrs_app type) 203 { 204 switch (type) { 205 case DCB_ATTR_IEEE_APP: 206 case DCB_ATTR_DCB_APP: 207 return true; 208 default: 209 return false; 210 } 211 } 212 213 static bool dcbnl_app_selector_validate(enum ieee_attrs_app type, u8 selector) 214 { 215 return dcbnl_app_attr_type_get(selector) == type; 216 } 217 218 static struct sk_buff *dcbnl_newmsg(int type, u8 cmd, u32 port, u32 seq, 219 u32 flags, struct nlmsghdr **nlhp) 220 { 221 struct sk_buff *skb; 222 struct dcbmsg *dcb; 223 struct nlmsghdr *nlh; 224 225 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 226 if (!skb) 227 return NULL; 228 229 nlh = nlmsg_put(skb, port, seq, type, sizeof(*dcb), flags); 230 BUG_ON(!nlh); 231 232 dcb = nlmsg_data(nlh); 233 dcb->dcb_family = AF_UNSPEC; 234 dcb->cmd = cmd; 235 dcb->dcb_pad = 0; 236 237 if (nlhp) 238 *nlhp = nlh; 239 240 return skb; 241 } 242 243 static int dcbnl_getstate(struct net_device *netdev, struct nlmsghdr *nlh, 244 u32 seq, struct nlattr **tb, struct sk_buff *skb) 245 { 246 /* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */ 247 if (!netdev->dcbnl_ops->getstate) 248 return -EOPNOTSUPP; 249 250 return nla_put_u8(skb, DCB_ATTR_STATE, 251 netdev->dcbnl_ops->getstate(netdev)); 252 } 253 254 static int dcbnl_getpfccfg(struct net_device *netdev, struct nlmsghdr *nlh, 255 u32 seq, struct nlattr **tb, struct sk_buff *skb) 256 { 257 struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest; 258 u8 value; 259 int ret; 260 int i; 261 int getall = 0; 262 263 if (!tb[DCB_ATTR_PFC_CFG]) 264 return -EINVAL; 265 266 if (!netdev->dcbnl_ops->getpfccfg) 267 return -EOPNOTSUPP; 268 269 ret = nla_parse_nested_deprecated(data, DCB_PFC_UP_ATTR_MAX, 270 tb[DCB_ATTR_PFC_CFG], 271 dcbnl_pfc_up_nest, NULL); 272 if (ret) 273 return ret; 274 275 nest = nla_nest_start_noflag(skb, DCB_ATTR_PFC_CFG); 276 if (!nest) 277 return -EMSGSIZE; 278 279 if (data[DCB_PFC_UP_ATTR_ALL]) 280 getall = 1; 281 282 for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { 283 if (!getall && !data[i]) 284 continue; 285 286 netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, 287 &value); 288 ret = nla_put_u8(skb, i, value); 289 if (ret) { 290 nla_nest_cancel(skb, nest); 291 return ret; 292 } 293 } 294 nla_nest_end(skb, nest); 295 296 return 0; 297 } 298 299 static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlmsghdr *nlh, 300 u32 seq, struct nlattr **tb, struct sk_buff *skb) 301 { 302 u8 perm_addr[MAX_ADDR_LEN]; 303 304 if (!netdev->dcbnl_ops->getpermhwaddr) 305 return -EOPNOTSUPP; 306 307 memset(perm_addr, 0, sizeof(perm_addr)); 308 netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr); 309 310 return nla_put(skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), perm_addr); 311 } 312 313 static int dcbnl_getcap(struct net_device *netdev, struct nlmsghdr *nlh, 314 u32 seq, struct nlattr **tb, struct sk_buff *skb) 315 { 316 struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest; 317 u8 value; 318 int ret; 319 int i; 320 int getall = 0; 321 322 if (!tb[DCB_ATTR_CAP]) 323 return -EINVAL; 324 325 if (!netdev->dcbnl_ops->getcap) 326 return -EOPNOTSUPP; 327 328 ret = nla_parse_nested_deprecated(data, DCB_CAP_ATTR_MAX, 329 tb[DCB_ATTR_CAP], dcbnl_cap_nest, 330 NULL); 331 if (ret) 332 return ret; 333 334 nest = nla_nest_start_noflag(skb, DCB_ATTR_CAP); 335 if (!nest) 336 return -EMSGSIZE; 337 338 if (data[DCB_CAP_ATTR_ALL]) 339 getall = 1; 340 341 for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) { 342 if (!getall && !data[i]) 343 continue; 344 345 if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) { 346 ret = nla_put_u8(skb, i, value); 347 if (ret) { 348 nla_nest_cancel(skb, nest); 349 return ret; 350 } 351 } 352 } 353 nla_nest_end(skb, nest); 354 355 return 0; 356 } 357 358 static int dcbnl_getnumtcs(struct net_device *netdev, struct nlmsghdr *nlh, 359 u32 seq, struct nlattr **tb, struct sk_buff *skb) 360 { 361 struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest; 362 u8 value; 363 int ret; 364 int i; 365 int getall = 0; 366 367 if (!tb[DCB_ATTR_NUMTCS]) 368 return -EINVAL; 369 370 if (!netdev->dcbnl_ops->getnumtcs) 371 return -EOPNOTSUPP; 372 373 ret = nla_parse_nested_deprecated(data, DCB_NUMTCS_ATTR_MAX, 374 tb[DCB_ATTR_NUMTCS], 375 dcbnl_numtcs_nest, NULL); 376 if (ret) 377 return ret; 378 379 nest = nla_nest_start_noflag(skb, DCB_ATTR_NUMTCS); 380 if (!nest) 381 return -EMSGSIZE; 382 383 if (data[DCB_NUMTCS_ATTR_ALL]) 384 getall = 1; 385 386 for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { 387 if (!getall && !data[i]) 388 continue; 389 390 ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value); 391 if (!ret) { 392 ret = nla_put_u8(skb, i, value); 393 if (ret) { 394 nla_nest_cancel(skb, nest); 395 return ret; 396 } 397 } else 398 return -EINVAL; 399 } 400 nla_nest_end(skb, nest); 401 402 return 0; 403 } 404 405 static int dcbnl_setnumtcs(struct net_device *netdev, struct nlmsghdr *nlh, 406 u32 seq, struct nlattr **tb, struct sk_buff *skb) 407 { 408 struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1]; 409 int ret; 410 u8 value; 411 int i; 412 413 if (!tb[DCB_ATTR_NUMTCS]) 414 return -EINVAL; 415 416 if (!netdev->dcbnl_ops->setnumtcs) 417 return -EOPNOTSUPP; 418 419 ret = nla_parse_nested_deprecated(data, DCB_NUMTCS_ATTR_MAX, 420 tb[DCB_ATTR_NUMTCS], 421 dcbnl_numtcs_nest, NULL); 422 if (ret) 423 return ret; 424 425 for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { 426 if (data[i] == NULL) 427 continue; 428 429 value = nla_get_u8(data[i]); 430 431 ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value); 432 if (ret) 433 break; 434 } 435 436 return nla_put_u8(skb, DCB_ATTR_NUMTCS, !!ret); 437 } 438 439 static int dcbnl_getpfcstate(struct net_device *netdev, struct nlmsghdr *nlh, 440 u32 seq, struct nlattr **tb, struct sk_buff *skb) 441 { 442 if (!netdev->dcbnl_ops->getpfcstate) 443 return -EOPNOTSUPP; 444 445 return nla_put_u8(skb, DCB_ATTR_PFC_STATE, 446 netdev->dcbnl_ops->getpfcstate(netdev)); 447 } 448 449 static int dcbnl_setpfcstate(struct net_device *netdev, struct nlmsghdr *nlh, 450 u32 seq, struct nlattr **tb, struct sk_buff *skb) 451 { 452 u8 value; 453 454 if (!tb[DCB_ATTR_PFC_STATE]) 455 return -EINVAL; 456 457 if (!netdev->dcbnl_ops->setpfcstate) 458 return -EOPNOTSUPP; 459 460 value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]); 461 462 netdev->dcbnl_ops->setpfcstate(netdev, value); 463 464 return nla_put_u8(skb, DCB_ATTR_PFC_STATE, 0); 465 } 466 467 static int dcbnl_getapp(struct net_device *netdev, struct nlmsghdr *nlh, 468 u32 seq, struct nlattr **tb, struct sk_buff *skb) 469 { 470 struct nlattr *app_nest; 471 struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; 472 u16 id; 473 u8 up, idtype; 474 int ret; 475 476 if (!tb[DCB_ATTR_APP]) 477 return -EINVAL; 478 479 ret = nla_parse_nested_deprecated(app_tb, DCB_APP_ATTR_MAX, 480 tb[DCB_ATTR_APP], dcbnl_app_nest, 481 NULL); 482 if (ret) 483 return ret; 484 485 /* all must be non-null */ 486 if ((!app_tb[DCB_APP_ATTR_IDTYPE]) || 487 (!app_tb[DCB_APP_ATTR_ID])) 488 return -EINVAL; 489 490 /* either by eth type or by socket number */ 491 idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]); 492 if ((idtype != DCB_APP_IDTYPE_ETHTYPE) && 493 (idtype != DCB_APP_IDTYPE_PORTNUM)) 494 return -EINVAL; 495 496 id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); 497 498 if (netdev->dcbnl_ops->getapp) { 499 ret = netdev->dcbnl_ops->getapp(netdev, idtype, id); 500 if (ret < 0) 501 return ret; 502 else 503 up = ret; 504 } else { 505 struct dcb_app app = { 506 .selector = idtype, 507 .protocol = id, 508 }; 509 up = dcb_getapp(netdev, &app); 510 } 511 512 app_nest = nla_nest_start_noflag(skb, DCB_ATTR_APP); 513 if (!app_nest) 514 return -EMSGSIZE; 515 516 ret = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE, idtype); 517 if (ret) 518 goto out_cancel; 519 520 ret = nla_put_u16(skb, DCB_APP_ATTR_ID, id); 521 if (ret) 522 goto out_cancel; 523 524 ret = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY, up); 525 if (ret) 526 goto out_cancel; 527 528 nla_nest_end(skb, app_nest); 529 530 return 0; 531 532 out_cancel: 533 nla_nest_cancel(skb, app_nest); 534 return ret; 535 } 536 537 static int dcbnl_setapp(struct net_device *netdev, struct nlmsghdr *nlh, 538 u32 seq, struct nlattr **tb, struct sk_buff *skb) 539 { 540 int ret; 541 u16 id; 542 u8 up, idtype; 543 struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; 544 545 if (!tb[DCB_ATTR_APP]) 546 return -EINVAL; 547 548 ret = nla_parse_nested_deprecated(app_tb, DCB_APP_ATTR_MAX, 549 tb[DCB_ATTR_APP], dcbnl_app_nest, 550 NULL); 551 if (ret) 552 return ret; 553 554 /* all must be non-null */ 555 if ((!app_tb[DCB_APP_ATTR_IDTYPE]) || 556 (!app_tb[DCB_APP_ATTR_ID]) || 557 (!app_tb[DCB_APP_ATTR_PRIORITY])) 558 return -EINVAL; 559 560 /* either by eth type or by socket number */ 561 idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]); 562 if ((idtype != DCB_APP_IDTYPE_ETHTYPE) && 563 (idtype != DCB_APP_IDTYPE_PORTNUM)) 564 return -EINVAL; 565 566 id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); 567 up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]); 568 569 if (netdev->dcbnl_ops->setapp) { 570 ret = netdev->dcbnl_ops->setapp(netdev, idtype, id, up); 571 if (ret < 0) 572 return ret; 573 } else { 574 struct dcb_app app; 575 app.selector = idtype; 576 app.protocol = id; 577 app.priority = up; 578 ret = dcb_setapp(netdev, &app); 579 } 580 581 ret = nla_put_u8(skb, DCB_ATTR_APP, ret); 582 dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SAPP, seq, 0); 583 584 return ret; 585 } 586 587 static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, 588 struct nlattr **tb, struct sk_buff *skb, int dir) 589 { 590 struct nlattr *pg_nest, *param_nest, *data; 591 struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; 592 struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; 593 u8 prio, pgid, tc_pct, up_map; 594 int ret; 595 int getall = 0; 596 int i; 597 598 if (!tb[DCB_ATTR_PG_CFG]) 599 return -EINVAL; 600 601 if (!netdev->dcbnl_ops->getpgtccfgtx || 602 !netdev->dcbnl_ops->getpgtccfgrx || 603 !netdev->dcbnl_ops->getpgbwgcfgtx || 604 !netdev->dcbnl_ops->getpgbwgcfgrx) 605 return -EOPNOTSUPP; 606 607 ret = nla_parse_nested_deprecated(pg_tb, DCB_PG_ATTR_MAX, 608 tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest, 609 NULL); 610 if (ret) 611 return ret; 612 613 pg_nest = nla_nest_start_noflag(skb, DCB_ATTR_PG_CFG); 614 if (!pg_nest) 615 return -EMSGSIZE; 616 617 if (pg_tb[DCB_PG_ATTR_TC_ALL]) 618 getall = 1; 619 620 for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { 621 if (!getall && !pg_tb[i]) 622 continue; 623 624 if (pg_tb[DCB_PG_ATTR_TC_ALL]) 625 data = pg_tb[DCB_PG_ATTR_TC_ALL]; 626 else 627 data = pg_tb[i]; 628 ret = nla_parse_nested_deprecated(param_tb, 629 DCB_TC_ATTR_PARAM_MAX, data, 630 dcbnl_tc_param_nest, NULL); 631 if (ret) 632 goto err_pg; 633 634 param_nest = nla_nest_start_noflag(skb, i); 635 if (!param_nest) 636 goto err_pg; 637 638 pgid = DCB_ATTR_VALUE_UNDEFINED; 639 prio = DCB_ATTR_VALUE_UNDEFINED; 640 tc_pct = DCB_ATTR_VALUE_UNDEFINED; 641 up_map = DCB_ATTR_VALUE_UNDEFINED; 642 643 if (dir) { 644 /* Rx */ 645 netdev->dcbnl_ops->getpgtccfgrx(netdev, 646 i - DCB_PG_ATTR_TC_0, &prio, 647 &pgid, &tc_pct, &up_map); 648 } else { 649 /* Tx */ 650 netdev->dcbnl_ops->getpgtccfgtx(netdev, 651 i - DCB_PG_ATTR_TC_0, &prio, 652 &pgid, &tc_pct, &up_map); 653 } 654 655 if (param_tb[DCB_TC_ATTR_PARAM_PGID] || 656 param_tb[DCB_TC_ATTR_PARAM_ALL]) { 657 ret = nla_put_u8(skb, 658 DCB_TC_ATTR_PARAM_PGID, pgid); 659 if (ret) 660 goto err_param; 661 } 662 if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] || 663 param_tb[DCB_TC_ATTR_PARAM_ALL]) { 664 ret = nla_put_u8(skb, 665 DCB_TC_ATTR_PARAM_UP_MAPPING, up_map); 666 if (ret) 667 goto err_param; 668 } 669 if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] || 670 param_tb[DCB_TC_ATTR_PARAM_ALL]) { 671 ret = nla_put_u8(skb, 672 DCB_TC_ATTR_PARAM_STRICT_PRIO, prio); 673 if (ret) 674 goto err_param; 675 } 676 if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] || 677 param_tb[DCB_TC_ATTR_PARAM_ALL]) { 678 ret = nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, 679 tc_pct); 680 if (ret) 681 goto err_param; 682 } 683 nla_nest_end(skb, param_nest); 684 } 685 686 if (pg_tb[DCB_PG_ATTR_BW_ID_ALL]) 687 getall = 1; 688 else 689 getall = 0; 690 691 for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) { 692 if (!getall && !pg_tb[i]) 693 continue; 694 695 tc_pct = DCB_ATTR_VALUE_UNDEFINED; 696 697 if (dir) { 698 /* Rx */ 699 netdev->dcbnl_ops->getpgbwgcfgrx(netdev, 700 i - DCB_PG_ATTR_BW_ID_0, &tc_pct); 701 } else { 702 /* Tx */ 703 netdev->dcbnl_ops->getpgbwgcfgtx(netdev, 704 i - DCB_PG_ATTR_BW_ID_0, &tc_pct); 705 } 706 ret = nla_put_u8(skb, i, tc_pct); 707 if (ret) 708 goto err_pg; 709 } 710 711 nla_nest_end(skb, pg_nest); 712 713 return 0; 714 715 err_param: 716 nla_nest_cancel(skb, param_nest); 717 err_pg: 718 nla_nest_cancel(skb, pg_nest); 719 720 return -EMSGSIZE; 721 } 722 723 static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, 724 u32 seq, struct nlattr **tb, struct sk_buff *skb) 725 { 726 return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 0); 727 } 728 729 static int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, 730 u32 seq, struct nlattr **tb, struct sk_buff *skb) 731 { 732 return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 1); 733 } 734 735 static int dcbnl_setstate(struct net_device *netdev, struct nlmsghdr *nlh, 736 u32 seq, struct nlattr **tb, struct sk_buff *skb) 737 { 738 u8 value; 739 740 if (!tb[DCB_ATTR_STATE]) 741 return -EINVAL; 742 743 if (!netdev->dcbnl_ops->setstate) 744 return -EOPNOTSUPP; 745 746 value = nla_get_u8(tb[DCB_ATTR_STATE]); 747 748 return nla_put_u8(skb, DCB_ATTR_STATE, 749 netdev->dcbnl_ops->setstate(netdev, value)); 750 } 751 752 static int dcbnl_setpfccfg(struct net_device *netdev, struct nlmsghdr *nlh, 753 u32 seq, struct nlattr **tb, struct sk_buff *skb) 754 { 755 struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1]; 756 int i; 757 int ret; 758 u8 value; 759 760 if (!tb[DCB_ATTR_PFC_CFG]) 761 return -EINVAL; 762 763 if (!netdev->dcbnl_ops->setpfccfg) 764 return -EOPNOTSUPP; 765 766 ret = nla_parse_nested_deprecated(data, DCB_PFC_UP_ATTR_MAX, 767 tb[DCB_ATTR_PFC_CFG], 768 dcbnl_pfc_up_nest, NULL); 769 if (ret) 770 return ret; 771 772 for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { 773 if (data[i] == NULL) 774 continue; 775 value = nla_get_u8(data[i]); 776 netdev->dcbnl_ops->setpfccfg(netdev, 777 data[i]->nla_type - DCB_PFC_UP_ATTR_0, value); 778 } 779 780 return nla_put_u8(skb, DCB_ATTR_PFC_CFG, 0); 781 } 782 783 static int dcbnl_setall(struct net_device *netdev, struct nlmsghdr *nlh, 784 u32 seq, struct nlattr **tb, struct sk_buff *skb) 785 { 786 int ret; 787 788 if (!tb[DCB_ATTR_SET_ALL]) 789 return -EINVAL; 790 791 if (!netdev->dcbnl_ops->setall) 792 return -EOPNOTSUPP; 793 794 ret = nla_put_u8(skb, DCB_ATTR_SET_ALL, 795 netdev->dcbnl_ops->setall(netdev)); 796 dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SET_ALL, seq, 0); 797 798 return ret; 799 } 800 801 static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, 802 u32 seq, struct nlattr **tb, struct sk_buff *skb, 803 int dir) 804 { 805 struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; 806 struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; 807 int ret; 808 int i; 809 u8 pgid; 810 u8 up_map; 811 u8 prio; 812 u8 tc_pct; 813 814 if (!tb[DCB_ATTR_PG_CFG]) 815 return -EINVAL; 816 817 if (!netdev->dcbnl_ops->setpgtccfgtx || 818 !netdev->dcbnl_ops->setpgtccfgrx || 819 !netdev->dcbnl_ops->setpgbwgcfgtx || 820 !netdev->dcbnl_ops->setpgbwgcfgrx) 821 return -EOPNOTSUPP; 822 823 ret = nla_parse_nested_deprecated(pg_tb, DCB_PG_ATTR_MAX, 824 tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest, 825 NULL); 826 if (ret) 827 return ret; 828 829 for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { 830 if (!pg_tb[i]) 831 continue; 832 833 ret = nla_parse_nested_deprecated(param_tb, 834 DCB_TC_ATTR_PARAM_MAX, 835 pg_tb[i], 836 dcbnl_tc_param_nest, NULL); 837 if (ret) 838 return ret; 839 840 pgid = DCB_ATTR_VALUE_UNDEFINED; 841 prio = DCB_ATTR_VALUE_UNDEFINED; 842 tc_pct = DCB_ATTR_VALUE_UNDEFINED; 843 up_map = DCB_ATTR_VALUE_UNDEFINED; 844 845 if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]) 846 prio = 847 nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]); 848 849 if (param_tb[DCB_TC_ATTR_PARAM_PGID]) 850 pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]); 851 852 if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT]) 853 tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]); 854 855 if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]) 856 up_map = 857 nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]); 858 859 /* dir: Tx = 0, Rx = 1 */ 860 if (dir) { 861 /* Rx */ 862 netdev->dcbnl_ops->setpgtccfgrx(netdev, 863 i - DCB_PG_ATTR_TC_0, 864 prio, pgid, tc_pct, up_map); 865 } else { 866 /* Tx */ 867 netdev->dcbnl_ops->setpgtccfgtx(netdev, 868 i - DCB_PG_ATTR_TC_0, 869 prio, pgid, tc_pct, up_map); 870 } 871 } 872 873 for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) { 874 if (!pg_tb[i]) 875 continue; 876 877 tc_pct = nla_get_u8(pg_tb[i]); 878 879 /* dir: Tx = 0, Rx = 1 */ 880 if (dir) { 881 /* Rx */ 882 netdev->dcbnl_ops->setpgbwgcfgrx(netdev, 883 i - DCB_PG_ATTR_BW_ID_0, tc_pct); 884 } else { 885 /* Tx */ 886 netdev->dcbnl_ops->setpgbwgcfgtx(netdev, 887 i - DCB_PG_ATTR_BW_ID_0, tc_pct); 888 } 889 } 890 891 return nla_put_u8(skb, DCB_ATTR_PG_CFG, 0); 892 } 893 894 static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, 895 u32 seq, struct nlattr **tb, struct sk_buff *skb) 896 { 897 return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 0); 898 } 899 900 static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, 901 u32 seq, struct nlattr **tb, struct sk_buff *skb) 902 { 903 return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 1); 904 } 905 906 static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, 907 u32 seq, struct nlattr **tb, struct sk_buff *skb) 908 { 909 struct nlattr *bcn_nest; 910 struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1]; 911 u8 value_byte; 912 u32 value_integer; 913 int ret; 914 bool getall = false; 915 int i; 916 917 if (!tb[DCB_ATTR_BCN]) 918 return -EINVAL; 919 920 if (!netdev->dcbnl_ops->getbcnrp || 921 !netdev->dcbnl_ops->getbcncfg) 922 return -EOPNOTSUPP; 923 924 ret = nla_parse_nested_deprecated(bcn_tb, DCB_BCN_ATTR_MAX, 925 tb[DCB_ATTR_BCN], dcbnl_bcn_nest, 926 NULL); 927 if (ret) 928 return ret; 929 930 bcn_nest = nla_nest_start_noflag(skb, DCB_ATTR_BCN); 931 if (!bcn_nest) 932 return -EMSGSIZE; 933 934 if (bcn_tb[DCB_BCN_ATTR_ALL]) 935 getall = true; 936 937 for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) { 938 if (!getall && !bcn_tb[i]) 939 continue; 940 941 netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0, 942 &value_byte); 943 ret = nla_put_u8(skb, i, value_byte); 944 if (ret) 945 goto err_bcn; 946 } 947 948 for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) { 949 if (!getall && !bcn_tb[i]) 950 continue; 951 952 netdev->dcbnl_ops->getbcncfg(netdev, i, 953 &value_integer); 954 ret = nla_put_u32(skb, i, value_integer); 955 if (ret) 956 goto err_bcn; 957 } 958 959 nla_nest_end(skb, bcn_nest); 960 961 return 0; 962 963 err_bcn: 964 nla_nest_cancel(skb, bcn_nest); 965 return ret; 966 } 967 968 static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, 969 u32 seq, struct nlattr **tb, struct sk_buff *skb) 970 { 971 struct nlattr *data[DCB_BCN_ATTR_MAX + 1]; 972 int i; 973 int ret; 974 u8 value_byte; 975 u32 value_int; 976 977 if (!tb[DCB_ATTR_BCN]) 978 return -EINVAL; 979 980 if (!netdev->dcbnl_ops->setbcncfg || 981 !netdev->dcbnl_ops->setbcnrp) 982 return -EOPNOTSUPP; 983 984 ret = nla_parse_nested_deprecated(data, DCB_BCN_ATTR_MAX, 985 tb[DCB_ATTR_BCN], dcbnl_bcn_nest, 986 NULL); 987 if (ret) 988 return ret; 989 990 for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) { 991 if (data[i] == NULL) 992 continue; 993 value_byte = nla_get_u8(data[i]); 994 netdev->dcbnl_ops->setbcnrp(netdev, 995 data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte); 996 } 997 998 for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) { 999 if (data[i] == NULL) 1000 continue; 1001 value_int = nla_get_u32(data[i]); 1002 netdev->dcbnl_ops->setbcncfg(netdev, 1003 i, value_int); 1004 } 1005 1006 return nla_put_u8(skb, DCB_ATTR_BCN, 0); 1007 } 1008 1009 static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb, 1010 int app_nested_type, int app_info_type, 1011 int app_entry_type) 1012 { 1013 struct dcb_peer_app_info info; 1014 struct dcb_app *table = NULL; 1015 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1016 u16 app_count; 1017 int err; 1018 1019 1020 /** 1021 * retrieve the peer app configuration form the driver. If the driver 1022 * handlers fail exit without doing anything 1023 */ 1024 err = ops->peer_getappinfo(netdev, &info, &app_count); 1025 if (!err && app_count) { 1026 table = kmalloc_array(app_count, sizeof(struct dcb_app), 1027 GFP_KERNEL); 1028 if (!table) 1029 return -ENOMEM; 1030 1031 err = ops->peer_getapptable(netdev, table); 1032 } 1033 1034 if (!err) { 1035 u16 i; 1036 struct nlattr *app; 1037 1038 /** 1039 * build the message, from here on the only possible failure 1040 * is due to the skb size 1041 */ 1042 err = -EMSGSIZE; 1043 1044 app = nla_nest_start_noflag(skb, app_nested_type); 1045 if (!app) 1046 goto nla_put_failure; 1047 1048 if (app_info_type && 1049 nla_put(skb, app_info_type, sizeof(info), &info)) 1050 goto nla_put_failure; 1051 1052 for (i = 0; i < app_count; i++) { 1053 if (nla_put(skb, app_entry_type, sizeof(struct dcb_app), 1054 &table[i])) 1055 goto nla_put_failure; 1056 } 1057 nla_nest_end(skb, app); 1058 } 1059 err = 0; 1060 1061 nla_put_failure: 1062 kfree(table); 1063 return err; 1064 } 1065 1066 static int dcbnl_getapptrust(struct net_device *netdev, struct sk_buff *skb) 1067 { 1068 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1069 enum ieee_attrs_app type; 1070 struct nlattr *apptrust; 1071 int nselectors, err, i; 1072 u8 *selectors; 1073 1074 selectors = kzalloc(IEEE_8021QAZ_APP_SEL_MAX + 1, GFP_KERNEL); 1075 if (!selectors) 1076 return -ENOMEM; 1077 1078 err = ops->dcbnl_getapptrust(netdev, selectors, &nselectors); 1079 if (err) { 1080 err = 0; 1081 goto out; 1082 } 1083 1084 apptrust = nla_nest_start(skb, DCB_ATTR_DCB_APP_TRUST_TABLE); 1085 if (!apptrust) { 1086 err = -EMSGSIZE; 1087 goto out; 1088 } 1089 1090 for (i = 0; i < nselectors; i++) { 1091 type = dcbnl_app_attr_type_get(selectors[i]); 1092 err = nla_put_u8(skb, type, selectors[i]); 1093 if (err) { 1094 nla_nest_cancel(skb, apptrust); 1095 goto out; 1096 } 1097 } 1098 nla_nest_end(skb, apptrust); 1099 1100 out: 1101 kfree(selectors); 1102 return err; 1103 } 1104 1105 /* Set or delete APP table or rewrite table entries. The APP struct is validated 1106 * and the appropriate callback function is called. 1107 */ 1108 static int dcbnl_app_table_setdel(struct nlattr *attr, 1109 struct net_device *netdev, 1110 int (*setdel)(struct net_device *dev, 1111 struct dcb_app *app)) 1112 { 1113 struct dcb_app *app_data; 1114 enum ieee_attrs_app type; 1115 struct nlattr *attr_itr; 1116 int rem, err; 1117 1118 nla_for_each_nested(attr_itr, attr, rem) { 1119 type = nla_type(attr_itr); 1120 1121 if (!dcbnl_app_attr_type_validate(type)) 1122 continue; 1123 1124 if (nla_len(attr_itr) < sizeof(struct dcb_app)) 1125 return -ERANGE; 1126 1127 app_data = nla_data(attr_itr); 1128 1129 if (!dcbnl_app_selector_validate(type, app_data->selector)) 1130 return -EINVAL; 1131 1132 err = setdel(netdev, app_data); 1133 if (err) 1134 return err; 1135 } 1136 1137 return 0; 1138 } 1139 1140 /* Handle IEEE 802.1Qaz/802.1Qau/802.1Qbb GET commands. */ 1141 static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) 1142 { 1143 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1144 struct nlattr *ieee, *app, *rewr; 1145 struct dcb_app_type *itr; 1146 int dcbx; 1147 int err; 1148 1149 if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name)) 1150 return -EMSGSIZE; 1151 1152 ieee = nla_nest_start_noflag(skb, DCB_ATTR_IEEE); 1153 if (!ieee) 1154 return -EMSGSIZE; 1155 1156 if (ops->ieee_getets) { 1157 struct ieee_ets ets; 1158 memset(&ets, 0, sizeof(ets)); 1159 err = ops->ieee_getets(netdev, &ets); 1160 if (!err && 1161 nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets)) 1162 return -EMSGSIZE; 1163 } 1164 1165 if (ops->ieee_getmaxrate) { 1166 struct ieee_maxrate maxrate; 1167 memset(&maxrate, 0, sizeof(maxrate)); 1168 err = ops->ieee_getmaxrate(netdev, &maxrate); 1169 if (!err) { 1170 err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE, 1171 sizeof(maxrate), &maxrate); 1172 if (err) 1173 return -EMSGSIZE; 1174 } 1175 } 1176 1177 if (ops->ieee_getqcn) { 1178 struct ieee_qcn qcn; 1179 1180 memset(&qcn, 0, sizeof(qcn)); 1181 err = ops->ieee_getqcn(netdev, &qcn); 1182 if (!err) { 1183 err = nla_put(skb, DCB_ATTR_IEEE_QCN, 1184 sizeof(qcn), &qcn); 1185 if (err) 1186 return -EMSGSIZE; 1187 } 1188 } 1189 1190 if (ops->ieee_getqcnstats) { 1191 struct ieee_qcn_stats qcn_stats; 1192 1193 memset(&qcn_stats, 0, sizeof(qcn_stats)); 1194 err = ops->ieee_getqcnstats(netdev, &qcn_stats); 1195 if (!err) { 1196 err = nla_put(skb, DCB_ATTR_IEEE_QCN_STATS, 1197 sizeof(qcn_stats), &qcn_stats); 1198 if (err) 1199 return -EMSGSIZE; 1200 } 1201 } 1202 1203 if (ops->ieee_getpfc) { 1204 struct ieee_pfc pfc; 1205 memset(&pfc, 0, sizeof(pfc)); 1206 err = ops->ieee_getpfc(netdev, &pfc); 1207 if (!err && 1208 nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc)) 1209 return -EMSGSIZE; 1210 } 1211 1212 if (ops->dcbnl_getbuffer) { 1213 struct dcbnl_buffer buffer; 1214 1215 memset(&buffer, 0, sizeof(buffer)); 1216 err = ops->dcbnl_getbuffer(netdev, &buffer); 1217 if (!err && 1218 nla_put(skb, DCB_ATTR_DCB_BUFFER, sizeof(buffer), &buffer)) 1219 return -EMSGSIZE; 1220 } 1221 1222 app = nla_nest_start_noflag(skb, DCB_ATTR_IEEE_APP_TABLE); 1223 if (!app) 1224 return -EMSGSIZE; 1225 1226 spin_lock_bh(&dcb_lock); 1227 list_for_each_entry(itr, &dcb_app_list, list) { 1228 if (itr->ifindex == netdev->ifindex) { 1229 enum ieee_attrs_app type = 1230 dcbnl_app_attr_type_get(itr->app.selector); 1231 err = nla_put(skb, type, sizeof(itr->app), &itr->app); 1232 if (err) { 1233 spin_unlock_bh(&dcb_lock); 1234 return -EMSGSIZE; 1235 } 1236 } 1237 } 1238 1239 if (netdev->dcbnl_ops->getdcbx) 1240 dcbx = netdev->dcbnl_ops->getdcbx(netdev); 1241 else 1242 dcbx = -EOPNOTSUPP; 1243 1244 spin_unlock_bh(&dcb_lock); 1245 nla_nest_end(skb, app); 1246 1247 rewr = nla_nest_start(skb, DCB_ATTR_DCB_REWR_TABLE); 1248 if (!rewr) 1249 return -EMSGSIZE; 1250 1251 spin_lock_bh(&dcb_lock); 1252 list_for_each_entry(itr, &dcb_rewr_list, list) { 1253 if (itr->ifindex == netdev->ifindex) { 1254 enum ieee_attrs_app type = 1255 dcbnl_app_attr_type_get(itr->app.selector); 1256 err = nla_put(skb, type, sizeof(itr->app), &itr->app); 1257 if (err) { 1258 spin_unlock_bh(&dcb_lock); 1259 nla_nest_cancel(skb, rewr); 1260 return -EMSGSIZE; 1261 } 1262 } 1263 } 1264 1265 spin_unlock_bh(&dcb_lock); 1266 nla_nest_end(skb, rewr); 1267 1268 if (ops->dcbnl_getapptrust) { 1269 err = dcbnl_getapptrust(netdev, skb); 1270 if (err) 1271 return err; 1272 } 1273 1274 /* get peer info if available */ 1275 if (ops->ieee_peer_getets) { 1276 struct ieee_ets ets; 1277 memset(&ets, 0, sizeof(ets)); 1278 err = ops->ieee_peer_getets(netdev, &ets); 1279 if (!err && 1280 nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets)) 1281 return -EMSGSIZE; 1282 } 1283 1284 if (ops->ieee_peer_getpfc) { 1285 struct ieee_pfc pfc; 1286 memset(&pfc, 0, sizeof(pfc)); 1287 err = ops->ieee_peer_getpfc(netdev, &pfc); 1288 if (!err && 1289 nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc)) 1290 return -EMSGSIZE; 1291 } 1292 1293 if (ops->peer_getappinfo && ops->peer_getapptable) { 1294 err = dcbnl_build_peer_app(netdev, skb, 1295 DCB_ATTR_IEEE_PEER_APP, 1296 DCB_ATTR_IEEE_APP_UNSPEC, 1297 DCB_ATTR_IEEE_APP); 1298 if (err) 1299 return -EMSGSIZE; 1300 } 1301 1302 nla_nest_end(skb, ieee); 1303 if (dcbx >= 0) { 1304 err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx); 1305 if (err) 1306 return -EMSGSIZE; 1307 } 1308 1309 return 0; 1310 } 1311 1312 static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev, 1313 int dir) 1314 { 1315 u8 pgid, up_map, prio, tc_pct; 1316 const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops; 1317 int i = dir ? DCB_ATTR_CEE_TX_PG : DCB_ATTR_CEE_RX_PG; 1318 struct nlattr *pg = nla_nest_start_noflag(skb, i); 1319 1320 if (!pg) 1321 return -EMSGSIZE; 1322 1323 for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { 1324 struct nlattr *tc_nest = nla_nest_start_noflag(skb, i); 1325 1326 if (!tc_nest) 1327 return -EMSGSIZE; 1328 1329 pgid = DCB_ATTR_VALUE_UNDEFINED; 1330 prio = DCB_ATTR_VALUE_UNDEFINED; 1331 tc_pct = DCB_ATTR_VALUE_UNDEFINED; 1332 up_map = DCB_ATTR_VALUE_UNDEFINED; 1333 1334 if (!dir) 1335 ops->getpgtccfgrx(dev, i - DCB_PG_ATTR_TC_0, 1336 &prio, &pgid, &tc_pct, &up_map); 1337 else 1338 ops->getpgtccfgtx(dev, i - DCB_PG_ATTR_TC_0, 1339 &prio, &pgid, &tc_pct, &up_map); 1340 1341 if (nla_put_u8(skb, DCB_TC_ATTR_PARAM_PGID, pgid) || 1342 nla_put_u8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map) || 1343 nla_put_u8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio) || 1344 nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct)) 1345 return -EMSGSIZE; 1346 nla_nest_end(skb, tc_nest); 1347 } 1348 1349 for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) { 1350 tc_pct = DCB_ATTR_VALUE_UNDEFINED; 1351 1352 if (!dir) 1353 ops->getpgbwgcfgrx(dev, i - DCB_PG_ATTR_BW_ID_0, 1354 &tc_pct); 1355 else 1356 ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0, 1357 &tc_pct); 1358 if (nla_put_u8(skb, i, tc_pct)) 1359 return -EMSGSIZE; 1360 } 1361 nla_nest_end(skb, pg); 1362 return 0; 1363 } 1364 1365 static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) 1366 { 1367 struct nlattr *cee, *app; 1368 struct dcb_app_type *itr; 1369 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1370 int dcbx, i, err = -EMSGSIZE; 1371 u8 value; 1372 1373 if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name)) 1374 goto nla_put_failure; 1375 cee = nla_nest_start_noflag(skb, DCB_ATTR_CEE); 1376 if (!cee) 1377 goto nla_put_failure; 1378 1379 /* local pg */ 1380 if (ops->getpgtccfgtx && ops->getpgbwgcfgtx) { 1381 err = dcbnl_cee_pg_fill(skb, netdev, 1); 1382 if (err) 1383 goto nla_put_failure; 1384 } 1385 1386 if (ops->getpgtccfgrx && ops->getpgbwgcfgrx) { 1387 err = dcbnl_cee_pg_fill(skb, netdev, 0); 1388 if (err) 1389 goto nla_put_failure; 1390 } 1391 1392 /* local pfc */ 1393 if (ops->getpfccfg) { 1394 struct nlattr *pfc_nest = nla_nest_start_noflag(skb, 1395 DCB_ATTR_CEE_PFC); 1396 1397 if (!pfc_nest) 1398 goto nla_put_failure; 1399 1400 for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { 1401 ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value); 1402 if (nla_put_u8(skb, i, value)) 1403 goto nla_put_failure; 1404 } 1405 nla_nest_end(skb, pfc_nest); 1406 } 1407 1408 /* local app */ 1409 spin_lock_bh(&dcb_lock); 1410 app = nla_nest_start_noflag(skb, DCB_ATTR_CEE_APP_TABLE); 1411 if (!app) 1412 goto dcb_unlock; 1413 1414 list_for_each_entry(itr, &dcb_app_list, list) { 1415 if (itr->ifindex == netdev->ifindex) { 1416 struct nlattr *app_nest = nla_nest_start_noflag(skb, 1417 DCB_ATTR_APP); 1418 if (!app_nest) 1419 goto dcb_unlock; 1420 1421 err = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE, 1422 itr->app.selector); 1423 if (err) 1424 goto dcb_unlock; 1425 1426 err = nla_put_u16(skb, DCB_APP_ATTR_ID, 1427 itr->app.protocol); 1428 if (err) 1429 goto dcb_unlock; 1430 1431 err = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY, 1432 itr->app.priority); 1433 if (err) 1434 goto dcb_unlock; 1435 1436 nla_nest_end(skb, app_nest); 1437 } 1438 } 1439 nla_nest_end(skb, app); 1440 1441 if (netdev->dcbnl_ops->getdcbx) 1442 dcbx = netdev->dcbnl_ops->getdcbx(netdev); 1443 else 1444 dcbx = -EOPNOTSUPP; 1445 1446 spin_unlock_bh(&dcb_lock); 1447 1448 /* features flags */ 1449 if (ops->getfeatcfg) { 1450 struct nlattr *feat = nla_nest_start_noflag(skb, 1451 DCB_ATTR_CEE_FEAT); 1452 if (!feat) 1453 goto nla_put_failure; 1454 1455 for (i = DCB_FEATCFG_ATTR_ALL + 1; i <= DCB_FEATCFG_ATTR_MAX; 1456 i++) 1457 if (!ops->getfeatcfg(netdev, i, &value) && 1458 nla_put_u8(skb, i, value)) 1459 goto nla_put_failure; 1460 1461 nla_nest_end(skb, feat); 1462 } 1463 1464 /* peer info if available */ 1465 if (ops->cee_peer_getpg) { 1466 struct cee_pg pg; 1467 memset(&pg, 0, sizeof(pg)); 1468 err = ops->cee_peer_getpg(netdev, &pg); 1469 if (!err && 1470 nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg)) 1471 goto nla_put_failure; 1472 } 1473 1474 if (ops->cee_peer_getpfc) { 1475 struct cee_pfc pfc; 1476 memset(&pfc, 0, sizeof(pfc)); 1477 err = ops->cee_peer_getpfc(netdev, &pfc); 1478 if (!err && 1479 nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc)) 1480 goto nla_put_failure; 1481 } 1482 1483 if (ops->peer_getappinfo && ops->peer_getapptable) { 1484 err = dcbnl_build_peer_app(netdev, skb, 1485 DCB_ATTR_CEE_PEER_APP_TABLE, 1486 DCB_ATTR_CEE_PEER_APP_INFO, 1487 DCB_ATTR_CEE_PEER_APP); 1488 if (err) 1489 goto nla_put_failure; 1490 } 1491 nla_nest_end(skb, cee); 1492 1493 /* DCBX state */ 1494 if (dcbx >= 0) { 1495 err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx); 1496 if (err) 1497 goto nla_put_failure; 1498 } 1499 return 0; 1500 1501 dcb_unlock: 1502 spin_unlock_bh(&dcb_lock); 1503 nla_put_failure: 1504 err = -EMSGSIZE; 1505 return err; 1506 } 1507 1508 static int dcbnl_notify(struct net_device *dev, int event, int cmd, 1509 u32 seq, u32 portid, int dcbx_ver) 1510 { 1511 struct net *net = dev_net(dev); 1512 struct sk_buff *skb; 1513 struct nlmsghdr *nlh; 1514 const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops; 1515 int err; 1516 1517 if (!ops) 1518 return -EOPNOTSUPP; 1519 1520 skb = dcbnl_newmsg(event, cmd, portid, seq, 0, &nlh); 1521 if (!skb) 1522 return -ENOMEM; 1523 1524 if (dcbx_ver == DCB_CAP_DCBX_VER_IEEE) 1525 err = dcbnl_ieee_fill(skb, dev); 1526 else 1527 err = dcbnl_cee_fill(skb, dev); 1528 1529 if (err < 0) { 1530 /* Report error to broadcast listeners */ 1531 nlmsg_free(skb); 1532 rtnl_set_sk_err(net, RTNLGRP_DCB, err); 1533 } else { 1534 /* End nlmsg and notify broadcast listeners */ 1535 nlmsg_end(skb, nlh); 1536 rtnl_notify(skb, net, 0, RTNLGRP_DCB, NULL, GFP_KERNEL); 1537 } 1538 1539 return err; 1540 } 1541 1542 int dcbnl_ieee_notify(struct net_device *dev, int event, int cmd, 1543 u32 seq, u32 portid) 1544 { 1545 return dcbnl_notify(dev, event, cmd, seq, portid, DCB_CAP_DCBX_VER_IEEE); 1546 } 1547 EXPORT_SYMBOL(dcbnl_ieee_notify); 1548 1549 int dcbnl_cee_notify(struct net_device *dev, int event, int cmd, 1550 u32 seq, u32 portid) 1551 { 1552 return dcbnl_notify(dev, event, cmd, seq, portid, DCB_CAP_DCBX_VER_CEE); 1553 } 1554 EXPORT_SYMBOL(dcbnl_cee_notify); 1555 1556 /* Handle IEEE 802.1Qaz/802.1Qau/802.1Qbb SET commands. 1557 * If any requested operation can not be completed 1558 * the entire msg is aborted and error value is returned. 1559 * No attempt is made to reconcile the case where only part of the 1560 * cmd can be completed. 1561 */ 1562 static int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh, 1563 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1564 { 1565 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1566 struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1]; 1567 int prio; 1568 int err; 1569 1570 if (!ops) 1571 return -EOPNOTSUPP; 1572 1573 if (!tb[DCB_ATTR_IEEE]) 1574 return -EINVAL; 1575 1576 err = nla_parse_nested_deprecated(ieee, DCB_ATTR_IEEE_MAX, 1577 tb[DCB_ATTR_IEEE], 1578 dcbnl_ieee_policy, NULL); 1579 if (err) 1580 return err; 1581 1582 if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) { 1583 struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]); 1584 err = ops->ieee_setets(netdev, ets); 1585 if (err) 1586 goto err; 1587 } 1588 1589 if (ieee[DCB_ATTR_IEEE_MAXRATE] && ops->ieee_setmaxrate) { 1590 struct ieee_maxrate *maxrate = 1591 nla_data(ieee[DCB_ATTR_IEEE_MAXRATE]); 1592 err = ops->ieee_setmaxrate(netdev, maxrate); 1593 if (err) 1594 goto err; 1595 } 1596 1597 if (ieee[DCB_ATTR_IEEE_QCN] && ops->ieee_setqcn) { 1598 struct ieee_qcn *qcn = 1599 nla_data(ieee[DCB_ATTR_IEEE_QCN]); 1600 1601 err = ops->ieee_setqcn(netdev, qcn); 1602 if (err) 1603 goto err; 1604 } 1605 1606 if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) { 1607 struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]); 1608 err = ops->ieee_setpfc(netdev, pfc); 1609 if (err) 1610 goto err; 1611 } 1612 1613 if (ieee[DCB_ATTR_DCB_BUFFER] && ops->dcbnl_setbuffer) { 1614 struct dcbnl_buffer *buffer = 1615 nla_data(ieee[DCB_ATTR_DCB_BUFFER]); 1616 1617 for (prio = 0; prio < ARRAY_SIZE(buffer->prio2buffer); prio++) { 1618 if (buffer->prio2buffer[prio] >= DCBX_MAX_BUFFERS) { 1619 err = -EINVAL; 1620 goto err; 1621 } 1622 } 1623 1624 err = ops->dcbnl_setbuffer(netdev, buffer); 1625 if (err) 1626 goto err; 1627 } 1628 1629 if (ieee[DCB_ATTR_DCB_REWR_TABLE]) { 1630 err = dcbnl_app_table_setdel(ieee[DCB_ATTR_DCB_REWR_TABLE], 1631 netdev, 1632 ops->dcbnl_setrewr ?: dcb_setrewr); 1633 if (err) 1634 goto err; 1635 } 1636 1637 if (ieee[DCB_ATTR_IEEE_APP_TABLE]) { 1638 err = dcbnl_app_table_setdel(ieee[DCB_ATTR_IEEE_APP_TABLE], 1639 netdev, ops->ieee_setapp ?: 1640 dcb_ieee_setapp); 1641 if (err) 1642 goto err; 1643 } 1644 1645 if (ieee[DCB_ATTR_DCB_APP_TRUST_TABLE]) { 1646 u8 selectors[IEEE_8021QAZ_APP_SEL_MAX + 1] = {0}; 1647 struct nlattr *attr; 1648 int nselectors = 0; 1649 int rem; 1650 1651 if (!ops->dcbnl_setapptrust) { 1652 err = -EOPNOTSUPP; 1653 goto err; 1654 } 1655 1656 nla_for_each_nested(attr, ieee[DCB_ATTR_DCB_APP_TRUST_TABLE], 1657 rem) { 1658 enum ieee_attrs_app type = nla_type(attr); 1659 u8 selector; 1660 int i; 1661 1662 if (!dcbnl_app_attr_type_validate(type) || 1663 nla_len(attr) != 1 || 1664 nselectors >= sizeof(selectors)) { 1665 err = -EINVAL; 1666 goto err; 1667 } 1668 1669 selector = nla_get_u8(attr); 1670 1671 if (!dcbnl_app_selector_validate(type, selector)) { 1672 err = -EINVAL; 1673 goto err; 1674 } 1675 1676 /* Duplicate selector ? */ 1677 for (i = 0; i < nselectors; i++) { 1678 if (selectors[i] == selector) { 1679 err = -EINVAL; 1680 goto err; 1681 } 1682 } 1683 1684 selectors[nselectors++] = selector; 1685 } 1686 1687 err = ops->dcbnl_setapptrust(netdev, selectors, nselectors); 1688 if (err) 1689 goto err; 1690 } 1691 1692 err: 1693 err = nla_put_u8(skb, DCB_ATTR_IEEE, err); 1694 dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0); 1695 return err; 1696 } 1697 1698 static int dcbnl_ieee_get(struct net_device *netdev, struct nlmsghdr *nlh, 1699 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1700 { 1701 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1702 1703 if (!ops) 1704 return -EOPNOTSUPP; 1705 1706 return dcbnl_ieee_fill(skb, netdev); 1707 } 1708 1709 static int dcbnl_ieee_del(struct net_device *netdev, struct nlmsghdr *nlh, 1710 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1711 { 1712 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1713 struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1]; 1714 int err; 1715 1716 if (!ops) 1717 return -EOPNOTSUPP; 1718 1719 if (!tb[DCB_ATTR_IEEE]) 1720 return -EINVAL; 1721 1722 err = nla_parse_nested_deprecated(ieee, DCB_ATTR_IEEE_MAX, 1723 tb[DCB_ATTR_IEEE], 1724 dcbnl_ieee_policy, NULL); 1725 if (err) 1726 return err; 1727 1728 if (ieee[DCB_ATTR_IEEE_APP_TABLE]) { 1729 err = dcbnl_app_table_setdel(ieee[DCB_ATTR_IEEE_APP_TABLE], 1730 netdev, ops->ieee_delapp ?: 1731 dcb_ieee_delapp); 1732 if (err) 1733 goto err; 1734 } 1735 1736 if (ieee[DCB_ATTR_DCB_REWR_TABLE]) { 1737 err = dcbnl_app_table_setdel(ieee[DCB_ATTR_DCB_REWR_TABLE], 1738 netdev, 1739 ops->dcbnl_delrewr ?: dcb_delrewr); 1740 if (err) 1741 goto err; 1742 } 1743 1744 err: 1745 err = nla_put_u8(skb, DCB_ATTR_IEEE, err); 1746 dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0); 1747 return err; 1748 } 1749 1750 1751 /* DCBX configuration */ 1752 static int dcbnl_getdcbx(struct net_device *netdev, struct nlmsghdr *nlh, 1753 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1754 { 1755 if (!netdev->dcbnl_ops->getdcbx) 1756 return -EOPNOTSUPP; 1757 1758 return nla_put_u8(skb, DCB_ATTR_DCBX, 1759 netdev->dcbnl_ops->getdcbx(netdev)); 1760 } 1761 1762 static int dcbnl_setdcbx(struct net_device *netdev, struct nlmsghdr *nlh, 1763 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1764 { 1765 u8 value; 1766 1767 if (!netdev->dcbnl_ops->setdcbx) 1768 return -EOPNOTSUPP; 1769 1770 if (!tb[DCB_ATTR_DCBX]) 1771 return -EINVAL; 1772 1773 value = nla_get_u8(tb[DCB_ATTR_DCBX]); 1774 1775 return nla_put_u8(skb, DCB_ATTR_DCBX, 1776 netdev->dcbnl_ops->setdcbx(netdev, value)); 1777 } 1778 1779 static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh, 1780 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1781 { 1782 struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest; 1783 u8 value; 1784 int ret, i; 1785 int getall = 0; 1786 1787 if (!netdev->dcbnl_ops->getfeatcfg) 1788 return -EOPNOTSUPP; 1789 1790 if (!tb[DCB_ATTR_FEATCFG]) 1791 return -EINVAL; 1792 1793 ret = nla_parse_nested_deprecated(data, DCB_FEATCFG_ATTR_MAX, 1794 tb[DCB_ATTR_FEATCFG], 1795 dcbnl_featcfg_nest, NULL); 1796 if (ret) 1797 return ret; 1798 1799 nest = nla_nest_start_noflag(skb, DCB_ATTR_FEATCFG); 1800 if (!nest) 1801 return -EMSGSIZE; 1802 1803 if (data[DCB_FEATCFG_ATTR_ALL]) 1804 getall = 1; 1805 1806 for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) { 1807 if (!getall && !data[i]) 1808 continue; 1809 1810 ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value); 1811 if (!ret) 1812 ret = nla_put_u8(skb, i, value); 1813 1814 if (ret) { 1815 nla_nest_cancel(skb, nest); 1816 goto nla_put_failure; 1817 } 1818 } 1819 nla_nest_end(skb, nest); 1820 1821 nla_put_failure: 1822 return ret; 1823 } 1824 1825 static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh, 1826 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1827 { 1828 struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1]; 1829 int ret, i; 1830 u8 value; 1831 1832 if (!netdev->dcbnl_ops->setfeatcfg) 1833 return -ENOTSUPP; 1834 1835 if (!tb[DCB_ATTR_FEATCFG]) 1836 return -EINVAL; 1837 1838 ret = nla_parse_nested_deprecated(data, DCB_FEATCFG_ATTR_MAX, 1839 tb[DCB_ATTR_FEATCFG], 1840 dcbnl_featcfg_nest, NULL); 1841 1842 if (ret) 1843 goto err; 1844 1845 for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) { 1846 if (data[i] == NULL) 1847 continue; 1848 1849 value = nla_get_u8(data[i]); 1850 1851 ret = netdev->dcbnl_ops->setfeatcfg(netdev, i, value); 1852 1853 if (ret) 1854 goto err; 1855 } 1856 err: 1857 ret = nla_put_u8(skb, DCB_ATTR_FEATCFG, ret); 1858 1859 return ret; 1860 } 1861 1862 /* Handle CEE DCBX GET commands. */ 1863 static int dcbnl_cee_get(struct net_device *netdev, struct nlmsghdr *nlh, 1864 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1865 { 1866 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1867 1868 if (!ops) 1869 return -EOPNOTSUPP; 1870 1871 return dcbnl_cee_fill(skb, netdev); 1872 } 1873 1874 struct reply_func { 1875 /* reply netlink message type */ 1876 int type; 1877 1878 /* function to fill message contents */ 1879 int (*cb)(struct net_device *, struct nlmsghdr *, u32, 1880 struct nlattr **, struct sk_buff *); 1881 }; 1882 1883 static const struct reply_func reply_funcs[DCB_CMD_MAX+1] = { 1884 [DCB_CMD_GSTATE] = { RTM_GETDCB, dcbnl_getstate }, 1885 [DCB_CMD_SSTATE] = { RTM_SETDCB, dcbnl_setstate }, 1886 [DCB_CMD_PFC_GCFG] = { RTM_GETDCB, dcbnl_getpfccfg }, 1887 [DCB_CMD_PFC_SCFG] = { RTM_SETDCB, dcbnl_setpfccfg }, 1888 [DCB_CMD_GPERM_HWADDR] = { RTM_GETDCB, dcbnl_getperm_hwaddr }, 1889 [DCB_CMD_GCAP] = { RTM_GETDCB, dcbnl_getcap }, 1890 [DCB_CMD_GNUMTCS] = { RTM_GETDCB, dcbnl_getnumtcs }, 1891 [DCB_CMD_SNUMTCS] = { RTM_SETDCB, dcbnl_setnumtcs }, 1892 [DCB_CMD_PFC_GSTATE] = { RTM_GETDCB, dcbnl_getpfcstate }, 1893 [DCB_CMD_PFC_SSTATE] = { RTM_SETDCB, dcbnl_setpfcstate }, 1894 [DCB_CMD_GAPP] = { RTM_GETDCB, dcbnl_getapp }, 1895 [DCB_CMD_SAPP] = { RTM_SETDCB, dcbnl_setapp }, 1896 [DCB_CMD_PGTX_GCFG] = { RTM_GETDCB, dcbnl_pgtx_getcfg }, 1897 [DCB_CMD_PGTX_SCFG] = { RTM_SETDCB, dcbnl_pgtx_setcfg }, 1898 [DCB_CMD_PGRX_GCFG] = { RTM_GETDCB, dcbnl_pgrx_getcfg }, 1899 [DCB_CMD_PGRX_SCFG] = { RTM_SETDCB, dcbnl_pgrx_setcfg }, 1900 [DCB_CMD_SET_ALL] = { RTM_SETDCB, dcbnl_setall }, 1901 [DCB_CMD_BCN_GCFG] = { RTM_GETDCB, dcbnl_bcn_getcfg }, 1902 [DCB_CMD_BCN_SCFG] = { RTM_SETDCB, dcbnl_bcn_setcfg }, 1903 [DCB_CMD_IEEE_GET] = { RTM_GETDCB, dcbnl_ieee_get }, 1904 [DCB_CMD_IEEE_SET] = { RTM_SETDCB, dcbnl_ieee_set }, 1905 [DCB_CMD_IEEE_DEL] = { RTM_SETDCB, dcbnl_ieee_del }, 1906 [DCB_CMD_GDCBX] = { RTM_GETDCB, dcbnl_getdcbx }, 1907 [DCB_CMD_SDCBX] = { RTM_SETDCB, dcbnl_setdcbx }, 1908 [DCB_CMD_GFEATCFG] = { RTM_GETDCB, dcbnl_getfeatcfg }, 1909 [DCB_CMD_SFEATCFG] = { RTM_SETDCB, dcbnl_setfeatcfg }, 1910 [DCB_CMD_CEE_GET] = { RTM_GETDCB, dcbnl_cee_get }, 1911 }; 1912 1913 static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, 1914 struct netlink_ext_ack *extack) 1915 { 1916 struct net *net = sock_net(skb->sk); 1917 struct net_device *netdev; 1918 struct dcbmsg *dcb = nlmsg_data(nlh); 1919 struct nlattr *tb[DCB_ATTR_MAX + 1]; 1920 u32 portid = NETLINK_CB(skb).portid; 1921 int ret = -EINVAL; 1922 struct sk_buff *reply_skb; 1923 struct nlmsghdr *reply_nlh = NULL; 1924 const struct reply_func *fn; 1925 1926 if ((nlh->nlmsg_type == RTM_SETDCB) && !netlink_capable(skb, CAP_NET_ADMIN)) 1927 return -EPERM; 1928 1929 ret = nlmsg_parse_deprecated(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX, 1930 dcbnl_rtnl_policy, extack); 1931 if (ret < 0) 1932 return ret; 1933 1934 if (dcb->cmd > DCB_CMD_MAX) 1935 return -EINVAL; 1936 1937 /* check if a reply function has been defined for the command */ 1938 fn = &reply_funcs[dcb->cmd]; 1939 if (!fn->cb) 1940 return -EOPNOTSUPP; 1941 if (fn->type == RTM_SETDCB && !netlink_capable(skb, CAP_NET_ADMIN)) 1942 return -EPERM; 1943 1944 if (!tb[DCB_ATTR_IFNAME]) 1945 return -EINVAL; 1946 1947 netdev = __dev_get_by_name(net, nla_data(tb[DCB_ATTR_IFNAME])); 1948 if (!netdev) 1949 return -ENODEV; 1950 1951 if (!netdev->dcbnl_ops) 1952 return -EOPNOTSUPP; 1953 1954 reply_skb = dcbnl_newmsg(fn->type, dcb->cmd, portid, nlh->nlmsg_seq, 1955 nlh->nlmsg_flags, &reply_nlh); 1956 if (!reply_skb) 1957 return -ENOMEM; 1958 1959 ret = fn->cb(netdev, nlh, nlh->nlmsg_seq, tb, reply_skb); 1960 if (ret < 0) { 1961 nlmsg_free(reply_skb); 1962 goto out; 1963 } 1964 1965 nlmsg_end(reply_skb, reply_nlh); 1966 1967 ret = rtnl_unicast(reply_skb, net, portid); 1968 out: 1969 return ret; 1970 } 1971 1972 static struct dcb_app_type *dcb_rewr_lookup(const struct dcb_app *app, 1973 int ifindex, int proto) 1974 { 1975 struct dcb_app_type *itr; 1976 1977 list_for_each_entry(itr, &dcb_rewr_list, list) { 1978 if (itr->app.selector == app->selector && 1979 itr->app.priority == app->priority && 1980 itr->ifindex == ifindex && 1981 ((proto == -1) || itr->app.protocol == proto)) 1982 return itr; 1983 } 1984 1985 return NULL; 1986 } 1987 1988 static struct dcb_app_type *dcb_app_lookup(const struct dcb_app *app, 1989 int ifindex, int prio) 1990 { 1991 struct dcb_app_type *itr; 1992 1993 list_for_each_entry(itr, &dcb_app_list, list) { 1994 if (itr->app.selector == app->selector && 1995 itr->app.protocol == app->protocol && 1996 itr->ifindex == ifindex && 1997 ((prio == -1) || itr->app.priority == prio)) 1998 return itr; 1999 } 2000 2001 return NULL; 2002 } 2003 2004 static int dcb_app_add(struct list_head *list, const struct dcb_app *app, 2005 int ifindex) 2006 { 2007 struct dcb_app_type *entry; 2008 2009 entry = kmalloc(sizeof(*entry), GFP_ATOMIC); 2010 if (!entry) 2011 return -ENOMEM; 2012 2013 memcpy(&entry->app, app, sizeof(*app)); 2014 entry->ifindex = ifindex; 2015 list_add(&entry->list, list); 2016 2017 return 0; 2018 } 2019 2020 /** 2021 * dcb_getapp - retrieve the DCBX application user priority 2022 * @dev: network interface 2023 * @app: application to get user priority of 2024 * 2025 * On success returns a non-zero 802.1p user priority bitmap 2026 * otherwise returns 0 as the invalid user priority bitmap to 2027 * indicate an error. 2028 */ 2029 u8 dcb_getapp(struct net_device *dev, struct dcb_app *app) 2030 { 2031 struct dcb_app_type *itr; 2032 u8 prio = 0; 2033 2034 spin_lock_bh(&dcb_lock); 2035 itr = dcb_app_lookup(app, dev->ifindex, -1); 2036 if (itr) 2037 prio = itr->app.priority; 2038 spin_unlock_bh(&dcb_lock); 2039 2040 return prio; 2041 } 2042 EXPORT_SYMBOL(dcb_getapp); 2043 2044 /** 2045 * dcb_setapp - add CEE dcb application data to app list 2046 * @dev: network interface 2047 * @new: application data to add 2048 * 2049 * Priority 0 is an invalid priority in CEE spec. This routine 2050 * removes applications from the app list if the priority is 2051 * set to zero. Priority is expected to be 8-bit 802.1p user priority bitmap 2052 */ 2053 int dcb_setapp(struct net_device *dev, struct dcb_app *new) 2054 { 2055 struct dcb_app_type *itr; 2056 struct dcb_app_type event; 2057 int err = 0; 2058 2059 event.ifindex = dev->ifindex; 2060 memcpy(&event.app, new, sizeof(event.app)); 2061 if (dev->dcbnl_ops->getdcbx) 2062 event.dcbx = dev->dcbnl_ops->getdcbx(dev); 2063 2064 spin_lock_bh(&dcb_lock); 2065 /* Search for existing match and replace */ 2066 itr = dcb_app_lookup(new, dev->ifindex, -1); 2067 if (itr) { 2068 if (new->priority) 2069 itr->app.priority = new->priority; 2070 else { 2071 list_del(&itr->list); 2072 kfree(itr); 2073 } 2074 goto out; 2075 } 2076 /* App type does not exist add new application type */ 2077 if (new->priority) 2078 err = dcb_app_add(&dcb_app_list, new, dev->ifindex); 2079 out: 2080 spin_unlock_bh(&dcb_lock); 2081 if (!err) 2082 call_dcbevent_notifiers(DCB_APP_EVENT, &event); 2083 return err; 2084 } 2085 EXPORT_SYMBOL(dcb_setapp); 2086 2087 /** 2088 * dcb_ieee_getapp_mask - retrieve the IEEE DCB application priority 2089 * @dev: network interface 2090 * @app: where to store the retrieve application data 2091 * 2092 * Helper routine which on success returns a non-zero 802.1Qaz user 2093 * priority bitmap otherwise returns 0 to indicate the dcb_app was 2094 * not found in APP list. 2095 */ 2096 u8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app) 2097 { 2098 struct dcb_app_type *itr; 2099 u8 prio = 0; 2100 2101 spin_lock_bh(&dcb_lock); 2102 itr = dcb_app_lookup(app, dev->ifindex, -1); 2103 if (itr) 2104 prio |= 1 << itr->app.priority; 2105 spin_unlock_bh(&dcb_lock); 2106 2107 return prio; 2108 } 2109 EXPORT_SYMBOL(dcb_ieee_getapp_mask); 2110 2111 /* Get protocol value from rewrite entry. */ 2112 u16 dcb_getrewr(struct net_device *dev, struct dcb_app *app) 2113 { 2114 struct dcb_app_type *itr; 2115 u16 proto = 0; 2116 2117 spin_lock_bh(&dcb_lock); 2118 itr = dcb_rewr_lookup(app, dev->ifindex, -1); 2119 if (itr) 2120 proto = itr->app.protocol; 2121 spin_unlock_bh(&dcb_lock); 2122 2123 return proto; 2124 } 2125 EXPORT_SYMBOL(dcb_getrewr); 2126 2127 /* Add rewrite entry to the rewrite list. */ 2128 int dcb_setrewr(struct net_device *dev, struct dcb_app *new) 2129 { 2130 int err; 2131 2132 spin_lock_bh(&dcb_lock); 2133 /* Search for existing match and abort if found. */ 2134 if (dcb_rewr_lookup(new, dev->ifindex, new->protocol)) { 2135 err = -EEXIST; 2136 goto out; 2137 } 2138 2139 err = dcb_app_add(&dcb_rewr_list, new, dev->ifindex); 2140 out: 2141 spin_unlock_bh(&dcb_lock); 2142 2143 return err; 2144 } 2145 EXPORT_SYMBOL(dcb_setrewr); 2146 2147 /* Delete rewrite entry from the rewrite list. */ 2148 int dcb_delrewr(struct net_device *dev, struct dcb_app *del) 2149 { 2150 struct dcb_app_type *itr; 2151 int err = -ENOENT; 2152 2153 spin_lock_bh(&dcb_lock); 2154 /* Search for existing match and remove it. */ 2155 itr = dcb_rewr_lookup(del, dev->ifindex, del->protocol); 2156 if (itr) { 2157 list_del(&itr->list); 2158 kfree(itr); 2159 err = 0; 2160 } 2161 2162 spin_unlock_bh(&dcb_lock); 2163 2164 return err; 2165 } 2166 EXPORT_SYMBOL(dcb_delrewr); 2167 2168 /** 2169 * dcb_ieee_setapp - add IEEE dcb application data to app list 2170 * @dev: network interface 2171 * @new: application data to add 2172 * 2173 * This adds Application data to the list. Multiple application 2174 * entries may exists for the same selector and protocol as long 2175 * as the priorities are different. Priority is expected to be a 2176 * 3-bit unsigned integer 2177 */ 2178 int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new) 2179 { 2180 struct dcb_app_type event; 2181 int err = 0; 2182 2183 event.ifindex = dev->ifindex; 2184 memcpy(&event.app, new, sizeof(event.app)); 2185 if (dev->dcbnl_ops->getdcbx) 2186 event.dcbx = dev->dcbnl_ops->getdcbx(dev); 2187 2188 spin_lock_bh(&dcb_lock); 2189 /* Search for existing match and abort if found */ 2190 if (dcb_app_lookup(new, dev->ifindex, new->priority)) { 2191 err = -EEXIST; 2192 goto out; 2193 } 2194 2195 err = dcb_app_add(&dcb_app_list, new, dev->ifindex); 2196 out: 2197 spin_unlock_bh(&dcb_lock); 2198 if (!err) 2199 call_dcbevent_notifiers(DCB_APP_EVENT, &event); 2200 return err; 2201 } 2202 EXPORT_SYMBOL(dcb_ieee_setapp); 2203 2204 /** 2205 * dcb_ieee_delapp - delete IEEE dcb application data from list 2206 * @dev: network interface 2207 * @del: application data to delete 2208 * 2209 * This removes a matching APP data from the APP list 2210 */ 2211 int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del) 2212 { 2213 struct dcb_app_type *itr; 2214 struct dcb_app_type event; 2215 int err = -ENOENT; 2216 2217 event.ifindex = dev->ifindex; 2218 memcpy(&event.app, del, sizeof(event.app)); 2219 if (dev->dcbnl_ops->getdcbx) 2220 event.dcbx = dev->dcbnl_ops->getdcbx(dev); 2221 2222 spin_lock_bh(&dcb_lock); 2223 /* Search for existing match and remove it. */ 2224 if ((itr = dcb_app_lookup(del, dev->ifindex, del->priority))) { 2225 list_del(&itr->list); 2226 kfree(itr); 2227 err = 0; 2228 } 2229 2230 spin_unlock_bh(&dcb_lock); 2231 if (!err) 2232 call_dcbevent_notifiers(DCB_APP_EVENT, &event); 2233 return err; 2234 } 2235 EXPORT_SYMBOL(dcb_ieee_delapp); 2236 2237 /* dcb_getrewr_prio_pcp_mask_map - For a given device, find mapping from 2238 * priorities to the PCP and DEI values assigned to that priority. 2239 */ 2240 void dcb_getrewr_prio_pcp_mask_map(const struct net_device *dev, 2241 struct dcb_rewr_prio_pcp_map *p_map) 2242 { 2243 int ifindex = dev->ifindex; 2244 struct dcb_app_type *itr; 2245 u8 prio; 2246 2247 memset(p_map->map, 0, sizeof(p_map->map)); 2248 2249 spin_lock_bh(&dcb_lock); 2250 list_for_each_entry(itr, &dcb_rewr_list, list) { 2251 if (itr->ifindex == ifindex && 2252 itr->app.selector == DCB_APP_SEL_PCP && 2253 itr->app.protocol < 16 && 2254 itr->app.priority < IEEE_8021QAZ_MAX_TCS) { 2255 prio = itr->app.priority; 2256 p_map->map[prio] |= 1 << itr->app.protocol; 2257 } 2258 } 2259 spin_unlock_bh(&dcb_lock); 2260 } 2261 EXPORT_SYMBOL(dcb_getrewr_prio_pcp_mask_map); 2262 2263 /* dcb_getrewr_prio_dscp_mask_map - For a given device, find mapping from 2264 * priorities to the DSCP values assigned to that priority. 2265 */ 2266 void dcb_getrewr_prio_dscp_mask_map(const struct net_device *dev, 2267 struct dcb_ieee_app_prio_map *p_map) 2268 { 2269 int ifindex = dev->ifindex; 2270 struct dcb_app_type *itr; 2271 u8 prio; 2272 2273 memset(p_map->map, 0, sizeof(p_map->map)); 2274 2275 spin_lock_bh(&dcb_lock); 2276 list_for_each_entry(itr, &dcb_rewr_list, list) { 2277 if (itr->ifindex == ifindex && 2278 itr->app.selector == IEEE_8021QAZ_APP_SEL_DSCP && 2279 itr->app.protocol < 64 && 2280 itr->app.priority < IEEE_8021QAZ_MAX_TCS) { 2281 prio = itr->app.priority; 2282 p_map->map[prio] |= 1ULL << itr->app.protocol; 2283 } 2284 } 2285 spin_unlock_bh(&dcb_lock); 2286 } 2287 EXPORT_SYMBOL(dcb_getrewr_prio_dscp_mask_map); 2288 2289 /* 2290 * dcb_ieee_getapp_prio_dscp_mask_map - For a given device, find mapping from 2291 * priorities to the DSCP values assigned to that priority. Initialize p_map 2292 * such that each map element holds a bit mask of DSCP values configured for 2293 * that priority by APP entries. 2294 */ 2295 void dcb_ieee_getapp_prio_dscp_mask_map(const struct net_device *dev, 2296 struct dcb_ieee_app_prio_map *p_map) 2297 { 2298 int ifindex = dev->ifindex; 2299 struct dcb_app_type *itr; 2300 u8 prio; 2301 2302 memset(p_map->map, 0, sizeof(p_map->map)); 2303 2304 spin_lock_bh(&dcb_lock); 2305 list_for_each_entry(itr, &dcb_app_list, list) { 2306 if (itr->ifindex == ifindex && 2307 itr->app.selector == IEEE_8021QAZ_APP_SEL_DSCP && 2308 itr->app.protocol < 64 && 2309 itr->app.priority < IEEE_8021QAZ_MAX_TCS) { 2310 prio = itr->app.priority; 2311 p_map->map[prio] |= 1ULL << itr->app.protocol; 2312 } 2313 } 2314 spin_unlock_bh(&dcb_lock); 2315 } 2316 EXPORT_SYMBOL(dcb_ieee_getapp_prio_dscp_mask_map); 2317 2318 /* 2319 * dcb_ieee_getapp_dscp_prio_mask_map - For a given device, find mapping from 2320 * DSCP values to the priorities assigned to that DSCP value. Initialize p_map 2321 * such that each map element holds a bit mask of priorities configured for a 2322 * given DSCP value by APP entries. 2323 */ 2324 void 2325 dcb_ieee_getapp_dscp_prio_mask_map(const struct net_device *dev, 2326 struct dcb_ieee_app_dscp_map *p_map) 2327 { 2328 int ifindex = dev->ifindex; 2329 struct dcb_app_type *itr; 2330 2331 memset(p_map->map, 0, sizeof(p_map->map)); 2332 2333 spin_lock_bh(&dcb_lock); 2334 list_for_each_entry(itr, &dcb_app_list, list) { 2335 if (itr->ifindex == ifindex && 2336 itr->app.selector == IEEE_8021QAZ_APP_SEL_DSCP && 2337 itr->app.protocol < 64 && 2338 itr->app.priority < IEEE_8021QAZ_MAX_TCS) 2339 p_map->map[itr->app.protocol] |= 1 << itr->app.priority; 2340 } 2341 spin_unlock_bh(&dcb_lock); 2342 } 2343 EXPORT_SYMBOL(dcb_ieee_getapp_dscp_prio_mask_map); 2344 2345 /* 2346 * Per 802.1Q-2014, the selector value of 1 is used for matching on Ethernet 2347 * type, with valid PID values >= 1536. A special meaning is then assigned to 2348 * protocol value of 0: "default priority. For use when priority is not 2349 * otherwise specified". 2350 * 2351 * dcb_ieee_getapp_default_prio_mask - For a given device, find all APP entries 2352 * of the form {$PRIO, ETHERTYPE, 0} and construct a bit mask of all default 2353 * priorities set by these entries. 2354 */ 2355 u8 dcb_ieee_getapp_default_prio_mask(const struct net_device *dev) 2356 { 2357 int ifindex = dev->ifindex; 2358 struct dcb_app_type *itr; 2359 u8 mask = 0; 2360 2361 spin_lock_bh(&dcb_lock); 2362 list_for_each_entry(itr, &dcb_app_list, list) { 2363 if (itr->ifindex == ifindex && 2364 itr->app.selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE && 2365 itr->app.protocol == 0 && 2366 itr->app.priority < IEEE_8021QAZ_MAX_TCS) 2367 mask |= 1 << itr->app.priority; 2368 } 2369 spin_unlock_bh(&dcb_lock); 2370 2371 return mask; 2372 } 2373 EXPORT_SYMBOL(dcb_ieee_getapp_default_prio_mask); 2374 2375 static void dcbnl_flush_dev(struct net_device *dev) 2376 { 2377 struct dcb_app_type *itr, *tmp; 2378 2379 spin_lock_bh(&dcb_lock); 2380 2381 list_for_each_entry_safe(itr, tmp, &dcb_app_list, list) { 2382 if (itr->ifindex == dev->ifindex) { 2383 list_del(&itr->list); 2384 kfree(itr); 2385 } 2386 } 2387 2388 spin_unlock_bh(&dcb_lock); 2389 } 2390 2391 static int dcbnl_netdevice_event(struct notifier_block *nb, 2392 unsigned long event, void *ptr) 2393 { 2394 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 2395 2396 switch (event) { 2397 case NETDEV_UNREGISTER: 2398 if (!dev->dcbnl_ops) 2399 return NOTIFY_DONE; 2400 2401 dcbnl_flush_dev(dev); 2402 2403 return NOTIFY_OK; 2404 default: 2405 return NOTIFY_DONE; 2406 } 2407 } 2408 2409 static struct notifier_block dcbnl_nb __read_mostly = { 2410 .notifier_call = dcbnl_netdevice_event, 2411 }; 2412 2413 static const struct rtnl_msg_handler dcbnl_rtnl_msg_handlers[] __initconst = { 2414 {.msgtype = RTM_GETDCB, .doit = dcb_doit}, 2415 {.msgtype = RTM_SETDCB, .doit = dcb_doit}, 2416 }; 2417 2418 static int __init dcbnl_init(void) 2419 { 2420 int err; 2421 2422 err = register_netdevice_notifier(&dcbnl_nb); 2423 if (err) 2424 return err; 2425 2426 rtnl_register_many(dcbnl_rtnl_msg_handlers); 2427 2428 return 0; 2429 } 2430 device_initcall(dcbnl_init); 2431