Commit 46132188bf72e22ef097f16ed5c969ee8cea1e8b
Committed by
David S. Miller
1 parent
2f90b8657e
Exists in
master
and in
7 other branches
DCB: Add interface to query for the DCB capabilities of an device.
Adds to the netlink interface for Data Center Bridging (DCB), allowing the DCB capabilities supported by a device to be queried. 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 161 additions and 1 deletions Side-by-side Diff
drivers/net/ixgbe/ixgbe_dcb_nl.c
... | ... | @@ -337,6 +337,45 @@ |
337 | 337 | return ret; |
338 | 338 | } |
339 | 339 | |
340 | +static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap) | |
341 | +{ | |
342 | + struct ixgbe_adapter *adapter = netdev_priv(netdev); | |
343 | + u8 rval = 0; | |
344 | + | |
345 | + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | |
346 | + switch (capid) { | |
347 | + case DCB_CAP_ATTR_PG: | |
348 | + *cap = true; | |
349 | + break; | |
350 | + case DCB_CAP_ATTR_PFC: | |
351 | + *cap = true; | |
352 | + break; | |
353 | + case DCB_CAP_ATTR_UP2TC: | |
354 | + *cap = false; | |
355 | + break; | |
356 | + case DCB_CAP_ATTR_PG_TCS: | |
357 | + *cap = 0x80; | |
358 | + break; | |
359 | + case DCB_CAP_ATTR_PFC_TCS: | |
360 | + *cap = 0x80; | |
361 | + break; | |
362 | + case DCB_CAP_ATTR_GSP: | |
363 | + *cap = true; | |
364 | + break; | |
365 | + case DCB_CAP_ATTR_BCN: | |
366 | + *cap = false; | |
367 | + break; | |
368 | + default: | |
369 | + rval = -EINVAL; | |
370 | + break; | |
371 | + } | |
372 | + } else { | |
373 | + rval = -EINVAL; | |
374 | + } | |
375 | + | |
376 | + return rval; | |
377 | +} | |
378 | + | |
340 | 379 | struct dcbnl_rtnl_ops dcbnl_ops = { |
341 | 380 | .getstate = ixgbe_dcbnl_get_state, |
342 | 381 | .setstate = ixgbe_dcbnl_set_state, |
... | ... | @@ -351,6 +390,7 @@ |
351 | 390 | .getpgbwgcfgrx = ixgbe_dcbnl_get_pg_bwg_cfg_rx, |
352 | 391 | .setpfccfg = ixgbe_dcbnl_set_pfc_cfg, |
353 | 392 | .getpfccfg = ixgbe_dcbnl_get_pfc_cfg, |
354 | - .setall = ixgbe_dcbnl_set_all | |
393 | + .setall = ixgbe_dcbnl_set_all, | |
394 | + .getcap = ixgbe_dcbnl_getcap | |
355 | 395 | }; |
include/linux/dcbnl.h
... | ... | @@ -43,6 +43,7 @@ |
43 | 43 | * @DCB_CMD_SET_ALL: apply all changes to the underlying device |
44 | 44 | * @DCB_CMD_GPERM_HWADDR: get the permanent MAC address of the underlying |
45 | 45 | * device. Only useful when using bonding. |
46 | + * @DCB_CMD_GCAP: request the DCB capabilities of the device | |
46 | 47 | */ |
47 | 48 | enum dcbnl_commands { |
48 | 49 | DCB_CMD_UNDEFINED, |
... | ... | @@ -60,6 +61,7 @@ |
60 | 61 | |
61 | 62 | DCB_CMD_SET_ALL, |
62 | 63 | DCB_CMD_GPERM_HWADDR, |
64 | + DCB_CMD_GCAP, | |
63 | 65 | |
64 | 66 | __DCB_CMD_ENUM_MAX, |
65 | 67 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, |
... | ... | @@ -78,6 +80,7 @@ |
78 | 80 | * @DCB_ATTR_PG_CFG: priority group configuration (NLA_NESTED) |
79 | 81 | * @DCB_ATTR_SET_ALL: bool to commit changes to hardware or not (NLA_U8) |
80 | 82 | * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED) |
83 | + * @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED) | |
81 | 84 | */ |
82 | 85 | enum dcbnl_attrs { |
83 | 86 | DCB_ATTR_UNDEFINED, |
... | ... | @@ -90,6 +93,7 @@ |
90 | 93 | DCB_ATTR_PG_CFG, |
91 | 94 | DCB_ATTR_SET_ALL, |
92 | 95 | DCB_ATTR_PERM_HWADDR, |
96 | + DCB_ATTR_CAP, | |
93 | 97 | |
94 | 98 | __DCB_ATTR_ENUM_MAX, |
95 | 99 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, |
... | ... | @@ -216,6 +220,39 @@ |
216 | 220 | DCB_TC_ATTR_PARAM_MAX = __DCB_TC_ATTR_PARAM_ENUM_MAX - 1, |
217 | 221 | }; |
218 | 222 | |
223 | +/** | |
224 | + * enum dcbnl_cap_attrs - DCB Capability attributes | |
225 | + * | |
226 | + * @DCB_CAP_ATTR_UNDEFINED: unspecified attribute to catch errors | |
227 | + * @DCB_CAP_ATTR_ALL: (NLA_FLAG) all capability parameters | |
228 | + * @DCB_CAP_ATTR_PG: (NLA_U8) device supports Priority Groups | |
229 | + * @DCB_CAP_ATTR_PFC: (NLA_U8) device supports Priority Flow Control | |
230 | + * @DCB_CAP_ATTR_UP2TC: (NLA_U8) device supports user priority to | |
231 | + * traffic class mapping | |
232 | + * @DCB_CAP_ATTR_PG_TCS: (NLA_U8) bitmap where each bit represents a | |
233 | + * number of traffic classes the device | |
234 | + * can be configured to use for Priority Groups | |
235 | + * @DCB_CAP_ATTR_PFC_TCS: (NLA_U8) bitmap where each bit represents a | |
236 | + * number of traffic classes the device can be | |
237 | + * configured to use for Priority Flow Control | |
238 | + * @DCB_CAP_ATTR_GSP: (NLA_U8) device supports group strict priority | |
239 | + * @DCB_CAP_ATTR_BCN: (NLA_U8) device supports Backwards Congestion | |
240 | + * Notification | |
241 | + */ | |
242 | +enum dcbnl_cap_attrs { | |
243 | + DCB_CAP_ATTR_UNDEFINED, | |
244 | + DCB_CAP_ATTR_ALL, | |
245 | + DCB_CAP_ATTR_PG, | |
246 | + DCB_CAP_ATTR_PFC, | |
247 | + DCB_CAP_ATTR_UP2TC, | |
248 | + DCB_CAP_ATTR_PG_TCS, | |
249 | + DCB_CAP_ATTR_PFC_TCS, | |
250 | + DCB_CAP_ATTR_GSP, | |
251 | + DCB_CAP_ATTR_BCN, | |
252 | + | |
253 | + __DCB_CAP_ATTR_ENUM_MAX, | |
254 | + DCB_CAP_ATTR_MAX = __DCB_CAP_ATTR_ENUM_MAX - 1, | |
255 | +}; | |
219 | 256 | /** |
220 | 257 | * enum dcb_general_attr_values - general DCB attribute values |
221 | 258 | * |
include/net/dcbnl.h
net/dcb/dcbnl.c
... | ... | @@ -61,6 +61,7 @@ |
61 | 61 | [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED}, |
62 | 62 | [DCB_ATTR_SET_ALL] = {.type = NLA_U8}, |
63 | 63 | [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG}, |
64 | + [DCB_ATTR_CAP] = {.type = NLA_NESTED}, | |
64 | 65 | }; |
65 | 66 | |
66 | 67 | /* DCB priority flow control to User Priority nested attributes */ |
... | ... | @@ -107,6 +108,17 @@ |
107 | 108 | [DCB_TC_ATTR_PARAM_ALL] = {.type = NLA_FLAG}, |
108 | 109 | }; |
109 | 110 | |
111 | +/* DCB capabilities nested attributes. */ | |
112 | +static struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = { | |
113 | + [DCB_CAP_ATTR_ALL] = {.type = NLA_FLAG}, | |
114 | + [DCB_CAP_ATTR_PG] = {.type = NLA_U8}, | |
115 | + [DCB_CAP_ATTR_PFC] = {.type = NLA_U8}, | |
116 | + [DCB_CAP_ATTR_UP2TC] = {.type = NLA_U8}, | |
117 | + [DCB_CAP_ATTR_PG_TCS] = {.type = NLA_U8}, | |
118 | + [DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8}, | |
119 | + [DCB_CAP_ATTR_GSP] = {.type = NLA_U8}, | |
120 | + [DCB_CAP_ATTR_BCN] = {.type = NLA_U8}, | |
121 | +}; | |
110 | 122 | |
111 | 123 | /* standard netlink reply call */ |
112 | 124 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, |
... | ... | @@ -269,6 +281,72 @@ |
269 | 281 | return -EINVAL; |
270 | 282 | } |
271 | 283 | |
284 | +static int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb, | |
285 | + u32 pid, u32 seq, u16 flags) | |
286 | +{ | |
287 | + struct sk_buff *dcbnl_skb; | |
288 | + struct nlmsghdr *nlh; | |
289 | + struct dcbmsg *dcb; | |
290 | + struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest; | |
291 | + u8 value; | |
292 | + int ret = -EINVAL; | |
293 | + int i; | |
294 | + int getall = 0; | |
295 | + | |
296 | + if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap) | |
297 | + return ret; | |
298 | + | |
299 | + ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP], | |
300 | + dcbnl_cap_nest); | |
301 | + if (ret) | |
302 | + goto err_out; | |
303 | + | |
304 | + dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | |
305 | + if (!dcbnl_skb) | |
306 | + goto err_out; | |
307 | + | |
308 | + nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); | |
309 | + | |
310 | + dcb = NLMSG_DATA(nlh); | |
311 | + dcb->dcb_family = AF_UNSPEC; | |
312 | + dcb->cmd = DCB_CMD_GCAP; | |
313 | + | |
314 | + nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP); | |
315 | + if (!nest) | |
316 | + goto err; | |
317 | + | |
318 | + if (data[DCB_CAP_ATTR_ALL]) | |
319 | + getall = 1; | |
320 | + | |
321 | + for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) { | |
322 | + if (!getall && !data[i]) | |
323 | + continue; | |
324 | + | |
325 | + if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) { | |
326 | + ret = nla_put_u8(dcbnl_skb, i, value); | |
327 | + | |
328 | + if (ret) { | |
329 | + nla_nest_cancel(dcbnl_skb, nest); | |
330 | + goto err; | |
331 | + } | |
332 | + } | |
333 | + } | |
334 | + nla_nest_end(dcbnl_skb, nest); | |
335 | + | |
336 | + nlmsg_end(dcbnl_skb, nlh); | |
337 | + | |
338 | + ret = rtnl_unicast(dcbnl_skb, &init_net, pid); | |
339 | + if (ret) | |
340 | + goto err; | |
341 | + | |
342 | + return 0; | |
343 | +nlmsg_failure: | |
344 | +err: | |
345 | + kfree(dcbnl_skb); | |
346 | +err_out: | |
347 | + return -EINVAL; | |
348 | +} | |
349 | + | |
272 | 350 | static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, |
273 | 351 | u32 pid, u32 seq, u16 flags, int dir) |
274 | 352 | { |
... | ... | @@ -674,6 +752,10 @@ |
674 | 752 | case DCB_CMD_PGRX_SCFG: |
675 | 753 | ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, |
676 | 754 | nlh->nlmsg_flags); |
755 | + goto out; | |
756 | + case DCB_CMD_GCAP: | |
757 | + ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq, | |
758 | + nlh->nlmsg_flags); | |
677 | 759 | goto out; |
678 | 760 | default: |
679 | 761 | goto errout; |