1 /* 2 * Copyright (c) 2008, Intel Corporation. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * You should have received a copy of the GNU General Public License along with 14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 15 * Place - Suite 330, Boston, MA 02111-1307 USA. 16 * 17 * Author: Lucy Liu <lucy.liu@intel.com> 18 */ 19 20 #include <linux/netdevice.h> 21 #include <linux/netlink.h> 22 #include <net/netlink.h> 23 #include <net/rtnetlink.h> 24 #include <linux/dcbnl.h> 25 #include <linux/rtnetlink.h> 26 #include <net/sock.h> 27 28 /** 29 * Data Center Bridging (DCB) is a collection of Ethernet enhancements 30 * intended to allow network traffic with differing requirements 31 * (highly reliable, no drops vs. best effort vs. low latency) to operate 32 * and co-exist on Ethernet. Current DCB features are: 33 * 34 * Enhanced Transmission Selection (aka Priority Grouping [PG]) - provides a 35 * framework for assigning bandwidth guarantees to traffic classes. 36 * 37 * Priority-based Flow Control (PFC) - provides a flow control mechanism which 38 * can work independently for each 802.1p priority. 39 * 40 * Congestion Notification - provides a mechanism for end-to-end congestion 41 * control for protocols which do not have built-in congestion management. 42 * 43 * More information about the emerging standards for these Ethernet features 44 * can be found at: http://www.ieee802.org/1/pages/dcbridges.html 45 * 46 * This file implements an rtnetlink interface to allow configuration of DCB 47 * features for capable devices. 48 */ 49 50 MODULE_AUTHOR("Lucy Liu, <lucy.liu@intel.com>"); 51 MODULE_DESCRIPTION("Data Center Bridging netlink interface"); 52 MODULE_LICENSE("GPL"); 53 54 /**************** DCB attribute policies *************************************/ 55 56 /* DCB netlink attributes policy */ 57 static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { 58 [DCB_ATTR_IFNAME] = {.type = NLA_NUL_STRING, .len = IFNAMSIZ - 1}, 59 [DCB_ATTR_STATE] = {.type = NLA_U8}, 60 [DCB_ATTR_PFC_CFG] = {.type = NLA_NESTED}, 61 [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED}, 62 [DCB_ATTR_SET_ALL] = {.type = NLA_U8}, 63 [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG}, 64 [DCB_ATTR_CAP] = {.type = NLA_NESTED}, 65 [DCB_ATTR_PFC_STATE] = {.type = NLA_U8}, 66 [DCB_ATTR_BCN] = {.type = NLA_NESTED}, 67 [DCB_ATTR_APP] = {.type = NLA_NESTED}, 68 }; 69 70 /* DCB priority flow control to User Priority nested attributes */ 71 static struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = { 72 [DCB_PFC_UP_ATTR_0] = {.type = NLA_U8}, 73 [DCB_PFC_UP_ATTR_1] = {.type = NLA_U8}, 74 [DCB_PFC_UP_ATTR_2] = {.type = NLA_U8}, 75 [DCB_PFC_UP_ATTR_3] = {.type = NLA_U8}, 76 [DCB_PFC_UP_ATTR_4] = {.type = NLA_U8}, 77 [DCB_PFC_UP_ATTR_5] = {.type = NLA_U8}, 78 [DCB_PFC_UP_ATTR_6] = {.type = NLA_U8}, 79 [DCB_PFC_UP_ATTR_7] = {.type = NLA_U8}, 80 [DCB_PFC_UP_ATTR_ALL] = {.type = NLA_FLAG}, 81 }; 82 83 /* DCB priority grouping nested attributes */ 84 static struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = { 85 [DCB_PG_ATTR_TC_0] = {.type = NLA_NESTED}, 86 [DCB_PG_ATTR_TC_1] = {.type = NLA_NESTED}, 87 [DCB_PG_ATTR_TC_2] = {.type = NLA_NESTED}, 88 [DCB_PG_ATTR_TC_3] = {.type = NLA_NESTED}, 89 [DCB_PG_ATTR_TC_4] = {.type = NLA_NESTED}, 90 [DCB_PG_ATTR_TC_5] = {.type = NLA_NESTED}, 91 [DCB_PG_ATTR_TC_6] = {.type = NLA_NESTED}, 92 [DCB_PG_ATTR_TC_7] = {.type = NLA_NESTED}, 93 [DCB_PG_ATTR_TC_ALL] = {.type = NLA_NESTED}, 94 [DCB_PG_ATTR_BW_ID_0] = {.type = NLA_U8}, 95 [DCB_PG_ATTR_BW_ID_1] = {.type = NLA_U8}, 96 [DCB_PG_ATTR_BW_ID_2] = {.type = NLA_U8}, 97 [DCB_PG_ATTR_BW_ID_3] = {.type = NLA_U8}, 98 [DCB_PG_ATTR_BW_ID_4] = {.type = NLA_U8}, 99 [DCB_PG_ATTR_BW_ID_5] = {.type = NLA_U8}, 100 [DCB_PG_ATTR_BW_ID_6] = {.type = NLA_U8}, 101 [DCB_PG_ATTR_BW_ID_7] = {.type = NLA_U8}, 102 [DCB_PG_ATTR_BW_ID_ALL] = {.type = NLA_FLAG}, 103 }; 104 105 /* DCB traffic class nested attributes. */ 106 static struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = { 107 [DCB_TC_ATTR_PARAM_PGID] = {.type = NLA_U8}, 108 [DCB_TC_ATTR_PARAM_UP_MAPPING] = {.type = NLA_U8}, 109 [DCB_TC_ATTR_PARAM_STRICT_PRIO] = {.type = NLA_U8}, 110 [DCB_TC_ATTR_PARAM_BW_PCT] = {.type = NLA_U8}, 111 [DCB_TC_ATTR_PARAM_ALL] = {.type = NLA_FLAG}, 112 }; 113 114 /* DCB capabilities nested attributes. */ 115 static struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = { 116 [DCB_CAP_ATTR_ALL] = {.type = NLA_FLAG}, 117 [DCB_CAP_ATTR_PG] = {.type = NLA_U8}, 118 [DCB_CAP_ATTR_PFC] = {.type = NLA_U8}, 119 [DCB_CAP_ATTR_UP2TC] = {.type = NLA_U8}, 120 [DCB_CAP_ATTR_PG_TCS] = {.type = NLA_U8}, 121 [DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8}, 122 [DCB_CAP_ATTR_GSP] = {.type = NLA_U8}, 123 [DCB_CAP_ATTR_BCN] = {.type = NLA_U8}, 124 }; 125 126 /* DCB capabilities nested attributes. */ 127 static struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = { 128 [DCB_NUMTCS_ATTR_ALL] = {.type = NLA_FLAG}, 129 [DCB_NUMTCS_ATTR_PG] = {.type = NLA_U8}, 130 [DCB_NUMTCS_ATTR_PFC] = {.type = NLA_U8}, 131 }; 132 133 /* DCB BCN nested attributes. */ 134 static struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = { 135 [DCB_BCN_ATTR_RP_0] = {.type = NLA_U8}, 136 [DCB_BCN_ATTR_RP_1] = {.type = NLA_U8}, 137 [DCB_BCN_ATTR_RP_2] = {.type = NLA_U8}, 138 [DCB_BCN_ATTR_RP_3] = {.type = NLA_U8}, 139 [DCB_BCN_ATTR_RP_4] = {.type = NLA_U8}, 140 [DCB_BCN_ATTR_RP_5] = {.type = NLA_U8}, 141 [DCB_BCN_ATTR_RP_6] = {.type = NLA_U8}, 142 [DCB_BCN_ATTR_RP_7] = {.type = NLA_U8}, 143 [DCB_BCN_ATTR_RP_ALL] = {.type = NLA_FLAG}, 144 [DCB_BCN_ATTR_BCNA_0] = {.type = NLA_U32}, 145 [DCB_BCN_ATTR_BCNA_1] = {.type = NLA_U32}, 146 [DCB_BCN_ATTR_ALPHA] = {.type = NLA_U32}, 147 [DCB_BCN_ATTR_BETA] = {.type = NLA_U32}, 148 [DCB_BCN_ATTR_GD] = {.type = NLA_U32}, 149 [DCB_BCN_ATTR_GI] = {.type = NLA_U32}, 150 [DCB_BCN_ATTR_TMAX] = {.type = NLA_U32}, 151 [DCB_BCN_ATTR_TD] = {.type = NLA_U32}, 152 [DCB_BCN_ATTR_RMIN] = {.type = NLA_U32}, 153 [DCB_BCN_ATTR_W] = {.type = NLA_U32}, 154 [DCB_BCN_ATTR_RD] = {.type = NLA_U32}, 155 [DCB_BCN_ATTR_RU] = {.type = NLA_U32}, 156 [DCB_BCN_ATTR_WRTT] = {.type = NLA_U32}, 157 [DCB_BCN_ATTR_RI] = {.type = NLA_U32}, 158 [DCB_BCN_ATTR_C] = {.type = NLA_U32}, 159 [DCB_BCN_ATTR_ALL] = {.type = NLA_FLAG}, 160 }; 161 162 /* DCB APP nested attributes. */ 163 static struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = { 164 [DCB_APP_ATTR_IDTYPE] = {.type = NLA_U8}, 165 [DCB_APP_ATTR_ID] = {.type = NLA_U16}, 166 [DCB_APP_ATTR_PRIORITY] = {.type = NLA_U8}, 167 }; 168 169 /* standard netlink reply call */ 170 static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, 171 u32 seq, u16 flags) 172 { 173 struct sk_buff *dcbnl_skb; 174 struct dcbmsg *dcb; 175 struct nlmsghdr *nlh; 176 int ret = -EINVAL; 177 178 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 179 if (!dcbnl_skb) 180 return ret; 181 182 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags); 183 184 dcb = NLMSG_DATA(nlh); 185 dcb->dcb_family = AF_UNSPEC; 186 dcb->cmd = cmd; 187 dcb->dcb_pad = 0; 188 189 ret = nla_put_u8(dcbnl_skb, attr, value); 190 if (ret) 191 goto err; 192 193 /* end the message, assign the nlmsg_len. */ 194 nlmsg_end(dcbnl_skb, nlh); 195 ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 196 if (ret) 197 goto err; 198 199 return 0; 200 nlmsg_failure: 201 err: 202 kfree_skb(dcbnl_skb); 203 return ret; 204 } 205 206 static int dcbnl_getstate(struct net_device *netdev, struct nlattr **tb, 207 u32 pid, u32 seq, u16 flags) 208 { 209 int ret = -EINVAL; 210 211 /* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */ 212 if (!netdev->dcbnl_ops->getstate) 213 return ret; 214 215 ret = dcbnl_reply(netdev->dcbnl_ops->getstate(netdev), RTM_GETDCB, 216 DCB_CMD_GSTATE, DCB_ATTR_STATE, pid, seq, flags); 217 218 return ret; 219 } 220 221 static int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb, 222 u32 pid, u32 seq, u16 flags) 223 { 224 struct sk_buff *dcbnl_skb; 225 struct nlmsghdr *nlh; 226 struct dcbmsg *dcb; 227 struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest; 228 u8 value; 229 int ret = -EINVAL; 230 int i; 231 int getall = 0; 232 233 if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->getpfccfg) 234 return ret; 235 236 ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, 237 tb[DCB_ATTR_PFC_CFG], 238 dcbnl_pfc_up_nest); 239 if (ret) 240 goto err_out; 241 242 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 243 if (!dcbnl_skb) 244 goto err_out; 245 246 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 247 248 dcb = NLMSG_DATA(nlh); 249 dcb->dcb_family = AF_UNSPEC; 250 dcb->cmd = DCB_CMD_PFC_GCFG; 251 252 nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG); 253 if (!nest) 254 goto err; 255 256 if (data[DCB_PFC_UP_ATTR_ALL]) 257 getall = 1; 258 259 for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { 260 if (!getall && !data[i]) 261 continue; 262 263 netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, 264 &value); 265 ret = nla_put_u8(dcbnl_skb, i, value); 266 267 if (ret) { 268 nla_nest_cancel(dcbnl_skb, nest); 269 goto err; 270 } 271 } 272 nla_nest_end(dcbnl_skb, nest); 273 274 nlmsg_end(dcbnl_skb, nlh); 275 276 ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 277 if (ret) 278 goto err; 279 280 return 0; 281 nlmsg_failure: 282 err: 283 kfree_skb(dcbnl_skb); 284 err_out: 285 return -EINVAL; 286 } 287 288 static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb, 289 u32 pid, u32 seq, u16 flags) 290 { 291 struct sk_buff *dcbnl_skb; 292 struct nlmsghdr *nlh; 293 struct dcbmsg *dcb; 294 u8 perm_addr[MAX_ADDR_LEN]; 295 int ret = -EINVAL; 296 297 if (!netdev->dcbnl_ops->getpermhwaddr) 298 return ret; 299 300 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 301 if (!dcbnl_skb) 302 goto err_out; 303 304 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 305 306 dcb = NLMSG_DATA(nlh); 307 dcb->dcb_family = AF_UNSPEC; 308 dcb->cmd = DCB_CMD_GPERM_HWADDR; 309 310 netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr); 311 312 ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), 313 perm_addr); 314 315 nlmsg_end(dcbnl_skb, nlh); 316 317 ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 318 if (ret) 319 goto err; 320 321 return 0; 322 323 nlmsg_failure: 324 err: 325 kfree_skb(dcbnl_skb); 326 err_out: 327 return -EINVAL; 328 } 329 330 static int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb, 331 u32 pid, u32 seq, u16 flags) 332 { 333 struct sk_buff *dcbnl_skb; 334 struct nlmsghdr *nlh; 335 struct dcbmsg *dcb; 336 struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest; 337 u8 value; 338 int ret = -EINVAL; 339 int i; 340 int getall = 0; 341 342 if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap) 343 return ret; 344 345 ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP], 346 dcbnl_cap_nest); 347 if (ret) 348 goto err_out; 349 350 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 351 if (!dcbnl_skb) 352 goto err_out; 353 354 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 355 356 dcb = NLMSG_DATA(nlh); 357 dcb->dcb_family = AF_UNSPEC; 358 dcb->cmd = DCB_CMD_GCAP; 359 360 nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP); 361 if (!nest) 362 goto err; 363 364 if (data[DCB_CAP_ATTR_ALL]) 365 getall = 1; 366 367 for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) { 368 if (!getall && !data[i]) 369 continue; 370 371 if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) { 372 ret = nla_put_u8(dcbnl_skb, i, value); 373 374 if (ret) { 375 nla_nest_cancel(dcbnl_skb, nest); 376 goto err; 377 } 378 } 379 } 380 nla_nest_end(dcbnl_skb, nest); 381 382 nlmsg_end(dcbnl_skb, nlh); 383 384 ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 385 if (ret) 386 goto err; 387 388 return 0; 389 nlmsg_failure: 390 err: 391 kfree_skb(dcbnl_skb); 392 err_out: 393 return -EINVAL; 394 } 395 396 static int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb, 397 u32 pid, u32 seq, u16 flags) 398 { 399 struct sk_buff *dcbnl_skb; 400 struct nlmsghdr *nlh; 401 struct dcbmsg *dcb; 402 struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest; 403 u8 value; 404 int ret = -EINVAL; 405 int i; 406 int getall = 0; 407 408 if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs) 409 return ret; 410 411 ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], 412 dcbnl_numtcs_nest); 413 if (ret) { 414 ret = -EINVAL; 415 goto err_out; 416 } 417 418 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 419 if (!dcbnl_skb) { 420 ret = -EINVAL; 421 goto err_out; 422 } 423 424 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 425 426 dcb = NLMSG_DATA(nlh); 427 dcb->dcb_family = AF_UNSPEC; 428 dcb->cmd = DCB_CMD_GNUMTCS; 429 430 nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS); 431 if (!nest) { 432 ret = -EINVAL; 433 goto err; 434 } 435 436 if (data[DCB_NUMTCS_ATTR_ALL]) 437 getall = 1; 438 439 for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { 440 if (!getall && !data[i]) 441 continue; 442 443 ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value); 444 if (!ret) { 445 ret = nla_put_u8(dcbnl_skb, i, value); 446 447 if (ret) { 448 nla_nest_cancel(dcbnl_skb, nest); 449 ret = -EINVAL; 450 goto err; 451 } 452 } else { 453 goto err; 454 } 455 } 456 nla_nest_end(dcbnl_skb, nest); 457 458 nlmsg_end(dcbnl_skb, nlh); 459 460 ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 461 if (ret) { 462 ret = -EINVAL; 463 goto err; 464 } 465 466 return 0; 467 nlmsg_failure: 468 err: 469 kfree_skb(dcbnl_skb); 470 err_out: 471 return ret; 472 } 473 474 static int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb, 475 u32 pid, u32 seq, u16 flags) 476 { 477 struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1]; 478 int ret = -EINVAL; 479 u8 value; 480 int i; 481 482 if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setnumtcs) 483 return ret; 484 485 ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], 486 dcbnl_numtcs_nest); 487 488 if (ret) { 489 ret = -EINVAL; 490 goto err; 491 } 492 493 for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { 494 if (data[i] == NULL) 495 continue; 496 497 value = nla_get_u8(data[i]); 498 499 ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value); 500 501 if (ret) 502 goto operr; 503 } 504 505 operr: 506 ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS, 507 DCB_ATTR_NUMTCS, pid, seq, flags); 508 509 err: 510 return ret; 511 } 512 513 static int dcbnl_getpfcstate(struct net_device *netdev, struct nlattr **tb, 514 u32 pid, u32 seq, u16 flags) 515 { 516 int ret = -EINVAL; 517 518 if (!netdev->dcbnl_ops->getpfcstate) 519 return ret; 520 521 ret = dcbnl_reply(netdev->dcbnl_ops->getpfcstate(netdev), RTM_GETDCB, 522 DCB_CMD_PFC_GSTATE, DCB_ATTR_PFC_STATE, 523 pid, seq, flags); 524 525 return ret; 526 } 527 528 static int dcbnl_setpfcstate(struct net_device *netdev, struct nlattr **tb, 529 u32 pid, u32 seq, u16 flags) 530 { 531 int ret = -EINVAL; 532 u8 value; 533 534 if (!tb[DCB_ATTR_PFC_STATE] || !netdev->dcbnl_ops->setpfcstate) 535 return ret; 536 537 value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]); 538 539 netdev->dcbnl_ops->setpfcstate(netdev, value); 540 541 ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SSTATE, DCB_ATTR_PFC_STATE, 542 pid, seq, flags); 543 544 return ret; 545 } 546 547 static int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb, 548 u32 pid, u32 seq, u16 flags) 549 { 550 struct sk_buff *dcbnl_skb; 551 struct nlmsghdr *nlh; 552 struct dcbmsg *dcb; 553 struct nlattr *app_nest; 554 struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; 555 u16 id; 556 u8 up, idtype; 557 int ret = -EINVAL; 558 559 if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->getapp) 560 goto out; 561 562 ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], 563 dcbnl_app_nest); 564 if (ret) 565 goto out; 566 567 ret = -EINVAL; 568 /* all must be non-null */ 569 if ((!app_tb[DCB_APP_ATTR_IDTYPE]) || 570 (!app_tb[DCB_APP_ATTR_ID])) 571 goto out; 572 573 /* either by eth type or by socket number */ 574 idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]); 575 if ((idtype != DCB_APP_IDTYPE_ETHTYPE) && 576 (idtype != DCB_APP_IDTYPE_PORTNUM)) 577 goto out; 578 579 id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); 580 up = netdev->dcbnl_ops->getapp(netdev, idtype, id); 581 582 /* send this back */ 583 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 584 if (!dcbnl_skb) 585 goto out; 586 587 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 588 dcb = NLMSG_DATA(nlh); 589 dcb->dcb_family = AF_UNSPEC; 590 dcb->cmd = DCB_CMD_GAPP; 591 592 app_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_APP); 593 ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype); 594 if (ret) 595 goto out_cancel; 596 597 ret = nla_put_u16(dcbnl_skb, DCB_APP_ATTR_ID, id); 598 if (ret) 599 goto out_cancel; 600 601 ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_PRIORITY, up); 602 if (ret) 603 goto out_cancel; 604 605 nla_nest_end(dcbnl_skb, app_nest); 606 nlmsg_end(dcbnl_skb, nlh); 607 608 ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 609 if (ret) 610 goto nlmsg_failure; 611 612 goto out; 613 614 out_cancel: 615 nla_nest_cancel(dcbnl_skb, app_nest); 616 nlmsg_failure: 617 kfree_skb(dcbnl_skb); 618 out: 619 return ret; 620 } 621 622 static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb, 623 u32 pid, u32 seq, u16 flags) 624 { 625 int ret = -EINVAL; 626 u16 id; 627 u8 up, idtype; 628 struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; 629 630 if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->setapp) 631 goto out; 632 633 ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], 634 dcbnl_app_nest); 635 if (ret) 636 goto out; 637 638 ret = -EINVAL; 639 /* all must be non-null */ 640 if ((!app_tb[DCB_APP_ATTR_IDTYPE]) || 641 (!app_tb[DCB_APP_ATTR_ID]) || 642 (!app_tb[DCB_APP_ATTR_PRIORITY])) 643 goto out; 644 645 /* either by eth type or by socket number */ 646 idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]); 647 if ((idtype != DCB_APP_IDTYPE_ETHTYPE) && 648 (idtype != DCB_APP_IDTYPE_PORTNUM)) 649 goto out; 650 651 id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); 652 up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]); 653 654 ret = dcbnl_reply(netdev->dcbnl_ops->setapp(netdev, idtype, id, up), 655 RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP, 656 pid, seq, flags); 657 out: 658 return ret; 659 } 660 661 static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, 662 u32 pid, u32 seq, u16 flags, int dir) 663 { 664 struct sk_buff *dcbnl_skb; 665 struct nlmsghdr *nlh; 666 struct dcbmsg *dcb; 667 struct nlattr *pg_nest, *param_nest, *data; 668 struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; 669 struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; 670 u8 prio, pgid, tc_pct, up_map; 671 int ret = -EINVAL; 672 int getall = 0; 673 int i; 674 675 if (!tb[DCB_ATTR_PG_CFG] || 676 !netdev->dcbnl_ops->getpgtccfgtx || 677 !netdev->dcbnl_ops->getpgtccfgrx || 678 !netdev->dcbnl_ops->getpgbwgcfgtx || 679 !netdev->dcbnl_ops->getpgbwgcfgrx) 680 return ret; 681 682 ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, 683 tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest); 684 685 if (ret) 686 goto err_out; 687 688 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 689 if (!dcbnl_skb) 690 goto err_out; 691 692 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 693 694 dcb = NLMSG_DATA(nlh); 695 dcb->dcb_family = AF_UNSPEC; 696 dcb->cmd = (dir) ? DCB_CMD_PGRX_GCFG : DCB_CMD_PGTX_GCFG; 697 698 pg_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PG_CFG); 699 if (!pg_nest) 700 goto err; 701 702 if (pg_tb[DCB_PG_ATTR_TC_ALL]) 703 getall = 1; 704 705 for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { 706 if (!getall && !pg_tb[i]) 707 continue; 708 709 if (pg_tb[DCB_PG_ATTR_TC_ALL]) 710 data = pg_tb[DCB_PG_ATTR_TC_ALL]; 711 else 712 data = pg_tb[i]; 713 ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX, 714 data, dcbnl_tc_param_nest); 715 if (ret) 716 goto err_pg; 717 718 param_nest = nla_nest_start(dcbnl_skb, i); 719 if (!param_nest) 720 goto err_pg; 721 722 pgid = DCB_ATTR_VALUE_UNDEFINED; 723 prio = DCB_ATTR_VALUE_UNDEFINED; 724 tc_pct = DCB_ATTR_VALUE_UNDEFINED; 725 up_map = DCB_ATTR_VALUE_UNDEFINED; 726 727 if (dir) { 728 /* Rx */ 729 netdev->dcbnl_ops->getpgtccfgrx(netdev, 730 i - DCB_PG_ATTR_TC_0, &prio, 731 &pgid, &tc_pct, &up_map); 732 } else { 733 /* Tx */ 734 netdev->dcbnl_ops->getpgtccfgtx(netdev, 735 i - DCB_PG_ATTR_TC_0, &prio, 736 &pgid, &tc_pct, &up_map); 737 } 738 739 if (param_tb[DCB_TC_ATTR_PARAM_PGID] || 740 param_tb[DCB_TC_ATTR_PARAM_ALL]) { 741 ret = nla_put_u8(dcbnl_skb, 742 DCB_TC_ATTR_PARAM_PGID, pgid); 743 if (ret) 744 goto err_param; 745 } 746 if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] || 747 param_tb[DCB_TC_ATTR_PARAM_ALL]) { 748 ret = nla_put_u8(dcbnl_skb, 749 DCB_TC_ATTR_PARAM_UP_MAPPING, up_map); 750 if (ret) 751 goto err_param; 752 } 753 if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] || 754 param_tb[DCB_TC_ATTR_PARAM_ALL]) { 755 ret = nla_put_u8(dcbnl_skb, 756 DCB_TC_ATTR_PARAM_STRICT_PRIO, prio); 757 if (ret) 758 goto err_param; 759 } 760 if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] || 761 param_tb[DCB_TC_ATTR_PARAM_ALL]) { 762 ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_BW_PCT, 763 tc_pct); 764 if (ret) 765 goto err_param; 766 } 767 nla_nest_end(dcbnl_skb, param_nest); 768 } 769 770 if (pg_tb[DCB_PG_ATTR_BW_ID_ALL]) 771 getall = 1; 772 else 773 getall = 0; 774 775 for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) { 776 if (!getall && !pg_tb[i]) 777 continue; 778 779 tc_pct = DCB_ATTR_VALUE_UNDEFINED; 780 781 if (dir) { 782 /* Rx */ 783 netdev->dcbnl_ops->getpgbwgcfgrx(netdev, 784 i - DCB_PG_ATTR_BW_ID_0, &tc_pct); 785 } else { 786 /* Tx */ 787 netdev->dcbnl_ops->getpgbwgcfgtx(netdev, 788 i - DCB_PG_ATTR_BW_ID_0, &tc_pct); 789 } 790 ret = nla_put_u8(dcbnl_skb, i, tc_pct); 791 792 if (ret) 793 goto err_pg; 794 } 795 796 nla_nest_end(dcbnl_skb, pg_nest); 797 798 nlmsg_end(dcbnl_skb, nlh); 799 800 ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 801 if (ret) 802 goto err; 803 804 return 0; 805 806 err_param: 807 nla_nest_cancel(dcbnl_skb, param_nest); 808 err_pg: 809 nla_nest_cancel(dcbnl_skb, pg_nest); 810 nlmsg_failure: 811 err: 812 kfree_skb(dcbnl_skb); 813 err_out: 814 ret = -EINVAL; 815 return ret; 816 } 817 818 static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlattr **tb, 819 u32 pid, u32 seq, u16 flags) 820 { 821 return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 0); 822 } 823 824 static int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlattr **tb, 825 u32 pid, u32 seq, u16 flags) 826 { 827 return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 1); 828 } 829 830 static int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb, 831 u32 pid, u32 seq, u16 flags) 832 { 833 int ret = -EINVAL; 834 u8 value; 835 836 if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate) 837 return ret; 838 839 value = nla_get_u8(tb[DCB_ATTR_STATE]); 840 841 ret = dcbnl_reply(netdev->dcbnl_ops->setstate(netdev, value), 842 RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE, 843 pid, seq, flags); 844 845 return ret; 846 } 847 848 static int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb, 849 u32 pid, u32 seq, u16 flags) 850 { 851 struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1]; 852 int i; 853 int ret = -EINVAL; 854 u8 value; 855 856 if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->setpfccfg) 857 return ret; 858 859 ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, 860 tb[DCB_ATTR_PFC_CFG], 861 dcbnl_pfc_up_nest); 862 if (ret) 863 goto err; 864 865 for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { 866 if (data[i] == NULL) 867 continue; 868 value = nla_get_u8(data[i]); 869 netdev->dcbnl_ops->setpfccfg(netdev, 870 data[i]->nla_type - DCB_PFC_UP_ATTR_0, value); 871 } 872 873 ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SCFG, DCB_ATTR_PFC_CFG, 874 pid, seq, flags); 875 err: 876 return ret; 877 } 878 879 static int dcbnl_setall(struct net_device *netdev, struct nlattr **tb, 880 u32 pid, u32 seq, u16 flags) 881 { 882 int ret = -EINVAL; 883 884 if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall) 885 return ret; 886 887 ret = dcbnl_reply(netdev->dcbnl_ops->setall(netdev), RTM_SETDCB, 888 DCB_CMD_SET_ALL, DCB_ATTR_SET_ALL, pid, seq, flags); 889 890 return ret; 891 } 892 893 static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb, 894 u32 pid, u32 seq, u16 flags, int dir) 895 { 896 struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; 897 struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; 898 int ret = -EINVAL; 899 int i; 900 u8 pgid; 901 u8 up_map; 902 u8 prio; 903 u8 tc_pct; 904 905 if (!tb[DCB_ATTR_PG_CFG] || 906 !netdev->dcbnl_ops->setpgtccfgtx || 907 !netdev->dcbnl_ops->setpgtccfgrx || 908 !netdev->dcbnl_ops->setpgbwgcfgtx || 909 !netdev->dcbnl_ops->setpgbwgcfgrx) 910 return ret; 911 912 ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, 913 tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest); 914 if (ret) 915 goto err; 916 917 for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { 918 if (!pg_tb[i]) 919 continue; 920 921 ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX, 922 pg_tb[i], dcbnl_tc_param_nest); 923 if (ret) 924 goto err; 925 926 pgid = DCB_ATTR_VALUE_UNDEFINED; 927 prio = DCB_ATTR_VALUE_UNDEFINED; 928 tc_pct = DCB_ATTR_VALUE_UNDEFINED; 929 up_map = DCB_ATTR_VALUE_UNDEFINED; 930 931 if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]) 932 prio = 933 nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]); 934 935 if (param_tb[DCB_TC_ATTR_PARAM_PGID]) 936 pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]); 937 938 if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT]) 939 tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]); 940 941 if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]) 942 up_map = 943 nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]); 944 945 /* dir: Tx = 0, Rx = 1 */ 946 if (dir) { 947 /* Rx */ 948 netdev->dcbnl_ops->setpgtccfgrx(netdev, 949 i - DCB_PG_ATTR_TC_0, 950 prio, pgid, tc_pct, up_map); 951 } else { 952 /* Tx */ 953 netdev->dcbnl_ops->setpgtccfgtx(netdev, 954 i - DCB_PG_ATTR_TC_0, 955 prio, pgid, tc_pct, up_map); 956 } 957 } 958 959 for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) { 960 if (!pg_tb[i]) 961 continue; 962 963 tc_pct = nla_get_u8(pg_tb[i]); 964 965 /* dir: Tx = 0, Rx = 1 */ 966 if (dir) { 967 /* Rx */ 968 netdev->dcbnl_ops->setpgbwgcfgrx(netdev, 969 i - DCB_PG_ATTR_BW_ID_0, tc_pct); 970 } else { 971 /* Tx */ 972 netdev->dcbnl_ops->setpgbwgcfgtx(netdev, 973 i - DCB_PG_ATTR_BW_ID_0, tc_pct); 974 } 975 } 976 977 ret = dcbnl_reply(0, RTM_SETDCB, 978 (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG), 979 DCB_ATTR_PG_CFG, pid, seq, flags); 980 981 err: 982 return ret; 983 } 984 985 static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlattr **tb, 986 u32 pid, u32 seq, u16 flags) 987 { 988 return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 0); 989 } 990 991 static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb, 992 u32 pid, u32 seq, u16 flags) 993 { 994 return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1); 995 } 996 997 static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb, 998 u32 pid, u32 seq, u16 flags) 999 { 1000 struct sk_buff *dcbnl_skb; 1001 struct nlmsghdr *nlh; 1002 struct dcbmsg *dcb; 1003 struct nlattr *bcn_nest; 1004 struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1]; 1005 u8 value_byte; 1006 u32 value_integer; 1007 int ret = -EINVAL; 1008 bool getall = false; 1009 int i; 1010 1011 if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->getbcnrp || 1012 !netdev->dcbnl_ops->getbcncfg) 1013 return ret; 1014 1015 ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX, 1016 tb[DCB_ATTR_BCN], dcbnl_bcn_nest); 1017 1018 if (ret) 1019 goto err_out; 1020 1021 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1022 if (!dcbnl_skb) 1023 goto err_out; 1024 1025 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 1026 1027 dcb = NLMSG_DATA(nlh); 1028 dcb->dcb_family = AF_UNSPEC; 1029 dcb->cmd = DCB_CMD_BCN_GCFG; 1030 1031 bcn_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_BCN); 1032 if (!bcn_nest) 1033 goto err; 1034 1035 if (bcn_tb[DCB_BCN_ATTR_ALL]) 1036 getall = true; 1037 1038 for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) { 1039 if (!getall && !bcn_tb[i]) 1040 continue; 1041 1042 netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0, 1043 &value_byte); 1044 ret = nla_put_u8(dcbnl_skb, i, value_byte); 1045 if (ret) 1046 goto err_bcn; 1047 } 1048 1049 for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) { 1050 if (!getall && !bcn_tb[i]) 1051 continue; 1052 1053 netdev->dcbnl_ops->getbcncfg(netdev, i, 1054 &value_integer); 1055 ret = nla_put_u32(dcbnl_skb, i, value_integer); 1056 if (ret) 1057 goto err_bcn; 1058 } 1059 1060 nla_nest_end(dcbnl_skb, bcn_nest); 1061 1062 nlmsg_end(dcbnl_skb, nlh); 1063 1064 ret = rtnl_unicast(dcbnl_skb, &init_net, pid); 1065 if (ret) 1066 goto err; 1067 1068 return 0; 1069 1070 err_bcn: 1071 nla_nest_cancel(dcbnl_skb, bcn_nest); 1072 nlmsg_failure: 1073 err: 1074 kfree_skb(dcbnl_skb); 1075 err_out: 1076 ret = -EINVAL; 1077 return ret; 1078 } 1079 1080 static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlattr **tb, 1081 u32 pid, u32 seq, u16 flags) 1082 { 1083 struct nlattr *data[DCB_BCN_ATTR_MAX + 1]; 1084 int i; 1085 int ret = -EINVAL; 1086 u8 value_byte; 1087 u32 value_int; 1088 1089 if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg 1090 || !netdev->dcbnl_ops->setbcnrp) 1091 return ret; 1092 1093 ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX, 1094 tb[DCB_ATTR_BCN], 1095 dcbnl_pfc_up_nest); 1096 if (ret) 1097 goto err; 1098 1099 for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) { 1100 if (data[i] == NULL) 1101 continue; 1102 value_byte = nla_get_u8(data[i]); 1103 netdev->dcbnl_ops->setbcnrp(netdev, 1104 data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte); 1105 } 1106 1107 for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) { 1108 if (data[i] == NULL) 1109 continue; 1110 value_int = nla_get_u32(data[i]); 1111 netdev->dcbnl_ops->setbcncfg(netdev, 1112 i, value_int); 1113 } 1114 1115 ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_BCN_SCFG, DCB_ATTR_BCN, 1116 pid, seq, flags); 1117 err: 1118 return ret; 1119 } 1120 1121 static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 1122 { 1123 struct net *net = sock_net(skb->sk); 1124 struct net_device *netdev; 1125 struct dcbmsg *dcb = (struct dcbmsg *)NLMSG_DATA(nlh); 1126 struct nlattr *tb[DCB_ATTR_MAX + 1]; 1127 u32 pid = skb ? NETLINK_CB(skb).pid : 0; 1128 int ret = -EINVAL; 1129 1130 if (net != &init_net) 1131 return -EINVAL; 1132 1133 ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX, 1134 dcbnl_rtnl_policy); 1135 if (ret < 0) 1136 return ret; 1137 1138 if (!tb[DCB_ATTR_IFNAME]) 1139 return -EINVAL; 1140 1141 netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME])); 1142 if (!netdev) 1143 return -EINVAL; 1144 1145 if (!netdev->dcbnl_ops) 1146 goto errout; 1147 1148 switch (dcb->cmd) { 1149 case DCB_CMD_GSTATE: 1150 ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq, 1151 nlh->nlmsg_flags); 1152 goto out; 1153 case DCB_CMD_PFC_GCFG: 1154 ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq, 1155 nlh->nlmsg_flags); 1156 goto out; 1157 case DCB_CMD_GPERM_HWADDR: 1158 ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq, 1159 nlh->nlmsg_flags); 1160 goto out; 1161 case DCB_CMD_PGTX_GCFG: 1162 ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq, 1163 nlh->nlmsg_flags); 1164 goto out; 1165 case DCB_CMD_PGRX_GCFG: 1166 ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq, 1167 nlh->nlmsg_flags); 1168 goto out; 1169 case DCB_CMD_BCN_GCFG: 1170 ret = dcbnl_bcn_getcfg(netdev, tb, pid, nlh->nlmsg_seq, 1171 nlh->nlmsg_flags); 1172 goto out; 1173 case DCB_CMD_SSTATE: 1174 ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq, 1175 nlh->nlmsg_flags); 1176 goto out; 1177 case DCB_CMD_PFC_SCFG: 1178 ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq, 1179 nlh->nlmsg_flags); 1180 goto out; 1181 1182 case DCB_CMD_SET_ALL: 1183 ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq, 1184 nlh->nlmsg_flags); 1185 goto out; 1186 case DCB_CMD_PGTX_SCFG: 1187 ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, 1188 nlh->nlmsg_flags); 1189 goto out; 1190 case DCB_CMD_PGRX_SCFG: 1191 ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, 1192 nlh->nlmsg_flags); 1193 goto out; 1194 case DCB_CMD_GCAP: 1195 ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq, 1196 nlh->nlmsg_flags); 1197 goto out; 1198 case DCB_CMD_GNUMTCS: 1199 ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq, 1200 nlh->nlmsg_flags); 1201 goto out; 1202 case DCB_CMD_SNUMTCS: 1203 ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq, 1204 nlh->nlmsg_flags); 1205 goto out; 1206 case DCB_CMD_PFC_GSTATE: 1207 ret = dcbnl_getpfcstate(netdev, tb, pid, nlh->nlmsg_seq, 1208 nlh->nlmsg_flags); 1209 goto out; 1210 case DCB_CMD_PFC_SSTATE: 1211 ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq, 1212 nlh->nlmsg_flags); 1213 goto out; 1214 case DCB_CMD_BCN_SCFG: 1215 ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq, 1216 nlh->nlmsg_flags); 1217 goto out; 1218 case DCB_CMD_GAPP: 1219 ret = dcbnl_getapp(netdev, tb, pid, nlh->nlmsg_seq, 1220 nlh->nlmsg_flags); 1221 goto out; 1222 case DCB_CMD_SAPP: 1223 ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq, 1224 nlh->nlmsg_flags); 1225 goto out; 1226 default: 1227 goto errout; 1228 } 1229 errout: 1230 ret = -EINVAL; 1231 out: 1232 dev_put(netdev); 1233 return ret; 1234 } 1235 1236 static int __init dcbnl_init(void) 1237 { 1238 rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL); 1239 rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL); 1240 1241 return 0; 1242 } 1243 module_init(dcbnl_init); 1244 1245 static void __exit dcbnl_exit(void) 1246 { 1247 rtnl_unregister(PF_UNSPEC, RTM_GETDCB); 1248 rtnl_unregister(PF_UNSPEC, RTM_SETDCB); 1249 } 1250 module_exit(dcbnl_exit); 1251 1252 1253