Commit 859ee3c43812051e21816c6d6d4cc04fb7ce9b2e

Authored by Alexander Duyck
Committed by David S. Miller
1 parent 0eb3aa9bab

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 /**
... ... @@ -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__ */
... ... @@ -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;