Commit 33dbabc4a7f7bd72313c73a3c199f31f3900336f

Authored by Alexander Duyck
Committed by David S. Miller
1 parent 46132188bf

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 *
... ... @@ -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__ */
... ... @@ -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;