aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_nl.c33
-rw-r--r--include/linux/dcbnl.h27
-rw-r--r--include/net/dcbnl.h2
-rw-r--r--net/dcb/dcbnl.c132
4 files changed, 193 insertions, 1 deletions
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c
index eb3a6cea1aaa..5921795f8403 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c
@@ -376,6 +376,35 @@ static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap)
376 return rval; 376 return rval;
377} 377}
378 378
379static 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
403static u8 ixgbe_dcbnl_setnumtcs(struct net_device *netdev, int tcid, u8 num)
404{
405 return -EINVAL;
406}
407
379struct dcbnl_rtnl_ops dcbnl_ops = { 408struct dcbnl_rtnl_ops dcbnl_ops = {
380 .getstate = ixgbe_dcbnl_get_state, 409 .getstate = ixgbe_dcbnl_get_state,
381 .setstate = ixgbe_dcbnl_set_state, 410 .setstate = ixgbe_dcbnl_set_state,
@@ -391,6 +420,8 @@ struct dcbnl_rtnl_ops dcbnl_ops = {
391 .setpfccfg = ixgbe_dcbnl_set_pfc_cfg, 420 .setpfccfg = ixgbe_dcbnl_set_pfc_cfg,
392 .getpfccfg = ixgbe_dcbnl_get_pfc_cfg, 421 .getpfccfg = ixgbe_dcbnl_get_pfc_cfg,
393 .setall = ixgbe_dcbnl_set_all, 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};
396 427
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h
index 13f0c638a695..1077fba1dadc 100644
--- a/include/linux/dcbnl.h
+++ b/include/linux/dcbnl.h
@@ -44,6 +44,8 @@ struct dcbmsg {
44 * @DCB_CMD_GPERM_HWADDR: get the permanent MAC address of the underlying 44 * @DCB_CMD_GPERM_HWADDR: get the permanent MAC address of the underlying
45 * device. Only useful when using bonding. 45 * device. Only useful when using bonding.
46 * @DCB_CMD_GCAP: request the DCB capabilities of the device 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 */
48enum dcbnl_commands { 50enum dcbnl_commands {
49 DCB_CMD_UNDEFINED, 51 DCB_CMD_UNDEFINED,
@@ -62,6 +64,8 @@ enum dcbnl_commands {
62 DCB_CMD_SET_ALL, 64 DCB_CMD_SET_ALL,
63 DCB_CMD_GPERM_HWADDR, 65 DCB_CMD_GPERM_HWADDR,
64 DCB_CMD_GCAP, 66 DCB_CMD_GCAP,
67 DCB_CMD_GNUMTCS,
68 DCB_CMD_SNUMTCS,
65 69
66 __DCB_CMD_ENUM_MAX, 70 __DCB_CMD_ENUM_MAX,
67 DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, 71 DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1,
@@ -81,6 +85,7 @@ enum dcbnl_commands {
81 * @DCB_ATTR_SET_ALL: bool to commit changes to hardware or not (NLA_U8) 85 * @DCB_ATTR_SET_ALL: bool to commit changes to hardware or not (NLA_U8)
82 * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED) 86 * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED)
83 * @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED) 87 * @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED)
88 * @DCB_ATTR_NUMTCS: number of traffic classes supported (NLA_NESTED)
84 */ 89 */
85enum dcbnl_attrs { 90enum dcbnl_attrs {
86 DCB_ATTR_UNDEFINED, 91 DCB_ATTR_UNDEFINED,
@@ -94,6 +99,7 @@ enum dcbnl_attrs {
94 DCB_ATTR_SET_ALL, 99 DCB_ATTR_SET_ALL,
95 DCB_ATTR_PERM_HWADDR, 100 DCB_ATTR_PERM_HWADDR,
96 DCB_ATTR_CAP, 101 DCB_ATTR_CAP,
102 DCB_ATTR_NUMTCS,
97 103
98 __DCB_ATTR_ENUM_MAX, 104 __DCB_ATTR_ENUM_MAX,
99 DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, 105 DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1,
@@ -253,6 +259,27 @@ enum dcbnl_cap_attrs {
253 __DCB_CAP_ATTR_ENUM_MAX, 259 __DCB_CAP_ATTR_ENUM_MAX,
254 DCB_CAP_ATTR_MAX = __DCB_CAP_ATTR_ENUM_MAX - 1, 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 */
273enum 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 * enum dcb_general_attr_values - general DCB attribute values 284 * enum dcb_general_attr_values - general DCB attribute values
258 * 285 *
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h
index 183ed040cf4c..f0a65281ea73 100644
--- a/include/net/dcbnl.h
+++ b/include/net/dcbnl.h
@@ -40,6 +40,8 @@ struct dcbnl_rtnl_ops {
40 void (*getpfccfg)(struct net_device *, int, u8 *); 40 void (*getpfccfg)(struct net_device *, int, u8 *);
41 u8 (*setall)(struct net_device *); 41 u8 (*setall)(struct net_device *);
42 u8 (*getcap)(struct net_device *, int, u8 *); 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#endif /* __NET_DCBNL_H__ */ 47#endif /* __NET_DCBNL_H__ */
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 }