aboutsummaryrefslogtreecommitdiffstats
path: root/net/dcb/dcbnl.c
diff options
context:
space:
mode:
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 }