aboutsummaryrefslogtreecommitdiffstats
path: root/net/dcb/dcbnl.c
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2008-11-21 00:08:19 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-21 00:08:19 -0500
commit33dbabc4a7f7bd72313c73a3c199f31f3900336f (patch)
treef56e24fec9369ca1d1ef12eb18e4000a09fb5c3e /net/dcb/dcbnl.c
parent46132188bf72e22ef097f16ed5c969ee8cea1e8b (diff)
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>
Diffstat (limited to 'net/dcb/dcbnl.c')
-rw-r--r--net/dcb/dcbnl.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index de61d64d102d..5ff7e3c0c172 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -120,6 +120,13 @@ static struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = {
120 [DCB_CAP_ATTR_BCN] = {.type = NLA_U8}, 120 [DCB_CAP_ATTR_BCN] = {.type = NLA_U8},
121}; 121};
122 122
123/* DCB capabilities nested attributes. */
124static 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/* standard netlink reply call */ 130/* standard netlink reply call */
124static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, 131static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
125 u32 seq, u16 flags) 132 u32 seq, u16 flags)
@@ -347,6 +354,123 @@ err_out:
347 return -EINVAL; 354 return -EINVAL;
348} 355}
349 356
357static 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;
428nlmsg_failure:
429err:
430 kfree(dcbnl_skb);
431err_out:
432 return ret;
433}
434
435static 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
466operr:
467 ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS,
468 DCB_ATTR_NUMTCS, pid, seq, flags);
469
470err:
471 return ret;
472}
473
350static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, 474static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb,
351 u32 pid, u32 seq, u16 flags, int dir) 475 u32 pid, u32 seq, u16 flags, int dir)
352{ 476{
@@ -757,6 +881,14 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
757 ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq, 881 ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq,
758 nlh->nlmsg_flags); 882 nlh->nlmsg_flags);
759 goto out; 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);
891 goto out;
760 default: 892 default:
761 goto errout; 893 goto errout;
762 } 894 }