aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn Fastabend <john.r.fastabend@intel.com>2010-12-30 04:26:31 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-31 13:47:45 -0500
commit9ab933ab2cc80f04690d6aa385b1110075c5e507 (patch)
tree439f1d393d080473575f5ecfe6dcd4f3c10775e9 /net
parent3e29027af43728c2a91fe3f735ab2822edaf54a8 (diff)
dcbnl: add appliction tlv handlers
This patch adds application tlv handlers. Networking stacks may use the application priority to set the skb priority of their stack using the negoatiated dcbx priority. This patch provides the dcb_{get|set}app() routines for the stack to query these parameters. Notice lower layer drivers can use the dcbnl_ops routines if additional handling is needed. Perhaps in the firmware case for example Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Signed-off-by: Shmulik Ravid <shmulikr@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/dcb/dcbnl.c133
1 files changed, 123 insertions, 10 deletions
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
182static LIST_HEAD(dcb_app_list);
183static DEFINE_SPINLOCK(dcb_lock);
184
182/* standard netlink reply call */ 185/* standard netlink reply call */
183static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, 186static 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:
634static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb, 637static 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);
669out: 681out:
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 */
1403u8 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}
1421EXPORT_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 */
1429u8 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 }
1461out:
1462 spin_unlock(&dcb_lock);
1463 return 0;
1464}
1465EXPORT_SYMBOL(dcb_setapp);
1466
1467void 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
1367static int __init dcbnl_init(void) 1479static 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}
1381module_exit(dcbnl_exit); 1496module_exit(dcbnl_exit);
1382
1383