diff options
-rw-r--r-- | include/linux/dcbnl.h | 28 | ||||
-rw-r--r-- | include/net/dcbnl.h | 6 | ||||
-rw-r--r-- | net/dcb/dcbnl.c | 69 |
3 files changed, 103 insertions, 0 deletions
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h index 4c5b26e0cc48..2542685f8b3e 100644 --- a/include/linux/dcbnl.h +++ b/include/linux/dcbnl.h | |||
@@ -110,6 +110,20 @@ struct dcb_app { | |||
110 | __u16 protocol; | 110 | __u16 protocol; |
111 | }; | 111 | }; |
112 | 112 | ||
113 | /** | ||
114 | * struct dcb_peer_app_info - APP feature information sent by the peer | ||
115 | * | ||
116 | * @willing: willing bit in the peer APP tlv | ||
117 | * @error: error bit in the peer APP tlv | ||
118 | * | ||
119 | * In addition to this information the full peer APP tlv also contains | ||
120 | * a table of 'app_count' APP objects defined above. | ||
121 | */ | ||
122 | struct dcb_peer_app_info { | ||
123 | __u8 willing; | ||
124 | __u8 error; | ||
125 | }; | ||
126 | |||
113 | struct dcbmsg { | 127 | struct dcbmsg { |
114 | __u8 dcb_family; | 128 | __u8 dcb_family; |
115 | __u8 cmd; | 129 | __u8 cmd; |
@@ -235,11 +249,25 @@ enum dcbnl_attrs { | |||
235 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, | 249 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, |
236 | }; | 250 | }; |
237 | 251 | ||
252 | /** | ||
253 | * enum ieee_attrs - IEEE 802.1Qaz get/set attributes | ||
254 | * | ||
255 | * @DCB_ATTR_IEEE_UNSPEC: unspecified | ||
256 | * @DCB_ATTR_IEEE_ETS: negotiated ETS configuration | ||
257 | * @DCB_ATTR_IEEE_PFC: negotiated PFC configuration | ||
258 | * @DCB_ATTR_IEEE_APP_TABLE: negotiated APP configuration | ||
259 | * @DCB_ATTR_IEEE_PEER_ETS: peer ETS configuration - get only | ||
260 | * @DCB_ATTR_IEEE_PEER_PFC: peer PFC configuration - get only | ||
261 | * @DCB_ATTR_IEEE_PEER_APP: peer APP tlv - get only | ||
262 | */ | ||
238 | enum ieee_attrs { | 263 | enum ieee_attrs { |
239 | DCB_ATTR_IEEE_UNSPEC, | 264 | DCB_ATTR_IEEE_UNSPEC, |
240 | DCB_ATTR_IEEE_ETS, | 265 | DCB_ATTR_IEEE_ETS, |
241 | DCB_ATTR_IEEE_PFC, | 266 | DCB_ATTR_IEEE_PFC, |
242 | DCB_ATTR_IEEE_APP_TABLE, | 267 | DCB_ATTR_IEEE_APP_TABLE, |
268 | DCB_ATTR_IEEE_PEER_ETS, | ||
269 | DCB_ATTR_IEEE_PEER_PFC, | ||
270 | DCB_ATTR_IEEE_PEER_APP, | ||
243 | __DCB_ATTR_IEEE_MAX | 271 | __DCB_ATTR_IEEE_MAX |
244 | }; | 272 | }; |
245 | #define DCB_ATTR_IEEE_MAX (__DCB_ATTR_IEEE_MAX - 1) | 273 | #define DCB_ATTR_IEEE_MAX (__DCB_ATTR_IEEE_MAX - 1) |
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h index a8e7852b10ab..7b7180e692ef 100644 --- a/include/net/dcbnl.h +++ b/include/net/dcbnl.h | |||
@@ -43,6 +43,8 @@ struct dcbnl_rtnl_ops { | |||
43 | int (*ieee_setpfc) (struct net_device *, struct ieee_pfc *); | 43 | int (*ieee_setpfc) (struct net_device *, struct ieee_pfc *); |
44 | int (*ieee_getapp) (struct net_device *, struct dcb_app *); | 44 | int (*ieee_getapp) (struct net_device *, struct dcb_app *); |
45 | int (*ieee_setapp) (struct net_device *, struct dcb_app *); | 45 | int (*ieee_setapp) (struct net_device *, struct dcb_app *); |
46 | int (*ieee_peer_getets) (struct net_device *, struct ieee_ets *); | ||
47 | int (*ieee_peer_getpfc) (struct net_device *, struct ieee_pfc *); | ||
46 | 48 | ||
47 | /* CEE std */ | 49 | /* CEE std */ |
48 | u8 (*getstate)(struct net_device *); | 50 | u8 (*getstate)(struct net_device *); |
@@ -77,6 +79,10 @@ struct dcbnl_rtnl_ops { | |||
77 | u8 (*getdcbx)(struct net_device *); | 79 | u8 (*getdcbx)(struct net_device *); |
78 | u8 (*setdcbx)(struct net_device *, u8); | 80 | u8 (*setdcbx)(struct net_device *, u8); |
79 | 81 | ||
82 | /* peer apps */ | ||
83 | int (*peer_getappinfo)(struct net_device *, struct dcb_peer_app_info *, | ||
84 | u16 *); | ||
85 | int (*peer_getapptable)(struct net_device *, struct dcb_app *); | ||
80 | 86 | ||
81 | }; | 87 | }; |
82 | 88 | ||
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index d5074a567289..2e6dcf2967e2 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c | |||
@@ -1224,6 +1224,54 @@ err: | |||
1224 | return err; | 1224 | return err; |
1225 | } | 1225 | } |
1226 | 1226 | ||
1227 | static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb) | ||
1228 | { | ||
1229 | struct dcb_peer_app_info info; | ||
1230 | struct dcb_app *table = NULL; | ||
1231 | const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; | ||
1232 | u16 app_count; | ||
1233 | int err; | ||
1234 | |||
1235 | |||
1236 | /** | ||
1237 | * retrieve the peer app configuration form the driver. If the driver | ||
1238 | * handlers fail exit without doing anything | ||
1239 | */ | ||
1240 | err = ops->peer_getappinfo(netdev, &info, &app_count); | ||
1241 | if (!err && app_count) { | ||
1242 | table = kmalloc(sizeof(struct dcb_app) * app_count, GFP_KERNEL); | ||
1243 | if (!table) | ||
1244 | return -ENOMEM; | ||
1245 | |||
1246 | err = ops->peer_getapptable(netdev, table); | ||
1247 | } | ||
1248 | |||
1249 | if (!err) { | ||
1250 | u16 i; | ||
1251 | struct nlattr *app; | ||
1252 | |||
1253 | /** | ||
1254 | * build the message, from here on the only possible failure | ||
1255 | * is due to the skb size | ||
1256 | */ | ||
1257 | err = -EMSGSIZE; | ||
1258 | |||
1259 | app = nla_nest_start(skb, DCB_ATTR_IEEE_PEER_APP); | ||
1260 | if (!app) | ||
1261 | goto nla_put_failure; | ||
1262 | |||
1263 | for (i = 0; i < app_count; i++) | ||
1264 | NLA_PUT(skb, DCB_ATTR_IEEE_APP, sizeof(struct dcb_app), | ||
1265 | &table[i]); | ||
1266 | |||
1267 | nla_nest_end(skb, app); | ||
1268 | } | ||
1269 | err = 0; | ||
1270 | |||
1271 | nla_put_failure: | ||
1272 | kfree(table); | ||
1273 | return err; | ||
1274 | } | ||
1227 | 1275 | ||
1228 | /* Handle IEEE 802.1Qaz GET commands. */ | 1276 | /* Handle IEEE 802.1Qaz GET commands. */ |
1229 | static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, | 1277 | static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, |
@@ -1288,6 +1336,27 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, | |||
1288 | spin_unlock(&dcb_lock); | 1336 | spin_unlock(&dcb_lock); |
1289 | nla_nest_end(skb, app); | 1337 | nla_nest_end(skb, app); |
1290 | 1338 | ||
1339 | /* get peer info if available */ | ||
1340 | if (ops->ieee_peer_getets) { | ||
1341 | struct ieee_ets ets; | ||
1342 | err = ops->ieee_peer_getets(netdev, &ets); | ||
1343 | if (!err) | ||
1344 | NLA_PUT(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets); | ||
1345 | } | ||
1346 | |||
1347 | if (ops->ieee_peer_getpfc) { | ||
1348 | struct ieee_pfc pfc; | ||
1349 | err = ops->ieee_peer_getpfc(netdev, &pfc); | ||
1350 | if (!err) | ||
1351 | NLA_PUT(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc); | ||
1352 | } | ||
1353 | |||
1354 | if (ops->peer_getappinfo && ops->peer_getapptable) { | ||
1355 | err = dcbnl_build_peer_app(netdev, skb); | ||
1356 | if (err) | ||
1357 | goto nla_put_failure; | ||
1358 | } | ||
1359 | |||
1291 | nla_nest_end(skb, ieee); | 1360 | nla_nest_end(skb, ieee); |
1292 | nlmsg_end(skb, nlh); | 1361 | nlmsg_end(skb, nlh); |
1293 | 1362 | ||