diff options
-rw-r--r-- | include/linux/rtnetlink.h | 2 | ||||
-rw-r--r-- | include/net/dcbnl.h | 2 | ||||
-rw-r--r-- | net/dcb/dcbnl.c | 229 |
3 files changed, 150 insertions, 83 deletions
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index bbad657a3725..c81226a9a35c 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 e5983c9053dc..b3cf10d9b828 100644 --- a/include/net/dcbnl.h +++ b/include/net/dcbnl.h | |||
@@ -31,6 +31,8 @@ struct dcb_app_type { | |||
31 | u8 dcb_setapp(struct net_device *, struct dcb_app *); | 31 | u8 dcb_setapp(struct net_device *, struct dcb_app *); |
32 | u8 dcb_getapp(struct net_device *, struct dcb_app *); | 32 | u8 dcb_getapp(struct net_device *, struct dcb_app *); |
33 | 33 | ||
34 | int 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 3a6d97d5280c..ffba32692bdb 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 | */ | ||
1174 | static 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 | |||
1221 | err: | ||
1222 | dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE, | ||
1223 | pid, seq, flags); | ||
1224 | return err; | ||
1225 | } | ||
1226 | |||
1227 | static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb, | 1169 | static 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. */ |
1282 | static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, | 1224 | static 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 | |||
1384 | nla_put_failure: | 1309 | nla_put_failure: |
1385 | nlmsg_cancel(skb, nlh); | 1310 | return err; |
1386 | nlmsg_failure: | ||
1387 | kfree_skb(skb); | ||
1388 | return -1; | ||
1389 | } | 1311 | } |
1390 | 1312 | ||
1313 | int 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 | } | ||
1354 | EXPORT_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 | */ | ||
1361 | static 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 | |||
1408 | err: | ||
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 | |||
1415 | static 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 */ |
1392 | static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb, | 1455 | static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb, |
1393 | u32 pid, u32 seq, u16 flags) | 1456 | u32 pid, u32 seq, u16 flags) |