Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

John Fastabend and committed by
David S. Miller
9ab933ab 3e29027a

+135 -11
+3 -1
include/linux/dcbnl.h
··· 82 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 89 * @selector: protocol identifier type 88 90 * @protocol: protocol of type indicated
+9
include/net/dcbnl.h
··· 22 22 23 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 35 * Ops struct for the netlink callbacks. Used by DCB-enabled drivers through 27 36 * the netdevice struct.
+123 -10
net/dcb/dcbnl.c
··· 179 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 185 /* standard netlink reply call */ 183 186 static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, 184 187 u32 seq, u16 flags) ··· 637 634 static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb, 638 635 u32 pid, u32 seq, u16 flags) 639 636 { 640 - int ret = -EINVAL; 637 + int err, ret = -EINVAL; 641 638 u16 id; 642 639 u8 up, idtype; 643 640 struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; 644 641 645 - if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->setapp) 642 + if (!tb[DCB_ATTR_APP]) 646 643 goto out; 647 644 648 645 ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], ··· 666 663 id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); 667 664 up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]); 668 665 669 - ret = dcbnl_reply(netdev->dcbnl_ops->setapp(netdev, idtype, id, up), 670 - RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP, 671 - pid, seq, flags); 666 + if (netdev->dcbnl_ops->setapp) { 667 + err = netdev->dcbnl_ops->setapp(netdev, idtype, id, up); 668 + } else { 669 + struct dcb_app app; 670 + app.selector = idtype; 671 + app.protocol = id; 672 + app.priority = up; 673 + err = dcb_setapp(netdev, &app); 674 + } 675 + 676 + ret = dcbnl_reply(err, RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP, 677 + pid, seq, flags); 672 678 out: 673 679 return ret; 674 680 } ··· 1176 1164 goto err; 1177 1165 } 1178 1166 1179 - if (ieee[DCB_ATTR_IEEE_APP_TABLE] && ops->ieee_setapp) { 1167 + if (ieee[DCB_ATTR_IEEE_APP_TABLE]) { 1180 1168 struct nlattr *attr; 1181 1169 int rem; 1182 1170 ··· 1185 1173 if (nla_type(attr) != DCB_ATTR_IEEE_APP) 1186 1174 continue; 1187 1175 app_data = nla_data(attr); 1188 - err = ops->ieee_setapp(netdev, app_data); 1176 + if (ops->ieee_setapp) 1177 + err = ops->ieee_setapp(netdev, app_data); 1178 + else 1179 + err = dcb_setapp(netdev, app_data); 1189 1180 if (err) 1190 1181 goto err; 1191 1182 } ··· 1208 1193 struct sk_buff *skb; 1209 1194 struct nlmsghdr *nlh; 1210 1195 struct dcbmsg *dcb; 1211 - struct nlattr *ieee; 1196 + struct nlattr *ieee, *app; 1197 + struct dcb_app_type *itr; 1212 1198 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1213 1199 int err; 1214 1200 ··· 1245 1229 if (!err) 1246 1230 NLA_PUT(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc); 1247 1231 } 1232 + 1233 + app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE); 1234 + if (!app) 1235 + goto nla_put_failure; 1236 + 1237 + spin_lock(&dcb_lock); 1238 + list_for_each_entry(itr, &dcb_app_list, list) { 1239 + if (strncmp(itr->name, netdev->name, IFNAMSIZ) == 0) 1240 + NLA_PUT(skb, DCB_ATTR_IEEE_APP, 1241 + sizeof(itr->app), &itr->app); 1242 + } 1243 + spin_unlock(&dcb_lock); 1244 + nla_nest_end(skb, app); 1248 1245 1249 1246 nla_nest_end(skb, ieee); 1250 1247 nlmsg_end(skb, nlh); ··· 1393 1364 return ret; 1394 1365 } 1395 1366 1367 + /** 1368 + * dcb_getapp - retrieve the DCBX application user priority 1369 + * 1370 + * On success returns a non-zero 802.1p user priority bitmap 1371 + * otherwise returns 0 as the invalid user priority bitmap to 1372 + * indicate an error. 1373 + */ 1374 + u8 dcb_getapp(struct net_device *dev, struct dcb_app *app) 1375 + { 1376 + struct dcb_app_type *itr; 1377 + u8 prio = 0; 1378 + 1379 + spin_lock(&dcb_lock); 1380 + list_for_each_entry(itr, &dcb_app_list, list) { 1381 + if (itr->app.selector == app->selector && 1382 + itr->app.protocol == app->protocol && 1383 + (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) { 1384 + prio = itr->app.priority; 1385 + break; 1386 + } 1387 + } 1388 + spin_unlock(&dcb_lock); 1389 + 1390 + return prio; 1391 + } 1392 + EXPORT_SYMBOL(dcb_getapp); 1393 + 1394 + /** 1395 + * ixgbe_dcbnl_setapp - add dcb application data to app list 1396 + * 1397 + * Priority 0 is the default priority this removes applications 1398 + * from the app list if the priority is set to zero. 1399 + */ 1400 + u8 dcb_setapp(struct net_device *dev, struct dcb_app *new) 1401 + { 1402 + struct dcb_app_type *itr; 1403 + 1404 + spin_lock(&dcb_lock); 1405 + /* Search for existing match and replace */ 1406 + list_for_each_entry(itr, &dcb_app_list, list) { 1407 + if (itr->app.selector == new->selector && 1408 + itr->app.protocol == new->protocol && 1409 + (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) { 1410 + if (new->priority) 1411 + itr->app.priority = new->priority; 1412 + else { 1413 + list_del(&itr->list); 1414 + kfree(itr); 1415 + } 1416 + goto out; 1417 + } 1418 + } 1419 + /* App type does not exist add new application type */ 1420 + if (new->priority) { 1421 + struct dcb_app_type *entry; 1422 + entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC); 1423 + if (!entry) { 1424 + spin_unlock(&dcb_lock); 1425 + return -ENOMEM; 1426 + } 1427 + 1428 + memcpy(&entry->app, new, sizeof(*new)); 1429 + strncpy(entry->name, dev->name, IFNAMSIZ); 1430 + list_add(&entry->list, &dcb_app_list); 1431 + } 1432 + out: 1433 + spin_unlock(&dcb_lock); 1434 + return 0; 1435 + } 1436 + EXPORT_SYMBOL(dcb_setapp); 1437 + 1438 + void dcb_flushapp(void) 1439 + { 1440 + struct dcb_app_type *app; 1441 + 1442 + spin_lock(&dcb_lock); 1443 + list_for_each_entry(app, &dcb_app_list, list) { 1444 + list_del(&app->list); 1445 + kfree(app); 1446 + } 1447 + spin_unlock(&dcb_lock); 1448 + } 1449 + 1396 1450 static int __init dcbnl_init(void) 1397 1451 { 1452 + INIT_LIST_HEAD(&dcb_app_list); 1453 + 1398 1454 rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL); 1399 1455 rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL); 1400 1456 ··· 1491 1377 { 1492 1378 rtnl_unregister(PF_UNSPEC, RTM_GETDCB); 1493 1379 rtnl_unregister(PF_UNSPEC, RTM_SETDCB); 1380 + dcb_flushapp(); 1494 1381 } 1495 1382 module_exit(dcbnl_exit); 1496 - 1497 -