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.c150
1 files changed, 148 insertions, 2 deletions
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index d5074a567289..3609eacaf4ce 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2008, Intel Corporation. 2 * Copyright (c) 2008-2011, Intel Corporation.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License, 5 * under the terms and conditions of the GNU General Public License,
@@ -1193,7 +1193,7 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
1193 goto err; 1193 goto err;
1194 } 1194 }
1195 1195
1196 if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setets) { 1196 if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
1197 struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]); 1197 struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
1198 err = ops->ieee_setpfc(netdev, pfc); 1198 err = ops->ieee_setpfc(netdev, pfc);
1199 if (err) 1199 if (err)
@@ -1224,6 +1224,59 @@ err:
1224 return err; 1224 return err;
1225} 1225}
1226 1226
1227static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
1228 int app_nested_type, int app_info_type,
1229 int app_entry_type)
1230{
1231 struct dcb_peer_app_info info;
1232 struct dcb_app *table = NULL;
1233 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1234 u16 app_count;
1235 int err;
1236
1237
1238 /**
1239 * retrieve the peer app configuration form the driver. If the driver
1240 * handlers fail exit without doing anything
1241 */
1242 err = ops->peer_getappinfo(netdev, &info, &app_count);
1243 if (!err && app_count) {
1244 table = kmalloc(sizeof(struct dcb_app) * app_count, GFP_KERNEL);
1245 if (!table)
1246 return -ENOMEM;
1247
1248 err = ops->peer_getapptable(netdev, table);
1249 }
1250
1251 if (!err) {
1252 u16 i;
1253 struct nlattr *app;
1254
1255 /**
1256 * build the message, from here on the only possible failure
1257 * is due to the skb size
1258 */
1259 err = -EMSGSIZE;
1260
1261 app = nla_nest_start(skb, app_nested_type);
1262 if (!app)
1263 goto nla_put_failure;
1264
1265 if (app_info_type)
1266 NLA_PUT(skb, app_info_type, sizeof(info), &info);
1267
1268 for (i = 0; i < app_count; i++)
1269 NLA_PUT(skb, app_entry_type, sizeof(struct dcb_app),
1270 &table[i]);
1271
1272 nla_nest_end(skb, app);
1273 }
1274 err = 0;
1275
1276nla_put_failure:
1277 kfree(table);
1278 return err;
1279}
1227 1280
1228/* Handle IEEE 802.1Qaz GET commands. */ 1281/* Handle IEEE 802.1Qaz GET commands. */
1229static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, 1282static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
@@ -1288,6 +1341,30 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
1288 spin_unlock(&dcb_lock); 1341 spin_unlock(&dcb_lock);
1289 nla_nest_end(skb, app); 1342 nla_nest_end(skb, app);
1290 1343
1344 /* get peer info if available */
1345 if (ops->ieee_peer_getets) {
1346 struct ieee_ets ets;
1347 err = ops->ieee_peer_getets(netdev, &ets);
1348 if (!err)
1349 NLA_PUT(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets);
1350 }
1351
1352 if (ops->ieee_peer_getpfc) {
1353 struct ieee_pfc pfc;
1354 err = ops->ieee_peer_getpfc(netdev, &pfc);
1355 if (!err)
1356 NLA_PUT(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc);
1357 }
1358
1359 if (ops->peer_getappinfo && ops->peer_getapptable) {
1360 err = dcbnl_build_peer_app(netdev, skb,
1361 DCB_ATTR_IEEE_PEER_APP,
1362 DCB_ATTR_IEEE_APP_UNSPEC,
1363 DCB_ATTR_IEEE_APP);
1364 if (err)
1365 goto nla_put_failure;
1366 }
1367
1291 nla_nest_end(skb, ieee); 1368 nla_nest_end(skb, ieee);
1292 nlmsg_end(skb, nlh); 1369 nlmsg_end(skb, nlh);
1293 1370
@@ -1441,6 +1518,71 @@ err:
1441 return ret; 1518 return ret;
1442} 1519}
1443 1520
1521/* Handle CEE DCBX GET commands. */
1522static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
1523 u32 pid, u32 seq, u16 flags)
1524{
1525 struct sk_buff *skb;
1526 struct nlmsghdr *nlh;
1527 struct dcbmsg *dcb;
1528 struct nlattr *cee;
1529 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1530 int err;
1531
1532 if (!ops)
1533 return -EOPNOTSUPP;
1534
1535 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1536 if (!skb)
1537 return -ENOBUFS;
1538
1539 nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1540
1541 dcb = NLMSG_DATA(nlh);
1542 dcb->dcb_family = AF_UNSPEC;
1543 dcb->cmd = DCB_CMD_CEE_GET;
1544
1545 NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
1546
1547 cee = nla_nest_start(skb, DCB_ATTR_CEE);
1548 if (!cee)
1549 goto nla_put_failure;
1550
1551 /* get peer info if available */
1552 if (ops->cee_peer_getpg) {
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 }
1574
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}
1585
1444static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 1586static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1445{ 1587{
1446 struct net *net = sock_net(skb->sk); 1588 struct net *net = sock_net(skb->sk);
@@ -1570,6 +1712,10 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1570 ret = dcbnl_setfeatcfg(netdev, tb, pid, nlh->nlmsg_seq, 1712 ret = dcbnl_setfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
1571 nlh->nlmsg_flags); 1713 nlh->nlmsg_flags);
1572 goto out; 1714 goto out;
1715 case DCB_CMD_CEE_GET:
1716 ret = dcbnl_cee_get(netdev, tb, pid, nlh->nlmsg_seq,
1717 nlh->nlmsg_flags);
1718 goto out;
1573 default: 1719 default:
1574 goto errout; 1720 goto errout;
1575 } 1721 }