aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/rtnetlink.h2
-rw-r--r--include/net/dcbnl.h2
-rw-r--r--net/dcb/dcbnl.c229
3 files changed, 150 insertions, 83 deletions
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index bbad657a372..c81226a9a35 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -585,6 +585,8 @@ enum rtnetlink_groups {
585#define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR 585#define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR
586 RTNLGRP_PHONET_ROUTE, 586 RTNLGRP_PHONET_ROUTE,
587#define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE 587#define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE
588 RTNLGRP_DCB,
589#define RTNLGRP_DCB RTNLGRP_DCB
588 __RTNLGRP_MAX 590 __RTNLGRP_MAX
589}; 591};
590#define RTNLGRP_MAX (__RTNLGRP_MAX - 1) 592#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h
index e5983c9053d..b3cf10d9b82 100644
--- a/include/net/dcbnl.h
+++ b/include/net/dcbnl.h
@@ -31,6 +31,8 @@ struct dcb_app_type {
31u8 dcb_setapp(struct net_device *, struct dcb_app *); 31u8 dcb_setapp(struct net_device *, struct dcb_app *);
32u8 dcb_getapp(struct net_device *, struct dcb_app *); 32u8 dcb_getapp(struct net_device *, struct dcb_app *);
33 33
34int dcbnl_notify(struct net_device *dev, int event, int cmd, u32 seq, u32 pid);
35
34/* 36/*
35 * Ops struct for the netlink callbacks. Used by DCB-enabled drivers through 37 * Ops struct for the netlink callbacks. Used by DCB-enabled drivers through
36 * the netdevice struct. 38 * the netdevice struct.
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 3a6d97d5280..ffba32692bd 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,30 +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 dcbx; 1229 int dcbx;
1292 int err; 1230 int err = -EMSGSIZE;
1293
1294 if (!ops)
1295 return -EOPNOTSUPP;
1296
1297 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1298 if (!skb)
1299 return -ENOBUFS;
1300
1301 nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1302
1303 dcb = NLMSG_DATA(nlh);
1304 dcb->dcb_family = AF_UNSPEC;
1305 dcb->cmd = DCB_CMD_IEEE_GET;
1306 1231
1307 NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name); 1232 NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
1308 1233
@@ -1378,16 +1303,154 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
1378 if (err) 1303 if (err)
1379 goto nla_put_failure; 1304 goto nla_put_failure;
1380 } 1305 }
1381 nlmsg_end(skb, nlh);
1382 1306
1383 return rtnl_unicast(skb, &init_net, pid); 1307 return 0;
1308
1384nla_put_failure: 1309nla_put_failure:
1385 nlmsg_cancel(skb, nlh); 1310 return err;
1386nlmsg_failure:
1387 kfree_skb(skb);
1388 return -1;
1389} 1311}
1390 1312
1313int dcbnl_notify(struct net_device *dev, int event, int cmd,
1314 u32 seq, u32 pid)
1315{
1316 struct net *net = dev_net(dev);
1317 struct sk_buff *skb;
1318 struct nlmsghdr *nlh;
1319 struct dcbmsg *dcb;
1320 const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
1321 int err;
1322
1323 if (!ops)
1324 return -EOPNOTSUPP;
1325
1326 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1327 if (!skb)
1328 return -ENOBUFS;
1329
1330 nlh = nlmsg_put(skb, pid, 0, event, sizeof(*dcb), 0);
1331 if (nlh == NULL) {
1332 kfree(skb);
1333 return -EMSGSIZE;
1334 }
1335
1336 dcb = NLMSG_DATA(nlh);
1337 dcb->dcb_family = AF_UNSPEC;
1338 dcb->cmd = cmd;
1339
1340 err = dcbnl_ieee_fill(skb, dev);
1341 if (err < 0) {
1342 /* Report error to broadcast listeners */
1343 nlmsg_cancel(skb, nlh);
1344 kfree_skb(skb);
1345 rtnl_set_sk_err(net, RTNLGRP_DCB, err);
1346 } else {
1347 /* End nlmsg and notify broadcast listeners */
1348 nlmsg_end(skb, nlh);
1349 rtnl_notify(skb, net, 0, RTNLGRP_DCB, NULL, GFP_KERNEL);
1350 }
1351
1352 return err;
1353}
1354EXPORT_SYMBOL(dcbnl_notify);
1355
1356/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
1357 * be completed the entire msg is aborted and error value is returned.
1358 * No attempt is made to reconcile the case where only part of the
1359 * cmd can be completed.
1360 */
1361static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
1362 u32 pid, u32 seq, u16 flags)
1363{
1364 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1365 struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
1366 int err = -EOPNOTSUPP;
1367
1368 if (!ops)
1369 return err;
1370
1371 err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1372 tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1373 if (err)
1374 return err;
1375
1376 if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
1377 struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
1378 err = ops->ieee_setets(netdev, ets);
1379 if (err)
1380 goto err;
1381 }
1382
1383 if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
1384 struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
1385 err = ops->ieee_setpfc(netdev, pfc);
1386 if (err)
1387 goto err;
1388 }
1389
1390 if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
1391 struct nlattr *attr;
1392 int rem;
1393
1394 nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1395 struct dcb_app *app_data;
1396 if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1397 continue;
1398 app_data = nla_data(attr);
1399 if (ops->ieee_setapp)
1400 err = ops->ieee_setapp(netdev, app_data);
1401 else
1402 err = dcb_setapp(netdev, app_data);
1403 if (err)
1404 goto err;
1405 }
1406 }
1407
1408err:
1409 dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
1410 pid, seq, flags);
1411 dcbnl_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0);
1412 return err;
1413}
1414
1415static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
1416 u32 pid, u32 seq, u16 flags)
1417{
1418 struct net *net = dev_net(netdev);
1419 struct sk_buff *skb;
1420 struct nlmsghdr *nlh;
1421 struct dcbmsg *dcb;
1422 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1423 int err;
1424
1425 if (!ops)
1426 return -EOPNOTSUPP;
1427
1428 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1429 if (!skb)
1430 return -ENOBUFS;
1431
1432 nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1433 if (nlh == NULL) {
1434 kfree(skb);
1435 return -EMSGSIZE;
1436 }
1437
1438 dcb = NLMSG_DATA(nlh);
1439 dcb->dcb_family = AF_UNSPEC;
1440 dcb->cmd = DCB_CMD_IEEE_GET;
1441
1442 err = dcbnl_ieee_fill(skb, netdev);
1443
1444 if (err < 0) {
1445 nlmsg_cancel(skb, nlh);
1446 kfree_skb(skb);
1447 } else {
1448 nlmsg_end(skb, nlh);
1449 err = rtnl_unicast(skb, net, pid);
1450 }
1451
1452 return err;
1453}
1391/* DCBX configuration */ 1454/* DCBX configuration */
1392static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb, 1455static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
1393 u32 pid, u32 seq, u16 flags) 1456 u32 pid, u32 seq, u16 flags)