aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2008-11-21 00:10:23 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-21 00:10:23 -0500
commit859ee3c43812051e21816c6d6d4cc04fb7ce9b2e (patch)
treeef3c3717038b5d4600065550f422fd8abf72de35
parent0eb3aa9bab20217fb42244ccdcb5bf8a002f504c (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.h27
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_nl.c176
-rw-r--r--include/linux/dcbnl.h44
-rw-r--r--include/net/dcbnl.h4
-rw-r--r--net/dcb/dcbnl.c174
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 */
119struct 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
111struct ixgbe_dcb_config { 136struct 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
38int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg, 39int 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
439static 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
448static 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
495static 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
507static 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
420struct dcbnl_rtnl_ops dcbnl_ops = { 590struct 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 */
50enum dcbnl_commands { 52enum 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 */
92enum dcbnl_attrs { 101enum 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
295enum 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 */
57static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { 57static 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. */
133static 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 */
132static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, 160static 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
874static 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
947err_bcn:
948 nla_nest_cancel(dcbnl_skb, bcn_nest);
949nlmsg_failure:
950err:
951 kfree(dcbnl_skb);
952err_out:
953 ret = -EINVAL;
954 return ret;
955}
956
957static 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);
994err:
995 return ret;
996}
997
846static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 998static 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 }