diff options
-rw-r--r-- | include/linux/dcbnl.h | 4 | ||||
-rw-r--r-- | include/net/dcbnl.h | 9 | ||||
-rw-r--r-- | net/dcb/dcbnl.c | 133 |
3 files changed, 135 insertions, 11 deletions
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h index 287b5618e296..775bdb4465bf 100644 --- a/include/linux/dcbnl.h +++ b/include/linux/dcbnl.h | |||
@@ -82,7 +82,9 @@ struct ieee_pfc { | |||
82 | __u64 indications[IEEE_8021QAZ_MAX_TCS]; | 82 | __u64 indications[IEEE_8021QAZ_MAX_TCS]; |
83 | }; | 83 | }; |
84 | 84 | ||
85 | /* This structure contains the IEEE 802.1Qaz APP managed object | 85 | /* This structure contains the IEEE 802.1Qaz APP managed object. This |
86 | * object is also used for the CEE std as well. There is no difference | ||
87 | * between the objects. | ||
86 | * | 88 | * |
87 | * @selector: protocol identifier type | 89 | * @selector: protocol identifier type |
88 | * @protocol: protocol of type indicated | 90 | * @protocol: protocol of type indicated |
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h index e2d841e963b3..ab7d623a2793 100644 --- a/include/net/dcbnl.h +++ b/include/net/dcbnl.h | |||
@@ -22,6 +22,15 @@ | |||
22 | 22 | ||
23 | #include <linux/dcbnl.h> | 23 | #include <linux/dcbnl.h> |
24 | 24 | ||
25 | struct dcb_app_type { | ||
26 | char name[IFNAMSIZ]; | ||
27 | struct dcb_app app; | ||
28 | struct list_head list; | ||
29 | }; | ||
30 | |||
31 | u8 dcb_setapp(struct net_device *, struct dcb_app *); | ||
32 | u8 dcb_getapp(struct net_device *, struct dcb_app *); | ||
33 | |||
25 | /* | 34 | /* |
26 | * Ops struct for the netlink callbacks. Used by DCB-enabled drivers through | 35 | * Ops struct for the netlink callbacks. Used by DCB-enabled drivers through |
27 | * the netdevice struct. | 36 | * the netdevice struct. |
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 2ff908498924..cfd731faf6c6 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c | |||
@@ -179,6 +179,9 @@ static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = { | |||
179 | [DCB_ATTR_IEEE_APP] = {.len = sizeof(struct dcb_app)}, | 179 | [DCB_ATTR_IEEE_APP] = {.len = sizeof(struct dcb_app)}, |
180 | }; | 180 | }; |
181 | 181 | ||
182 | static LIST_HEAD(dcb_app_list); | ||
183 | static DEFINE_SPINLOCK(dcb_lock); | ||
184 | |||
182 | /* standard netlink reply call */ | 185 | /* standard netlink reply call */ |
183 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, | 186 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, |
184 | u32 seq, u16 flags) | 187 | u32 seq, u16 flags) |
@@ -634,12 +637,12 @@ out: | |||
634 | static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb, | 637 | static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb, |
635 | u32 pid, u32 seq, u16 flags) | 638 | u32 pid, u32 seq, u16 flags) |
636 | { | 639 | { |
637 | int ret = -EINVAL; | 640 | int err, ret = -EINVAL; |
638 | u16 id; | 641 | u16 id; |
639 | u8 up, idtype; | 642 | u8 up, idtype; |
640 | struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; | 643 | struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; |
641 | 644 | ||
642 | if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->setapp) | 645 | if (!tb[DCB_ATTR_APP]) |
643 | goto out; | 646 | goto out; |
644 | 647 | ||
645 | ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], | 648 | ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], |
@@ -663,9 +666,18 @@ static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb, | |||
663 | id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); | 666 | id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); |
664 | up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]); | 667 | up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]); |
665 | 668 | ||
666 | ret = dcbnl_reply(netdev->dcbnl_ops->setapp(netdev, idtype, id, up), | 669 | if (netdev->dcbnl_ops->setapp) { |
667 | RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP, | 670 | err = netdev->dcbnl_ops->setapp(netdev, idtype, id, up); |
668 | pid, seq, flags); | 671 | } else { |
672 | struct dcb_app app; | ||
673 | app.selector = idtype; | ||
674 | app.protocol = id; | ||
675 | app.priority = up; | ||
676 | err = dcb_setapp(netdev, &app); | ||
677 | } | ||
678 | |||
679 | ret = dcbnl_reply(err, RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP, | ||
680 | pid, seq, flags); | ||
669 | out: | 681 | out: |
670 | return ret; | 682 | return ret; |
671 | } | 683 | } |
@@ -1164,7 +1176,7 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb, | |||
1164 | goto err; | 1176 | goto err; |
1165 | } | 1177 | } |
1166 | 1178 | ||
1167 | if (ieee[DCB_ATTR_IEEE_APP_TABLE] && ops->ieee_setapp) { | 1179 | if (ieee[DCB_ATTR_IEEE_APP_TABLE]) { |
1168 | struct nlattr *attr; | 1180 | struct nlattr *attr; |
1169 | int rem; | 1181 | int rem; |
1170 | 1182 | ||
@@ -1173,7 +1185,10 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb, | |||
1173 | if (nla_type(attr) != DCB_ATTR_IEEE_APP) | 1185 | if (nla_type(attr) != DCB_ATTR_IEEE_APP) |
1174 | continue; | 1186 | continue; |
1175 | app_data = nla_data(attr); | 1187 | app_data = nla_data(attr); |
1176 | err = ops->ieee_setapp(netdev, app_data); | 1188 | if (ops->ieee_setapp) |
1189 | err = ops->ieee_setapp(netdev, app_data); | ||
1190 | else | ||
1191 | err = dcb_setapp(netdev, app_data); | ||
1177 | if (err) | 1192 | if (err) |
1178 | goto err; | 1193 | goto err; |
1179 | } | 1194 | } |
@@ -1193,7 +1208,8 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, | |||
1193 | struct sk_buff *skb; | 1208 | struct sk_buff *skb; |
1194 | struct nlmsghdr *nlh; | 1209 | struct nlmsghdr *nlh; |
1195 | struct dcbmsg *dcb; | 1210 | struct dcbmsg *dcb; |
1196 | struct nlattr *ieee; | 1211 | struct nlattr *ieee, *app; |
1212 | struct dcb_app_type *itr; | ||
1197 | const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; | 1213 | const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; |
1198 | int err; | 1214 | int err; |
1199 | 1215 | ||
@@ -1230,6 +1246,19 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, | |||
1230 | NLA_PUT(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc); | 1246 | NLA_PUT(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc); |
1231 | } | 1247 | } |
1232 | 1248 | ||
1249 | app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE); | ||
1250 | if (!app) | ||
1251 | goto nla_put_failure; | ||
1252 | |||
1253 | spin_lock(&dcb_lock); | ||
1254 | list_for_each_entry(itr, &dcb_app_list, list) { | ||
1255 | if (strncmp(itr->name, netdev->name, IFNAMSIZ) == 0) | ||
1256 | NLA_PUT(skb, DCB_ATTR_IEEE_APP, | ||
1257 | sizeof(itr->app), &itr->app); | ||
1258 | } | ||
1259 | spin_unlock(&dcb_lock); | ||
1260 | nla_nest_end(skb, app); | ||
1261 | |||
1233 | nla_nest_end(skb, ieee); | 1262 | nla_nest_end(skb, ieee); |
1234 | nlmsg_end(skb, nlh); | 1263 | nlmsg_end(skb, nlh); |
1235 | 1264 | ||
@@ -1364,8 +1393,93 @@ out: | |||
1364 | return ret; | 1393 | return ret; |
1365 | } | 1394 | } |
1366 | 1395 | ||
1396 | /** | ||
1397 | * dcb_getapp - retrieve the DCBX application user priority | ||
1398 | * | ||
1399 | * On success returns a non-zero 802.1p user priority bitmap | ||
1400 | * otherwise returns 0 as the invalid user priority bitmap to | ||
1401 | * indicate an error. | ||
1402 | */ | ||
1403 | u8 dcb_getapp(struct net_device *dev, struct dcb_app *app) | ||
1404 | { | ||
1405 | struct dcb_app_type *itr; | ||
1406 | u8 prio = 0; | ||
1407 | |||
1408 | spin_lock(&dcb_lock); | ||
1409 | list_for_each_entry(itr, &dcb_app_list, list) { | ||
1410 | if (itr->app.selector == app->selector && | ||
1411 | itr->app.protocol == app->protocol && | ||
1412 | (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) { | ||
1413 | prio = itr->app.priority; | ||
1414 | break; | ||
1415 | } | ||
1416 | } | ||
1417 | spin_unlock(&dcb_lock); | ||
1418 | |||
1419 | return prio; | ||
1420 | } | ||
1421 | EXPORT_SYMBOL(dcb_getapp); | ||
1422 | |||
1423 | /** | ||
1424 | * ixgbe_dcbnl_setapp - add dcb application data to app list | ||
1425 | * | ||
1426 | * Priority 0 is the default priority this removes applications | ||
1427 | * from the app list if the priority is set to zero. | ||
1428 | */ | ||
1429 | u8 dcb_setapp(struct net_device *dev, struct dcb_app *new) | ||
1430 | { | ||
1431 | struct dcb_app_type *itr; | ||
1432 | |||
1433 | spin_lock(&dcb_lock); | ||
1434 | /* Search for existing match and replace */ | ||
1435 | list_for_each_entry(itr, &dcb_app_list, list) { | ||
1436 | if (itr->app.selector == new->selector && | ||
1437 | itr->app.protocol == new->protocol && | ||
1438 | (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) { | ||
1439 | if (new->priority) | ||
1440 | itr->app.priority = new->priority; | ||
1441 | else { | ||
1442 | list_del(&itr->list); | ||
1443 | kfree(itr); | ||
1444 | } | ||
1445 | goto out; | ||
1446 | } | ||
1447 | } | ||
1448 | /* App type does not exist add new application type */ | ||
1449 | if (new->priority) { | ||
1450 | struct dcb_app_type *entry; | ||
1451 | entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC); | ||
1452 | if (!entry) { | ||
1453 | spin_unlock(&dcb_lock); | ||
1454 | return -ENOMEM; | ||
1455 | } | ||
1456 | |||
1457 | memcpy(&entry->app, new, sizeof(*new)); | ||
1458 | strncpy(entry->name, dev->name, IFNAMSIZ); | ||
1459 | list_add(&entry->list, &dcb_app_list); | ||
1460 | } | ||
1461 | out: | ||
1462 | spin_unlock(&dcb_lock); | ||
1463 | return 0; | ||
1464 | } | ||
1465 | EXPORT_SYMBOL(dcb_setapp); | ||
1466 | |||
1467 | void dcb_flushapp(void) | ||
1468 | { | ||
1469 | struct dcb_app_type *app; | ||
1470 | |||
1471 | spin_lock(&dcb_lock); | ||
1472 | list_for_each_entry(app, &dcb_app_list, list) { | ||
1473 | list_del(&app->list); | ||
1474 | kfree(app); | ||
1475 | } | ||
1476 | spin_unlock(&dcb_lock); | ||
1477 | } | ||
1478 | |||
1367 | static int __init dcbnl_init(void) | 1479 | static int __init dcbnl_init(void) |
1368 | { | 1480 | { |
1481 | INIT_LIST_HEAD(&dcb_app_list); | ||
1482 | |||
1369 | rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL); | 1483 | rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL); |
1370 | rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL); | 1484 | rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL); |
1371 | 1485 | ||
@@ -1377,7 +1491,6 @@ static void __exit dcbnl_exit(void) | |||
1377 | { | 1491 | { |
1378 | rtnl_unregister(PF_UNSPEC, RTM_GETDCB); | 1492 | rtnl_unregister(PF_UNSPEC, RTM_GETDCB); |
1379 | rtnl_unregister(PF_UNSPEC, RTM_SETDCB); | 1493 | rtnl_unregister(PF_UNSPEC, RTM_SETDCB); |
1494 | dcb_flushapp(); | ||
1380 | } | 1495 | } |
1381 | module_exit(dcbnl_exit); | 1496 | module_exit(dcbnl_exit); |
1382 | |||
1383 | |||