Commit 859ee3c43812051e21816c6d6d4cc04fb7ce9b2e
Committed by
David S. Miller
1 parent
0eb3aa9bab
Exists in
master
and in
20 other branches
DCB: Add support for DCB BCN
Adds an interface to configure the Backward Congestion Notification (BCN) feature. In a BCN capabale network, congestion notifications from congested points out in the network can cause the end station limit the rate of a given traffic flow. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 5 changed files with 416 additions and 9 deletions Side-by-side Diff
drivers/net/ixgbe/ixgbe_dcb.h
... | ... | @@ -108,7 +108,34 @@ |
108 | 108 | pba_80_48 /* PBA[0-3] each use 80KB, PBA[4-7] each use 48KB */ |
109 | 109 | }; |
110 | 110 | |
111 | +/* | |
112 | + * This structure contains many values encoded as fixed-point | |
113 | + * numbers, meaning that some of bits are dedicated to the | |
114 | + * magnitude and others to the fraction part. In the comments | |
115 | + * this is shown as f=n, where n is the number of fraction bits. | |
116 | + * These fraction bits are always the low-order bits. The size | |
117 | + * of the magnitude is not specified. | |
118 | + */ | |
119 | +struct bcn_config { | |
120 | + u32 rp_admin_mode[MAX_TRAFFIC_CLASS]; /* BCN enabled, per TC */ | |
121 | + u32 bcna_option[2]; /* BCNA Port + MAC Addr */ | |
122 | + u32 rp_w; /* Derivative Weight, f=3 */ | |
123 | + u32 rp_gi; /* Increase Gain, f=12 */ | |
124 | + u32 rp_gd; /* Decrease Gain, f=12 */ | |
125 | + u32 rp_ru; /* Rate Unit */ | |
126 | + u32 rp_alpha; /* Max Decrease Factor, f=12 */ | |
127 | + u32 rp_beta; /* Max Increase Factor, f=12 */ | |
128 | + u32 rp_ri; /* Initial Rate */ | |
129 | + u32 rp_td; /* Drift Interval Timer */ | |
130 | + u32 rp_rd; /* Drift Increase */ | |
131 | + u32 rp_tmax; /* Severe Congestion Backoff Timer Range */ | |
132 | + u32 rp_rmin; /* Severe Congestion Restart Rate */ | |
133 | + u32 rp_wrtt; /* RTT Moving Average Weight */ | |
134 | +}; | |
135 | + | |
111 | 136 | struct ixgbe_dcb_config { |
137 | + struct bcn_config bcn; | |
138 | + | |
112 | 139 | struct tc_configuration tc_config[MAX_TRAFFIC_CLASS]; |
113 | 140 | u8 bw_percentage[2][MAX_BW_GROUP]; /* One each for Tx/Rx */ |
114 | 141 |
drivers/net/ixgbe/ixgbe_dcb_nl.c
... | ... | @@ -34,6 +34,7 @@ |
34 | 34 | #define BIT_PFC 0x02 |
35 | 35 | #define BIT_PG_RX 0x04 |
36 | 36 | #define BIT_PG_TX 0x08 |
37 | +#define BIT_BCN 0x10 | |
37 | 38 | |
38 | 39 | int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg, |
39 | 40 | struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max) |
... | ... | @@ -88,6 +89,23 @@ |
88 | 89 | src_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc; |
89 | 90 | } |
90 | 91 | |
92 | + for (i = DCB_BCN_ATTR_RP_0; i < DCB_BCN_ATTR_RP_ALL; i++) { | |
93 | + dst_dcb_cfg->bcn.rp_admin_mode[i - DCB_BCN_ATTR_RP_0] = | |
94 | + src_dcb_cfg->bcn.rp_admin_mode[i - DCB_BCN_ATTR_RP_0]; | |
95 | + } | |
96 | + dst_dcb_cfg->bcn.rp_alpha = src_dcb_cfg->bcn.rp_alpha; | |
97 | + dst_dcb_cfg->bcn.rp_beta = src_dcb_cfg->bcn.rp_beta; | |
98 | + dst_dcb_cfg->bcn.rp_gd = src_dcb_cfg->bcn.rp_gd; | |
99 | + dst_dcb_cfg->bcn.rp_gi = src_dcb_cfg->bcn.rp_gi; | |
100 | + dst_dcb_cfg->bcn.rp_tmax = src_dcb_cfg->bcn.rp_tmax; | |
101 | + dst_dcb_cfg->bcn.rp_td = src_dcb_cfg->bcn.rp_td; | |
102 | + dst_dcb_cfg->bcn.rp_rmin = src_dcb_cfg->bcn.rp_rmin; | |
103 | + dst_dcb_cfg->bcn.rp_w = src_dcb_cfg->bcn.rp_w; | |
104 | + dst_dcb_cfg->bcn.rp_rd = src_dcb_cfg->bcn.rp_rd; | |
105 | + dst_dcb_cfg->bcn.rp_ru = src_dcb_cfg->bcn.rp_ru; | |
106 | + dst_dcb_cfg->bcn.rp_wrtt = src_dcb_cfg->bcn.rp_wrtt; | |
107 | + dst_dcb_cfg->bcn.rp_ri = src_dcb_cfg->bcn.rp_ri; | |
108 | + | |
91 | 109 | return 0; |
92 | 110 | } |
93 | 111 | |
... | ... | @@ -313,6 +331,7 @@ |
313 | 331 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
314 | 332 | int ret; |
315 | 333 | |
334 | + adapter->dcb_set_bitmap &= ~BIT_BCN; /* no set for BCN */ | |
316 | 335 | if (!adapter->dcb_set_bitmap) |
317 | 336 | return 1; |
318 | 337 | |
... | ... | @@ -417,6 +436,157 @@ |
417 | 436 | return; |
418 | 437 | } |
419 | 438 | |
439 | +static void ixgbe_dcbnl_getbcnrp(struct net_device *netdev, int priority, | |
440 | + u8 *setting) | |
441 | +{ | |
442 | + struct ixgbe_adapter *adapter = netdev_priv(netdev); | |
443 | + | |
444 | + *setting = adapter->dcb_cfg.bcn.rp_admin_mode[priority]; | |
445 | +} | |
446 | + | |
447 | + | |
448 | +static void ixgbe_dcbnl_getbcncfg(struct net_device *netdev, int enum_index, | |
449 | + u32 *setting) | |
450 | +{ | |
451 | + struct ixgbe_adapter *adapter = netdev_priv(netdev); | |
452 | + | |
453 | + switch (enum_index) { | |
454 | + case DCB_BCN_ATTR_ALPHA: | |
455 | + *setting = adapter->dcb_cfg.bcn.rp_alpha; | |
456 | + break; | |
457 | + case DCB_BCN_ATTR_BETA: | |
458 | + *setting = adapter->dcb_cfg.bcn.rp_beta; | |
459 | + break; | |
460 | + case DCB_BCN_ATTR_GD: | |
461 | + *setting = adapter->dcb_cfg.bcn.rp_gd; | |
462 | + break; | |
463 | + case DCB_BCN_ATTR_GI: | |
464 | + *setting = adapter->dcb_cfg.bcn.rp_gi; | |
465 | + break; | |
466 | + case DCB_BCN_ATTR_TMAX: | |
467 | + *setting = adapter->dcb_cfg.bcn.rp_tmax; | |
468 | + break; | |
469 | + case DCB_BCN_ATTR_TD: | |
470 | + *setting = adapter->dcb_cfg.bcn.rp_td; | |
471 | + break; | |
472 | + case DCB_BCN_ATTR_RMIN: | |
473 | + *setting = adapter->dcb_cfg.bcn.rp_rmin; | |
474 | + break; | |
475 | + case DCB_BCN_ATTR_W: | |
476 | + *setting = adapter->dcb_cfg.bcn.rp_w; | |
477 | + break; | |
478 | + case DCB_BCN_ATTR_RD: | |
479 | + *setting = adapter->dcb_cfg.bcn.rp_rd; | |
480 | + break; | |
481 | + case DCB_BCN_ATTR_RU: | |
482 | + *setting = adapter->dcb_cfg.bcn.rp_ru; | |
483 | + break; | |
484 | + case DCB_BCN_ATTR_WRTT: | |
485 | + *setting = adapter->dcb_cfg.bcn.rp_wrtt; | |
486 | + break; | |
487 | + case DCB_BCN_ATTR_RI: | |
488 | + *setting = adapter->dcb_cfg.bcn.rp_ri; | |
489 | + break; | |
490 | + default: | |
491 | + *setting = -1; | |
492 | + } | |
493 | +} | |
494 | + | |
495 | +static void ixgbe_dcbnl_setbcnrp(struct net_device *netdev, int priority, | |
496 | + u8 setting) | |
497 | +{ | |
498 | + struct ixgbe_adapter *adapter = netdev_priv(netdev); | |
499 | + | |
500 | + adapter->temp_dcb_cfg.bcn.rp_admin_mode[priority] = setting; | |
501 | + | |
502 | + if (adapter->temp_dcb_cfg.bcn.rp_admin_mode[priority] != | |
503 | + adapter->dcb_cfg.bcn.rp_admin_mode[priority]) | |
504 | + adapter->dcb_set_bitmap |= BIT_BCN; | |
505 | +} | |
506 | + | |
507 | +static void ixgbe_dcbnl_setbcncfg(struct net_device *netdev, int enum_index, | |
508 | + u32 setting) | |
509 | +{ | |
510 | + struct ixgbe_adapter *adapter = netdev_priv(netdev); | |
511 | + | |
512 | + switch (enum_index) { | |
513 | + case DCB_BCN_ATTR_ALPHA: | |
514 | + adapter->temp_dcb_cfg.bcn.rp_alpha = setting; | |
515 | + if (adapter->temp_dcb_cfg.bcn.rp_alpha != | |
516 | + adapter->dcb_cfg.bcn.rp_alpha) | |
517 | + adapter->dcb_set_bitmap |= BIT_BCN; | |
518 | + break; | |
519 | + case DCB_BCN_ATTR_BETA: | |
520 | + adapter->temp_dcb_cfg.bcn.rp_beta = setting; | |
521 | + if (adapter->temp_dcb_cfg.bcn.rp_beta != | |
522 | + adapter->dcb_cfg.bcn.rp_beta) | |
523 | + adapter->dcb_set_bitmap |= BIT_BCN; | |
524 | + break; | |
525 | + case DCB_BCN_ATTR_GD: | |
526 | + adapter->temp_dcb_cfg.bcn.rp_gd = setting; | |
527 | + if (adapter->temp_dcb_cfg.bcn.rp_gd != | |
528 | + adapter->dcb_cfg.bcn.rp_gd) | |
529 | + adapter->dcb_set_bitmap |= BIT_BCN; | |
530 | + break; | |
531 | + case DCB_BCN_ATTR_GI: | |
532 | + adapter->temp_dcb_cfg.bcn.rp_gi = setting; | |
533 | + if (adapter->temp_dcb_cfg.bcn.rp_gi != | |
534 | + adapter->dcb_cfg.bcn.rp_gi) | |
535 | + adapter->dcb_set_bitmap |= BIT_BCN; | |
536 | + break; | |
537 | + case DCB_BCN_ATTR_TMAX: | |
538 | + adapter->temp_dcb_cfg.bcn.rp_tmax = setting; | |
539 | + if (adapter->temp_dcb_cfg.bcn.rp_tmax != | |
540 | + adapter->dcb_cfg.bcn.rp_tmax) | |
541 | + adapter->dcb_set_bitmap |= BIT_BCN; | |
542 | + break; | |
543 | + case DCB_BCN_ATTR_TD: | |
544 | + adapter->temp_dcb_cfg.bcn.rp_td = setting; | |
545 | + if (adapter->temp_dcb_cfg.bcn.rp_td != | |
546 | + adapter->dcb_cfg.bcn.rp_td) | |
547 | + adapter->dcb_set_bitmap |= BIT_BCN; | |
548 | + break; | |
549 | + case DCB_BCN_ATTR_RMIN: | |
550 | + adapter->temp_dcb_cfg.bcn.rp_rmin = setting; | |
551 | + if (adapter->temp_dcb_cfg.bcn.rp_rmin != | |
552 | + adapter->dcb_cfg.bcn.rp_rmin) | |
553 | + adapter->dcb_set_bitmap |= BIT_BCN; | |
554 | + break; | |
555 | + case DCB_BCN_ATTR_W: | |
556 | + adapter->temp_dcb_cfg.bcn.rp_w = setting; | |
557 | + if (adapter->temp_dcb_cfg.bcn.rp_w != | |
558 | + adapter->dcb_cfg.bcn.rp_w) | |
559 | + adapter->dcb_set_bitmap |= BIT_BCN; | |
560 | + break; | |
561 | + case DCB_BCN_ATTR_RD: | |
562 | + adapter->temp_dcb_cfg.bcn.rp_rd = setting; | |
563 | + if (adapter->temp_dcb_cfg.bcn.rp_rd != | |
564 | + adapter->dcb_cfg.bcn.rp_rd) | |
565 | + adapter->dcb_set_bitmap |= BIT_BCN; | |
566 | + break; | |
567 | + case DCB_BCN_ATTR_RU: | |
568 | + adapter->temp_dcb_cfg.bcn.rp_ru = setting; | |
569 | + if (adapter->temp_dcb_cfg.bcn.rp_ru != | |
570 | + adapter->dcb_cfg.bcn.rp_ru) | |
571 | + adapter->dcb_set_bitmap |= BIT_BCN; | |
572 | + break; | |
573 | + case DCB_BCN_ATTR_WRTT: | |
574 | + adapter->temp_dcb_cfg.bcn.rp_wrtt = setting; | |
575 | + if (adapter->temp_dcb_cfg.bcn.rp_wrtt != | |
576 | + adapter->dcb_cfg.bcn.rp_wrtt) | |
577 | + adapter->dcb_set_bitmap |= BIT_BCN; | |
578 | + break; | |
579 | + case DCB_BCN_ATTR_RI: | |
580 | + adapter->temp_dcb_cfg.bcn.rp_ri = setting; | |
581 | + if (adapter->temp_dcb_cfg.bcn.rp_ri != | |
582 | + adapter->dcb_cfg.bcn.rp_ri) | |
583 | + adapter->dcb_set_bitmap |= BIT_BCN; | |
584 | + break; | |
585 | + default: | |
586 | + break; | |
587 | + } | |
588 | +} | |
589 | + | |
420 | 590 | struct dcbnl_rtnl_ops dcbnl_ops = { |
421 | 591 | .getstate = ixgbe_dcbnl_get_state, |
422 | 592 | .setstate = ixgbe_dcbnl_set_state, |
... | ... | @@ -436,6 +606,10 @@ |
436 | 606 | .getnumtcs = ixgbe_dcbnl_getnumtcs, |
437 | 607 | .setnumtcs = ixgbe_dcbnl_setnumtcs, |
438 | 608 | .getpfcstate = ixgbe_dcbnl_getpfcstate, |
439 | - .setpfcstate = ixgbe_dcbnl_setpfcstate | |
609 | + .setpfcstate = ixgbe_dcbnl_setpfcstate, | |
610 | + .getbcncfg = ixgbe_dcbnl_getbcncfg, | |
611 | + .getbcnrp = ixgbe_dcbnl_getbcnrp, | |
612 | + .setbcncfg = ixgbe_dcbnl_setbcncfg, | |
613 | + .setbcnrp = ixgbe_dcbnl_setbcnrp | |
440 | 614 | }; |
include/linux/dcbnl.h
... | ... | @@ -46,6 +46,8 @@ |
46 | 46 | * @DCB_CMD_GCAP: request the DCB capabilities of the device |
47 | 47 | * @DCB_CMD_GNUMTCS: get the number of traffic classes currently supported |
48 | 48 | * @DCB_CMD_SNUMTCS: set the number of traffic classes |
49 | + * @DCB_CMD_GBCN: set backward congestion notification configuration | |
50 | + * @DCB_CMD_SBCN: get backward congestion notification configration. | |
49 | 51 | */ |
50 | 52 | enum dcbnl_commands { |
51 | 53 | DCB_CMD_UNDEFINED, |
52 | 54 | |
53 | 55 | |
54 | 56 | |
55 | 57 | |
56 | 58 | |
... | ... | @@ -62,18 +64,24 @@ |
62 | 64 | DCB_CMD_PFC_SCFG, |
63 | 65 | |
64 | 66 | DCB_CMD_SET_ALL, |
67 | + | |
65 | 68 | DCB_CMD_GPERM_HWADDR, |
69 | + | |
66 | 70 | DCB_CMD_GCAP, |
71 | + | |
67 | 72 | DCB_CMD_GNUMTCS, |
68 | 73 | DCB_CMD_SNUMTCS, |
74 | + | |
69 | 75 | DCB_CMD_PFC_GSTATE, |
70 | 76 | DCB_CMD_PFC_SSTATE, |
71 | 77 | |
78 | + DCB_CMD_BCN_GCFG, | |
79 | + DCB_CMD_BCN_SCFG, | |
80 | + | |
72 | 81 | __DCB_CMD_ENUM_MAX, |
73 | 82 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, |
74 | 83 | }; |
75 | 84 | |
76 | - | |
77 | 85 | /** |
78 | 86 | * enum dcbnl_attrs - DCB top-level netlink attributes |
79 | 87 | * |
... | ... | @@ -88,6 +96,7 @@ |
88 | 96 | * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED) |
89 | 97 | * @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED) |
90 | 98 | * @DCB_ATTR_NUMTCS: number of traffic classes supported (NLA_NESTED) |
99 | + * @DCB_ATTR_BCN: backward congestion notification configuration (NLA_NESTED) | |
91 | 100 | */ |
92 | 101 | enum dcbnl_attrs { |
93 | 102 | DCB_ATTR_UNDEFINED, |
... | ... | @@ -102,6 +111,7 @@ |
102 | 111 | DCB_ATTR_PERM_HWADDR, |
103 | 112 | DCB_ATTR_CAP, |
104 | 113 | DCB_ATTR_NUMTCS, |
114 | + DCB_ATTR_BCN, | |
105 | 115 | |
106 | 116 | __DCB_ATTR_ENUM_MAX, |
107 | 117 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, |
... | ... | @@ -280,6 +290,38 @@ |
280 | 290 | |
281 | 291 | __DCB_NUMTCS_ATTR_ENUM_MAX, |
282 | 292 | DCB_NUMTCS_ATTR_MAX = __DCB_NUMTCS_ATTR_ENUM_MAX - 1, |
293 | +}; | |
294 | + | |
295 | +enum dcbnl_bcn_attrs{ | |
296 | + DCB_BCN_ATTR_UNDEFINED = 0, | |
297 | + | |
298 | + DCB_BCN_ATTR_RP_0, | |
299 | + DCB_BCN_ATTR_RP_1, | |
300 | + DCB_BCN_ATTR_RP_2, | |
301 | + DCB_BCN_ATTR_RP_3, | |
302 | + DCB_BCN_ATTR_RP_4, | |
303 | + DCB_BCN_ATTR_RP_5, | |
304 | + DCB_BCN_ATTR_RP_6, | |
305 | + DCB_BCN_ATTR_RP_7, | |
306 | + DCB_BCN_ATTR_RP_ALL, | |
307 | + | |
308 | + DCB_BCN_ATTR_ALPHA, | |
309 | + DCB_BCN_ATTR_BETA, | |
310 | + DCB_BCN_ATTR_GD, | |
311 | + DCB_BCN_ATTR_GI, | |
312 | + DCB_BCN_ATTR_TMAX, | |
313 | + DCB_BCN_ATTR_TD, | |
314 | + DCB_BCN_ATTR_RMIN, | |
315 | + DCB_BCN_ATTR_W, | |
316 | + DCB_BCN_ATTR_RD, | |
317 | + DCB_BCN_ATTR_RU, | |
318 | + DCB_BCN_ATTR_WRTT, | |
319 | + DCB_BCN_ATTR_RI, | |
320 | + DCB_BCN_ATTR_C, | |
321 | + DCB_BCN_ATTR_ALL, | |
322 | + | |
323 | + __DCB_BCN_ATTR_ENUM_MAX, | |
324 | + DCB_BCN_ATTR_MAX = __DCB_BCN_ATTR_ENUM_MAX - 1, | |
283 | 325 | }; |
284 | 326 | |
285 | 327 | /** |
include/net/dcbnl.h
... | ... | @@ -44,6 +44,10 @@ |
44 | 44 | u8 (*setnumtcs)(struct net_device *, int, u8); |
45 | 45 | u8 (*getpfcstate)(struct net_device *); |
46 | 46 | void (*setpfcstate)(struct net_device *, u8); |
47 | + void (*getbcncfg)(struct net_device *, int, u32 *); | |
48 | + void (*setbcncfg)(struct net_device *, int, u32); | |
49 | + void (*getbcnrp)(struct net_device *, int, u8 *); | |
50 | + void (*setbcnrp)(struct net_device *, int, u8); | |
47 | 51 | }; |
48 | 52 | |
49 | 53 | #endif /* __NET_DCBNL_H__ */ |
net/dcb/dcbnl.c
... | ... | @@ -55,14 +55,15 @@ |
55 | 55 | |
56 | 56 | /* DCB netlink attributes policy */ |
57 | 57 | static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { |
58 | - [DCB_ATTR_IFNAME] = {.type = NLA_STRING, .len = IFNAMSIZ - 1}, | |
59 | - [DCB_ATTR_STATE] = {.type = NLA_U8}, | |
60 | - [DCB_ATTR_PFC_CFG] = {.type = NLA_NESTED}, | |
61 | - [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED}, | |
62 | - [DCB_ATTR_SET_ALL] = {.type = NLA_U8}, | |
58 | + [DCB_ATTR_IFNAME] = {.type = NLA_NUL_STRING, .len = IFNAMSIZ - 1}, | |
59 | + [DCB_ATTR_STATE] = {.type = NLA_U8}, | |
60 | + [DCB_ATTR_PFC_CFG] = {.type = NLA_NESTED}, | |
61 | + [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED}, | |
62 | + [DCB_ATTR_SET_ALL] = {.type = NLA_U8}, | |
63 | 63 | [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG}, |
64 | - [DCB_ATTR_CAP] = {.type = NLA_NESTED}, | |
65 | - [DCB_ATTR_PFC_STATE] = {.type = NLA_U8}, | |
64 | + [DCB_ATTR_CAP] = {.type = NLA_NESTED}, | |
65 | + [DCB_ATTR_PFC_STATE] = {.type = NLA_U8}, | |
66 | + [DCB_ATTR_BCN] = {.type = NLA_NESTED}, | |
66 | 67 | }; |
67 | 68 | |
68 | 69 | /* DCB priority flow control to User Priority nested attributes */ |
... | ... | @@ -128,6 +129,33 @@ |
128 | 129 | [DCB_NUMTCS_ATTR_PFC] = {.type = NLA_U8}, |
129 | 130 | }; |
130 | 131 | |
132 | +/* DCB BCN nested attributes. */ | |
133 | +static struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = { | |
134 | + [DCB_BCN_ATTR_RP_0] = {.type = NLA_U8}, | |
135 | + [DCB_BCN_ATTR_RP_1] = {.type = NLA_U8}, | |
136 | + [DCB_BCN_ATTR_RP_2] = {.type = NLA_U8}, | |
137 | + [DCB_BCN_ATTR_RP_3] = {.type = NLA_U8}, | |
138 | + [DCB_BCN_ATTR_RP_4] = {.type = NLA_U8}, | |
139 | + [DCB_BCN_ATTR_RP_5] = {.type = NLA_U8}, | |
140 | + [DCB_BCN_ATTR_RP_6] = {.type = NLA_U8}, | |
141 | + [DCB_BCN_ATTR_RP_7] = {.type = NLA_U8}, | |
142 | + [DCB_BCN_ATTR_RP_ALL] = {.type = NLA_FLAG}, | |
143 | + [DCB_BCN_ATTR_ALPHA] = {.type = NLA_U32}, | |
144 | + [DCB_BCN_ATTR_BETA] = {.type = NLA_U32}, | |
145 | + [DCB_BCN_ATTR_GD] = {.type = NLA_U32}, | |
146 | + [DCB_BCN_ATTR_GI] = {.type = NLA_U32}, | |
147 | + [DCB_BCN_ATTR_TMAX] = {.type = NLA_U32}, | |
148 | + [DCB_BCN_ATTR_TD] = {.type = NLA_U32}, | |
149 | + [DCB_BCN_ATTR_RMIN] = {.type = NLA_U32}, | |
150 | + [DCB_BCN_ATTR_W] = {.type = NLA_U32}, | |
151 | + [DCB_BCN_ATTR_RD] = {.type = NLA_U32}, | |
152 | + [DCB_BCN_ATTR_RU] = {.type = NLA_U32}, | |
153 | + [DCB_BCN_ATTR_WRTT] = {.type = NLA_U32}, | |
154 | + [DCB_BCN_ATTR_RI] = {.type = NLA_U32}, | |
155 | + [DCB_BCN_ATTR_C] = {.type = NLA_U32}, | |
156 | + [DCB_BCN_ATTR_ALL] = {.type = NLA_FLAG}, | |
157 | +}; | |
158 | + | |
131 | 159 | /* standard netlink reply call */ |
132 | 160 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, |
133 | 161 | u32 seq, u16 flags) |
... | ... | @@ -843,6 +871,130 @@ |
843 | 871 | return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1); |
844 | 872 | } |
845 | 873 | |
874 | +static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb, | |
875 | + u32 pid, u32 seq, u16 flags) | |
876 | +{ | |
877 | + struct sk_buff *dcbnl_skb; | |
878 | + struct nlmsghdr *nlh; | |
879 | + struct dcbmsg *dcb; | |
880 | + struct nlattr *bcn_nest; | |
881 | + struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1]; | |
882 | + u8 value_byte; | |
883 | + u32 value_integer; | |
884 | + int ret = -EINVAL; | |
885 | + bool getall = false; | |
886 | + int i; | |
887 | + | |
888 | + if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->getbcnrp || | |
889 | + !netdev->dcbnl_ops->getbcncfg) | |
890 | + return ret; | |
891 | + | |
892 | + ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX, | |
893 | + tb[DCB_ATTR_BCN], dcbnl_bcn_nest); | |
894 | + | |
895 | + if (ret) | |
896 | + goto err_out; | |
897 | + | |
898 | + dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | |
899 | + if (!dcbnl_skb) | |
900 | + goto err_out; | |
901 | + | |
902 | + nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); | |
903 | + | |
904 | + dcb = NLMSG_DATA(nlh); | |
905 | + dcb->dcb_family = AF_UNSPEC; | |
906 | + dcb->cmd = DCB_CMD_BCN_GCFG; | |
907 | + | |
908 | + bcn_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_BCN); | |
909 | + if (!bcn_nest) | |
910 | + goto err; | |
911 | + | |
912 | + if (bcn_tb[DCB_BCN_ATTR_ALL]) | |
913 | + getall = true; | |
914 | + | |
915 | + for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) { | |
916 | + if (!getall && !bcn_tb[i]) | |
917 | + continue; | |
918 | + | |
919 | + netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0, | |
920 | + &value_byte); | |
921 | + ret = nla_put_u8(dcbnl_skb, i, value_byte); | |
922 | + if (ret) | |
923 | + goto err_bcn; | |
924 | + } | |
925 | + | |
926 | + for (i = DCB_BCN_ATTR_ALPHA; i <= DCB_BCN_ATTR_RI; i++) { | |
927 | + if (!getall && !bcn_tb[i]) | |
928 | + continue; | |
929 | + | |
930 | + netdev->dcbnl_ops->getbcncfg(netdev, i, | |
931 | + &value_integer); | |
932 | + ret = nla_put_u32(dcbnl_skb, i, value_integer); | |
933 | + if (ret) | |
934 | + goto err_bcn; | |
935 | + } | |
936 | + | |
937 | + nla_nest_end(dcbnl_skb, bcn_nest); | |
938 | + | |
939 | + nlmsg_end(dcbnl_skb, nlh); | |
940 | + | |
941 | + ret = rtnl_unicast(dcbnl_skb, &init_net, pid); | |
942 | + if (ret) | |
943 | + goto err; | |
944 | + | |
945 | + return 0; | |
946 | + | |
947 | +err_bcn: | |
948 | + nla_nest_cancel(dcbnl_skb, bcn_nest); | |
949 | +nlmsg_failure: | |
950 | +err: | |
951 | + kfree(dcbnl_skb); | |
952 | +err_out: | |
953 | + ret = -EINVAL; | |
954 | + return ret; | |
955 | +} | |
956 | + | |
957 | +static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlattr **tb, | |
958 | + u32 pid, u32 seq, u16 flags) | |
959 | +{ | |
960 | + struct nlattr *data[DCB_BCN_ATTR_MAX + 1]; | |
961 | + int i; | |
962 | + int ret = -EINVAL; | |
963 | + u8 value_byte; | |
964 | + u32 value_int; | |
965 | + | |
966 | + if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg | |
967 | + || !netdev->dcbnl_ops->setbcnrp) | |
968 | + return ret; | |
969 | + | |
970 | + ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX, | |
971 | + tb[DCB_ATTR_BCN], | |
972 | + dcbnl_pfc_up_nest); | |
973 | + if (ret) | |
974 | + goto err; | |
975 | + | |
976 | + for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) { | |
977 | + if (data[i] == NULL) | |
978 | + continue; | |
979 | + value_byte = nla_get_u8(data[i]); | |
980 | + netdev->dcbnl_ops->setbcnrp(netdev, | |
981 | + data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte); | |
982 | + } | |
983 | + | |
984 | + for (i = DCB_BCN_ATTR_ALPHA; i <= DCB_BCN_ATTR_RI; i++) { | |
985 | + if (data[i] == NULL) | |
986 | + continue; | |
987 | + value_int = nla_get_u32(data[i]); | |
988 | + netdev->dcbnl_ops->setbcncfg(netdev, | |
989 | + i, value_int); | |
990 | + } | |
991 | + | |
992 | + ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_BCN_SCFG, DCB_ATTR_BCN, | |
993 | + pid, seq, flags); | |
994 | +err: | |
995 | + return ret; | |
996 | +} | |
997 | + | |
846 | 998 | static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
847 | 999 | { |
848 | 1000 | struct net *net = sock_net(skb->sk); |
... | ... | @@ -891,6 +1043,10 @@ |
891 | 1043 | ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq, |
892 | 1044 | nlh->nlmsg_flags); |
893 | 1045 | goto out; |
1046 | + case DCB_CMD_BCN_GCFG: | |
1047 | + ret = dcbnl_bcn_getcfg(netdev, tb, pid, nlh->nlmsg_seq, | |
1048 | + nlh->nlmsg_flags); | |
1049 | + goto out; | |
894 | 1050 | case DCB_CMD_SSTATE: |
895 | 1051 | ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq, |
896 | 1052 | nlh->nlmsg_flags); |
... | ... | @@ -931,6 +1087,10 @@ |
931 | 1087 | case DCB_CMD_PFC_SSTATE: |
932 | 1088 | ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq, |
933 | 1089 | nlh->nlmsg_flags); |
1090 | + goto out; | |
1091 | + case DCB_CMD_BCN_SCFG: | |
1092 | + ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq, | |
1093 | + nlh->nlmsg_flags); | |
934 | 1094 | goto out; |
935 | 1095 | default: |
936 | 1096 | goto errout; |