aboutsummaryrefslogtreecommitdiffstats
path: root/net/dcb
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /net/dcb
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'net/dcb')
-rw-r--r--net/dcb/dcbevent.c1
-rw-r--r--net/dcb/dcbnl.c1279
2 files changed, 805 insertions, 475 deletions
diff --git a/net/dcb/dcbevent.c b/net/dcb/dcbevent.c
index 1d9eb7c60a6..665a8802105 100644
--- a/net/dcb/dcbevent.c
+++ b/net/dcb/dcbevent.c
@@ -19,7 +19,6 @@
19 19
20#include <linux/rtnetlink.h> 20#include <linux/rtnetlink.h>
21#include <linux/notifier.h> 21#include <linux/notifier.h>
22#include <linux/export.h>
23 22
24static ATOMIC_NOTIFIER_HEAD(dcbevent_notif_chain); 23static ATOMIC_NOTIFIER_HEAD(dcbevent_notif_chain);
25 24
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 1b588e23cf8..3cb56af4e13 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -25,10 +25,10 @@
25#include <linux/dcbnl.h> 25#include <linux/dcbnl.h>
26#include <net/dcbevent.h> 26#include <net/dcbevent.h>
27#include <linux/rtnetlink.h> 27#include <linux/rtnetlink.h>
28#include <linux/module.h>
29#include <net/sock.h> 28#include <net/sock.h>
30 29
31/* Data Center Bridging (DCB) is a collection of Ethernet enhancements 30/**
31 * Data Center Bridging (DCB) is a collection of Ethernet enhancements
32 * intended to allow network traffic with differing requirements 32 * intended to allow network traffic with differing requirements
33 * (highly reliable, no drops vs. best effort vs. low latency) to operate 33 * (highly reliable, no drops vs. best effort vs. low latency) to operate
34 * and co-exist on Ethernet. Current DCB features are: 34 * and co-exist on Ethernet. Current DCB features are:
@@ -177,7 +177,6 @@ static const struct nla_policy dcbnl_ieee_policy[DCB_ATTR_IEEE_MAX + 1] = {
177 [DCB_ATTR_IEEE_ETS] = {.len = sizeof(struct ieee_ets)}, 177 [DCB_ATTR_IEEE_ETS] = {.len = sizeof(struct ieee_ets)},
178 [DCB_ATTR_IEEE_PFC] = {.len = sizeof(struct ieee_pfc)}, 178 [DCB_ATTR_IEEE_PFC] = {.len = sizeof(struct ieee_pfc)},
179 [DCB_ATTR_IEEE_APP_TABLE] = {.type = NLA_NESTED}, 179 [DCB_ATTR_IEEE_APP_TABLE] = {.type = NLA_NESTED},
180 [DCB_ATTR_IEEE_MAXRATE] = {.len = sizeof(struct ieee_maxrate)},
181}; 180};
182 181
183static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = { 182static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = {
@@ -195,66 +194,92 @@ static const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = {
195static LIST_HEAD(dcb_app_list); 194static LIST_HEAD(dcb_app_list);
196static DEFINE_SPINLOCK(dcb_lock); 195static DEFINE_SPINLOCK(dcb_lock);
197 196
198static struct sk_buff *dcbnl_newmsg(int type, u8 cmd, u32 port, u32 seq, 197/* standard netlink reply call */
199 u32 flags, struct nlmsghdr **nlhp) 198static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
199 u32 seq, u16 flags)
200{ 200{
201 struct sk_buff *skb; 201 struct sk_buff *dcbnl_skb;
202 struct dcbmsg *dcb; 202 struct dcbmsg *dcb;
203 struct nlmsghdr *nlh; 203 struct nlmsghdr *nlh;
204 int ret = -EINVAL;
204 205
205 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 206 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
206 if (!skb) 207 if (!dcbnl_skb)
207 return NULL; 208 return ret;
208 209
209 nlh = nlmsg_put(skb, port, seq, type, sizeof(*dcb), flags); 210 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags);
210 BUG_ON(!nlh);
211 211
212 dcb = nlmsg_data(nlh); 212 dcb = NLMSG_DATA(nlh);
213 dcb->dcb_family = AF_UNSPEC; 213 dcb->dcb_family = AF_UNSPEC;
214 dcb->cmd = cmd; 214 dcb->cmd = cmd;
215 dcb->dcb_pad = 0; 215 dcb->dcb_pad = 0;
216 216
217 if (nlhp) 217 ret = nla_put_u8(dcbnl_skb, attr, value);
218 *nlhp = nlh; 218 if (ret)
219 goto err;
219 220
220 return skb; 221 /* end the message, assign the nlmsg_len. */
222 nlmsg_end(dcbnl_skb, nlh);
223 ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
224 if (ret)
225 return -EINVAL;
226
227 return 0;
228nlmsg_failure:
229err:
230 kfree_skb(dcbnl_skb);
231 return ret;
221} 232}
222 233
223static int dcbnl_getstate(struct net_device *netdev, struct nlmsghdr *nlh, 234static int dcbnl_getstate(struct net_device *netdev, struct nlattr **tb,
224 u32 seq, struct nlattr **tb, struct sk_buff *skb) 235 u32 pid, u32 seq, u16 flags)
225{ 236{
237 int ret = -EINVAL;
238
226 /* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */ 239 /* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */
227 if (!netdev->dcbnl_ops->getstate) 240 if (!netdev->dcbnl_ops->getstate)
228 return -EOPNOTSUPP; 241 return ret;
242
243 ret = dcbnl_reply(netdev->dcbnl_ops->getstate(netdev), RTM_GETDCB,
244 DCB_CMD_GSTATE, DCB_ATTR_STATE, pid, seq, flags);
229 245
230 return nla_put_u8(skb, DCB_ATTR_STATE, 246 return ret;
231 netdev->dcbnl_ops->getstate(netdev));
232} 247}
233 248
234static int dcbnl_getpfccfg(struct net_device *netdev, struct nlmsghdr *nlh, 249static int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb,
235 u32 seq, struct nlattr **tb, struct sk_buff *skb) 250 u32 pid, u32 seq, u16 flags)
236{ 251{
252 struct sk_buff *dcbnl_skb;
253 struct nlmsghdr *nlh;
254 struct dcbmsg *dcb;
237 struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest; 255 struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest;
238 u8 value; 256 u8 value;
239 int ret; 257 int ret = -EINVAL;
240 int i; 258 int i;
241 int getall = 0; 259 int getall = 0;
242 260
243 if (!tb[DCB_ATTR_PFC_CFG]) 261 if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->getpfccfg)
244 return -EINVAL; 262 return ret;
245
246 if (!netdev->dcbnl_ops->getpfccfg)
247 return -EOPNOTSUPP;
248 263
249 ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, 264 ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
250 tb[DCB_ATTR_PFC_CFG], 265 tb[DCB_ATTR_PFC_CFG],
251 dcbnl_pfc_up_nest); 266 dcbnl_pfc_up_nest);
252 if (ret) 267 if (ret)
253 return ret; 268 goto err_out;
254 269
255 nest = nla_nest_start(skb, DCB_ATTR_PFC_CFG); 270 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
271 if (!dcbnl_skb)
272 goto err_out;
273
274 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
275
276 dcb = NLMSG_DATA(nlh);
277 dcb->dcb_family = AF_UNSPEC;
278 dcb->cmd = DCB_CMD_PFC_GCFG;
279
280 nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG);
256 if (!nest) 281 if (!nest)
257 return -EMSGSIZE; 282 goto err;
258 283
259 if (data[DCB_PFC_UP_ATTR_ALL]) 284 if (data[DCB_PFC_UP_ATTR_ALL])
260 getall = 1; 285 getall = 1;
@@ -265,53 +290,103 @@ static int dcbnl_getpfccfg(struct net_device *netdev, struct nlmsghdr *nlh,
265 290
266 netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, 291 netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0,
267 &value); 292 &value);
268 ret = nla_put_u8(skb, i, value); 293 ret = nla_put_u8(dcbnl_skb, i, value);
294
269 if (ret) { 295 if (ret) {
270 nla_nest_cancel(skb, nest); 296 nla_nest_cancel(dcbnl_skb, nest);
271 return ret; 297 goto err;
272 } 298 }
273 } 299 }
274 nla_nest_end(skb, nest); 300 nla_nest_end(dcbnl_skb, nest);
301
302 nlmsg_end(dcbnl_skb, nlh);
303
304 ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
305 if (ret)
306 goto err_out;
275 307
276 return 0; 308 return 0;
309nlmsg_failure:
310err:
311 kfree_skb(dcbnl_skb);
312err_out:
313 return -EINVAL;
277} 314}
278 315
279static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlmsghdr *nlh, 316static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb,
280 u32 seq, struct nlattr **tb, struct sk_buff *skb) 317 u32 pid, u32 seq, u16 flags)
281{ 318{
319 struct sk_buff *dcbnl_skb;
320 struct nlmsghdr *nlh;
321 struct dcbmsg *dcb;
282 u8 perm_addr[MAX_ADDR_LEN]; 322 u8 perm_addr[MAX_ADDR_LEN];
323 int ret = -EINVAL;
283 324
284 if (!netdev->dcbnl_ops->getpermhwaddr) 325 if (!netdev->dcbnl_ops->getpermhwaddr)
285 return -EOPNOTSUPP; 326 return ret;
327
328 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
329 if (!dcbnl_skb)
330 goto err_out;
331
332 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
333
334 dcb = NLMSG_DATA(nlh);
335 dcb->dcb_family = AF_UNSPEC;
336 dcb->cmd = DCB_CMD_GPERM_HWADDR;
286 337
287 netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr); 338 netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
288 339
289 return nla_put(skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), perm_addr); 340 ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr),
341 perm_addr);
342
343 nlmsg_end(dcbnl_skb, nlh);
344
345 ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
346 if (ret)
347 goto err_out;
348
349 return 0;
350
351nlmsg_failure:
352 kfree_skb(dcbnl_skb);
353err_out:
354 return -EINVAL;
290} 355}
291 356
292static int dcbnl_getcap(struct net_device *netdev, struct nlmsghdr *nlh, 357static int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb,
293 u32 seq, struct nlattr **tb, struct sk_buff *skb) 358 u32 pid, u32 seq, u16 flags)
294{ 359{
360 struct sk_buff *dcbnl_skb;
361 struct nlmsghdr *nlh;
362 struct dcbmsg *dcb;
295 struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest; 363 struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest;
296 u8 value; 364 u8 value;
297 int ret; 365 int ret = -EINVAL;
298 int i; 366 int i;
299 int getall = 0; 367 int getall = 0;
300 368
301 if (!tb[DCB_ATTR_CAP]) 369 if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap)
302 return -EINVAL; 370 return ret;
303
304 if (!netdev->dcbnl_ops->getcap)
305 return -EOPNOTSUPP;
306 371
307 ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP], 372 ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP],
308 dcbnl_cap_nest); 373 dcbnl_cap_nest);
309 if (ret) 374 if (ret)
310 return ret; 375 goto err_out;
376
377 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
378 if (!dcbnl_skb)
379 goto err_out;
311 380
312 nest = nla_nest_start(skb, DCB_ATTR_CAP); 381 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
382
383 dcb = NLMSG_DATA(nlh);
384 dcb->dcb_family = AF_UNSPEC;
385 dcb->cmd = DCB_CMD_GCAP;
386
387 nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP);
313 if (!nest) 388 if (!nest)
314 return -EMSGSIZE; 389 goto err;
315 390
316 if (data[DCB_CAP_ATTR_ALL]) 391 if (data[DCB_CAP_ATTR_ALL])
317 getall = 1; 392 getall = 1;
@@ -321,41 +396,69 @@ static int dcbnl_getcap(struct net_device *netdev, struct nlmsghdr *nlh,
321 continue; 396 continue;
322 397
323 if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) { 398 if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) {
324 ret = nla_put_u8(skb, i, value); 399 ret = nla_put_u8(dcbnl_skb, i, value);
400
325 if (ret) { 401 if (ret) {
326 nla_nest_cancel(skb, nest); 402 nla_nest_cancel(dcbnl_skb, nest);
327 return ret; 403 goto err;
328 } 404 }
329 } 405 }
330 } 406 }
331 nla_nest_end(skb, nest); 407 nla_nest_end(dcbnl_skb, nest);
408
409 nlmsg_end(dcbnl_skb, nlh);
410
411 ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
412 if (ret)
413 goto err_out;
332 414
333 return 0; 415 return 0;
416nlmsg_failure:
417err:
418 kfree_skb(dcbnl_skb);
419err_out:
420 return -EINVAL;
334} 421}
335 422
336static int dcbnl_getnumtcs(struct net_device *netdev, struct nlmsghdr *nlh, 423static int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb,
337 u32 seq, struct nlattr **tb, struct sk_buff *skb) 424 u32 pid, u32 seq, u16 flags)
338{ 425{
426 struct sk_buff *dcbnl_skb;
427 struct nlmsghdr *nlh;
428 struct dcbmsg *dcb;
339 struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest; 429 struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest;
340 u8 value; 430 u8 value;
341 int ret; 431 int ret = -EINVAL;
342 int i; 432 int i;
343 int getall = 0; 433 int getall = 0;
344 434
345 if (!tb[DCB_ATTR_NUMTCS]) 435 if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs)
346 return -EINVAL; 436 return ret;
347
348 if (!netdev->dcbnl_ops->getnumtcs)
349 return -EOPNOTSUPP;
350 437
351 ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], 438 ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
352 dcbnl_numtcs_nest); 439 dcbnl_numtcs_nest);
353 if (ret) 440 if (ret) {
354 return ret; 441 ret = -EINVAL;
442 goto err_out;
443 }
355 444
356 nest = nla_nest_start(skb, DCB_ATTR_NUMTCS); 445 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
357 if (!nest) 446 if (!dcbnl_skb) {
358 return -EMSGSIZE; 447 ret = -EINVAL;
448 goto err_out;
449 }
450
451 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
452
453 dcb = NLMSG_DATA(nlh);
454 dcb->dcb_family = AF_UNSPEC;
455 dcb->cmd = DCB_CMD_GNUMTCS;
456
457 nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS);
458 if (!nest) {
459 ret = -EINVAL;
460 goto err;
461 }
359 462
360 if (data[DCB_NUMTCS_ATTR_ALL]) 463 if (data[DCB_NUMTCS_ATTR_ALL])
361 getall = 1; 464 getall = 1;
@@ -366,37 +469,53 @@ static int dcbnl_getnumtcs(struct net_device *netdev, struct nlmsghdr *nlh,
366 469
367 ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value); 470 ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value);
368 if (!ret) { 471 if (!ret) {
369 ret = nla_put_u8(skb, i, value); 472 ret = nla_put_u8(dcbnl_skb, i, value);
473
370 if (ret) { 474 if (ret) {
371 nla_nest_cancel(skb, nest); 475 nla_nest_cancel(dcbnl_skb, nest);
372 return ret; 476 ret = -EINVAL;
477 goto err;
373 } 478 }
374 } else 479 } else {
375 return -EINVAL; 480 goto err;
481 }
482 }
483 nla_nest_end(dcbnl_skb, nest);
484
485 nlmsg_end(dcbnl_skb, nlh);
486
487 ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
488 if (ret) {
489 ret = -EINVAL;
490 goto err_out;
376 } 491 }
377 nla_nest_end(skb, nest);
378 492
379 return 0; 493 return 0;
494nlmsg_failure:
495err:
496 kfree_skb(dcbnl_skb);
497err_out:
498 return ret;
380} 499}
381 500
382static int dcbnl_setnumtcs(struct net_device *netdev, struct nlmsghdr *nlh, 501static int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb,
383 u32 seq, struct nlattr **tb, struct sk_buff *skb) 502 u32 pid, u32 seq, u16 flags)
384{ 503{
385 struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1]; 504 struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1];
386 int ret; 505 int ret = -EINVAL;
387 u8 value; 506 u8 value;
388 int i; 507 int i;
389 508
390 if (!tb[DCB_ATTR_NUMTCS]) 509 if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setnumtcs)
391 return -EINVAL; 510 return ret;
392
393 if (!netdev->dcbnl_ops->setnumtcs)
394 return -EOPNOTSUPP;
395 511
396 ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], 512 ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
397 dcbnl_numtcs_nest); 513 dcbnl_numtcs_nest);
398 if (ret) 514
399 return ret; 515 if (ret) {
516 ret = -EINVAL;
517 goto err;
518 }
400 519
401 for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { 520 for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
402 if (data[i] == NULL) 521 if (data[i] == NULL)
@@ -405,68 +524,84 @@ static int dcbnl_setnumtcs(struct net_device *netdev, struct nlmsghdr *nlh,
405 value = nla_get_u8(data[i]); 524 value = nla_get_u8(data[i]);
406 525
407 ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value); 526 ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value);
527
408 if (ret) 528 if (ret)
409 break; 529 goto operr;
410 } 530 }
411 531
412 return nla_put_u8(skb, DCB_ATTR_NUMTCS, !!ret); 532operr:
533 ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS,
534 DCB_ATTR_NUMTCS, pid, seq, flags);
535
536err:
537 return ret;
413} 538}
414 539
415static int dcbnl_getpfcstate(struct net_device *netdev, struct nlmsghdr *nlh, 540static int dcbnl_getpfcstate(struct net_device *netdev, struct nlattr **tb,
416 u32 seq, struct nlattr **tb, struct sk_buff *skb) 541 u32 pid, u32 seq, u16 flags)
417{ 542{
543 int ret = -EINVAL;
544
418 if (!netdev->dcbnl_ops->getpfcstate) 545 if (!netdev->dcbnl_ops->getpfcstate)
419 return -EOPNOTSUPP; 546 return ret;
547
548 ret = dcbnl_reply(netdev->dcbnl_ops->getpfcstate(netdev), RTM_GETDCB,
549 DCB_CMD_PFC_GSTATE, DCB_ATTR_PFC_STATE,
550 pid, seq, flags);
420 551
421 return nla_put_u8(skb, DCB_ATTR_PFC_STATE, 552 return ret;
422 netdev->dcbnl_ops->getpfcstate(netdev));
423} 553}
424 554
425static int dcbnl_setpfcstate(struct net_device *netdev, struct nlmsghdr *nlh, 555static int dcbnl_setpfcstate(struct net_device *netdev, struct nlattr **tb,
426 u32 seq, struct nlattr **tb, struct sk_buff *skb) 556 u32 pid, u32 seq, u16 flags)
427{ 557{
558 int ret = -EINVAL;
428 u8 value; 559 u8 value;
429 560
430 if (!tb[DCB_ATTR_PFC_STATE]) 561 if (!tb[DCB_ATTR_PFC_STATE] || !netdev->dcbnl_ops->setpfcstate)
431 return -EINVAL; 562 return ret;
432
433 if (!netdev->dcbnl_ops->setpfcstate)
434 return -EOPNOTSUPP;
435 563
436 value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]); 564 value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]);
437 565
438 netdev->dcbnl_ops->setpfcstate(netdev, value); 566 netdev->dcbnl_ops->setpfcstate(netdev, value);
439 567
440 return nla_put_u8(skb, DCB_ATTR_PFC_STATE, 0); 568 ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SSTATE, DCB_ATTR_PFC_STATE,
569 pid, seq, flags);
570
571 return ret;
441} 572}
442 573
443static int dcbnl_getapp(struct net_device *netdev, struct nlmsghdr *nlh, 574static int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb,
444 u32 seq, struct nlattr **tb, struct sk_buff *skb) 575 u32 pid, u32 seq, u16 flags)
445{ 576{
577 struct sk_buff *dcbnl_skb;
578 struct nlmsghdr *nlh;
579 struct dcbmsg *dcb;
446 struct nlattr *app_nest; 580 struct nlattr *app_nest;
447 struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; 581 struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
448 u16 id; 582 u16 id;
449 u8 up, idtype; 583 u8 up, idtype;
450 int ret; 584 int ret = -EINVAL;
451 585
452 if (!tb[DCB_ATTR_APP]) 586 if (!tb[DCB_ATTR_APP])
453 return -EINVAL; 587 goto out;
454 588
455 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],
456 dcbnl_app_nest); 590 dcbnl_app_nest);
457 if (ret) 591 if (ret)
458 return ret; 592 goto out;
459 593
594 ret = -EINVAL;
460 /* all must be non-null */ 595 /* all must be non-null */
461 if ((!app_tb[DCB_APP_ATTR_IDTYPE]) || 596 if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
462 (!app_tb[DCB_APP_ATTR_ID])) 597 (!app_tb[DCB_APP_ATTR_ID]))
463 return -EINVAL; 598 goto out;
464 599
465 /* either by eth type or by socket number */ 600 /* either by eth type or by socket number */
466 idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]); 601 idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
467 if ((idtype != DCB_APP_IDTYPE_ETHTYPE) && 602 if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
468 (idtype != DCB_APP_IDTYPE_PORTNUM)) 603 (idtype != DCB_APP_IDTYPE_PORTNUM))
469 return -EINVAL; 604 goto out;
470 605
471 id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); 606 id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
472 607
@@ -480,106 +615,137 @@ static int dcbnl_getapp(struct net_device *netdev, struct nlmsghdr *nlh,
480 up = dcb_getapp(netdev, &app); 615 up = dcb_getapp(netdev, &app);
481 } 616 }
482 617
483 app_nest = nla_nest_start(skb, DCB_ATTR_APP); 618 /* send this back */
619 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
620 if (!dcbnl_skb)
621 goto out;
622
623 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
624 dcb = NLMSG_DATA(nlh);
625 dcb->dcb_family = AF_UNSPEC;
626 dcb->cmd = DCB_CMD_GAPP;
627
628 app_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_APP);
484 if (!app_nest) 629 if (!app_nest)
485 return -EMSGSIZE; 630 goto out_cancel;
486 631
487 ret = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE, idtype); 632 ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype);
488 if (ret) 633 if (ret)
489 goto out_cancel; 634 goto out_cancel;
490 635
491 ret = nla_put_u16(skb, DCB_APP_ATTR_ID, id); 636 ret = nla_put_u16(dcbnl_skb, DCB_APP_ATTR_ID, id);
492 if (ret) 637 if (ret)
493 goto out_cancel; 638 goto out_cancel;
494 639
495 ret = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY, up); 640 ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_PRIORITY, up);
496 if (ret) 641 if (ret)
497 goto out_cancel; 642 goto out_cancel;
498 643
499 nla_nest_end(skb, app_nest); 644 nla_nest_end(dcbnl_skb, app_nest);
645 nlmsg_end(dcbnl_skb, nlh);
500 646
501 return 0; 647 ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
648 if (ret)
649 goto nlmsg_failure;
650
651 goto out;
502 652
503out_cancel: 653out_cancel:
504 nla_nest_cancel(skb, app_nest); 654 nla_nest_cancel(dcbnl_skb, app_nest);
655nlmsg_failure:
656 kfree_skb(dcbnl_skb);
657out:
505 return ret; 658 return ret;
506} 659}
507 660
508static int dcbnl_setapp(struct net_device *netdev, struct nlmsghdr *nlh, 661static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb,
509 u32 seq, struct nlattr **tb, struct sk_buff *skb) 662 u32 pid, u32 seq, u16 flags)
510{ 663{
511 int ret; 664 int err, ret = -EINVAL;
512 u16 id; 665 u16 id;
513 u8 up, idtype; 666 u8 up, idtype;
514 struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; 667 struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
515 668
516 if (!tb[DCB_ATTR_APP]) 669 if (!tb[DCB_ATTR_APP])
517 return -EINVAL; 670 goto out;
518 671
519 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],
520 dcbnl_app_nest); 673 dcbnl_app_nest);
521 if (ret) 674 if (ret)
522 return ret; 675 goto out;
523 676
677 ret = -EINVAL;
524 /* all must be non-null */ 678 /* all must be non-null */
525 if ((!app_tb[DCB_APP_ATTR_IDTYPE]) || 679 if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
526 (!app_tb[DCB_APP_ATTR_ID]) || 680 (!app_tb[DCB_APP_ATTR_ID]) ||
527 (!app_tb[DCB_APP_ATTR_PRIORITY])) 681 (!app_tb[DCB_APP_ATTR_PRIORITY]))
528 return -EINVAL; 682 goto out;
529 683
530 /* either by eth type or by socket number */ 684 /* either by eth type or by socket number */
531 idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]); 685 idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
532 if ((idtype != DCB_APP_IDTYPE_ETHTYPE) && 686 if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
533 (idtype != DCB_APP_IDTYPE_PORTNUM)) 687 (idtype != DCB_APP_IDTYPE_PORTNUM))
534 return -EINVAL; 688 goto out;
535 689
536 id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); 690 id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
537 up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]); 691 up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]);
538 692
539 if (netdev->dcbnl_ops->setapp) { 693 if (netdev->dcbnl_ops->setapp) {
540 ret = netdev->dcbnl_ops->setapp(netdev, idtype, id, up); 694 err = netdev->dcbnl_ops->setapp(netdev, idtype, id, up);
541 } else { 695 } else {
542 struct dcb_app app; 696 struct dcb_app app;
543 app.selector = idtype; 697 app.selector = idtype;
544 app.protocol = id; 698 app.protocol = id;
545 app.priority = up; 699 app.priority = up;
546 ret = dcb_setapp(netdev, &app); 700 err = dcb_setapp(netdev, &app);
547 } 701 }
548 702
549 ret = nla_put_u8(skb, DCB_ATTR_APP, ret); 703 ret = dcbnl_reply(err, RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP,
550 dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SAPP, seq, 0); 704 pid, seq, flags);
551 705out:
552 return ret; 706 return ret;
553} 707}
554 708
555static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, 709static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb,
556 struct nlattr **tb, struct sk_buff *skb, int dir) 710 u32 pid, u32 seq, u16 flags, int dir)
557{ 711{
712 struct sk_buff *dcbnl_skb;
713 struct nlmsghdr *nlh;
714 struct dcbmsg *dcb;
558 struct nlattr *pg_nest, *param_nest, *data; 715 struct nlattr *pg_nest, *param_nest, *data;
559 struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; 716 struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
560 struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; 717 struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
561 u8 prio, pgid, tc_pct, up_map; 718 u8 prio, pgid, tc_pct, up_map;
562 int ret; 719 int ret = -EINVAL;
563 int getall = 0; 720 int getall = 0;
564 int i; 721 int i;
565 722
566 if (!tb[DCB_ATTR_PG_CFG]) 723 if (!tb[DCB_ATTR_PG_CFG] ||
567 return -EINVAL; 724 !netdev->dcbnl_ops->getpgtccfgtx ||
568
569 if (!netdev->dcbnl_ops->getpgtccfgtx ||
570 !netdev->dcbnl_ops->getpgtccfgrx || 725 !netdev->dcbnl_ops->getpgtccfgrx ||
571 !netdev->dcbnl_ops->getpgbwgcfgtx || 726 !netdev->dcbnl_ops->getpgbwgcfgtx ||
572 !netdev->dcbnl_ops->getpgbwgcfgrx) 727 !netdev->dcbnl_ops->getpgbwgcfgrx)
573 return -EOPNOTSUPP; 728 return ret;
574 729
575 ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, 730 ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
576 tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest); 731 tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
732
577 if (ret) 733 if (ret)
578 return ret; 734 goto err_out;
735
736 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
737 if (!dcbnl_skb)
738 goto err_out;
739
740 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
741
742 dcb = NLMSG_DATA(nlh);
743 dcb->dcb_family = AF_UNSPEC;
744 dcb->cmd = (dir) ? DCB_CMD_PGRX_GCFG : DCB_CMD_PGTX_GCFG;
579 745
580 pg_nest = nla_nest_start(skb, DCB_ATTR_PG_CFG); 746 pg_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PG_CFG);
581 if (!pg_nest) 747 if (!pg_nest)
582 return -EMSGSIZE; 748 goto err;
583 749
584 if (pg_tb[DCB_PG_ATTR_TC_ALL]) 750 if (pg_tb[DCB_PG_ATTR_TC_ALL])
585 getall = 1; 751 getall = 1;
@@ -597,7 +763,7 @@ static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
597 if (ret) 763 if (ret)
598 goto err_pg; 764 goto err_pg;
599 765
600 param_nest = nla_nest_start(skb, i); 766 param_nest = nla_nest_start(dcbnl_skb, i);
601 if (!param_nest) 767 if (!param_nest)
602 goto err_pg; 768 goto err_pg;
603 769
@@ -620,33 +786,33 @@ static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
620 786
621 if (param_tb[DCB_TC_ATTR_PARAM_PGID] || 787 if (param_tb[DCB_TC_ATTR_PARAM_PGID] ||
622 param_tb[DCB_TC_ATTR_PARAM_ALL]) { 788 param_tb[DCB_TC_ATTR_PARAM_ALL]) {
623 ret = nla_put_u8(skb, 789 ret = nla_put_u8(dcbnl_skb,
624 DCB_TC_ATTR_PARAM_PGID, pgid); 790 DCB_TC_ATTR_PARAM_PGID, pgid);
625 if (ret) 791 if (ret)
626 goto err_param; 792 goto err_param;
627 } 793 }
628 if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] || 794 if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] ||
629 param_tb[DCB_TC_ATTR_PARAM_ALL]) { 795 param_tb[DCB_TC_ATTR_PARAM_ALL]) {
630 ret = nla_put_u8(skb, 796 ret = nla_put_u8(dcbnl_skb,
631 DCB_TC_ATTR_PARAM_UP_MAPPING, up_map); 797 DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
632 if (ret) 798 if (ret)
633 goto err_param; 799 goto err_param;
634 } 800 }
635 if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] || 801 if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] ||
636 param_tb[DCB_TC_ATTR_PARAM_ALL]) { 802 param_tb[DCB_TC_ATTR_PARAM_ALL]) {
637 ret = nla_put_u8(skb, 803 ret = nla_put_u8(dcbnl_skb,
638 DCB_TC_ATTR_PARAM_STRICT_PRIO, prio); 804 DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
639 if (ret) 805 if (ret)
640 goto err_param; 806 goto err_param;
641 } 807 }
642 if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] || 808 if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] ||
643 param_tb[DCB_TC_ATTR_PARAM_ALL]) { 809 param_tb[DCB_TC_ATTR_PARAM_ALL]) {
644 ret = nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, 810 ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_BW_PCT,
645 tc_pct); 811 tc_pct);
646 if (ret) 812 if (ret)
647 goto err_param; 813 goto err_param;
648 } 814 }
649 nla_nest_end(skb, param_nest); 815 nla_nest_end(dcbnl_skb, param_nest);
650 } 816 }
651 817
652 if (pg_tb[DCB_PG_ATTR_BW_ID_ALL]) 818 if (pg_tb[DCB_PG_ATTR_BW_ID_ALL])
@@ -669,71 +835,80 @@ static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
669 netdev->dcbnl_ops->getpgbwgcfgtx(netdev, 835 netdev->dcbnl_ops->getpgbwgcfgtx(netdev,
670 i - DCB_PG_ATTR_BW_ID_0, &tc_pct); 836 i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
671 } 837 }
672 ret = nla_put_u8(skb, i, tc_pct); 838 ret = nla_put_u8(dcbnl_skb, i, tc_pct);
839
673 if (ret) 840 if (ret)
674 goto err_pg; 841 goto err_pg;
675 } 842 }
676 843
677 nla_nest_end(skb, pg_nest); 844 nla_nest_end(dcbnl_skb, pg_nest);
845
846 nlmsg_end(dcbnl_skb, nlh);
847
848 ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
849 if (ret)
850 goto err_out;
678 851
679 return 0; 852 return 0;
680 853
681err_param: 854err_param:
682 nla_nest_cancel(skb, param_nest); 855 nla_nest_cancel(dcbnl_skb, param_nest);
683err_pg: 856err_pg:
684 nla_nest_cancel(skb, pg_nest); 857 nla_nest_cancel(dcbnl_skb, pg_nest);
685 858nlmsg_failure:
686 return -EMSGSIZE; 859err:
860 kfree_skb(dcbnl_skb);
861err_out:
862 ret = -EINVAL;
863 return ret;
687} 864}
688 865
689static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, 866static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlattr **tb,
690 u32 seq, struct nlattr **tb, struct sk_buff *skb) 867 u32 pid, u32 seq, u16 flags)
691{ 868{
692 return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 0); 869 return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 0);
693} 870}
694 871
695static int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, 872static int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlattr **tb,
696 u32 seq, struct nlattr **tb, struct sk_buff *skb) 873 u32 pid, u32 seq, u16 flags)
697{ 874{
698 return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 1); 875 return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 1);
699} 876}
700 877
701static int dcbnl_setstate(struct net_device *netdev, struct nlmsghdr *nlh, 878static int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb,
702 u32 seq, struct nlattr **tb, struct sk_buff *skb) 879 u32 pid, u32 seq, u16 flags)
703{ 880{
881 int ret = -EINVAL;
704 u8 value; 882 u8 value;
705 883
706 if (!tb[DCB_ATTR_STATE]) 884 if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate)
707 return -EINVAL; 885 return ret;
708
709 if (!netdev->dcbnl_ops->setstate)
710 return -EOPNOTSUPP;
711 886
712 value = nla_get_u8(tb[DCB_ATTR_STATE]); 887 value = nla_get_u8(tb[DCB_ATTR_STATE]);
713 888
714 return nla_put_u8(skb, DCB_ATTR_STATE, 889 ret = dcbnl_reply(netdev->dcbnl_ops->setstate(netdev, value),
715 netdev->dcbnl_ops->setstate(netdev, value)); 890 RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE,
891 pid, seq, flags);
892
893 return ret;
716} 894}
717 895
718static int dcbnl_setpfccfg(struct net_device *netdev, struct nlmsghdr *nlh, 896static int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb,
719 u32 seq, struct nlattr **tb, struct sk_buff *skb) 897 u32 pid, u32 seq, u16 flags)
720{ 898{
721 struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1]; 899 struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1];
722 int i; 900 int i;
723 int ret; 901 int ret = -EINVAL;
724 u8 value; 902 u8 value;
725 903
726 if (!tb[DCB_ATTR_PFC_CFG]) 904 if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->setpfccfg)
727 return -EINVAL; 905 return ret;
728
729 if (!netdev->dcbnl_ops->setpfccfg)
730 return -EOPNOTSUPP;
731 906
732 ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, 907 ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
733 tb[DCB_ATTR_PFC_CFG], 908 tb[DCB_ATTR_PFC_CFG],
734 dcbnl_pfc_up_nest); 909 dcbnl_pfc_up_nest);
735 if (ret) 910 if (ret)
736 return ret; 911 goto err;
737 912
738 for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { 913 for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
739 if (data[i] == NULL) 914 if (data[i] == NULL)
@@ -743,53 +918,49 @@ static int dcbnl_setpfccfg(struct net_device *netdev, struct nlmsghdr *nlh,
743 data[i]->nla_type - DCB_PFC_UP_ATTR_0, value); 918 data[i]->nla_type - DCB_PFC_UP_ATTR_0, value);
744 } 919 }
745 920
746 return nla_put_u8(skb, DCB_ATTR_PFC_CFG, 0); 921 ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SCFG, DCB_ATTR_PFC_CFG,
922 pid, seq, flags);
923err:
924 return ret;
747} 925}
748 926
749static int dcbnl_setall(struct net_device *netdev, struct nlmsghdr *nlh, 927static int dcbnl_setall(struct net_device *netdev, struct nlattr **tb,
750 u32 seq, struct nlattr **tb, struct sk_buff *skb) 928 u32 pid, u32 seq, u16 flags)
751{ 929{
752 int ret; 930 int ret = -EINVAL;
753
754 if (!tb[DCB_ATTR_SET_ALL])
755 return -EINVAL;
756 931
757 if (!netdev->dcbnl_ops->setall) 932 if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall)
758 return -EOPNOTSUPP; 933 return ret;
759 934
760 ret = nla_put_u8(skb, DCB_ATTR_SET_ALL, 935 ret = dcbnl_reply(netdev->dcbnl_ops->setall(netdev), RTM_SETDCB,
761 netdev->dcbnl_ops->setall(netdev)); 936 DCB_CMD_SET_ALL, DCB_ATTR_SET_ALL, pid, seq, flags);
762 dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SET_ALL, seq, 0);
763 937
764 return ret; 938 return ret;
765} 939}
766 940
767static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, 941static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb,
768 u32 seq, struct nlattr **tb, struct sk_buff *skb, 942 u32 pid, u32 seq, u16 flags, int dir)
769 int dir)
770{ 943{
771 struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; 944 struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
772 struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; 945 struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
773 int ret; 946 int ret = -EINVAL;
774 int i; 947 int i;
775 u8 pgid; 948 u8 pgid;
776 u8 up_map; 949 u8 up_map;
777 u8 prio; 950 u8 prio;
778 u8 tc_pct; 951 u8 tc_pct;
779 952
780 if (!tb[DCB_ATTR_PG_CFG]) 953 if (!tb[DCB_ATTR_PG_CFG] ||
781 return -EINVAL; 954 !netdev->dcbnl_ops->setpgtccfgtx ||
782
783 if (!netdev->dcbnl_ops->setpgtccfgtx ||
784 !netdev->dcbnl_ops->setpgtccfgrx || 955 !netdev->dcbnl_ops->setpgtccfgrx ||
785 !netdev->dcbnl_ops->setpgbwgcfgtx || 956 !netdev->dcbnl_ops->setpgbwgcfgtx ||
786 !netdev->dcbnl_ops->setpgbwgcfgrx) 957 !netdev->dcbnl_ops->setpgbwgcfgrx)
787 return -EOPNOTSUPP; 958 return ret;
788 959
789 ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, 960 ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
790 tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest); 961 tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
791 if (ret) 962 if (ret)
792 return ret; 963 goto err;
793 964
794 for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { 965 for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
795 if (!pg_tb[i]) 966 if (!pg_tb[i])
@@ -798,7 +969,7 @@ static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
798 ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX, 969 ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
799 pg_tb[i], dcbnl_tc_param_nest); 970 pg_tb[i], dcbnl_tc_param_nest);
800 if (ret) 971 if (ret)
801 return ret; 972 goto err;
802 973
803 pgid = DCB_ATTR_VALUE_UNDEFINED; 974 pgid = DCB_ATTR_VALUE_UNDEFINED;
804 prio = DCB_ATTR_VALUE_UNDEFINED; 975 prio = DCB_ATTR_VALUE_UNDEFINED;
@@ -851,47 +1022,63 @@ static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
851 } 1022 }
852 } 1023 }
853 1024
854 return nla_put_u8(skb, DCB_ATTR_PG_CFG, 0); 1025 ret = dcbnl_reply(0, RTM_SETDCB,
1026 (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG),
1027 DCB_ATTR_PG_CFG, pid, seq, flags);
1028
1029err:
1030 return ret;
855} 1031}
856 1032
857static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, 1033static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlattr **tb,
858 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1034 u32 pid, u32 seq, u16 flags)
859{ 1035{
860 return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 0); 1036 return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 0);
861} 1037}
862 1038
863static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, 1039static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb,
864 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1040 u32 pid, u32 seq, u16 flags)
865{ 1041{
866 return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 1); 1042 return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1);
867} 1043}
868 1044
869static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, 1045static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb,
870 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1046 u32 pid, u32 seq, u16 flags)
871{ 1047{
1048 struct sk_buff *dcbnl_skb;
1049 struct nlmsghdr *nlh;
1050 struct dcbmsg *dcb;
872 struct nlattr *bcn_nest; 1051 struct nlattr *bcn_nest;
873 struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1]; 1052 struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1];
874 u8 value_byte; 1053 u8 value_byte;
875 u32 value_integer; 1054 u32 value_integer;
876 int ret; 1055 int ret = -EINVAL;
877 bool getall = false; 1056 bool getall = false;
878 int i; 1057 int i;
879 1058
880 if (!tb[DCB_ATTR_BCN]) 1059 if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->getbcnrp ||
881 return -EINVAL;
882
883 if (!netdev->dcbnl_ops->getbcnrp ||
884 !netdev->dcbnl_ops->getbcncfg) 1060 !netdev->dcbnl_ops->getbcncfg)
885 return -EOPNOTSUPP; 1061 return ret;
886 1062
887 ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX, 1063 ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX,
888 tb[DCB_ATTR_BCN], dcbnl_bcn_nest); 1064 tb[DCB_ATTR_BCN], dcbnl_bcn_nest);
1065
889 if (ret) 1066 if (ret)
890 return ret; 1067 goto err_out;
1068
1069 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1070 if (!dcbnl_skb)
1071 goto err_out;
1072
1073 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
891 1074
892 bcn_nest = nla_nest_start(skb, DCB_ATTR_BCN); 1075 dcb = NLMSG_DATA(nlh);
1076 dcb->dcb_family = AF_UNSPEC;
1077 dcb->cmd = DCB_CMD_BCN_GCFG;
1078
1079 bcn_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_BCN);
893 if (!bcn_nest) 1080 if (!bcn_nest)
894 return -EMSGSIZE; 1081 goto err;
895 1082
896 if (bcn_tb[DCB_BCN_ATTR_ALL]) 1083 if (bcn_tb[DCB_BCN_ATTR_ALL])
897 getall = true; 1084 getall = true;
@@ -902,7 +1089,7 @@ static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
902 1089
903 netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0, 1090 netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0,
904 &value_byte); 1091 &value_byte);
905 ret = nla_put_u8(skb, i, value_byte); 1092 ret = nla_put_u8(dcbnl_skb, i, value_byte);
906 if (ret) 1093 if (ret)
907 goto err_bcn; 1094 goto err_bcn;
908 } 1095 }
@@ -913,41 +1100,49 @@ static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlmsghdr *nlh,
913 1100
914 netdev->dcbnl_ops->getbcncfg(netdev, i, 1101 netdev->dcbnl_ops->getbcncfg(netdev, i,
915 &value_integer); 1102 &value_integer);
916 ret = nla_put_u32(skb, i, value_integer); 1103 ret = nla_put_u32(dcbnl_skb, i, value_integer);
917 if (ret) 1104 if (ret)
918 goto err_bcn; 1105 goto err_bcn;
919 } 1106 }
920 1107
921 nla_nest_end(skb, bcn_nest); 1108 nla_nest_end(dcbnl_skb, bcn_nest);
1109
1110 nlmsg_end(dcbnl_skb, nlh);
1111
1112 ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
1113 if (ret)
1114 goto err_out;
922 1115
923 return 0; 1116 return 0;
924 1117
925err_bcn: 1118err_bcn:
926 nla_nest_cancel(skb, bcn_nest); 1119 nla_nest_cancel(dcbnl_skb, bcn_nest);
1120nlmsg_failure:
1121err:
1122 kfree_skb(dcbnl_skb);
1123err_out:
1124 ret = -EINVAL;
927 return ret; 1125 return ret;
928} 1126}
929 1127
930static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, 1128static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlattr **tb,
931 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1129 u32 pid, u32 seq, u16 flags)
932{ 1130{
933 struct nlattr *data[DCB_BCN_ATTR_MAX + 1]; 1131 struct nlattr *data[DCB_BCN_ATTR_MAX + 1];
934 int i; 1132 int i;
935 int ret; 1133 int ret = -EINVAL;
936 u8 value_byte; 1134 u8 value_byte;
937 u32 value_int; 1135 u32 value_int;
938 1136
939 if (!tb[DCB_ATTR_BCN]) 1137 if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg ||
940 return -EINVAL;
941
942 if (!netdev->dcbnl_ops->setbcncfg ||
943 !netdev->dcbnl_ops->setbcnrp) 1138 !netdev->dcbnl_ops->setbcnrp)
944 return -EOPNOTSUPP; 1139 return ret;
945 1140
946 ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX, 1141 ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX,
947 tb[DCB_ATTR_BCN], 1142 tb[DCB_ATTR_BCN],
948 dcbnl_pfc_up_nest); 1143 dcbnl_pfc_up_nest);
949 if (ret) 1144 if (ret)
950 return ret; 1145 goto err;
951 1146
952 for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) { 1147 for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
953 if (data[i] == NULL) 1148 if (data[i] == NULL)
@@ -965,7 +1160,10 @@ static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
965 i, value_int); 1160 i, value_int);
966 } 1161 }
967 1162
968 return nla_put_u8(skb, DCB_ATTR_BCN, 0); 1163 ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_BCN_SCFG, DCB_ATTR_BCN,
1164 pid, seq, flags);
1165err:
1166 return ret;
969} 1167}
970 1168
971static 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,
@@ -1006,15 +1204,13 @@ static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
1006 if (!app) 1204 if (!app)
1007 goto nla_put_failure; 1205 goto nla_put_failure;
1008 1206
1009 if (app_info_type && 1207 if (app_info_type)
1010 nla_put(skb, app_info_type, sizeof(info), &info)) 1208 NLA_PUT(skb, app_info_type, sizeof(info), &info);
1011 goto nla_put_failure; 1209
1210 for (i = 0; i < app_count; i++)
1211 NLA_PUT(skb, app_entry_type, sizeof(struct dcb_app),
1212 &table[i]);
1012 1213
1013 for (i = 0; i < app_count; i++) {
1014 if (nla_put(skb, app_entry_type, sizeof(struct dcb_app),
1015 &table[i]))
1016 goto nla_put_failure;
1017 }
1018 nla_nest_end(skb, app); 1214 nla_nest_end(skb, app);
1019 } 1215 }
1020 err = 0; 1216 err = 0;
@@ -1031,54 +1227,40 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
1031 struct dcb_app_type *itr; 1227 struct dcb_app_type *itr;
1032 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1228 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1033 int dcbx; 1229 int dcbx;
1034 int err; 1230 int err = -EMSGSIZE;
1035 1231
1036 if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name)) 1232 NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
1037 return -EMSGSIZE;
1038 1233
1039 ieee = nla_nest_start(skb, DCB_ATTR_IEEE); 1234 ieee = nla_nest_start(skb, DCB_ATTR_IEEE);
1040 if (!ieee) 1235 if (!ieee)
1041 return -EMSGSIZE; 1236 goto nla_put_failure;
1042 1237
1043 if (ops->ieee_getets) { 1238 if (ops->ieee_getets) {
1044 struct ieee_ets ets; 1239 struct ieee_ets ets;
1045 err = ops->ieee_getets(netdev, &ets); 1240 err = ops->ieee_getets(netdev, &ets);
1046 if (!err && 1241 if (!err)
1047 nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets)) 1242 NLA_PUT(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets);
1048 return -EMSGSIZE;
1049 }
1050
1051 if (ops->ieee_getmaxrate) {
1052 struct ieee_maxrate maxrate;
1053 err = ops->ieee_getmaxrate(netdev, &maxrate);
1054 if (!err) {
1055 err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE,
1056 sizeof(maxrate), &maxrate);
1057 if (err)
1058 return -EMSGSIZE;
1059 }
1060 } 1243 }
1061 1244
1062 if (ops->ieee_getpfc) { 1245 if (ops->ieee_getpfc) {
1063 struct ieee_pfc pfc; 1246 struct ieee_pfc pfc;
1064 err = ops->ieee_getpfc(netdev, &pfc); 1247 err = ops->ieee_getpfc(netdev, &pfc);
1065 if (!err && 1248 if (!err)
1066 nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc)) 1249 NLA_PUT(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc);
1067 return -EMSGSIZE;
1068 } 1250 }
1069 1251
1070 app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE); 1252 app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE);
1071 if (!app) 1253 if (!app)
1072 return -EMSGSIZE; 1254 goto nla_put_failure;
1073 1255
1074 spin_lock(&dcb_lock); 1256 spin_lock(&dcb_lock);
1075 list_for_each_entry(itr, &dcb_app_list, list) { 1257 list_for_each_entry(itr, &dcb_app_list, list) {
1076 if (itr->ifindex == netdev->ifindex) { 1258 if (strncmp(itr->name, netdev->name, IFNAMSIZ) == 0) {
1077 err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app), 1259 err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app),
1078 &itr->app); 1260 &itr->app);
1079 if (err) { 1261 if (err) {
1080 spin_unlock(&dcb_lock); 1262 spin_unlock(&dcb_lock);
1081 return -EMSGSIZE; 1263 goto nla_put_failure;
1082 } 1264 }
1083 } 1265 }
1084 } 1266 }
@@ -1095,17 +1277,15 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
1095 if (ops->ieee_peer_getets) { 1277 if (ops->ieee_peer_getets) {
1096 struct ieee_ets ets; 1278 struct ieee_ets ets;
1097 err = ops->ieee_peer_getets(netdev, &ets); 1279 err = ops->ieee_peer_getets(netdev, &ets);
1098 if (!err && 1280 if (!err)
1099 nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets)) 1281 NLA_PUT(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets);
1100 return -EMSGSIZE;
1101 } 1282 }
1102 1283
1103 if (ops->ieee_peer_getpfc) { 1284 if (ops->ieee_peer_getpfc) {
1104 struct ieee_pfc pfc; 1285 struct ieee_pfc pfc;
1105 err = ops->ieee_peer_getpfc(netdev, &pfc); 1286 err = ops->ieee_peer_getpfc(netdev, &pfc);
1106 if (!err && 1287 if (!err)
1107 nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc)) 1288 NLA_PUT(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc);
1108 return -EMSGSIZE;
1109 } 1289 }
1110 1290
1111 if (ops->peer_getappinfo && ops->peer_getapptable) { 1291 if (ops->peer_getappinfo && ops->peer_getapptable) {
@@ -1114,17 +1294,20 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
1114 DCB_ATTR_IEEE_APP_UNSPEC, 1294 DCB_ATTR_IEEE_APP_UNSPEC,
1115 DCB_ATTR_IEEE_APP); 1295 DCB_ATTR_IEEE_APP);
1116 if (err) 1296 if (err)
1117 return -EMSGSIZE; 1297 goto nla_put_failure;
1118 } 1298 }
1119 1299
1120 nla_nest_end(skb, ieee); 1300 nla_nest_end(skb, ieee);
1121 if (dcbx >= 0) { 1301 if (dcbx >= 0) {
1122 err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx); 1302 err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
1123 if (err) 1303 if (err)
1124 return -EMSGSIZE; 1304 goto nla_put_failure;
1125 } 1305 }
1126 1306
1127 return 0; 1307 return 0;
1308
1309nla_put_failure:
1310 return err;
1128} 1311}
1129 1312
1130static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev, 1313static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
@@ -1136,13 +1319,13 @@ static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
1136 struct nlattr *pg = nla_nest_start(skb, i); 1319 struct nlattr *pg = nla_nest_start(skb, i);
1137 1320
1138 if (!pg) 1321 if (!pg)
1139 return -EMSGSIZE; 1322 goto nla_put_failure;
1140 1323
1141 for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { 1324 for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
1142 struct nlattr *tc_nest = nla_nest_start(skb, i); 1325 struct nlattr *tc_nest = nla_nest_start(skb, i);
1143 1326
1144 if (!tc_nest) 1327 if (!tc_nest)
1145 return -EMSGSIZE; 1328 goto nla_put_failure;
1146 1329
1147 pgid = DCB_ATTR_VALUE_UNDEFINED; 1330 pgid = DCB_ATTR_VALUE_UNDEFINED;
1148 prio = DCB_ATTR_VALUE_UNDEFINED; 1331 prio = DCB_ATTR_VALUE_UNDEFINED;
@@ -1156,11 +1339,10 @@ static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
1156 ops->getpgtccfgtx(dev, i - DCB_PG_ATTR_TC_0, 1339 ops->getpgtccfgtx(dev, i - DCB_PG_ATTR_TC_0,
1157 &prio, &pgid, &tc_pct, &up_map); 1340 &prio, &pgid, &tc_pct, &up_map);
1158 1341
1159 if (nla_put_u8(skb, DCB_TC_ATTR_PARAM_PGID, pgid) || 1342 NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_PGID, pgid);
1160 nla_put_u8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map) || 1343 NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
1161 nla_put_u8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio) || 1344 NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
1162 nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct)) 1345 NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct);
1163 return -EMSGSIZE;
1164 nla_nest_end(skb, tc_nest); 1346 nla_nest_end(skb, tc_nest);
1165 } 1347 }
1166 1348
@@ -1173,11 +1355,13 @@ static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
1173 else 1355 else
1174 ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0, 1356 ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0,
1175 &tc_pct); 1357 &tc_pct);
1176 if (nla_put_u8(skb, i, tc_pct)) 1358 NLA_PUT_U8(skb, i, tc_pct);
1177 return -EMSGSIZE;
1178 } 1359 }
1179 nla_nest_end(skb, pg); 1360 nla_nest_end(skb, pg);
1180 return 0; 1361 return 0;
1362
1363nla_put_failure:
1364 return -EMSGSIZE;
1181} 1365}
1182 1366
1183static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) 1367static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
@@ -1188,8 +1372,8 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
1188 int dcbx, i, err = -EMSGSIZE; 1372 int dcbx, i, err = -EMSGSIZE;
1189 u8 value; 1373 u8 value;
1190 1374
1191 if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name)) 1375 NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
1192 goto nla_put_failure; 1376
1193 cee = nla_nest_start(skb, DCB_ATTR_CEE); 1377 cee = nla_nest_start(skb, DCB_ATTR_CEE);
1194 if (!cee) 1378 if (!cee)
1195 goto nla_put_failure; 1379 goto nla_put_failure;
@@ -1216,8 +1400,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
1216 1400
1217 for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { 1401 for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
1218 ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value); 1402 ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value);
1219 if (nla_put_u8(skb, i, value)) 1403 NLA_PUT_U8(skb, i, value);
1220 goto nla_put_failure;
1221 } 1404 }
1222 nla_nest_end(skb, pfc_nest); 1405 nla_nest_end(skb, pfc_nest);
1223 } 1406 }
@@ -1229,7 +1412,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
1229 goto dcb_unlock; 1412 goto dcb_unlock;
1230 1413
1231 list_for_each_entry(itr, &dcb_app_list, list) { 1414 list_for_each_entry(itr, &dcb_app_list, list) {
1232 if (itr->ifindex == netdev->ifindex) { 1415 if (strncmp(itr->name, netdev->name, IFNAMSIZ) == 0) {
1233 struct nlattr *app_nest = nla_nest_start(skb, 1416 struct nlattr *app_nest = nla_nest_start(skb,
1234 DCB_ATTR_APP); 1417 DCB_ATTR_APP);
1235 if (!app_nest) 1418 if (!app_nest)
@@ -1270,9 +1453,8 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
1270 1453
1271 for (i = DCB_FEATCFG_ATTR_ALL + 1; i <= DCB_FEATCFG_ATTR_MAX; 1454 for (i = DCB_FEATCFG_ATTR_ALL + 1; i <= DCB_FEATCFG_ATTR_MAX;
1272 i++) 1455 i++)
1273 if (!ops->getfeatcfg(netdev, i, &value) && 1456 if (!ops->getfeatcfg(netdev, i, &value))
1274 nla_put_u8(skb, i, value)) 1457 NLA_PUT_U8(skb, i, value);
1275 goto nla_put_failure;
1276 1458
1277 nla_nest_end(skb, feat); 1459 nla_nest_end(skb, feat);
1278 } 1460 }
@@ -1281,17 +1463,15 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
1281 if (ops->cee_peer_getpg) { 1463 if (ops->cee_peer_getpg) {
1282 struct cee_pg pg; 1464 struct cee_pg pg;
1283 err = ops->cee_peer_getpg(netdev, &pg); 1465 err = ops->cee_peer_getpg(netdev, &pg);
1284 if (!err && 1466 if (!err)
1285 nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg)) 1467 NLA_PUT(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg);
1286 goto nla_put_failure;
1287 } 1468 }
1288 1469
1289 if (ops->cee_peer_getpfc) { 1470 if (ops->cee_peer_getpfc) {
1290 struct cee_pfc pfc; 1471 struct cee_pfc pfc;
1291 err = ops->cee_peer_getpfc(netdev, &pfc); 1472 err = ops->cee_peer_getpfc(netdev, &pfc);
1292 if (!err && 1473 if (!err)
1293 nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc)) 1474 NLA_PUT(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc);
1294 goto nla_put_failure;
1295 } 1475 }
1296 1476
1297 if (ops->peer_getappinfo && ops->peer_getapptable) { 1477 if (ops->peer_getappinfo && ops->peer_getapptable) {
@@ -1319,21 +1499,32 @@ nla_put_failure:
1319} 1499}
1320 1500
1321static int dcbnl_notify(struct net_device *dev, int event, int cmd, 1501static int dcbnl_notify(struct net_device *dev, int event, int cmd,
1322 u32 seq, u32 portid, int dcbx_ver) 1502 u32 seq, u32 pid, int dcbx_ver)
1323{ 1503{
1324 struct net *net = dev_net(dev); 1504 struct net *net = dev_net(dev);
1325 struct sk_buff *skb; 1505 struct sk_buff *skb;
1326 struct nlmsghdr *nlh; 1506 struct nlmsghdr *nlh;
1507 struct dcbmsg *dcb;
1327 const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops; 1508 const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
1328 int err; 1509 int err;
1329 1510
1330 if (!ops) 1511 if (!ops)
1331 return -EOPNOTSUPP; 1512 return -EOPNOTSUPP;
1332 1513
1333 skb = dcbnl_newmsg(event, cmd, portid, seq, 0, &nlh); 1514 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1334 if (!skb) 1515 if (!skb)
1335 return -ENOBUFS; 1516 return -ENOBUFS;
1336 1517
1518 nlh = nlmsg_put(skb, pid, 0, event, sizeof(*dcb), 0);
1519 if (nlh == NULL) {
1520 nlmsg_free(skb);
1521 return -EMSGSIZE;
1522 }
1523
1524 dcb = NLMSG_DATA(nlh);
1525 dcb->dcb_family = AF_UNSPEC;
1526 dcb->cmd = cmd;
1527
1337 if (dcbx_ver == DCB_CAP_DCBX_VER_IEEE) 1528 if (dcbx_ver == DCB_CAP_DCBX_VER_IEEE)
1338 err = dcbnl_ieee_fill(skb, dev); 1529 err = dcbnl_ieee_fill(skb, dev);
1339 else 1530 else
@@ -1341,7 +1532,8 @@ static int dcbnl_notify(struct net_device *dev, int event, int cmd,
1341 1532
1342 if (err < 0) { 1533 if (err < 0) {
1343 /* Report error to broadcast listeners */ 1534 /* Report error to broadcast listeners */
1344 nlmsg_free(skb); 1535 nlmsg_cancel(skb, nlh);
1536 kfree_skb(skb);
1345 rtnl_set_sk_err(net, RTNLGRP_DCB, err); 1537 rtnl_set_sk_err(net, RTNLGRP_DCB, err);
1346 } else { 1538 } else {
1347 /* End nlmsg and notify broadcast listeners */ 1539 /* End nlmsg and notify broadcast listeners */
@@ -1353,16 +1545,16 @@ static int dcbnl_notify(struct net_device *dev, int event, int cmd,
1353} 1545}
1354 1546
1355int dcbnl_ieee_notify(struct net_device *dev, int event, int cmd, 1547int dcbnl_ieee_notify(struct net_device *dev, int event, int cmd,
1356 u32 seq, u32 portid) 1548 u32 seq, u32 pid)
1357{ 1549{
1358 return dcbnl_notify(dev, event, cmd, seq, portid, DCB_CAP_DCBX_VER_IEEE); 1550 return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_IEEE);
1359} 1551}
1360EXPORT_SYMBOL(dcbnl_ieee_notify); 1552EXPORT_SYMBOL(dcbnl_ieee_notify);
1361 1553
1362int dcbnl_cee_notify(struct net_device *dev, int event, int cmd, 1554int dcbnl_cee_notify(struct net_device *dev, int event, int cmd,
1363 u32 seq, u32 portid) 1555 u32 seq, u32 pid)
1364{ 1556{
1365 return dcbnl_notify(dev, event, cmd, seq, portid, DCB_CAP_DCBX_VER_CEE); 1557 return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_CEE);
1366} 1558}
1367EXPORT_SYMBOL(dcbnl_cee_notify); 1559EXPORT_SYMBOL(dcbnl_cee_notify);
1368 1560
@@ -1371,15 +1563,15 @@ EXPORT_SYMBOL(dcbnl_cee_notify);
1371 * No attempt is made to reconcile the case where only part of the 1563 * No attempt is made to reconcile the case where only part of the
1372 * cmd can be completed. 1564 * cmd can be completed.
1373 */ 1565 */
1374static int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh, 1566static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
1375 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1567 u32 pid, u32 seq, u16 flags)
1376{ 1568{
1377 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1569 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1378 struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1]; 1570 struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
1379 int err; 1571 int err = -EOPNOTSUPP;
1380 1572
1381 if (!ops) 1573 if (!ops)
1382 return -EOPNOTSUPP; 1574 return err;
1383 1575
1384 if (!tb[DCB_ATTR_IEEE]) 1576 if (!tb[DCB_ATTR_IEEE])
1385 return -EINVAL; 1577 return -EINVAL;
@@ -1396,14 +1588,6 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh,
1396 goto err; 1588 goto err;
1397 } 1589 }
1398 1590
1399 if (ieee[DCB_ATTR_IEEE_MAXRATE] && ops->ieee_setmaxrate) {
1400 struct ieee_maxrate *maxrate =
1401 nla_data(ieee[DCB_ATTR_IEEE_MAXRATE]);
1402 err = ops->ieee_setmaxrate(netdev, maxrate);
1403 if (err)
1404 goto err;
1405 }
1406
1407 if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) { 1591 if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
1408 struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]); 1592 struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
1409 err = ops->ieee_setpfc(netdev, pfc); 1593 err = ops->ieee_setpfc(netdev, pfc);
@@ -1430,28 +1614,58 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh,
1430 } 1614 }
1431 1615
1432err: 1616err:
1433 err = nla_put_u8(skb, DCB_ATTR_IEEE, err); 1617 dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
1618 pid, seq, flags);
1434 dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0); 1619 dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0);
1435 return err; 1620 return err;
1436} 1621}
1437 1622
1438static int dcbnl_ieee_get(struct net_device *netdev, struct nlmsghdr *nlh, 1623static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
1439 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1624 u32 pid, u32 seq, u16 flags)
1440{ 1625{
1626 struct net *net = dev_net(netdev);
1627 struct sk_buff *skb;
1628 struct nlmsghdr *nlh;
1629 struct dcbmsg *dcb;
1441 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1630 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1631 int err;
1442 1632
1443 if (!ops) 1633 if (!ops)
1444 return -EOPNOTSUPP; 1634 return -EOPNOTSUPP;
1445 1635
1446 return dcbnl_ieee_fill(skb, netdev); 1636 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1637 if (!skb)
1638 return -ENOBUFS;
1639
1640 nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1641 if (nlh == NULL) {
1642 nlmsg_free(skb);
1643 return -EMSGSIZE;
1644 }
1645
1646 dcb = NLMSG_DATA(nlh);
1647 dcb->dcb_family = AF_UNSPEC;
1648 dcb->cmd = DCB_CMD_IEEE_GET;
1649
1650 err = dcbnl_ieee_fill(skb, netdev);
1651
1652 if (err < 0) {
1653 nlmsg_cancel(skb, nlh);
1654 kfree_skb(skb);
1655 } else {
1656 nlmsg_end(skb, nlh);
1657 err = rtnl_unicast(skb, net, pid);
1658 }
1659
1660 return err;
1447} 1661}
1448 1662
1449static int dcbnl_ieee_del(struct net_device *netdev, struct nlmsghdr *nlh, 1663static int dcbnl_ieee_del(struct net_device *netdev, struct nlattr **tb,
1450 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1664 u32 pid, u32 seq, u16 flags)
1451{ 1665{
1452 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1666 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1453 struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1]; 1667 struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
1454 int err; 1668 int err = -EOPNOTSUPP;
1455 1669
1456 if (!ops) 1670 if (!ops)
1457 return -EOPNOTSUPP; 1671 return -EOPNOTSUPP;
@@ -1484,26 +1698,32 @@ static int dcbnl_ieee_del(struct net_device *netdev, struct nlmsghdr *nlh,
1484 } 1698 }
1485 1699
1486err: 1700err:
1487 err = nla_put_u8(skb, DCB_ATTR_IEEE, err); 1701 dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_DEL, DCB_ATTR_IEEE,
1702 pid, seq, flags);
1488 dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0); 1703 dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0);
1489 return err; 1704 return err;
1490} 1705}
1491 1706
1492 1707
1493/* DCBX configuration */ 1708/* DCBX configuration */
1494static int dcbnl_getdcbx(struct net_device *netdev, struct nlmsghdr *nlh, 1709static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
1495 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1710 u32 pid, u32 seq, u16 flags)
1496{ 1711{
1712 int ret;
1713
1497 if (!netdev->dcbnl_ops->getdcbx) 1714 if (!netdev->dcbnl_ops->getdcbx)
1498 return -EOPNOTSUPP; 1715 return -EOPNOTSUPP;
1499 1716
1500 return nla_put_u8(skb, DCB_ATTR_DCBX, 1717 ret = dcbnl_reply(netdev->dcbnl_ops->getdcbx(netdev), RTM_GETDCB,
1501 netdev->dcbnl_ops->getdcbx(netdev)); 1718 DCB_CMD_GDCBX, DCB_ATTR_DCBX, pid, seq, flags);
1719
1720 return ret;
1502} 1721}
1503 1722
1504static int dcbnl_setdcbx(struct net_device *netdev, struct nlmsghdr *nlh, 1723static int dcbnl_setdcbx(struct net_device *netdev, struct nlattr **tb,
1505 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1724 u32 pid, u32 seq, u16 flags)
1506{ 1725{
1726 int ret;
1507 u8 value; 1727 u8 value;
1508 1728
1509 if (!netdev->dcbnl_ops->setdcbx) 1729 if (!netdev->dcbnl_ops->setdcbx)
@@ -1514,13 +1734,19 @@ static int dcbnl_setdcbx(struct net_device *netdev, struct nlmsghdr *nlh,
1514 1734
1515 value = nla_get_u8(tb[DCB_ATTR_DCBX]); 1735 value = nla_get_u8(tb[DCB_ATTR_DCBX]);
1516 1736
1517 return nla_put_u8(skb, DCB_ATTR_DCBX, 1737 ret = dcbnl_reply(netdev->dcbnl_ops->setdcbx(netdev, value),
1518 netdev->dcbnl_ops->setdcbx(netdev, value)); 1738 RTM_SETDCB, DCB_CMD_SDCBX, DCB_ATTR_DCBX,
1739 pid, seq, flags);
1740
1741 return ret;
1519} 1742}
1520 1743
1521static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh, 1744static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb,
1522 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1745 u32 pid, u32 seq, u16 flags)
1523{ 1746{
1747 struct sk_buff *dcbnl_skb;
1748 struct nlmsghdr *nlh;
1749 struct dcbmsg *dcb;
1524 struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest; 1750 struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest;
1525 u8 value; 1751 u8 value;
1526 int ret, i; 1752 int ret, i;
@@ -1535,11 +1761,25 @@ static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh,
1535 ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG], 1761 ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG],
1536 dcbnl_featcfg_nest); 1762 dcbnl_featcfg_nest);
1537 if (ret) 1763 if (ret)
1538 return ret; 1764 goto err_out;
1539 1765
1540 nest = nla_nest_start(skb, DCB_ATTR_FEATCFG); 1766 dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1541 if (!nest) 1767 if (!dcbnl_skb) {
1542 return -EMSGSIZE; 1768 ret = -ENOBUFS;
1769 goto err_out;
1770 }
1771
1772 nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1773
1774 dcb = NLMSG_DATA(nlh);
1775 dcb->dcb_family = AF_UNSPEC;
1776 dcb->cmd = DCB_CMD_GFEATCFG;
1777
1778 nest = nla_nest_start(dcbnl_skb, DCB_ATTR_FEATCFG);
1779 if (!nest) {
1780 ret = -EMSGSIZE;
1781 goto nla_put_failure;
1782 }
1543 1783
1544 if (data[DCB_FEATCFG_ATTR_ALL]) 1784 if (data[DCB_FEATCFG_ATTR_ALL])
1545 getall = 1; 1785 getall = 1;
@@ -1550,21 +1790,28 @@ static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh,
1550 1790
1551 ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value); 1791 ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value);
1552 if (!ret) 1792 if (!ret)
1553 ret = nla_put_u8(skb, i, value); 1793 ret = nla_put_u8(dcbnl_skb, i, value);
1554 1794
1555 if (ret) { 1795 if (ret) {
1556 nla_nest_cancel(skb, nest); 1796 nla_nest_cancel(dcbnl_skb, nest);
1557 goto nla_put_failure; 1797 goto nla_put_failure;
1558 } 1798 }
1559 } 1799 }
1560 nla_nest_end(skb, nest); 1800 nla_nest_end(dcbnl_skb, nest);
1561 1801
1802 nlmsg_end(dcbnl_skb, nlh);
1803
1804 return rtnl_unicast(dcbnl_skb, &init_net, pid);
1562nla_put_failure: 1805nla_put_failure:
1806 nlmsg_cancel(dcbnl_skb, nlh);
1807nlmsg_failure:
1808 kfree_skb(dcbnl_skb);
1809err_out:
1563 return ret; 1810 return ret;
1564} 1811}
1565 1812
1566static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh, 1813static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlattr **tb,
1567 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1814 u32 pid, u32 seq, u16 flags)
1568{ 1815{
1569 struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1]; 1816 struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1];
1570 int ret, i; 1817 int ret, i;
@@ -1594,154 +1841,199 @@ static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh,
1594 goto err; 1841 goto err;
1595 } 1842 }
1596err: 1843err:
1597 ret = nla_put_u8(skb, DCB_ATTR_FEATCFG, ret); 1844 dcbnl_reply(ret, RTM_SETDCB, DCB_CMD_SFEATCFG, DCB_ATTR_FEATCFG,
1845 pid, seq, flags);
1598 1846
1599 return ret; 1847 return ret;
1600} 1848}
1601 1849
1602/* Handle CEE DCBX GET commands. */ 1850/* Handle CEE DCBX GET commands. */
1603static int dcbnl_cee_get(struct net_device *netdev, struct nlmsghdr *nlh, 1851static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
1604 u32 seq, struct nlattr **tb, struct sk_buff *skb) 1852 u32 pid, u32 seq, u16 flags)
1605{ 1853{
1854 struct net *net = dev_net(netdev);
1855 struct sk_buff *skb;
1856 struct nlmsghdr *nlh;
1857 struct dcbmsg *dcb;
1606 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1858 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1859 int err;
1607 1860
1608 if (!ops) 1861 if (!ops)
1609 return -EOPNOTSUPP; 1862 return -EOPNOTSUPP;
1610 1863
1611 return dcbnl_cee_fill(skb, netdev); 1864 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1612} 1865 if (!skb)
1866 return -ENOBUFS;
1613 1867
1614struct reply_func { 1868 nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1615 /* reply netlink message type */ 1869 if (nlh == NULL) {
1616 int type; 1870 nlmsg_free(skb);
1871 return -EMSGSIZE;
1872 }
1617 1873
1618 /* function to fill message contents */ 1874 dcb = NLMSG_DATA(nlh);
1619 int (*cb)(struct net_device *, struct nlmsghdr *, u32, 1875 dcb->dcb_family = AF_UNSPEC;
1620 struct nlattr **, struct sk_buff *); 1876 dcb->cmd = DCB_CMD_CEE_GET;
1621};
1622 1877
1623static const struct reply_func reply_funcs[DCB_CMD_MAX+1] = { 1878 err = dcbnl_cee_fill(skb, netdev);
1624 [DCB_CMD_GSTATE] = { RTM_GETDCB, dcbnl_getstate }, 1879
1625 [DCB_CMD_SSTATE] = { RTM_SETDCB, dcbnl_setstate }, 1880 if (err < 0) {
1626 [DCB_CMD_PFC_GCFG] = { RTM_GETDCB, dcbnl_getpfccfg }, 1881 nlmsg_cancel(skb, nlh);
1627 [DCB_CMD_PFC_SCFG] = { RTM_SETDCB, dcbnl_setpfccfg }, 1882 nlmsg_free(skb);
1628 [DCB_CMD_GPERM_HWADDR] = { RTM_GETDCB, dcbnl_getperm_hwaddr }, 1883 } else {
1629 [DCB_CMD_GCAP] = { RTM_GETDCB, dcbnl_getcap }, 1884 nlmsg_end(skb, nlh);
1630 [DCB_CMD_GNUMTCS] = { RTM_GETDCB, dcbnl_getnumtcs }, 1885 err = rtnl_unicast(skb, net, pid);
1631 [DCB_CMD_SNUMTCS] = { RTM_SETDCB, dcbnl_setnumtcs }, 1886 }
1632 [DCB_CMD_PFC_GSTATE] = { RTM_GETDCB, dcbnl_getpfcstate }, 1887 return err;
1633 [DCB_CMD_PFC_SSTATE] = { RTM_SETDCB, dcbnl_setpfcstate }, 1888}
1634 [DCB_CMD_GAPP] = { RTM_GETDCB, dcbnl_getapp },
1635 [DCB_CMD_SAPP] = { RTM_SETDCB, dcbnl_setapp },
1636 [DCB_CMD_PGTX_GCFG] = { RTM_GETDCB, dcbnl_pgtx_getcfg },
1637 [DCB_CMD_PGTX_SCFG] = { RTM_SETDCB, dcbnl_pgtx_setcfg },
1638 [DCB_CMD_PGRX_GCFG] = { RTM_GETDCB, dcbnl_pgrx_getcfg },
1639 [DCB_CMD_PGRX_SCFG] = { RTM_SETDCB, dcbnl_pgrx_setcfg },
1640 [DCB_CMD_SET_ALL] = { RTM_SETDCB, dcbnl_setall },
1641 [DCB_CMD_BCN_GCFG] = { RTM_GETDCB, dcbnl_bcn_getcfg },
1642 [DCB_CMD_BCN_SCFG] = { RTM_SETDCB, dcbnl_bcn_setcfg },
1643 [DCB_CMD_IEEE_GET] = { RTM_GETDCB, dcbnl_ieee_get },
1644 [DCB_CMD_IEEE_SET] = { RTM_SETDCB, dcbnl_ieee_set },
1645 [DCB_CMD_IEEE_DEL] = { RTM_SETDCB, dcbnl_ieee_del },
1646 [DCB_CMD_GDCBX] = { RTM_GETDCB, dcbnl_getdcbx },
1647 [DCB_CMD_SDCBX] = { RTM_SETDCB, dcbnl_setdcbx },
1648 [DCB_CMD_GFEATCFG] = { RTM_GETDCB, dcbnl_getfeatcfg },
1649 [DCB_CMD_SFEATCFG] = { RTM_SETDCB, dcbnl_setfeatcfg },
1650 [DCB_CMD_CEE_GET] = { RTM_GETDCB, dcbnl_cee_get },
1651};
1652 1889
1653static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 1890static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1654{ 1891{
1655 struct net *net = sock_net(skb->sk); 1892 struct net *net = sock_net(skb->sk);
1656 struct net_device *netdev; 1893 struct net_device *netdev;
1657 struct dcbmsg *dcb = nlmsg_data(nlh); 1894 struct dcbmsg *dcb = (struct dcbmsg *)NLMSG_DATA(nlh);
1658 struct nlattr *tb[DCB_ATTR_MAX + 1]; 1895 struct nlattr *tb[DCB_ATTR_MAX + 1];
1659 u32 portid = skb ? NETLINK_CB(skb).portid : 0; 1896 u32 pid = skb ? NETLINK_CB(skb).pid : 0;
1660 int ret = -EINVAL; 1897 int ret = -EINVAL;
1661 struct sk_buff *reply_skb;
1662 struct nlmsghdr *reply_nlh = NULL;
1663 const struct reply_func *fn;
1664 1898
1665 if ((nlh->nlmsg_type == RTM_SETDCB) && !capable(CAP_NET_ADMIN)) 1899 if (!net_eq(net, &init_net))
1666 return -EPERM; 1900 return -EINVAL;
1667 1901
1668 ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX, 1902 ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
1669 dcbnl_rtnl_policy); 1903 dcbnl_rtnl_policy);
1670 if (ret < 0) 1904 if (ret < 0)
1671 return ret; 1905 return ret;
1672 1906
1673 if (dcb->cmd > DCB_CMD_MAX)
1674 return -EINVAL;
1675
1676 /* check if a reply function has been defined for the command */
1677 fn = &reply_funcs[dcb->cmd];
1678 if (!fn->cb)
1679 return -EOPNOTSUPP;
1680
1681 if (!tb[DCB_ATTR_IFNAME]) 1907 if (!tb[DCB_ATTR_IFNAME])
1682 return -EINVAL; 1908 return -EINVAL;
1683 1909
1684 netdev = dev_get_by_name(net, nla_data(tb[DCB_ATTR_IFNAME])); 1910 netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME]));
1685 if (!netdev) 1911 if (!netdev)
1686 return -ENODEV; 1912 return -EINVAL;
1687 1913
1688 if (!netdev->dcbnl_ops) { 1914 if (!netdev->dcbnl_ops)
1689 ret = -EOPNOTSUPP; 1915 goto errout;
1690 goto out;
1691 }
1692 1916
1693 reply_skb = dcbnl_newmsg(fn->type, dcb->cmd, portid, nlh->nlmsg_seq, 1917 switch (dcb->cmd) {
1694 nlh->nlmsg_flags, &reply_nlh); 1918 case DCB_CMD_GSTATE:
1695 if (!reply_skb) { 1919 ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq,
1696 ret = -ENOBUFS; 1920 nlh->nlmsg_flags);
1921 goto out;
1922 case DCB_CMD_PFC_GCFG:
1923 ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
1924 nlh->nlmsg_flags);
1925 goto out;
1926 case DCB_CMD_GPERM_HWADDR:
1927 ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq,
1928 nlh->nlmsg_flags);
1929 goto out;
1930 case DCB_CMD_PGTX_GCFG:
1931 ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
1932 nlh->nlmsg_flags);
1933 goto out;
1934 case DCB_CMD_PGRX_GCFG:
1935 ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
1936 nlh->nlmsg_flags);
1937 goto out;
1938 case DCB_CMD_BCN_GCFG:
1939 ret = dcbnl_bcn_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
1940 nlh->nlmsg_flags);
1941 goto out;
1942 case DCB_CMD_SSTATE:
1943 ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq,
1944 nlh->nlmsg_flags);
1945 goto out;
1946 case DCB_CMD_PFC_SCFG:
1947 ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
1948 nlh->nlmsg_flags);
1697 goto out; 1949 goto out;
1698 }
1699 1950
1700 ret = fn->cb(netdev, nlh, nlh->nlmsg_seq, tb, reply_skb); 1951 case DCB_CMD_SET_ALL:
1701 if (ret < 0) { 1952 ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq,
1702 nlmsg_free(reply_skb); 1953 nlh->nlmsg_flags);
1954 goto out;
1955 case DCB_CMD_PGTX_SCFG:
1956 ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
1957 nlh->nlmsg_flags);
1958 goto out;
1959 case DCB_CMD_PGRX_SCFG:
1960 ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
1961 nlh->nlmsg_flags);
1962 goto out;
1963 case DCB_CMD_GCAP:
1964 ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq,
1965 nlh->nlmsg_flags);
1966 goto out;
1967 case DCB_CMD_GNUMTCS:
1968 ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
1969 nlh->nlmsg_flags);
1970 goto out;
1971 case DCB_CMD_SNUMTCS:
1972 ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
1973 nlh->nlmsg_flags);
1974 goto out;
1975 case DCB_CMD_PFC_GSTATE:
1976 ret = dcbnl_getpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
1977 nlh->nlmsg_flags);
1978 goto out;
1979 case DCB_CMD_PFC_SSTATE:
1980 ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
1981 nlh->nlmsg_flags);
1982 goto out;
1983 case DCB_CMD_BCN_SCFG:
1984 ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
1985 nlh->nlmsg_flags);
1986 goto out;
1987 case DCB_CMD_GAPP:
1988 ret = dcbnl_getapp(netdev, tb, pid, nlh->nlmsg_seq,
1989 nlh->nlmsg_flags);
1990 goto out;
1991 case DCB_CMD_SAPP:
1992 ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq,
1993 nlh->nlmsg_flags);
1994 goto out;
1995 case DCB_CMD_IEEE_SET:
1996 ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq,
1997 nlh->nlmsg_flags);
1998 goto out;
1999 case DCB_CMD_IEEE_GET:
2000 ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq,
2001 nlh->nlmsg_flags);
2002 goto out;
2003 case DCB_CMD_IEEE_DEL:
2004 ret = dcbnl_ieee_del(netdev, tb, pid, nlh->nlmsg_seq,
2005 nlh->nlmsg_flags);
2006 goto out;
2007 case DCB_CMD_GDCBX:
2008 ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq,
2009 nlh->nlmsg_flags);
2010 goto out;
2011 case DCB_CMD_SDCBX:
2012 ret = dcbnl_setdcbx(netdev, tb, pid, nlh->nlmsg_seq,
2013 nlh->nlmsg_flags);
2014 goto out;
2015 case DCB_CMD_GFEATCFG:
2016 ret = dcbnl_getfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
2017 nlh->nlmsg_flags);
1703 goto out; 2018 goto out;
2019 case DCB_CMD_SFEATCFG:
2020 ret = dcbnl_setfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
2021 nlh->nlmsg_flags);
2022 goto out;
2023 case DCB_CMD_CEE_GET:
2024 ret = dcbnl_cee_get(netdev, tb, pid, nlh->nlmsg_seq,
2025 nlh->nlmsg_flags);
2026 goto out;
2027 default:
2028 goto errout;
1704 } 2029 }
1705 2030errout:
1706 nlmsg_end(reply_skb, reply_nlh); 2031 ret = -EINVAL;
1707
1708 ret = rtnl_unicast(reply_skb, net, portid);
1709out: 2032out:
1710 dev_put(netdev); 2033 dev_put(netdev);
1711 return ret; 2034 return ret;
1712} 2035}
1713 2036
1714static struct dcb_app_type *dcb_app_lookup(const struct dcb_app *app,
1715 int ifindex, int prio)
1716{
1717 struct dcb_app_type *itr;
1718
1719 list_for_each_entry(itr, &dcb_app_list, list) {
1720 if (itr->app.selector == app->selector &&
1721 itr->app.protocol == app->protocol &&
1722 itr->ifindex == ifindex &&
1723 (!prio || itr->app.priority == prio))
1724 return itr;
1725 }
1726
1727 return NULL;
1728}
1729
1730static int dcb_app_add(const struct dcb_app *app, int ifindex)
1731{
1732 struct dcb_app_type *entry;
1733
1734 entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
1735 if (!entry)
1736 return -ENOMEM;
1737
1738 memcpy(&entry->app, app, sizeof(*app));
1739 entry->ifindex = ifindex;
1740 list_add(&entry->list, &dcb_app_list);
1741
1742 return 0;
1743}
1744
1745/** 2037/**
1746 * dcb_getapp - retrieve the DCBX application user priority 2038 * dcb_getapp - retrieve the DCBX application user priority
1747 * 2039 *
@@ -1755,8 +2047,14 @@ u8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
1755 u8 prio = 0; 2047 u8 prio = 0;
1756 2048
1757 spin_lock(&dcb_lock); 2049 spin_lock(&dcb_lock);
1758 if ((itr = dcb_app_lookup(app, dev->ifindex, 0))) 2050 list_for_each_entry(itr, &dcb_app_list, list) {
1759 prio = itr->app.priority; 2051 if (itr->app.selector == app->selector &&
2052 itr->app.protocol == app->protocol &&
2053 (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
2054 prio = itr->app.priority;
2055 break;
2056 }
2057 }
1760 spin_unlock(&dcb_lock); 2058 spin_unlock(&dcb_lock);
1761 2059
1762 return prio; 2060 return prio;
@@ -1774,32 +2072,42 @@ int dcb_setapp(struct net_device *dev, struct dcb_app *new)
1774{ 2072{
1775 struct dcb_app_type *itr; 2073 struct dcb_app_type *itr;
1776 struct dcb_app_type event; 2074 struct dcb_app_type event;
1777 int err = 0;
1778 2075
1779 event.ifindex = dev->ifindex; 2076 memcpy(&event.name, dev->name, sizeof(event.name));
1780 memcpy(&event.app, new, sizeof(event.app)); 2077 memcpy(&event.app, new, sizeof(event.app));
1781 if (dev->dcbnl_ops->getdcbx)
1782 event.dcbx = dev->dcbnl_ops->getdcbx(dev);
1783 2078
1784 spin_lock(&dcb_lock); 2079 spin_lock(&dcb_lock);
1785 /* Search for existing match and replace */ 2080 /* Search for existing match and replace */
1786 if ((itr = dcb_app_lookup(new, dev->ifindex, 0))) { 2081 list_for_each_entry(itr, &dcb_app_list, list) {
1787 if (new->priority) 2082 if (itr->app.selector == new->selector &&
1788 itr->app.priority = new->priority; 2083 itr->app.protocol == new->protocol &&
1789 else { 2084 (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
1790 list_del(&itr->list); 2085 if (new->priority)
1791 kfree(itr); 2086 itr->app.priority = new->priority;
2087 else {
2088 list_del(&itr->list);
2089 kfree(itr);
2090 }
2091 goto out;
1792 } 2092 }
1793 goto out;
1794 } 2093 }
1795 /* App type does not exist add new application type */ 2094 /* App type does not exist add new application type */
1796 if (new->priority) 2095 if (new->priority) {
1797 err = dcb_app_add(new, dev->ifindex); 2096 struct dcb_app_type *entry;
2097 entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
2098 if (!entry) {
2099 spin_unlock(&dcb_lock);
2100 return -ENOMEM;
2101 }
2102
2103 memcpy(&entry->app, new, sizeof(*new));
2104 strncpy(entry->name, dev->name, IFNAMSIZ);
2105 list_add(&entry->list, &dcb_app_list);
2106 }
1798out: 2107out:
1799 spin_unlock(&dcb_lock); 2108 spin_unlock(&dcb_lock);
1800 if (!err) 2109 call_dcbevent_notifiers(DCB_APP_EVENT, &event);
1801 call_dcbevent_notifiers(DCB_APP_EVENT, &event); 2110 return 0;
1802 return err;
1803} 2111}
1804EXPORT_SYMBOL(dcb_setapp); 2112EXPORT_SYMBOL(dcb_setapp);
1805 2113
@@ -1816,8 +2124,13 @@ u8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
1816 u8 prio = 0; 2124 u8 prio = 0;
1817 2125
1818 spin_lock(&dcb_lock); 2126 spin_lock(&dcb_lock);
1819 if ((itr = dcb_app_lookup(app, dev->ifindex, 0))) 2127 list_for_each_entry(itr, &dcb_app_list, list) {
1820 prio |= 1 << itr->app.priority; 2128 if (itr->app.selector == app->selector &&
2129 itr->app.protocol == app->protocol &&
2130 (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
2131 prio |= 1 << itr->app.priority;
2132 }
2133 }
1821 spin_unlock(&dcb_lock); 2134 spin_unlock(&dcb_lock);
1822 2135
1823 return prio; 2136 return prio;
@@ -1833,22 +2146,35 @@ EXPORT_SYMBOL(dcb_ieee_getapp_mask);
1833 */ 2146 */
1834int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new) 2147int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
1835{ 2148{
2149 struct dcb_app_type *itr, *entry;
1836 struct dcb_app_type event; 2150 struct dcb_app_type event;
1837 int err = 0; 2151 int err = 0;
1838 2152
1839 event.ifindex = dev->ifindex; 2153 memcpy(&event.name, dev->name, sizeof(event.name));
1840 memcpy(&event.app, new, sizeof(event.app)); 2154 memcpy(&event.app, new, sizeof(event.app));
1841 if (dev->dcbnl_ops->getdcbx)
1842 event.dcbx = dev->dcbnl_ops->getdcbx(dev);
1843 2155
1844 spin_lock(&dcb_lock); 2156 spin_lock(&dcb_lock);
1845 /* Search for existing match and abort if found */ 2157 /* Search for existing match and abort if found */
1846 if (dcb_app_lookup(new, dev->ifindex, new->priority)) { 2158 list_for_each_entry(itr, &dcb_app_list, list) {
1847 err = -EEXIST; 2159 if (itr->app.selector == new->selector &&
2160 itr->app.protocol == new->protocol &&
2161 itr->app.priority == new->priority &&
2162 (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
2163 err = -EEXIST;
2164 goto out;
2165 }
2166 }
2167
2168 /* App entry does not exist add new entry */
2169 entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
2170 if (!entry) {
2171 err = -ENOMEM;
1848 goto out; 2172 goto out;
1849 } 2173 }
1850 2174
1851 err = dcb_app_add(new, dev->ifindex); 2175 memcpy(&entry->app, new, sizeof(*new));
2176 strncpy(entry->name, dev->name, IFNAMSIZ);
2177 list_add(&entry->list, &dcb_app_list);
1852out: 2178out:
1853 spin_unlock(&dcb_lock); 2179 spin_unlock(&dcb_lock);
1854 if (!err) 2180 if (!err)
@@ -1868,19 +2194,24 @@ int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
1868 struct dcb_app_type event; 2194 struct dcb_app_type event;
1869 int err = -ENOENT; 2195 int err = -ENOENT;
1870 2196
1871 event.ifindex = dev->ifindex; 2197 memcpy(&event.name, dev->name, sizeof(event.name));
1872 memcpy(&event.app, del, sizeof(event.app)); 2198 memcpy(&event.app, del, sizeof(event.app));
1873 if (dev->dcbnl_ops->getdcbx)
1874 event.dcbx = dev->dcbnl_ops->getdcbx(dev);
1875 2199
1876 spin_lock(&dcb_lock); 2200 spin_lock(&dcb_lock);
1877 /* Search for existing match and remove it. */ 2201 /* Search for existing match and remove it. */
1878 if ((itr = dcb_app_lookup(del, dev->ifindex, del->priority))) { 2202 list_for_each_entry(itr, &dcb_app_list, list) {
1879 list_del(&itr->list); 2203 if (itr->app.selector == del->selector &&
1880 kfree(itr); 2204 itr->app.protocol == del->protocol &&
1881 err = 0; 2205 itr->app.priority == del->priority &&
2206 (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
2207 list_del(&itr->list);
2208 kfree(itr);
2209 err = 0;
2210 goto out;
2211 }
1882 } 2212 }
1883 2213
2214out:
1884 spin_unlock(&dcb_lock); 2215 spin_unlock(&dcb_lock);
1885 if (!err) 2216 if (!err)
1886 call_dcbevent_notifiers(DCB_APP_EVENT, &event); 2217 call_dcbevent_notifiers(DCB_APP_EVENT, &event);