bonding: add new option lacp_active
authorHangbin Liu <liuhangbin@gmail.com>
Mon, 2 Aug 2021 03:02:19 +0000 (11:02 +0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 3 Aug 2021 10:50:22 +0000 (11:50 +0100)
Add an option lacp_active, which is similar with team's runner.active.
This option specifies whether to send LACPDU frames periodically. If set
on, the LACPDU frames are sent along with the configured lacp_rate
setting. If set off, the LACPDU frames acts as "speak when spoken to".

Note, the LACPDU state frames still will be sent when init or unbind port.

v2: remove module parameter

Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
12 files changed:
Documentation/networking/bonding.rst
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_netlink.c
drivers/net/bonding/bond_options.c
drivers/net/bonding/bond_procfs.c
drivers/net/bonding/bond_sysfs.c
include/net/bond_3ad.h
include/net/bond_options.h
include/net/bonding.h
include/uapi/linux/if_link.h
tools/include/uapi/linux/if_link.h

index 62f2aab8eaec0b65a7c4be0178241a74562bd93f..31cfd7d674a6cd767e31e0feb36e3fd1f4b127db 100644 (file)
@@ -501,6 +501,18 @@ fail_over_mac
        This option was added in bonding version 3.2.0.  The "follow"
        policy was added in bonding version 3.3.0.
 
+lacp_active
+       Option specifying whether to send LACPDU frames periodically.
+
+       off or 0
+               LACPDU frames acts as "speak when spoken to".
+
+       on or 1
+               LACPDU frames are sent along the configured links
+               periodically. See lacp_rate for more details.
+
+       The default is on.
+
 lacp_rate
 
        Option specifying the rate in which we'll ask our link partner
index 6908822d9773f76375027ef435459d8c1ab4f59d..a4a202b9a0a24d57a3f367ba30e09970e04feee5 100644 (file)
@@ -96,7 +96,7 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker);
 static void ad_mux_machine(struct port *port, bool *update_slave_arr);
 static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
 static void ad_tx_machine(struct port *port);
-static void ad_periodic_machine(struct port *port);
+static void ad_periodic_machine(struct port *port, struct bond_params bond_params);
 static void ad_port_selection_logic(struct port *port, bool *update_slave_arr);
 static void ad_agg_selection_logic(struct aggregator *aggregator,
                                   bool *update_slave_arr);
@@ -1294,10 +1294,11 @@ static void ad_tx_machine(struct port *port)
 /**
  * ad_periodic_machine - handle a port's periodic state machine
  * @port: the port we're looking at
+ * @bond_params: bond parameters we will use
  *
  * Turn ntt flag on priodically to perform periodic transmission of lacpdu's.
  */
-static void ad_periodic_machine(struct port *port)
+static void ad_periodic_machine(struct port *port, struct bond_params bond_params)
 {
        periodic_states_t last_state;
 
@@ -1306,8 +1307,8 @@ static void ad_periodic_machine(struct port *port)
 
        /* check if port was reinitialized */
        if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) ||
-           (!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY))
-          ) {
+           (!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY)) ||
+           !bond_params.lacp_active) {
                port->sm_periodic_state = AD_NO_PERIODIC;
        }
        /* check if state machine should change state */
@@ -2341,7 +2342,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
                }
 
                ad_rx_machine(NULL, port);
-               ad_periodic_machine(port);
+               ad_periodic_machine(port, bond->params);
                ad_port_selection_logic(port, &update_slave_arr);
                ad_mux_machine(port, &update_slave_arr);
                ad_tx_machine(port);
index 616ebbb08ca6b36d76c11e583b6792a2c9292861..3ba5f4871162b587afda412d474f6a3d59cc2402 100644 (file)
@@ -5478,6 +5478,7 @@ static int bond_check_params(struct bond_params *params)
        params->downdelay = downdelay;
        params->peer_notif_delay = 0;
        params->use_carrier = use_carrier;
+       params->lacp_active = 1;
        params->lacp_fast = lacp_fast;
        params->primary[0] = 0;
        params->primary_reselect = primary_reselect_value;
index 0561ece1ba45c97b58ae533dc1c5d4f688168746..5d54e11d18fa5d99e240fc5495510e700ef336e9 100644 (file)
@@ -100,6 +100,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
        [IFLA_BOND_MIN_LINKS]           = { .type = NLA_U32 },
        [IFLA_BOND_LP_INTERVAL]         = { .type = NLA_U32 },
        [IFLA_BOND_PACKETS_PER_SLAVE]   = { .type = NLA_U32 },
+       [IFLA_BOND_AD_LACP_ACTIVE]      = { .type = NLA_U8 },
        [IFLA_BOND_AD_LACP_RATE]        = { .type = NLA_U8 },
        [IFLA_BOND_AD_SELECT]           = { .type = NLA_U8 },
        [IFLA_BOND_AD_INFO]             = { .type = NLA_NESTED },
@@ -387,6 +388,16 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                if (err)
                        return err;
        }
