aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/dcbnl.h28
-rw-r--r--include/net/dcbnl.h6
-rw-r--r--net/dcb/dcbnl.c69
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 */
122struct dcb_peer_app_info {
123 __u8 willing;
124 __u8 error;
125};
126
113struct dcbmsg { 127struct 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 */
238enum ieee_attrs { 263enum 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
1227static 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
1271nla_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. */
1229static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, 1277static 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