diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2008-11-21 00:10:23 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-21 00:10:23 -0500 |
commit | 859ee3c43812051e21816c6d6d4cc04fb7ce9b2e (patch) | |
tree | ef3c3717038b5d4600065550f422fd8abf72de35 | |
parent | 0eb3aa9bab20217fb42244ccdcb5bf8a002f504c (diff) |
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>
-rw-r--r-- | drivers/net/ixgbe/ixgbe_dcb.h | 27 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_dcb_nl.c | 176 | ||||
-rw-r--r-- | include/linux/dcbnl.h | 44 | ||||
-rw-r--r-- | include/net/dcbnl.h | 4 | ||||
-rw-r--r-- | net/dcb/dcbnl.c | 174 |
5 files changed, 416 insertions, 9 deletions
diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h index 62dfd243bedc..75f6efe1e369 100644 --- a/drivers/net/ixgbe/ixgbe_dcb.h +++ b/drivers/net/ixgbe/ixgbe_dcb.h | |||
@@ -108,7 +108,34 @@ enum dcb_rx_pba_cfg { | |||
108 | pba_80_48 /* PBA[0-3] each use 80KB, PBA[4-7] each use 48KB */ | 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 | struct ixgbe_dcb_config { | 136 | struct ixgbe_dcb_config { |
137 | struct bcn_config bcn; | ||
138 | |||
112 | struct tc_configuration tc_config[MAX_TRAFFIC_CLASS]; | 139 | struct tc_configuration tc_config[MAX_TRAFFIC_CLASS]; |
113 | u8 bw_percentage[2][MAX_BW_GROUP]; /* One each for Tx/Rx */ | 140 | u8 bw_percentage[2][MAX_BW_GROUP]; /* One each for Tx/Rx */ |
114 | 141 | ||
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index dd940a8f9357..615c2803202a 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #define BIT_PFC 0x02 | 34 | #define BIT_PFC 0x02 |
35 | #define BIT_PG_RX 0x04 | 35 | #define BIT_PG_RX 0x04 |
36 | #define BIT_PG_TX 0x08 | 36 | #define BIT_PG_TX 0x08 |
37 | #define BIT_BCN 0x10 | ||
37 | 38 | ||
38 | int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg, | 39 | int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg, |
39 | struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max) | 40 | struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max) |
@@ -88,6 +89,23 @@ int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg, | |||
88 | src_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc; | 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 | return 0; | 109 | return 0; |
92 | } | 110 | } |
93 | 111 | ||
@@ -313,6 +331,7 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) | |||
313 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 331 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
314 | int ret; | 332 | int ret; |
315 | 333 | ||
334 | adapter->dcb_set_bitmap &= ~BIT_BCN; /* no set for BCN */ | ||
316 | if (!adapter->dcb_set_bitmap) | 335 | if (!adapter->dcb_set_bitmap) |
317 | return 1; | 336 | return 1; |
318 | 337 | ||
@@ -417,6 +436,157 @@ static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state) | |||
417 | return; | 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 | struct dcbnl_rtnl_ops dcbnl_ops = { | 590 | struct dcbnl_rtnl_ops dcbnl_ops = { |
421 | .getstate = ixgbe_dcbnl_get_state, | 591 | .getstate = ixgbe_dcbnl_get_state, |
422 | .setstate = ixgbe_dcbnl_set_state, | 592 | .setstate = ixgbe_dcbnl_set_state, |
@@ -436,6 +606,10 @@ struct dcbnl_rtnl_ops dcbnl_ops = { | |||
436 | .getnumtcs = ixgbe_dcbnl_getnumtcs, | 606 | .getnumtcs = ixgbe_dcbnl_getnumtcs, |
437 | .setnumtcs = ixgbe_dcbnl_setnumtcs, | 607 | .setnumtcs = ixgbe_dcbnl_setnumtcs, |
438 | .getpfcstate = ixgbe_dcbnl_getpfcstate, | 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 | }; |
441 | 615 | ||
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h index 6cc4560bc376..e73a61449ad6 100644 --- a/include/linux/dcbnl.h +++ b/include/linux/dcbnl.h | |||
@@ -46,6 +46,8 @@ struct dcbmsg { | |||
46 | * @DCB_CMD_GCAP: request the DCB capabilities of the device | 46 | * @DCB_CMD_GCAP: request the DCB capabilities of the device |
47 | * @DCB_CMD_GNUMTCS: get the number of traffic classes currently supported | 47 | * @DCB_CMD_GNUMTCS: get the number of traffic classes currently supported |
48 | * @DCB_CMD_SNUMTCS: set the number of traffic classes | 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 | enum dcbnl_commands { | 52 | enum dcbnl_commands { |
51 | DCB_CMD_UNDEFINED, | 53 | DCB_CMD_UNDEFINED, |
@@ -62,18 +64,24 @@ enum dcbnl_commands { | |||
62 | DCB_CMD_PFC_SCFG, | 64 | DCB_CMD_PFC_SCFG, |
63 | 65 | ||
64 | DCB_CMD_SET_ALL, | 66 | DCB_CMD_SET_ALL, |
67 | |||
65 | DCB_CMD_GPERM_HWADDR, | 68 | DCB_CMD_GPERM_HWADDR, |
69 | |||
66 | DCB_CMD_GCAP, | 70 | DCB_CMD_GCAP, |
71 | |||
67 | DCB_CMD_GNUMTCS, | 72 | DCB_CMD_GNUMTCS, |
68 | DCB_CMD_SNUMTCS, | 73 | DCB_CMD_SNUMTCS, |
74 | |||
69 | DCB_CMD_PFC_GSTATE, | 75 | DCB_CMD_PFC_GSTATE, |
70 | DCB_CMD_PFC_SSTATE, | 76 | DCB_CMD_PFC_SSTATE, |
71 | 77 | ||
78 | DCB_CMD_BCN_GCFG, | ||
79 | DCB_CMD_BCN_SCFG, | ||
80 | |||
72 | __DCB_CMD_ENUM_MAX, | 81 | __DCB_CMD_ENUM_MAX, |
73 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, | 82 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, |
74 | }; | 83 | }; |
75 | 84 | ||
76 | |||
77 | /** | 85 | /** |
78 | * enum dcbnl_attrs - DCB top-level netlink attributes | 86 | * enum dcbnl_attrs - DCB top-level netlink attributes |
79 | * | 87 | * |
@@ -88,6 +96,7 @@ enum dcbnl_commands { | |||
88 | * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED) | 96 | * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED) |
89 | * @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED) | 97 | * @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED) |
90 | * @DCB_ATTR_NUMTCS: number of traffic classes supported (NLA_NESTED) | 98 | * @DCB_ATTR_NUMTCS: number of traffic classes supported (NLA_NESTED) |
99 | * @DCB_ATTR_BCN: backward congestion notification configuration (NLA_NESTED) | ||
91 | */ | 100 | */ |
92 | enum dcbnl_attrs { | 101 | enum dcbnl_attrs { |
93 | DCB_ATTR_UNDEFINED, | 102 | DCB_ATTR_UNDEFINED, |
@@ -102,6 +111,7 @@ enum dcbnl_attrs { | |||
102 | DCB_ATTR_PERM_HWADDR, | 111 | DCB_ATTR_PERM_HWADDR, |
103 | DCB_ATTR_CAP, | 112 | DCB_ATTR_CAP, |
104 | DCB_ATTR_NUMTCS, | 113 | DCB_ATTR_NUMTCS, |
114 | DCB_ATTR_BCN, | ||
105 | 115 | ||
106 | __DCB_ATTR_ENUM_MAX, | 116 | __DCB_ATTR_ENUM_MAX, |
107 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, | 117 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, |
@@ -282,6 +292,38 @@ enum dcbnl_numtcs_attrs { | |||
282 | DCB_NUMTCS_ATTR_MAX = __DCB_NUMTCS_ATTR_ENUM_MAX - 1, | 292 | DCB_NUMTCS_ATTR_MAX = __DCB_NUMTCS_ATTR_ENUM_MAX - 1, |
283 | }; | 293 | }; |
284 | 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, | ||
325 | }; | ||
326 | |||
285 | /** | 327 | /** |
286 | * enum dcb_general_attr_values - general DCB attribute values | 328 | * enum dcb_general_attr_values - general DCB attribute values |
287 | * | 329 | * |
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h index c7d87caf3f99..91e0a3d7faf2 100644 --- a/include/net/dcbnl.h +++ b/include/net/dcbnl.h | |||
@@ -44,6 +44,10 @@ struct dcbnl_rtnl_ops { | |||
44 | u8 (*setnumtcs)(struct net_device *, int, u8); | 44 | u8 (*setnumtcs)(struct net_device *, int, u8); |
45 | u8 (*getpfcstate)(struct net_device *); | 45 | u8 (*getpfcstate)(struct net_device *); |
46 | void (*setpfcstate)(struct net_device *, u8); | 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 | #endif /* __NET_DCBNL_H__ */ | 53 | #endif /* __NET_DCBNL_H__ */ |
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 758419c6f59b..b2bda3f610df 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c | |||
@@ -55,14 +55,15 @@ MODULE_LICENSE("GPL"); | |||
55 | 55 | ||
56 | /* DCB netlink attributes policy */ | 56 | /* DCB netlink attributes policy */ |
57 | static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { | 57 | static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { |
58 | [DCB_ATTR_IFNAME] = {.type = NLA_STRING, .len = IFNAMSIZ - 1}, | 58 | [DCB_ATTR_IFNAME] = {.type = NLA_NUL_STRING, .len = IFNAMSIZ - 1}, |
59 | [DCB_ATTR_STATE] = {.type = NLA_U8}, | 59 | [DCB_ATTR_STATE] = {.type = NLA_U8}, |
60 | [DCB_ATTR_PFC_CFG] = {.type = NLA_NESTED}, | 60 | [DCB_ATTR_PFC_CFG] = {.type = NLA_NESTED}, |
61 | [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED}, | 61 | [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED}, |
62 | [DCB_ATTR_SET_ALL] = {.type = NLA_U8}, | 62 | [DCB_ATTR_SET_ALL] = {.type = NLA_U8}, |
63 | [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG}, | 63 | [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG}, |
64 | [DCB_ATTR_CAP] = {.type = NLA_NESTED}, | 64 | [DCB_ATTR_CAP] = {.type = NLA_NESTED}, |
65 | [DCB_ATTR_PFC_STATE] = {.type = NLA_U8}, | 65 | [DCB_ATTR_PFC_STATE] = {.type = NLA_U8}, |
66 | [DCB_ATTR_BCN] = {.type = NLA_NESTED}, | ||
66 | }; | 67 | }; |
67 | 68 | ||
68 | /* DCB priority flow control to User Priority nested attributes */ | 69 | /* DCB priority flow control to User Priority nested attributes */ |
@@ -128,6 +129,33 @@ static struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = { | |||
128 | [DCB_NUMTCS_ATTR_PFC] = {.type = NLA_U8}, | 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 | /* standard netlink reply call */ | 159 | /* standard netlink reply call */ |
132 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, | 160 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, |
133 | u32 seq, u16 flags) | 161 | u32 seq, u16 flags) |
@@ -843,6 +871,130 @@ static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb, | |||
843 | return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1); | 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 | static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 998 | static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
847 | { | 999 | { |
848 | struct net *net = sock_net(skb->sk); | 1000 | struct net *net = sock_net(skb->sk); |
@@ -891,6 +1043,10 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
891 | ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq, | 1043 | ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq, |
892 | nlh->nlmsg_flags); | 1044 | nlh->nlmsg_flags); |
893 | goto out; | 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 | case DCB_CMD_SSTATE: | 1050 | case DCB_CMD_SSTATE: |
895 | ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq, | 1051 | ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq, |
896 | nlh->nlmsg_flags); | 1052 | nlh->nlmsg_flags); |
@@ -932,6 +1088,10 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
932 | ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq, | 1088 | ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq, |
933 | nlh->nlmsg_flags); | 1089 | nlh->nlmsg_flags); |
934 | goto out; | 1090 | goto out; |
1091 | case DCB_CMD_BCN_SCFG: | ||
1092 | ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq, | ||
1093 | nlh->nlmsg_flags); | ||
1094 | goto out; | ||
935 | default: | 1095 | default: |
936 | goto errout; | 1096 | goto errout; |
937 | } | 1097 | } |