+
+       if (data[IFLA_BOND_AD_LACP_ACTIVE]) {
+               int lacp_active = nla_get_u8(data[IFLA_BOND_AD_LACP_ACTIVE]);
+
+               bond_opt_initval(&newval, lacp_active);
+               err = __bond_opt_set(bond, BOND_OPT_LACP_ACTIVE, &newval);
+               if (err)
+                       return err;
+       }
+
        if (data[IFLA_BOND_AD_LACP_RATE]) {
                int lacp_rate =
                        nla_get_u8(data[IFLA_BOND_AD_LACP_RATE]);
@@ -490,6 +501,7 @@ static size_t bond_get_size(const struct net_device *bond_dev)
                nla_total_size(sizeof(u32)) +   /* IFLA_BOND_MIN_LINKS */
                nla_total_size(sizeof(u32)) +   /* IFLA_BOND_LP_INTERVAL */
                nla_total_size(sizeof(u32)) +  /* IFLA_BOND_PACKETS_PER_SLAVE */
+               nla_total_size(sizeof(u8)) +    /* IFLA_BOND_AD_LACP_ACTIVE */
                nla_total_size(sizeof(u8)) +    /* IFLA_BOND_AD_LACP_RATE */
                nla_total_size(sizeof(u8)) +    /* IFLA_BOND_AD_SELECT */
                nla_total_size(sizeof(struct nlattr)) + /* IFLA_BOND_AD_INFO */
@@ -622,6 +634,10 @@ static int bond_fill_info(struct sk_buff *skb,
                        packets_per_slave))
                goto nla_put_failure;
 
+       if (nla_put_u8(skb, IFLA_BOND_AD_LACP_ACTIVE,
+                      bond->params.lacp_active))
+               goto nla_put_failure;
+
        if (nla_put_u8(skb, IFLA_BOND_AD_LACP_RATE,
                       bond->params.lacp_fast))
                goto nla_put_failure;
index 0cf25de6f46d8e13fd32751d5cae264e5dfbcc77..a8fde3bc458f6c360252f0a3e0648e533936524e 100644 (file)
@@ -58,6 +58,8 @@ static int bond_option_lp_interval_set(struct bonding *bond,
                                       const struct bond_opt_value *newval);
 static int bond_option_pps_set(struct bonding *bond,
                               const struct bond_opt_value *newval);
