aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/dcbnl.h33
-rw-r--r--include/net/dcbnl.h3
-rw-r--r--net/dcb/dcbnl.c133
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 */
141enum dcbnl_commands { 143enum 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 */
201enum dcbnl_attrs { 207enum 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 */
531enum 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. */
187static 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
185static LIST_HEAD(dcb_app_list); 194static LIST_HEAD(dcb_app_list);
186static DEFINE_SPINLOCK(dcb_lock); 195static 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
1318static 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;
1388nlmsg_failure:
1389err:
1390 kfree_skb(dcbnl_skb);
1391err_out:
1392 return ret;
1393}
1394
1395static 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
1426operr:
1427 ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SFEATCFG,
1428 DCB_ATTR_FEATCFG, pid, seq, flags);
1429
1430err:
1431 return ret;
1432}
1433
1309static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 1434static 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 }