diff options
-rw-r--r-- | include/linux/dcbnl.h | 33 | ||||
-rw-r--r-- | include/net/dcbnl.h | 3 | ||||
-rw-r--r-- | net/dcb/dcbnl.c | 133 |
3 files changed, 169 insertions, 0 deletions
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h index 16eea36d8934..68cd248f6d3e 100644 --- a/include/linux/dcbnl.h +++ b/include/linux/dcbnl.h | |||
@@ -137,6 +137,8 @@ struct dcbmsg { | |||
137 | * @DCB_CMD_IEEE_GET: get IEEE 802.1Qaz configuration | 137 | * @DCB_CMD_IEEE_GET: get IEEE 802.1Qaz configuration |
138 | * @DCB_CMD_GDCBX: get DCBX engine configuration | 138 | * @DCB_CMD_GDCBX: get DCBX engine configuration |
139 | * @DCB_CMD_SDCBX: set DCBX engine configuration | 139 | * @DCB_CMD_SDCBX: set DCBX engine configuration |
140 | * @DCB_CMD_GFEATCFG: get DCBX features flags | ||
141 | * @DCB_CMD_SFEATCFG: set DCBX features negotiation flags | ||
140 | */ | 142 | */ |
141 | enum dcbnl_commands { | 143 | enum dcbnl_commands { |
142 | DCB_CMD_UNDEFINED, | 144 | DCB_CMD_UNDEFINED, |
@@ -176,6 +178,9 @@ enum dcbnl_commands { | |||
176 | DCB_CMD_GDCBX, | 178 | DCB_CMD_GDCBX, |
177 | DCB_CMD_SDCBX, | 179 | DCB_CMD_SDCBX, |
178 | 180 | ||
181 | DCB_CMD_GFEATCFG, | ||
182 | DCB_CMD_SFEATCFG, | ||
183 | |||
179 | __DCB_CMD_ENUM_MAX, | 184 | __DCB_CMD_ENUM_MAX, |
180 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, | 185 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, |
181 | }; | 186 | }; |
@@ -197,6 +202,7 @@ enum dcbnl_commands { | |||
197 | * @DCB_ATTR_BCN: backward congestion notification configuration (NLA_NESTED) | 202 | * @DCB_ATTR_BCN: backward congestion notification configuration (NLA_NESTED) |
198 | * @DCB_ATTR_IEEE: IEEE 802.1Qaz supported attributes (NLA_NESTED) | 203 | * @DCB_ATTR_IEEE: IEEE 802.1Qaz supported attributes (NLA_NESTED) |
199 | * @DCB_ATTR_DCBX: DCBX engine configuration in the device (NLA_U8) | 204 | * @DCB_ATTR_DCBX: DCBX engine configuration in the device (NLA_U8) |
205 | * @DCB_ATTR_FEATCFG: DCBX features flags (NLA_NESTED) | ||
200 | */ | 206 | */ |
201 | enum dcbnl_attrs { | 207 | enum dcbnl_attrs { |
202 | DCB_ATTR_UNDEFINED, | 208 | DCB_ATTR_UNDEFINED, |
@@ -218,6 +224,7 @@ enum dcbnl_attrs { | |||
218 | DCB_ATTR_IEEE, | 224 | DCB_ATTR_IEEE, |
219 | 225 | ||
220 | DCB_ATTR_DCBX, | 226 | DCB_ATTR_DCBX, |
227 | DCB_ATTR_FEATCFG, | ||
221 | 228 | ||
222 | __DCB_ATTR_ENUM_MAX, | 229 | __DCB_ATTR_ENUM_MAX, |
223 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, | 230 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, |
@@ -506,4 +513,30 @@ enum dcbnl_app_attrs { | |||
506 | DCB_APP_ATTR_MAX = __DCB_APP_ATTR_ENUM_MAX - 1, | 513 | DCB_APP_ATTR_MAX = __DCB_APP_ATTR_ENUM_MAX - 1, |
507 | }; | 514 | }; |
508 | 515 | ||
516 | /** | ||
517 | * enum dcbnl_featcfg_attrs - features conifiguration flags | ||
518 | * | ||
519 | * @DCB_FEATCFG_ATTR_UNDEFINED: unspecified attribute to catch errors | ||
520 | * @DCB_FEATCFG_ATTR_ALL: (NLA_FLAG) all features configuration attributes | ||
521 | * @DCB_FEATCFG_ATTR_PG: (NLA_U8) configuration flags for priority groups | ||
522 | * @DCB_FEATCFG_ATTR_PFC: (NLA_U8) configuration flags for priority | ||
523 | * flow control | ||
524 | * @DCB_FEATCFG_ATTR_APP: (NLA_U8) configuration flags for application TLV | ||
525 | * | ||
526 | */ | ||
527 | #define DCB_FEATCFG_ERROR 0x01 /* error in feature resolution */ | ||
528 | #define DCB_FEATCFG_ENABLE 0x02 /* enable feature */ | ||
529 | #define DCB_FEATCFG_WILLING 0x04 /* feature is willing */ | ||
530 | #define DCB_FEATCFG_ADVERTISE 0x08 /* advertise feature */ | ||
531 | enum dcbnl_featcfg_attrs { | ||
532 | DCB_FEATCFG_ATTR_UNDEFINED, | ||
533 | DCB_FEATCFG_ATTR_ALL, | ||
534 | DCB_FEATCFG_ATTR_PG, | ||
535 | DCB_FEATCFG_ATTR_PFC, | ||
536 | DCB_FEATCFG_ATTR_APP, | ||
537 | |||
538 | __DCB_FEATCFG_ATTR_ENUM_MAX, | ||
539 | DCB_FEATCFG_ATTR_MAX = __DCB_FEATCFG_ATTR_ENUM_MAX - 1, | ||
540 | }; | ||
541 | |||
509 | #endif /* __LINUX_DCBNL_H__ */ | 542 | #endif /* __LINUX_DCBNL_H__ */ |
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h index c65347b3cbbf..a8e7852b10ab 100644 --- a/include/net/dcbnl.h +++ b/include/net/dcbnl.h | |||
@@ -70,11 +70,14 @@ struct dcbnl_rtnl_ops { | |||
70 | void (*setbcnrp)(struct net_device *, int, u8); | 70 | void (*setbcnrp)(struct net_device *, int, u8); |
71 | u8 (*setapp)(struct net_device *, u8, u16, u8); | 71 | u8 (*setapp)(struct net_device *, u8, u16, u8); |
72 | u8 (*getapp)(struct net_device *, u8, u16); | 72 | u8 (*getapp)(struct net_device *, u8, u16); |
73 | u8 (*getfeatcfg)(struct net_device *, int, u8 *); | ||
74 | u8 (*setfeatcfg)(struct net_device *, int, u8); | ||
73 | 75 | ||
74 | /* DCBX configuration */ | 76 | /* DCBX configuration */ |
75 | u8 (*getdcbx)(struct net_device *); | 77 | u8 (*getdcbx)(struct net_device *); |
76 | u8 (*setdcbx)(struct net_device *, u8); | 78 | u8 (*setdcbx)(struct net_device *, u8); |
77 | 79 | ||
80 | |||
78 | }; | 81 | }; |
79 | 82 | ||
80 | #endif /* __NET_DCBNL_H__ */ | 83 | #endif /* __NET_DCBNL_H__ */ |
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 8f83ad859d9b..075af0a08d84 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c | |||
@@ -69,6 +69,7 @@ static const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { | |||
69 | [DCB_ATTR_APP] = {.type = NLA_NESTED}, | 69 | [DCB_ATTR_APP] = {.type = NLA_NESTED}, |
70 | [DCB_ATTR_IEEE] = {.type = NLA_NESTED}, | 70 | [DCB_ATTR_IEEE] = {.type = NLA_NESTED}, |
71 | [DCB_ATTR_DCBX] = {.type = NLA_U8}, | 71 | [DCB_ATTR_DCBX] = {.type = NLA_U8}, |
72 | [DCB_ATTR_FEATCFG] = {.type = NLA_NESTED}, | ||
72 | }; | 73 | }; |
73 | 74 | ||
74 | /* DCB priority flow control to User Priority nested attributes */ | 75 | /* DCB priority flow control to User Priority nested attributes */ |
@@ -182,6 +183,14 @@ static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = { | |||
182 | [DCB_ATTR_IEEE_APP] = {.len = sizeof(struct dcb_app)}, | 183 | [DCB_ATTR_IEEE_APP] = {.len = sizeof(struct dcb_app)}, |
183 | }; | 184 | }; |
184 | 185 | ||
186 | /* DCB number of traffic classes nested attributes. */ | ||
187 | static const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = { | ||
188 | [DCB_FEATCFG_ATTR_ALL] = {.type = NLA_FLAG}, | ||
189 | [DCB_FEATCFG_ATTR_PG] = {.type = NLA_U8}, | ||
190 | [DCB_FEATCFG_ATTR_PFC] = {.type = NLA_U8}, | ||
191 | [DCB_FEATCFG_ATTR_APP] = {.type = NLA_U8}, | ||
192 | }; | ||
193 | |||
185 | static LIST_HEAD(dcb_app_list); | 194 | static LIST_HEAD(dcb_app_list); |
186 | static DEFINE_SPINLOCK(dcb_lock); | 195 | static DEFINE_SPINLOCK(dcb_lock); |
187 | 196 | ||
@@ -1306,6 +1315,122 @@ static int dcbnl_setdcbx(struct net_device *netdev, struct nlattr **tb, | |||
1306 | return ret; | 1315 | return ret; |
1307 | } | 1316 | } |
1308 | 1317 | ||
1318 | static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb, | ||
1319 | u32 pid, u32 seq, u16 flags) | ||
1320 | { | ||
1321 | struct sk_buff *dcbnl_skb; | ||
1322 | struct nlmsghdr *nlh; | ||
1323 | struct dcbmsg *dcb; | ||
1324 | struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest; | ||
1325 | u8 value; | ||
1326 | int ret = -EINVAL; | ||
1327 | int i; | ||
1328 | int getall = 0; | ||
1329 | |||
1330 | if (!tb[DCB_ATTR_FEATCFG] || !netdev->dcbnl_ops->getfeatcfg) | ||
1331 | return ret; | ||
1332 | |||
1333 | ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG], | ||
1334 | dcbnl_featcfg_nest); | ||
1335 | if (ret) { | ||
1336 | ret = -EINVAL; | ||
1337 | goto err_out; | ||
1338 | } | ||
1339 | |||
1340 | dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
1341 | if (!dcbnl_skb) { | ||
1342 | ret = -EINVAL; | ||
1343 | goto err_out; | ||
1344 | } | ||
1345 | |||
1346 | nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); | ||
1347 | |||
1348 | dcb = NLMSG_DATA(nlh); | ||
1349 | dcb->dcb_family = AF_UNSPEC; | ||
1350 | dcb->cmd = DCB_CMD_GFEATCFG; | ||
1351 | |||
1352 | nest = nla_nest_start(dcbnl_skb, DCB_ATTR_FEATCFG); | ||
1353 | if (!nest) { | ||
1354 | ret = -EINVAL; | ||
1355 | goto err; | ||
1356 | } | ||
1357 | |||
1358 | if (data[DCB_FEATCFG_ATTR_ALL]) | ||
1359 | getall = 1; | ||
1360 | |||
1361 | for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) { | ||
1362 | if (!getall && !data[i]) | ||
1363 | continue; | ||
1364 | |||
1365 | ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value); | ||
1366 | if (!ret) { | ||
1367 | ret = nla_put_u8(dcbnl_skb, i, value); | ||
1368 | |||
1369 | if (ret) { | ||
1370 | nla_nest_cancel(dcbnl_skb, nest); | ||
1371 | ret = -EINVAL; | ||
1372 | goto err; | ||
1373 | } | ||
1374 | } else | ||
1375 | goto err; | ||
1376 | } | ||
1377 | nla_nest_end(dcbnl_skb, nest); | ||
1378 | |||
1379 | nlmsg_end(dcbnl_skb, nlh); | ||
1380 | |||
1381 | ret = rtnl_unicast(dcbnl_skb, &init_net, pid); | ||
1382 | if (ret) { | ||
1383 | ret = -EINVAL; | ||
1384 | goto err_out; | ||
1385 | } | ||
1386 | |||
1387 | return 0; | ||
1388 | nlmsg_failure: | ||
1389 | err: | ||
1390 | kfree_skb(dcbnl_skb); | ||
1391 | err_out: | ||
1392 | return ret; | ||
1393 | } | ||
1394 | |||
1395 | static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlattr **tb, | ||
1396 | u32 pid, u32 seq, u16 flags) | ||
1397 | { | ||
1398 | struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1]; | ||
1399 | int ret = -EINVAL; | ||
1400 | u8 value; | ||
1401 | int i; | ||
1402 | |||
1403 | if (!tb[DCB_ATTR_FEATCFG] || !netdev->dcbnl_ops->setfeatcfg) | ||
1404 | return ret; | ||
1405 | |||
1406 | ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG], | ||
1407 | dcbnl_featcfg_nest); | ||
1408 | |||
1409 | if (ret) { | ||
1410 | ret = -EINVAL; | ||
1411 | goto err; | ||
1412 | } | ||
1413 | |||
1414 | for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) { | ||
1415 | if (data[i] == NULL) | ||
1416 | continue; | ||
1417 | |||
1418 | value = nla_get_u8(data[i]); | ||
1419 | |||
1420 | ret = netdev->dcbnl_ops->setfeatcfg(netdev, i, value); | ||
1421 | |||
1422 | if (ret) | ||
1423 | goto operr; | ||
1424 | } | ||
1425 | |||
1426 | operr: | ||
1427 | ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SFEATCFG, | ||
1428 | DCB_ATTR_FEATCFG, pid, seq, flags); | ||
1429 | |||
1430 | err: | ||
1431 | return ret; | ||
1432 | } | ||
1433 | |||
1309 | static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 1434 | static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
1310 | { | 1435 | { |
1311 | struct net *net = sock_net(skb->sk); | 1436 | struct net *net = sock_net(skb->sk); |
@@ -1427,6 +1552,14 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1427 | ret = dcbnl_setdcbx(netdev, tb, pid, nlh->nlmsg_seq, | 1552 | ret = dcbnl_setdcbx(netdev, tb, pid, nlh->nlmsg_seq, |
1428 | nlh->nlmsg_flags); | 1553 | nlh->nlmsg_flags); |
1429 | goto out; | 1554 | goto out; |
1555 | case DCB_CMD_GFEATCFG: | ||
1556 | ret = dcbnl_getfeatcfg(netdev, tb, pid, nlh->nlmsg_seq, | ||
1557 | nlh->nlmsg_flags); | ||
1558 | goto out; | ||
1559 | case DCB_CMD_SFEATCFG: | ||
1560 | ret = dcbnl_setfeatcfg(netdev, tb, pid, nlh->nlmsg_seq, | ||
1561 | nlh->nlmsg_flags); | ||
1562 | goto out; | ||
1430 | default: | 1563 | default: |
1431 | goto errout; | 1564 | goto errout; |
1432 | } | 1565 | } |