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.c455
1 files changed, 446 insertions, 9 deletions
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 19ac2b985485..d5074a567289 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -23,6 +23,7 @@
23#include <net/netlink.h> 23#include <net/netlink.h>
24#include <net/rtnetlink.h> 24#include <net/rtnetlink.h>
25#include <linux/dcbnl.h> 25#include <linux/dcbnl.h>
26#include <net/dcbevent.h>
26#include <linux/rtnetlink.h> 27#include <linux/rtnetlink.h>
27#include <net/sock.h> 28#include <net/sock.h>
28 29
@@ -66,6 +67,9 @@ static const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = {
66 [DCB_ATTR_PFC_STATE] = {.type = NLA_U8}, 67 [DCB_ATTR_PFC_STATE] = {.type = NLA_U8},
67 [DCB_ATTR_BCN] = {.type = NLA_NESTED}, 68 [DCB_ATTR_BCN] = {.type = NLA_NESTED},
68 [DCB_ATTR_APP] = {.type = NLA_NESTED}, 69 [DCB_ATTR_APP] = {.type = NLA_NESTED},
70 [DCB_ATTR_IEEE] = {.type = NLA_NESTED},
71 [DCB_ATTR_DCBX] = {.type = NLA_U8},
72 [DCB_ATTR_FEATCFG] = {.type = NLA_NESTED},
69}; 73};
70 74
71/* DCB priority flow control to User Priority nested attributes */ 75/* DCB priority flow control to User Priority nested attributes */
@@ -122,6 +126,7 @@ static const struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = {
122 [DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8}, 126 [DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8},
123 [DCB_CAP_ATTR_GSP] = {.type = NLA_U8}, 127 [DCB_CAP_ATTR_GSP] = {.type = NLA_U8},
124 [DCB_CAP_ATTR_BCN] = {.type = NLA_U8}, 128 [DCB_CAP_ATTR_BCN] = {.type = NLA_U8},
129 [DCB_CAP_ATTR_DCBX] = {.type = NLA_U8},
125}; 130};
126 131
127/* DCB capabilities nested attributes. */ 132/* DCB capabilities nested attributes. */
@@ -167,6 +172,28 @@ static const struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = {
167 [DCB_APP_ATTR_PRIORITY] = {.type = NLA_U8}, 172 [DCB_APP_ATTR_PRIORITY] = {.type = NLA_U8},
168}; 173};
169 174
175/* IEEE 802.1Qaz nested attributes. */
176static const struct nla_policy dcbnl_ieee_policy[DCB_ATTR_IEEE_MAX + 1] = {
177 [DCB_ATTR_IEEE_ETS] = {.len = sizeof(struct ieee_ets)},
178 [DCB_ATTR_IEEE_PFC] = {.len = sizeof(struct ieee_pfc)},
179 [DCB_ATTR_IEEE_APP_TABLE] = {.type = NLA_NESTED},
180};
181
182static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = {
183 [DCB_ATTR_IEEE_APP] = {.len = sizeof(struct dcb_app)},
184};
185
186/* DCB number of traffic classes nested attributes. */
187static const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = {
188 [DCB_FEATCFG_ATTR_ALL] = {.type = NLA_FLAG},
189 [DCB_FEATCFG_ATTR_PG] = {.type = NLA_U8},
190 [DCB_FEATCFG_ATTR_PFC] = {.type = NLA_U8},
191 [DCB_FEATCFG_ATTR_APP] = {.type = NLA_U8},
192};
193
194static LIST_HEAD(dcb_app_list);
195static DEFINE_SPINLOCK(dcb_lock);
196
170/* standard netlink reply call */ 197/* standard netlink reply call */
171static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, 198static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
172 u32 seq, u16 flags) 199 u32 seq, u16 flags)
@@ -556,7 +583,7 @@ static int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb,
556 u8 up, idtype; 583 u8 up, idtype;
557 int ret = -EINVAL; 584 int ret = -EINVAL;
558 585
559 if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->getapp) 586 if (!tb[DCB_ATTR_APP])
560 goto out; 587 goto out;
561 588
562 ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], 589 ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
@@ -577,7 +604,16 @@ static int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb,
577 goto out; 604 goto out;
578 605
579 id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); 606 id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
580 up = netdev->dcbnl_ops->getapp(netdev, idtype, id); 607
608 if (netdev->dcbnl_ops->getapp) {
609 up = netdev->dcbnl_ops->getapp(netdev, idtype, id);
610 } else {
611 struct dcb_app app = {
612 .selector = idtype,
613 .protocol = id,
614 };
615 up = dcb_getapp(netdev, &app);
616 }
581 617
582 /* send this back */ 618 /* send this back */
583 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 619 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
@@ -590,6 +626,9 @@ static int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb,
590 dcb->cmd = DCB_CMD_GAPP; 626 dcb->cmd = DCB_CMD_GAPP;
591 627
592 app_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_APP); 628 app_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_APP);
629 if (!app_nest)
630 goto out_cancel;
631
593 ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype); 632 ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype);
594 if (ret) 633 if (ret)
595 goto out_cancel; 634 goto out_cancel;
@@ -622,12 +661,12 @@ out:
622static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb, 661static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb,
623 u32 pid, u32 seq, u16 flags) 662 u32 pid, u32 seq, u16 flags)
624{ 663{
625 int ret = -EINVAL; 664 int err, ret = -EINVAL;
626 u16 id; 665 u16 id;
627 u8 up, idtype; 666 u8 up, idtype;
628 struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; 667 struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
629 668
630 if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->setapp) 669 if (!tb[DCB_ATTR_APP])
631 goto out; 670 goto out;
632 671
633 ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], 672 ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
@@ -651,9 +690,18 @@ static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb,
651 id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); 690 id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
652 up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]); 691 up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]);
653 692
654 ret = dcbnl_reply(netdev->dcbnl_ops->setapp(netdev, idtype, id, up), 693 if (netdev->dcbnl_ops->setapp) {
655 RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP, 694 err = netdev->dcbnl_ops->setapp(netdev, idtype, id, up);
656 pid, seq, flags); 695 } else {
696 struct dcb_app app;
697 app.selector = idtype;
698 app.protocol = id;
699 app.priority = up;
700 err = dcb_setapp(netdev, &app);
701 }
702
703 ret = dcbnl_reply(err, RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP,
704 pid, seq, flags);
657out: 705out:
658 return ret; 706 return ret;
659} 707}
@@ -1118,6 +1166,281 @@ err:
1118 return ret; 1166 return ret;
1119} 1167}
1120 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_setets) {
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
1227
1228/* Handle IEEE 802.1Qaz GET commands. */
1229static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
1230 u32 pid, u32 seq, u16 flags)
1231{
1232 struct sk_buff *skb;
1233 struct nlmsghdr *nlh;
1234 struct dcbmsg *dcb;
1235 struct nlattr *ieee, *app;
1236 struct dcb_app_type *itr;
1237 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1238 int err;
1239
1240 if (!ops)
1241 return -EOPNOTSUPP;
1242
1243 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1244 if (!skb)
1245 return -ENOBUFS;
1246
1247 nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1248
1249 dcb = NLMSG_DATA(nlh);
1250 dcb->dcb_family = AF_UNSPEC;
1251 dcb->cmd = DCB_CMD_IEEE_GET;
1252
1253 NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
1254
1255 ieee = nla_nest_start(skb, DCB_ATTR_IEEE);
1256 if (!ieee)
1257 goto nla_put_failure;
1258
1259 if (ops->ieee_getets) {
1260 struct ieee_ets ets;
1261 err = ops->ieee_getets(netdev, &ets);
1262 if (!err)
1263 NLA_PUT(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets);
1264 }
1265
1266 if (ops->ieee_getpfc) {
1267 struct ieee_pfc pfc;
1268 err = ops->ieee_getpfc(netdev, &pfc);
1269 if (!err)
1270 NLA_PUT(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc);
1271 }
1272
1273 app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE);
1274 if (!app)
1275 goto nla_put_failure;
1276
1277 spin_lock(&dcb_lock);
1278 list_for_each_entry(itr, &dcb_app_list, list) {
1279 if (strncmp(itr->name, netdev->name, IFNAMSIZ) == 0) {
1280 err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app),
1281 &itr->app);
1282 if (err) {
1283 spin_unlock(&dcb_lock);
1284 goto nla_put_failure;
1285 }
1286 }
1287 }
1288 spin_unlock(&dcb_lock);
1289 nla_nest_end(skb, app);
1290
1291 nla_nest_end(skb, ieee);
1292 nlmsg_end(skb, nlh);
1293
1294 return rtnl_unicast(skb, &init_net, pid);
1295nla_put_failure:
1296 nlmsg_cancel(skb, nlh);
1297nlmsg_failure:
1298 kfree_skb(skb);
1299 return -1;
1300}
1301
1302/* DCBX configuration */
1303static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
1304 u32 pid, u32 seq, u16 flags)
1305{
1306 int ret;
1307
1308 if (!netdev->dcbnl_ops->getdcbx)
1309 return -EOPNOTSUPP;
1310
1311 ret = dcbnl_reply(netdev->dcbnl_ops->getdcbx(netdev), RTM_GETDCB,
1312 DCB_CMD_GDCBX, DCB_ATTR_DCBX, pid, seq, flags);
1313
1314 return ret;
1315}
1316
1317static int dcbnl_setdcbx(struct net_device *netdev, struct nlattr **tb,
1318 u32 pid, u32 seq, u16 flags)
1319{
1320 int ret;
1321 u8 value;
1322
1323 if (!netdev->dcbnl_ops->setdcbx)
1324 return -EOPNOTSUPP;
1325
1326 if (!tb[DCB_ATTR_DCBX])
1327 return -EINVAL;
1328
1329 value = nla_get_u8(tb[DCB_ATTR_DCBX]);
1330
1331 ret = dcbnl_reply(netdev->dcbnl_ops->setdcbx(netdev, value),
1332 RTM_SETDCB, DCB_CMD_SDCBX, DCB_ATTR_DCBX,
1333 pid, seq, flags);
1334
1335 return ret;
1336}
1337
1338static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb,
1339 u32 pid, u32 seq, u16 flags)
1340{
1341 struct sk_buff *dcbnl_skb;
1342 struct nlmsghdr *nlh;
1343 struct dcbmsg *dcb;
1344 struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest;
1345 u8 value;
1346 int ret, i;
1347 int getall = 0;
1348
1349 if (!netdev->dcbnl_ops->getfeatcfg)
1350 return -EOPNOTSUPP;
1351
1352 if (!tb[DCB_ATTR_FEATCFG])
1353 return -EINVAL;
1354
1355 ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1356 dcbnl_featcfg_nest);
1357 if (ret)
1358 goto err_out;
1359
1360 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1361 if (!dcbnl_skb) {
1362 ret = -ENOBUFS;
1363 goto err_out;
1364 }
1365
1366 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1367
1368 dcb = NLMSG_DATA(nlh);
1369 dcb->dcb_family = AF_UNSPEC;
1370 dcb->cmd = DCB_CMD_GFEATCFG;
1371
1372 nest = nla_nest_start(dcbnl_skb, DCB_ATTR_FEATCFG);
1373 if (!nest) {
1374 ret = -EMSGSIZE;
1375 goto nla_put_failure;
1376 }
1377
1378 if (data[DCB_FEATCFG_ATTR_ALL])
1379 getall = 1;
1380
1381 for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1382 if (!getall && !data[i])
1383 continue;
1384
1385 ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value);
1386 if (!ret)
1387 ret = nla_put_u8(dcbnl_skb, i, value);
1388
1389 if (ret) {
1390 nla_nest_cancel(dcbnl_skb, nest);
1391 goto nla_put_failure;
1392 }
1393 }
1394 nla_nest_end(dcbnl_skb, nest);
1395
1396 nlmsg_end(dcbnl_skb, nlh);
1397
1398 return rtnl_unicast(dcbnl_skb, &init_net, pid);
1399nla_put_failure:
1400 nlmsg_cancel(dcbnl_skb, nlh);
1401nlmsg_failure:
1402 kfree_skb(dcbnl_skb);
1403err_out:
1404 return ret;
1405}
1406
1407static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlattr **tb,
1408 u32 pid, u32 seq, u16 flags)
1409{
1410 struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1];
1411 int ret, i;
1412 u8 value;
1413
1414 if (!netdev->dcbnl_ops->setfeatcfg)
1415 return -ENOTSUPP;
1416
1417 if (!tb[DCB_ATTR_FEATCFG])
1418 return -EINVAL;
1419
1420 ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1421 dcbnl_featcfg_nest);
1422
1423 if (ret)
1424 goto err;
1425
1426 for (i = DCB_FEATCFG_ATTR_ALL+1; i <= DCB_FEATCFG_ATTR_MAX; i++) {
1427 if (data[i] == NULL)
1428 continue;
1429
1430 value = nla_get_u8(data[i]);
1431
1432 ret = netdev->dcbnl_ops->setfeatcfg(netdev, i, value);
1433
1434 if (ret)
1435 goto err;
1436 }
1437err:
1438 dcbnl_reply(ret, RTM_SETDCB, DCB_CMD_SFEATCFG, DCB_ATTR_FEATCFG,
1439 pid, seq, flags);
1440
1441 return ret;
1442}
1443
1121static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 1444static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1122{ 1445{
1123 struct net *net = sock_net(skb->sk); 1446 struct net *net = sock_net(skb->sk);
@@ -1223,6 +1546,30 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1223 ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq, 1546 ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq,
1224 nlh->nlmsg_flags); 1547 nlh->nlmsg_flags);
1225 goto out; 1548 goto out;
1549 case DCB_CMD_IEEE_SET:
1550 ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq,
1551 nlh->nlmsg_flags);
1552 goto out;
1553 case DCB_CMD_IEEE_GET:
1554 ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq,
1555 nlh->nlmsg_flags);
1556 goto out;
1557 case DCB_CMD_GDCBX:
1558 ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq,
1559 nlh->nlmsg_flags);
1560 goto out;
1561 case DCB_CMD_SDCBX:
1562 ret = dcbnl_setdcbx(netdev, tb, pid, nlh->nlmsg_seq,
1563 nlh->nlmsg_flags);
1564 goto out;
1565 case DCB_CMD_GFEATCFG:
1566 ret = dcbnl_getfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
1567 nlh->nlmsg_flags);
1568 goto out;
1569 case DCB_CMD_SFEATCFG:
1570 ret = dcbnl_setfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
1571 nlh->nlmsg_flags);
1572 goto out;
1226 default: 1573 default:
1227 goto errout; 1574 goto errout;
1228 } 1575 }
@@ -1233,8 +1580,99 @@ out:
1233 return ret; 1580 return ret;
1234} 1581}
1235 1582
1583/**
1584 * dcb_getapp - retrieve the DCBX application user priority
1585 *
1586 * On success returns a non-zero 802.1p user priority bitmap
1587 * otherwise returns 0 as the invalid user priority bitmap to
1588 * indicate an error.
1589 */
1590u8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
1591{
1592 struct dcb_app_type *itr;
1593 u8 prio = 0;
1594
1595 spin_lock(&dcb_lock);
1596 list_for_each_entry(itr, &dcb_app_list, list) {
1597 if (itr->app.selector == app->selector &&
1598 itr->app.protocol == app->protocol &&
1599 (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
1600 prio = itr->app.priority;
1601 break;
1602 }
1603 }
1604 spin_unlock(&dcb_lock);
1605
1606 return prio;
1607}
1608EXPORT_SYMBOL(dcb_getapp);
1609
1610/**
1611 * ixgbe_dcbnl_setapp - add dcb application data to app list
1612 *
1613 * Priority 0 is the default priority this removes applications
1614 * from the app list if the priority is set to zero.
1615 */
1616u8 dcb_setapp(struct net_device *dev, struct dcb_app *new)
1617{
1618 struct dcb_app_type *itr;
1619 struct dcb_app_type event;
1620
1621 memcpy(&event.name, dev->name, sizeof(event.name));
1622 memcpy(&event.app, new, sizeof(event.app));
1623
1624 spin_lock(&dcb_lock);
1625 /* Search for existing match and replace */
1626 list_for_each_entry(itr, &dcb_app_list, list) {
1627 if (itr->app.selector == new->selector &&
1628 itr->app.protocol == new->protocol &&
1629 (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
1630 if (new->priority)
1631 itr->app.priority = new->priority;
1632 else {
1633 list_del(&itr->list);
1634 kfree(itr);
1635 }
1636 goto out;
1637 }
1638 }
1639 /* App type does not exist add new application type */
1640 if (new->priority) {
1641 struct dcb_app_type *entry;
1642 entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
1643 if (!entry) {
1644 spin_unlock(&dcb_lock);
1645 return -ENOMEM;
1646 }
1647
1648 memcpy(&entry->app, new, sizeof(*new));
1649 strncpy(entry->name, dev->name, IFNAMSIZ);
1650 list_add(&entry->list, &dcb_app_list);
1651 }
1652out:
1653 spin_unlock(&dcb_lock);
1654 call_dcbevent_notifiers(DCB_APP_EVENT, &event);
1655 return 0;
1656}
1657EXPORT_SYMBOL(dcb_setapp);
1658
1659static void dcb_flushapp(void)
1660{
1661 struct dcb_app_type *app;
1662 struct dcb_app_type *tmp;
1663
1664 spin_lock(&dcb_lock);
1665 list_for_each_entry_safe(app, tmp, &dcb_app_list, list) {
1666 list_del(&app->list);
1667 kfree(app);
1668 }
1669 spin_unlock(&dcb_lock);
1670}
1671
1236static int __init dcbnl_init(void) 1672static int __init dcbnl_init(void)
1237{ 1673{
1674 INIT_LIST_HEAD(&dcb_app_list);
1675
1238 rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL); 1676 rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL);
1239 rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL); 1677 rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL);
1240 1678
@@ -1246,7 +1684,6 @@ static void __exit dcbnl_exit(void)
1246{ 1684{
1247 rtnl_unregister(PF_UNSPEC, RTM_GETDCB); 1685 rtnl_unregister(PF_UNSPEC, RTM_GETDCB);
1248 rtnl_unregister(PF_UNSPEC, RTM_SETDCB); 1686 rtnl_unregister(PF_UNSPEC, RTM_SETDCB);
1687 dcb_flushapp();
1249} 1688}
1250module_exit(dcbnl_exit); 1689module_exit(dcbnl_exit);
1251
1252