+static int bond_option_lacp_active_set(struct bonding *bond,
+                                      const struct bond_opt_value *newval);
 static int bond_option_lacp_rate_set(struct bonding *bond,
                                     const struct bond_opt_value *newval);
 static int bond_option_ad_select_set(struct bonding *bond,
@@ -135,6 +137,12 @@ static const struct bond_opt_value bond_intmax_tbl[] = {
        { NULL,      -1,      0}
 };
 
+static const struct bond_opt_value bond_lacp_active[] = {
+       { "off", 0,  0},
+       { "on",  1,  BOND_VALFLAG_DEFAULT},
+       { NULL,  -1, 0}
+};
+
 static const struct bond_opt_value bond_lacp_rate_tbl[] = {
        { "slow", AD_LACP_SLOW, 0},
        { "fast", AD_LACP_FAST, 0},
@@ -283,6 +291,15 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = {
                .values = bond_intmax_tbl,
                .set = bond_option_updelay_set
        },
+       [BOND_OPT_LACP_ACTIVE] = {
+               .id = BOND_OPT_LACP_ACTIVE,
+               .name = "lacp_active",
+               .desc = "Send LACPDU frames with configured lacp rate or acts as speak when spoken to",
+               .flags = BOND_OPTFLAG_IFDOWN,
+               .unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_8023AD)),
+               .values = bond_lacp_active,
+               .set = bond_option_lacp_active_set
+       },
        [BOND_OPT_LACP_RATE] = {
                .id = BOND_OPT_LACP_RATE,
                .name = "lacp_rate",
@@ -1333,6 +1350,16 @@ static int bond_option_pps_set(struct bonding *bond,
        return 0;
 }
 
+static int bond_option_lacp_active_set(struct bonding *bond,
+                                      const struct bond_opt_value *newval)
+{
+       netdev_dbg(bond->dev, "Setting LACP active to %s (%llu)\n",
+                  newval->string, newval->value);
+       bond->params.lacp_active = newval->value;
+
+       return 0;
+}
+
 static int bond_option_lacp_rate_set(struct bonding *bond,
                                     const struct bond_opt_value *newval)
 {
index 0fb1da361bb18a4a9030c1ead42d312cce72ca79..f3e3bfd72556cc00f9500a5ef9c21d19a02582b7 100644 (file)
@@ -133,6 +133,8 @@ static void bond_info_show_master(struct seq_file *seq)
                struct ad_info ad_info;
 
                seq_puts(seq, "\n802.3ad info\n");
+               seq_printf(seq, "LACP active: %s\n",
+                          (bond->params.lacp_active) ? "on" : "off");
                seq_printf(seq, "LACP rate: %s\n",
                           (bond->params.lacp_fast) ? "fast" : "slow");
                seq_printf(seq, "Min links: %d\n", bond->params.min_links);
index 5f9e9a2402261933ea8351fd1cf81d7263f588e1..b9e9842fed94efcb28c01f06860670fae3b78802 100644 (file)
@@ -339,10 +339,24 @@ static ssize_t bonding_show_peer_notif_delay(struct device *d,
 static DEVICE_ATTR(peer_notif_delay, 0644,
                   bonding_show_peer_notif_delay, bonding_sysfs_store_option);
 
-/* Show the LACP interval. */
-static ssize_t bonding_show_lacp(struct device *d,
-                                struct device_attribute *attr,
-                                char *buf)
+/* Show the LACP activity and interval. */
+static ssize_t bonding_show_lacp_active(struct device *d,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct bonding *bond = to_bond(d);
+       const struct bond_opt_value *val;
+
+       val = bond_opt_get_val(BOND_OPT_LACP_ACTIVE, bond->params.lacp_active);
+
+       return sprintf(buf, "%s %d\n", val->string, bond->params.lacp_active);
+}
+static DEVICE_ATTR(lacp_active, 0644,
+                  bonding_show_lacp_active, bonding_sysfs_store_option);
+
+static ssize_t bonding_show_lacp_rate(struct device *d,
+                                     struct device_attribute *attr,
+                                     char *buf)
 {
        struct bonding *bond = to_bond(d);
        const struct bond_opt_value *val;
@@ -352,7 +366,7 @@ static ssize_t bonding_show_lacp(struct device *d,
        return sprintf(buf, "%s %d\n", val->string, bond->params.lacp_fast);
 }
 static DEVICE_ATTR(lacp_rate, 0644,
-                  bonding_show_lacp, bonding_sysfs_store_option);
+                  bonding_show_lacp_rate, bonding_sysfs_store_option);
 
 static ssize_t bonding_show_min_links(struct device *d,
                                      struct device_attribute *attr,
@@ -738,6 +752,7 @@ static struct attribute *per_bond_attrs[] = {
        &dev_attr_downdelay.attr,
        &dev_attr_updelay.attr,
        &dev_attr_peer_notif_delay.attr,
+       &dev_attr_lacp_active.attr,
        &dev_attr_lacp_rate.attr,
        &dev_attr_ad_select.attr,
        &dev_attr_xmit_hash_policy.attr,
index c8696a230b7d922479b6e2d8368f65050d4e2cc8..38785d48baff99da65d97ce974a831b77a8adc16 100644 (file)
@@ -303,6 +303,7 @@ int  __bond_3ad_get_active_agg_info(struct bonding *bond,
 int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
                         struct slave *slave);
 int bond_3ad_set_carrier(struct bonding *bond);
+void bond_3ad_update_lacp_active(struct bonding *bond);
 void bond_3ad_update_lacp_rate(struct bonding *bond);
 void bond_3ad_update_ad_actor_settings(struct bonding *bond);
 int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats);
index 9d382f2f0bc57b611b10b90dacd36060dd2980d3..e64833a674eb8df8011451e0ed8c0c01afac9aa7 100644 (file)
@@ -64,6 +64,7 @@ enum {
        BOND_OPT_AD_USER_PORT_KEY,
        BOND_OPT_NUM_PEER_NOTIF_ALIAS,
        BOND_OPT_PEER_NOTIF_DELAY,
+       BOND_OPT_LACP_ACTIVE,
        BOND_OPT_LAST
 };
 
index 625d9c72dee37d3fcac0691d2f3ef7ca84d67fdf..46df470048031426313f8dce4e25a35cc90cf6c4 100644 (file)
@@ -129,6 +129,7 @@ struct bond_params {
        int updelay;
        int downdelay;
        int peer_notif_delay;
+       int lacp_active;
        int lacp_fast;
        unsigned int min_links;
        int ad_select;
index 49b22afab78f1fb1a4e069abb51cb5c59ded58f4..5310003523ce0c927e8e9668ea70a94ed176b898 100644 (file)
@@ -855,6 +855,7 @@ enum {
        IFLA_BOND_AD_ACTOR_SYSTEM,
        IFLA_BOND_TLB_DYNAMIC_LB,
        IFLA_BOND_PEER_NOTIF_DELAY,
+       IFLA_BOND_AD_LACP_ACTIVE,
        __IFLA_BOND_MAX,
 };
 
index d208b2af697fde4b473aefa08d4c74499bde43e2..eb15f319aa571e96ce28bf6d6f2c5c20a98567bf 100644 (file)
@@ -653,6 +653,7 @@ enum {
        IFLA_BOND_AD_ACTOR_SYSTEM,
        IFLA_BOND_TLB_DYNAMIC_LB,
        IFLA_BOND_PEER_NOTIF_DELAY,
+       IFLA_BOND_AD_LACP_ACTIVE,
        __IFLA_BOND_MAX,
 };