aboutsummaryrefslogtreecommitdiffstats
path: root/net/dcb/dcbnl.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dcb/dcbnl.c')
-rw-r--r--net/dcb/dcbnl.c677
1 files changed, 547 insertions, 130 deletions
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 3609eacaf4ce..3cb56af4e13c 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1166,64 +1166,6 @@ err:
1166 return ret; 1166 return ret;
1167} 1167}
1168 1168
1169/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
1170 * be completed the entire msg is aborted and error value is returned.
1171 * No attempt is made to reconcile the case where only part of the
1172 * cmd can be completed.
1173 */
1174static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
1175 u32 pid, u32 seq, u16 flags)
1176{
1177 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1178 struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
1179 int err = -EOPNOTSUPP;
1180
1181 if (!ops)
1182 goto err;
1183
1184 err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1185 tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1186 if (err)
1187 goto err;
1188
1189 if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
1190 struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
1191 err = ops->ieee_setets(netdev, ets);
1192 if (err)
1193 goto err;
1194 }
1195
1196 if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
1197 struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
1198 err = ops->ieee_setpfc(netdev, pfc);
1199 if (err)
1200 goto err;
1201 }
1202
1203 if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1204 struct nlattr *attr;
1205 int rem;
1206
1207 nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1208 struct dcb_app *app_data;
1209 if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1210 continue;
1211 app_data = nla_data(attr);
1212 if (ops->ieee_setapp)
1213 err = ops->ieee_setapp(netdev, app_data);
1214 else
1215 err = dcb_setapp(netdev, app_data);
1216 if (err)
1217 goto err;
1218 }
1219 }
1220
1221err:
1222 dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
1223 pid, seq, flags);
1224 return err;
1225}
1226
1227static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb, 1169static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
1228 int app_nested_type, int app_info_type, 1170 int app_nested_type, int app_info_type,
1229 int app_entry_type) 1171 int app_entry_type)
@@ -1279,29 +1221,13 @@ nla_put_failure:
1279} 1221}
1280 1222
1281/* Handle IEEE 802.1Qaz GET commands. */ 1223/* Handle IEEE 802.1Qaz GET commands. */
1282static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, 1224static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
1283 u32 pid, u32 seq, u16 flags)
1284{ 1225{
1285 struct sk_buff *skb;
1286 struct nlmsghdr *nlh;
1287 struct dcbmsg *dcb;
1288 struct nlattr *ieee, *app; 1226 struct nlattr *ieee, *app;
1289 struct dcb_app_type *itr; 1227 struct dcb_app_type *itr;
1290 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1228 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1291 int err; 1229 int dcbx;
1292 1230 int err = -EMSGSIZE;
1293 if (!ops)
1294 return -EOPNOTSUPP;
1295
1296 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1297 if (!skb)
1298 return -ENOBUFS;
1299
1300 nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1301
1302 dcb = NLMSG_DATA(nlh);
1303 dcb->dcb_family = AF_UNSPEC;
1304 dcb->cmd = DCB_CMD_IEEE_GET;
1305 1231
1306 NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name); 1232 NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
1307 1233
@@ -1338,6 +1264,12 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
1338 } 1264 }
1339 } 1265 }
1340 } 1266 }
1267
1268 if (netdev->dcbnl_ops->getdcbx)
1269 dcbx = netdev->dcbnl_ops->getdcbx(netdev);
1270 else
1271 dcbx = -EOPNOTSUPP;
1272
1341 spin_unlock(&dcb_lock); 1273 spin_unlock(&dcb_lock);
1342 nla_nest_end(skb, app); 1274 nla_nest_end(skb, app);
1343 1275
@@ -1366,16 +1298,413 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
1366 } 1298 }
1367 1299
1368 nla_nest_end(skb, ieee); 1300 nla_nest_end(skb, ieee);
1369 nlmsg_end(skb, nlh); 1301 if (dcbx >= 0) {
1302 err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
1303 if (err)
1304 goto nla_put_failure;
1305 }
1306
1307 return 0;
1370 1308
1371 return rtnl_unicast(skb, &init_net, pid);
1372nla_put_failure: 1309nla_put_failure:
1373 nlmsg_cancel(skb, nlh); 1310 return err;
1374nlmsg_failure:
1375 kfree_skb(skb);
1376 return -1;
1377} 1311}
1378 1312
1313static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
1314 int dir)
1315{
1316 u8 pgid, up_map, prio, tc_pct;
1317 const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
1318 int i = dir ? DCB_ATTR_CEE_TX_PG : DCB_ATTR_CEE_RX_PG;
1319 struct nlattr *pg = nla_nest_start(skb, i);
1320
1321 if (!pg)
1322 goto nla_put_failure;
1323
1324 for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
1325 struct nlattr *tc_nest = nla_nest_start(skb, i);
1326
1327 if (!tc_nest)
1328 goto nla_put_failure;
1329
1330 pgid = DCB_ATTR_VALUE_UNDEFINED;
1331 prio = DCB_ATTR_VALUE_UNDEFINED;
1332 tc_pct = DCB_ATTR_VALUE_UNDEFINED;
1333 up_map = DCB_ATTR_VALUE_UNDEFINED;
1334
1335 if (!dir)
1336 ops->getpgtccfgrx(dev, i - DCB_PG_ATTR_TC_0,
1337 &prio, &pgid, &tc_pct, &up_map);
1338 else
1339 ops->getpgtccfgtx(dev, i - DCB_PG_ATTR_TC_0,
1340 &prio, &pgid, &tc_pct, &up_map);
1341
1342 NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_PGID, pgid);
1343 NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
1344 NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
1345 NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct);
1346 nla_nest_end(skb, tc_nest);
1347 }
1348
1349 for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
1350 tc_pct = DCB_ATTR_VALUE_UNDEFINED;
1351
1352 if (!dir)
1353 ops->getpgbwgcfgrx(dev, i - DCB_PG_ATTR_BW_ID_0,
1354 &tc_pct);
1355 else
1356 ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0,
1357 &tc_pct);
1358 NLA_PUT_U8(skb, i, tc_pct);
1359 }
1360 nla_nest_end(skb, pg);
1361 return 0;
1362
1363nla_put_failure:
1364 return -EMSGSIZE;
1365}
1366
1367static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
1368{
1369 struct nlattr *cee, *app;
1370 struct dcb_app_type *itr;
1371 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1372 int dcbx, i, err = -EMSGSIZE;
1373 u8 value;
1374
1375 NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
1376
1377 cee = nla_nest_start(skb, DCB_ATTR_CEE);
1378 if (!cee)
1379 goto nla_put_failure;
1380
1381 /* local pg */
1382 if (ops->getpgtccfgtx && ops->getpgbwgcfgtx) {
1383 err = dcbnl_cee_pg_fill(skb, netdev, 1);
1384 if (err)
1385 goto nla_put_failure;
1386 }
1387
1388 if (ops->getpgtccfgrx && ops->getpgbwgcfgrx) {
1389 err = dcbnl_cee_pg_fill(skb, netdev, 0);
1390 if (err)
1391 goto nla_put_failure;
1392 }
1393
1394 /* local pfc */
1395 if (ops->getpfccfg) {
1396 struct nlattr *pfc_nest = nla_nest_start(skb, DCB_ATTR_CEE_PFC);
1397
1398 if (!pfc_nest)
1399 goto nla_put_failure;
1400
1401 for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
1402 ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value);
1403 NLA_PUT_U8(skb, i, value);
1404 }
1405 nla_nest_end(skb, pfc_nest);
1406 }
1407
1408 /* local app */
1409 spin_lock(&dcb_lock);
1410 app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE);
1411 if (!app)
1412 goto dcb_unlock;
1413
1414 list_for_each_entry(itr, &dcb_app_list, list) {
1415 if (strncmp(itr->name, netdev->name, IFNAMSIZ) == 0) {
1416 struct nlattr *app_nest = nla_nest_start(skb,
1417 DCB_ATTR_APP);
1418 if (!app_nest)
1419 goto dcb_unlock;
1420
1421 err = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE,
1422 itr->app.selector);
1423 if (err)
1424 goto dcb_unlock;
1425
1426 err = nla_put_u16(skb, DCB_APP_ATTR_ID,
1427 itr->app.protocol);
1428 if (err)
1429 goto dcb_unlock;
1430
1431 err = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY,
1432 itr->app.priority);
1433 if (err)
1434 goto dcb_unlock;
1435
1436 nla_nest_end(skb, app_nest);
1437 }
1438 }
1439 nla_nest_end(skb, app);
1440
1441 if (netdev->dcbnl_ops->getdcbx)
1442 dcbx = netdev->dcbnl_ops->getdcbx(netdev);
1443 else
1444 dcbx = -EOPNOTSUPP;
1445
1446 spin_unlock(&dcb_lock);
1447
1448 /* features flags */
1449 if (ops->getfeatcfg) {
1450 struct nlattr *feat = nla_nest_start(skb, DCB_ATTR_CEE_FEAT);
1451 if (!feat)
1452 goto nla_put_failure;
1453
1454 for (i = DCB_FEATCFG_ATTR_ALL + 1; i <= DCB_FEATCFG_ATTR_MAX;
1455 i++)
1456 if (!ops->getfeatcfg(netdev, i, &value))
1457 NLA_PUT_U8(skb, i, value);
1458
1459 nla_nest_end(skb, feat);
1460 }
1461
1462 /* peer info if available */
1463 if (ops->cee_peer_getpg) {
1464 struct cee_pg pg;
1465 err = ops->cee_peer_getpg(netdev, &pg);
1466 if (!err)
1467 NLA_PUT(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg);
1468 }
1469
1470 if (ops->cee_peer_getpfc) {
1471 struct cee_pfc pfc;
1472 err = ops->cee_peer_getpfc(netdev, &pfc);
1473 if (!err)
1474 NLA_PUT(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc);
1475 }
1476
1477 if (ops->peer_getappinfo && ops->peer_getapptable) {
1478 err = dcbnl_build_peer_app(netdev, skb,
1479 DCB_ATTR_CEE_PEER_APP_TABLE,
1480 DCB_ATTR_CEE_PEER_APP_INFO,
1481 DCB_ATTR_CEE_PEER_APP);
1482 if (err)
1483 goto nla_put_failure;
1484 }
1485 nla_nest_end(skb, cee);
1486
1487 /* DCBX state */
1488 if (dcbx >= 0) {
1489 err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
1490 if (err)
1491 goto nla_put_failure;
1492 }
1493 return 0;
1494
1495dcb_unlock:
1496 spin_unlock(&dcb_lock);
1497nla_put_failure:
1498 return err;
1499}
1500
1501static int dcbnl_notify(struct net_device *dev, int event, int cmd,
1502 u32 seq, u32 pid, int dcbx_ver)
1503{
1504 struct net *net = dev_net(dev);
1505 struct sk_buff *skb;
1506 struct nlmsghdr *nlh;
1507 struct dcbmsg *dcb;
1508 const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
1509 int err;
1510
1511 if (!ops)
1512 return -EOPNOTSUPP;
1513
1514 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1515 if (!skb)
1516 return -ENOBUFS;
1517
1518 nlh = nlmsg_put(skb, pid, 0, event, sizeof(*dcb), 0);
1519 if (nlh == NULL) {
1520 nlmsg_free(skb);
1521 return -EMSGSIZE;
1522 }
1523
1524 dcb = NLMSG_DATA(nlh);
1525 dcb->dcb_family = AF_UNSPEC;
1526 dcb->cmd = cmd;
1527
1528 if (dcbx_ver == DCB_CAP_DCBX_VER_IEEE)
1529 err = dcbnl_ieee_fill(skb, dev);
1530 else
1531 err = dcbnl_cee_fill(skb, dev);
1532
1533 if (err < 0) {
1534 /* Report error to broadcast listeners */
1535 nlmsg_cancel(skb, nlh);
1536 kfree_skb(skb);
1537 rtnl_set_sk_err(net, RTNLGRP_DCB, err);
1538 } else {
1539 /* End nlmsg and notify broadcast listeners */
1540 nlmsg_end(skb, nlh);
1541 rtnl_notify(skb, net, 0, RTNLGRP_DCB, NULL, GFP_KERNEL);
1542 }
1543
1544 return err;
1545}
1546
1547int dcbnl_ieee_notify(struct net_device *dev, int event, int cmd,
1548 u32 seq, u32 pid)
1549{
1550 return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_IEEE);
1551}
1552EXPORT_SYMBOL(dcbnl_ieee_notify);
1553
1554int dcbnl_cee_notify(struct net_device *dev, int event, int cmd,
1555 u32 seq, u32 pid)
1556{
1557 return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_CEE);
1558}
1559EXPORT_SYMBOL(dcbnl_cee_notify);
1560
1561/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
1562 * be completed the entire msg is aborted and error value is returned.
1563 * No attempt is made to reconcile the case where only part of the
1564 * cmd can be completed.
1565 */
1566static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
1567 u32 pid, u32 seq, u16 flags)
1568{
1569 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1570 struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
1571 int err = -EOPNOTSUPP;
1572
1573 if (!ops)
1574 return err;
1575
1576 if (!tb[DCB_ATTR_IEEE])
1577 return -EINVAL;
1578
1579 err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1580 tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1581 if (err)
1582 return err;
1583
1584 if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
1585 struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
1586 err = ops->ieee_setets(netdev, ets);
1587 if (err)
1588 goto err;
1589 }
1590
1591 if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
1592 struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
1593 err = ops->ieee_setpfc(netdev, pfc);
1594 if (err)
1595 goto err;
1596 }
1597
1598 if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1599 struct nlattr *attr;
1600 int rem;
1601
1602 nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1603 struct dcb_app *app_data;
1604 if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1605 continue;
1606 app_data = nla_data(attr);
1607 if (ops->ieee_setapp)
1608 err = ops->ieee_setapp(netdev, app_data);
1609 else
1610 err = dcb_ieee_setapp(netdev, app_data);
1611 if (err)
1612 goto err;
1613 }
1614 }
1615
1616err:
1617 dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
1618 pid, seq, flags);
1619 dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0);
1620 return err;
1621}
1622
1623static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
1624 u32 pid, u32 seq, u16 flags)
1625{
1626 struct net *net = dev_net(netdev);
1627 struct sk_buff *skb;
1628 struct nlmsghdr *nlh;
1629 struct dcbmsg *dcb;
1630 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1631 int err;
1632
1633 if (!ops)
1634 return -EOPNOTSUPP;
1635
1636 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1637 if (!skb)
1638 return -ENOBUFS;
1639
1640 nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1641 if (nlh == NULL) {
1642 nlmsg_free(skb);
1643 return -EMSGSIZE;
1644 }
1645
1646 dcb = NLMSG_DATA(nlh);
1647 dcb->dcb_family = AF_UNSPEC;
1648 dcb->cmd = DCB_CMD_IEEE_GET;
1649
1650 err = dcbnl_ieee_fill(skb, netdev);
1651
1652 if (err < 0) {
1653 nlmsg_cancel(skb, nlh);
1654 kfree_skb(skb);
1655 } else {
1656 nlmsg_end(skb, nlh);
1657 err = rtnl_unicast(skb, net, pid);
1658 }
1659
1660 return err;
1661}
1662
1663static int dcbnl_ieee_del(struct net_device *netdev, struct nlattr **tb,
1664 u32 pid, u32 seq, u16 flags)
1665{
1666 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1667 struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
1668 int err = -EOPNOTSUPP;
1669
1670 if (!ops)
1671 return -EOPNOTSUPP;
1672
1673 if (!tb[DCB_ATTR_IEEE])
1674 return -EINVAL;
1675
1676 err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1677 tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1678 if (err)
1679 return err;
1680
1681 if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1682 struct nlattr *attr;
1683 int rem;
1684
1685 nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1686 struct dcb_app *app_data;
1687
1688 if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1689 continue;
1690 app_data = nla_data(attr);
1691 if (ops->ieee_delapp)
1692 err = ops->ieee_delapp(netdev, app_data);
1693 else
1694 err = dcb_ieee_delapp(netdev, app_data);
1695 if (err)
1696 goto err;
1697 }
1698 }
1699
1700err:
1701 dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_DEL, DCB_ATTR_IEEE,
1702 pid, seq, flags);
1703 dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0);
1704 return err;
1705}
1706
1707
1379/* DCBX configuration */ 1708/* DCBX configuration */
1380static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb, 1709static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
1381 u32 pid, u32 seq, u16 flags) 1710 u32 pid, u32 seq, u16 flags)
@@ -1522,10 +1851,10 @@ err:
1522static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb, 1851static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
1523 u32 pid, u32 seq, u16 flags) 1852 u32 pid, u32 seq, u16 flags)
1524{ 1853{
1854 struct net *net = dev_net(netdev);
1525 struct sk_buff *skb; 1855 struct sk_buff *skb;
1526 struct nlmsghdr *nlh; 1856 struct nlmsghdr *nlh;
1527 struct dcbmsg *dcb; 1857 struct dcbmsg *dcb;
1528 struct nlattr *cee;
1529 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1858 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1530 int err; 1859 int err;
1531 1860
@@ -1536,51 +1865,26 @@ static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
1536 if (!skb) 1865 if (!skb)
1537 return -ENOBUFS; 1866 return -ENOBUFS;
1538 1867
1539 nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); 1868 nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1869 if (nlh == NULL) {
1870 nlmsg_free(skb);
1871 return -EMSGSIZE;
1872 }
1540 1873
1541 dcb = NLMSG_DATA(nlh); 1874 dcb = NLMSG_DATA(nlh);
1542 dcb->dcb_family = AF_UNSPEC; 1875 dcb->dcb_family = AF_UNSPEC;
1543 dcb->cmd = DCB_CMD_CEE_GET; 1876 dcb->cmd = DCB_CMD_CEE_GET;
1544 1877
1545 NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name); 1878 err = dcbnl_cee_fill(skb, netdev);
1546 1879
1547 cee = nla_nest_start(skb, DCB_ATTR_CEE); 1880 if (err < 0) {
1548 if (!cee) 1881 nlmsg_cancel(skb, nlh);
1549 goto nla_put_failure; 1882 nlmsg_free(skb);
1550 1883 } else {
1551 /* get peer info if available */ 1884 nlmsg_end(skb, nlh);
1552 if (ops->cee_peer_getpg) { 1885 err = rtnl_unicast(skb, net, pid);
1553 struct cee_pg pg;
1554 err = ops->cee_peer_getpg(netdev, &pg);
1555 if (!err)
1556 NLA_PUT(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg);
1557 }
1558
1559 if (ops->cee_peer_getpfc) {
1560 struct cee_pfc pfc;
1561 err = ops->cee_peer_getpfc(netdev, &pfc);
1562 if (!err)
1563 NLA_PUT(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc);
1564 }
1565
1566 if (ops->peer_getappinfo && ops->peer_getapptable) {
1567 err = dcbnl_build_peer_app(netdev, skb,
1568 DCB_ATTR_CEE_PEER_APP_TABLE,
1569 DCB_ATTR_CEE_PEER_APP_INFO,
1570 DCB_ATTR_CEE_PEER_APP);
1571 if (err)
1572 goto nla_put_failure;
1573 } 1886 }
1574 1887 return err;
1575 nla_nest_end(skb, cee);
1576 nlmsg_end(skb, nlh);
1577
1578 return rtnl_unicast(skb, &init_net, pid);
1579nla_put_failure:
1580 nlmsg_cancel(skb, nlh);
1581nlmsg_failure:
1582 kfree_skb(skb);
1583 return -1;
1584} 1888}
1585 1889
1586static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 1890static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
@@ -1690,11 +1994,15 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1690 goto out; 1994 goto out;
1691 case DCB_CMD_IEEE_SET: 1995 case DCB_CMD_IEEE_SET:
1692 ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq, 1996 ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq,
1693 nlh->nlmsg_flags); 1997 nlh->nlmsg_flags);
1694 goto out; 1998 goto out;
1695 case DCB_CMD_IEEE_GET: 1999 case DCB_CMD_IEEE_GET:
1696 ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq, 2000 ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq,
1697 nlh->nlmsg_flags); 2001 nlh->nlmsg_flags);
2002 goto out;
2003 case DCB_CMD_IEEE_DEL:
2004 ret = dcbnl_ieee_del(netdev, tb, pid, nlh->nlmsg_seq,
2005 nlh->nlmsg_flags);
1698 goto out; 2006 goto out;
1699 case DCB_CMD_GDCBX: 2007 case DCB_CMD_GDCBX:
1700 ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq, 2008 ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq,
@@ -1754,12 +2062,13 @@ u8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
1754EXPORT_SYMBOL(dcb_getapp); 2062EXPORT_SYMBOL(dcb_getapp);
1755 2063
1756/** 2064/**
1757 * ixgbe_dcbnl_setapp - add dcb application data to app list 2065 * dcb_setapp - add CEE dcb application data to app list
1758 * 2066 *
1759 * Priority 0 is the default priority this removes applications 2067 * Priority 0 is an invalid priority in CEE spec. This routine
1760 * from the app list if the priority is set to zero. 2068 * removes applications from the app list if the priority is
2069 * set to zero.
1761 */ 2070 */
1762u8 dcb_setapp(struct net_device *dev, struct dcb_app *new) 2071int dcb_setapp(struct net_device *dev, struct dcb_app *new)
1763{ 2072{
1764 struct dcb_app_type *itr; 2073 struct dcb_app_type *itr;
1765 struct dcb_app_type event; 2074 struct dcb_app_type event;
@@ -1802,6 +2111,114 @@ out:
1802} 2111}
1803EXPORT_SYMBOL(dcb_setapp); 2112EXPORT_SYMBOL(dcb_setapp);
1804 2113
2114/**
2115 * dcb_ieee_getapp_mask - retrieve the IEEE DCB application priority
2116 *
2117 * Helper routine which on success returns a non-zero 802.1Qaz user
2118 * priority bitmap otherwise returns 0 to indicate the dcb_app was
2119 * not found in APP list.
2120 */
2121u8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
2122{
2123 struct dcb_app_type *itr;
2124 u8 prio = 0;
2125
2126 spin_lock(&dcb_lock);
2127 list_for_each_entry(itr, &dcb_app_list, list) {
2128 if (itr->app.selector == app->selector &&
2129 itr->app.protocol == app->protocol &&
2130 (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
2131 prio |= 1 << itr->app.priority;
2132 }
2133 }
2134 spin_unlock(&dcb_lock);
2135
2136 return prio;
2137}
2138EXPORT_SYMBOL(dcb_ieee_getapp_mask);
2139
2140/**
2141 * dcb_ieee_setapp - add IEEE dcb application data to app list
2142 *
2143 * This adds Application data to the list. Multiple application
2144 * entries may exists for the same selector and protocol as long
2145 * as the priorities are different.
2146 */
2147int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
2148{
2149 struct dcb_app_type *itr, *entry;
2150 struct dcb_app_type event;
2151 int err = 0;
2152
2153 memcpy(&event.name, dev->name, sizeof(event.name));
2154 memcpy(&event.app, new, sizeof(event.app));
2155
2156 spin_lock(&dcb_lock);
2157 /* Search for existing match and abort if found */
2158 list_for_each_entry(itr, &dcb_app_list, list) {
2159 if (itr->app.selector == new->selector &&
2160 itr->app.protocol == new->protocol &&
2161 itr->app.priority == new->priority &&
2162 (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
2163 err = -EEXIST;
2164 goto out;
2165 }
2166 }
2167
2168 /* App entry does not exist add new entry */
2169 entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
2170 if (!entry) {
2171 err = -ENOMEM;
2172 goto out;
2173 }
2174
2175 memcpy(&entry->app, new, sizeof(*new));
2176 strncpy(entry->name, dev->name, IFNAMSIZ);
2177 list_add(&entry->list, &dcb_app_list);
2178out:
2179 spin_unlock(&dcb_lock);
2180 if (!err)
2181 call_dcbevent_notifiers(DCB_APP_EVENT, &event);
2182 return err;
2183}
2184EXPORT_SYMBOL(dcb_ieee_setapp);
2185
2186/**
2187 * dcb_ieee_delapp - delete IEEE dcb application data from list
2188 *
2189 * This removes a matching APP data from the APP list
2190 */
2191int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
2192{
2193 struct dcb_app_type *itr;
2194 struct dcb_app_type event;
2195 int err = -ENOENT;
2196
2197 memcpy(&event.name, dev->name, sizeof(event.name));
2198 memcpy(&event.app, del, sizeof(event.app));
2199
2200 spin_lock(&dcb_lock);
2201 /* Search for existing match and remove it. */
2202 list_for_each_entry(itr, &dcb_app_list, list) {
2203 if (itr->app.selector == del->selector &&
2204 itr->app.protocol == del->protocol &&
2205 itr->app.priority == del->priority &&
2206 (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
2207 list_del(&itr->list);
2208 kfree(itr);
2209 err = 0;
2210 goto out;
2211 }
2212 }
2213
2214out:
2215 spin_unlock(&dcb_lock);
2216 if (!err)
2217 call_dcbevent_notifiers(DCB_APP_EVENT, &event);
2218 return err;
2219}
2220EXPORT_SYMBOL(dcb_ieee_delapp);
2221
1805static void dcb_flushapp(void) 2222static void dcb_flushapp(void)
1806{ 2223{
1807 struct dcb_app_type *app; 2224 struct dcb_app_type *app;
@@ -1819,8 +2236,8 @@ static int __init dcbnl_init(void)
1819{ 2236{
1820 INIT_LIST_HEAD(&dcb_app_list); 2237 INIT_LIST_HEAD(&dcb_app_list);
1821 2238
1822 rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL); 2239 rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, NULL);
1823 rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL); 2240 rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, NULL);
1824 2241
1825 return 0; 2242 return 0;
1826} 2243}