Commit 33dbabc4a7f7bd72313c73a3c199f31f3900336f
Committed by
David S. Miller
1 parent
46132188bf
Exists in
master
and in
20 other branches
DCB: Add interface to query # of TCs supported by device
Adds interface for Data Center Bridging (DCB) to query (and set if supported) the number of traffic classes currently supported by the device for the two (DCB) features: priority groups (PG) and priority flow control (PFC). Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 4 changed files with 193 additions and 1 deletions Side-by-side Diff
drivers/net/ixgbe/ixgbe_dcb_nl.c
... | ... | @@ -376,6 +376,35 @@ |
376 | 376 | return rval; |
377 | 377 | } |
378 | 378 | |
379 | +static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num) | |
380 | +{ | |
381 | + struct ixgbe_adapter *adapter = netdev_priv(netdev); | |
382 | + u8 rval = 0; | |
383 | + | |
384 | + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | |
385 | + switch (tcid) { | |
386 | + case DCB_NUMTCS_ATTR_PG: | |
387 | + *num = MAX_TRAFFIC_CLASS; | |
388 | + break; | |
389 | + case DCB_NUMTCS_ATTR_PFC: | |
390 | + *num = MAX_TRAFFIC_CLASS; | |
391 | + break; | |
392 | + default: | |
393 | + rval = -EINVAL; | |
394 | + break; | |
395 | + } | |
396 | + } else { | |
397 | + rval = -EINVAL; | |
398 | + } | |
399 | + | |
400 | + return rval; | |
401 | +} | |
402 | + | |
403 | +static u8 ixgbe_dcbnl_setnumtcs(struct net_device *netdev, int tcid, u8 num) | |
404 | +{ | |
405 | + return -EINVAL; | |
406 | +} | |
407 | + | |
379 | 408 | struct dcbnl_rtnl_ops dcbnl_ops = { |
380 | 409 | .getstate = ixgbe_dcbnl_get_state, |
381 | 410 | .setstate = ixgbe_dcbnl_set_state, |
... | ... | @@ -391,6 +420,8 @@ |
391 | 420 | .setpfccfg = ixgbe_dcbnl_set_pfc_cfg, |
392 | 421 | .getpfccfg = ixgbe_dcbnl_get_pfc_cfg, |
393 | 422 | .setall = ixgbe_dcbnl_set_all, |
394 | - .getcap = ixgbe_dcbnl_getcap | |
423 | + .getcap = ixgbe_dcbnl_getcap, | |
424 | + .getnumtcs = ixgbe_dcbnl_getnumtcs, | |
425 | + .setnumtcs = ixgbe_dcbnl_setnumtcs | |
395 | 426 | }; |
include/linux/dcbnl.h
... | ... | @@ -44,6 +44,8 @@ |
44 | 44 | * @DCB_CMD_GPERM_HWADDR: get the permanent MAC address of the underlying |
45 | 45 | * device. Only useful when using bonding. |
46 | 46 | * @DCB_CMD_GCAP: request the DCB capabilities of the device |
47 | + * @DCB_CMD_GNUMTCS: get the number of traffic classes currently supported | |
48 | + * @DCB_CMD_SNUMTCS: set the number of traffic classes | |
47 | 49 | */ |
48 | 50 | enum dcbnl_commands { |
49 | 51 | DCB_CMD_UNDEFINED, |
... | ... | @@ -62,6 +64,8 @@ |
62 | 64 | DCB_CMD_SET_ALL, |
63 | 65 | DCB_CMD_GPERM_HWADDR, |
64 | 66 | DCB_CMD_GCAP, |
67 | + DCB_CMD_GNUMTCS, | |
68 | + DCB_CMD_SNUMTCS, | |
65 | 69 | |
66 | 70 | __DCB_CMD_ENUM_MAX, |
67 | 71 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, |
... | ... | @@ -81,6 +85,7 @@ |
81 | 85 | * @DCB_ATTR_SET_ALL: bool to commit changes to hardware or not (NLA_U8) |
82 | 86 | * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED) |
83 | 87 | * @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED) |
88 | + * @DCB_ATTR_NUMTCS: number of traffic classes supported (NLA_NESTED) | |
84 | 89 | */ |
85 | 90 | enum dcbnl_attrs { |
86 | 91 | DCB_ATTR_UNDEFINED, |
... | ... | @@ -94,6 +99,7 @@ |
94 | 99 | DCB_ATTR_SET_ALL, |
95 | 100 | DCB_ATTR_PERM_HWADDR, |
96 | 101 | DCB_ATTR_CAP, |
102 | + DCB_ATTR_NUMTCS, | |
97 | 103 | |
98 | 104 | __DCB_ATTR_ENUM_MAX, |
99 | 105 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, |
... | ... | @@ -253,6 +259,27 @@ |
253 | 259 | __DCB_CAP_ATTR_ENUM_MAX, |
254 | 260 | DCB_CAP_ATTR_MAX = __DCB_CAP_ATTR_ENUM_MAX - 1, |
255 | 261 | }; |
262 | + | |
263 | +/** | |
264 | + * enum dcbnl_numtcs_attrs - number of traffic classes | |
265 | + * | |
266 | + * @DCB_NUMTCS_ATTR_UNDEFINED: unspecified attribute to catch errors | |
267 | + * @DCB_NUMTCS_ATTR_ALL: (NLA_FLAG) all traffic class attributes | |
268 | + * @DCB_NUMTCS_ATTR_PG: (NLA_U8) number of traffic classes used for | |
269 | + * priority groups | |
270 | + * @DCB_NUMTCS_ATTR_PFC: (NLA_U8) number of traffic classes which can | |
271 | + * support priority flow control | |
272 | + */ | |
273 | +enum dcbnl_numtcs_attrs { | |
274 | + DCB_NUMTCS_ATTR_UNDEFINED, | |
275 | + DCB_NUMTCS_ATTR_ALL, | |
276 | + DCB_NUMTCS_ATTR_PG, | |
277 | + DCB_NUMTCS_ATTR_PFC, | |
278 | + | |
279 | + __DCB_NUMTCS_ATTR_ENUM_MAX, | |
280 | + DCB_NUMTCS_ATTR_MAX = __DCB_NUMTCS_ATTR_ENUM_MAX - 1, | |
281 | +}; | |
282 | + | |
256 | 283 | /** |
257 | 284 | * enum dcb_general_attr_values - general DCB attribute values |
258 | 285 | * |
include/net/dcbnl.h
... | ... | @@ -40,6 +40,8 @@ |
40 | 40 | void (*getpfccfg)(struct net_device *, int, u8 *); |
41 | 41 | u8 (*setall)(struct net_device *); |
42 | 42 | u8 (*getcap)(struct net_device *, int, u8 *); |
43 | + u8 (*getnumtcs)(struct net_device *, int, u8 *); | |
44 | + u8 (*setnumtcs)(struct net_device *, int, u8); | |
43 | 45 | }; |
44 | 46 | |
45 | 47 | #endif /* __NET_DCBNL_H__ */ |
net/dcb/dcbnl.c
... | ... | @@ -120,6 +120,13 @@ |
120 | 120 | [DCB_CAP_ATTR_BCN] = {.type = NLA_U8}, |
121 | 121 | }; |
122 | 122 | |
123 | +/* DCB capabilities nested attributes. */ | |
124 | +static struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = { | |
125 | + [DCB_NUMTCS_ATTR_ALL] = {.type = NLA_FLAG}, | |
126 | + [DCB_NUMTCS_ATTR_PG] = {.type = NLA_U8}, | |
127 | + [DCB_NUMTCS_ATTR_PFC] = {.type = NLA_U8}, | |
128 | +}; | |
129 | + | |
123 | 130 | /* standard netlink reply call */ |
124 | 131 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, |
125 | 132 | u32 seq, u16 flags) |
... | ... | @@ -347,6 +354,123 @@ |
347 | 354 | return -EINVAL; |
348 | 355 | } |
349 | 356 | |
357 | +static int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb, | |
358 | + u32 pid, u32 seq, u16 flags) | |
359 | +{ | |
360 | + struct sk_buff *dcbnl_skb; | |
361 | + struct nlmsghdr *nlh; | |
362 | + struct dcbmsg *dcb; | |
363 | + struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest; | |
364 | + u8 value; | |
365 | + int ret = -EINVAL; | |
366 | + int i; | |
367 | + int getall = 0; | |
368 | + | |
369 | + if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs) | |
370 | + return ret; | |
371 | + | |
372 | + ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], | |
373 | + dcbnl_numtcs_nest); | |
374 | + if (ret) { | |
375 | + ret = -EINVAL; | |
376 | + goto err_out; | |
377 | + } | |
378 | + | |
379 | + dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | |
380 | + if (!dcbnl_skb) { | |
381 | + ret = -EINVAL; | |
382 | + goto err_out; | |
383 | + } | |
384 | + | |
385 | + nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); | |
386 | + | |
387 | + dcb = NLMSG_DATA(nlh); | |
388 | + dcb->dcb_family = AF_UNSPEC; | |
389 | + dcb->cmd = DCB_CMD_GNUMTCS; | |
390 | + | |
391 | + nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS); | |
392 | + if (!nest) { | |
393 | + ret = -EINVAL; | |
394 | + goto err; | |
395 | + } | |
396 | + | |
397 | + if (data[DCB_NUMTCS_ATTR_ALL]) | |
398 | + getall = 1; | |
399 | + | |
400 | + for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { | |
401 | + if (!getall && !data[i]) | |
402 | + continue; | |
403 | + | |
404 | + ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value); | |
405 | + if (!ret) { | |
406 | + ret = nla_put_u8(dcbnl_skb, i, value); | |
407 | + | |
408 | + if (ret) { | |
409 | + nla_nest_cancel(dcbnl_skb, nest); | |
410 | + ret = -EINVAL; | |
411 | + goto err; | |
412 | + } | |
413 | + } else { | |
414 | + goto err; | |
415 | + } | |
416 | + } | |
417 | + nla_nest_end(dcbnl_skb, nest); | |
418 | + | |
419 | + nlmsg_end(dcbnl_skb, nlh); | |
420 | + | |
421 | + ret = rtnl_unicast(dcbnl_skb, &init_net, pid); | |
422 | + if (ret) { | |
423 | + ret = -EINVAL; | |
424 | + goto err; | |
425 | + } | |
426 | + | |
427 | + return 0; | |
428 | +nlmsg_failure: | |
429 | +err: | |
430 | + kfree(dcbnl_skb); | |
431 | +err_out: | |
432 | + return ret; | |
433 | +} | |
434 | + | |
435 | +static int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb, | |
436 | + u32 pid, u32 seq, u16 flags) | |
437 | +{ | |
438 | + struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1]; | |
439 | + int ret = -EINVAL; | |
440 | + u8 value; | |
441 | + int i; | |
442 | + | |
443 | + if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setstate) | |
444 | + return ret; | |
445 | + | |
446 | + ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], | |
447 | + dcbnl_numtcs_nest); | |
448 | + | |
449 | + if (ret) { | |
450 | + ret = -EINVAL; | |
451 | + goto err; | |
452 | + } | |
453 | + | |
454 | + for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { | |
455 | + if (data[i] == NULL) | |
456 | + continue; | |
457 | + | |
458 | + value = nla_get_u8(data[i]); | |
459 | + | |
460 | + ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value); | |
461 | + | |
462 | + if (ret) | |
463 | + goto operr; | |
464 | + } | |
465 | + | |
466 | +operr: | |
467 | + ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS, | |
468 | + DCB_ATTR_NUMTCS, pid, seq, flags); | |
469 | + | |
470 | +err: | |
471 | + return ret; | |
472 | +} | |
473 | + | |
350 | 474 | static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, |
351 | 475 | u32 pid, u32 seq, u16 flags, int dir) |
352 | 476 | { |
... | ... | @@ -756,6 +880,14 @@ |
756 | 880 | case DCB_CMD_GCAP: |
757 | 881 | ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq, |
758 | 882 | nlh->nlmsg_flags); |
883 | + goto out; | |
884 | + case DCB_CMD_GNUMTCS: | |
885 | + ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq, | |
886 | + nlh->nlmsg_flags); | |
887 | + goto out; | |
888 | + case DCB_CMD_SNUMTCS: | |
889 | + ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq, | |
890 | + nlh->nlmsg_flags); | |
759 | 891 | goto out; |
760 | 892 | default: |
761 | 893 | goto errout; |