Commit bdebeece5 on git.openvswitch.org (lacp: Require successful LACP
negotiations when configured.) makes successful LACP negotiation
mandatory for the bond to come UP. This patch provides a configuration
option to bring up the bond by falling back to active-backup mode on
LACP negotiation failure .

Several of the physical switches that support LACP block all traffic for ports
that are configured to use LACP, until LACP is negotiated with the host. When
configuring a LACP bond on a OVS host (eg: XenServer), this means that there
will be an interruption of the network connectivity between the time the ports
on the physical switch and the bond on the OVS host are configured. The
interruption may be relatively long, if different people are responsible for
managing the switches and the OVS host.

Such network connectivity failure can be avoided if LACP can be configured on
the OVS host before configuring the physical switch, and having the OVS host
fall back to a bond mode (active-backup) till the physical switch LACP
configuration is complete. An option "lacp-fallback-ab" is introduced with this
patch to provide such behavior on openvswitch.

Signed-off-by: Ravi Kondamuru <ravi.kondam...@citrix.com>
Signed-off-by: Dominic Curran <dominic.cur...@citrix.com>
---
 lib/bond.c           |   47 +++++++++++++++++++++++++++++++----------------
 lib/bond.h           |    1 +
 lib/lacp.c           |   16 ++++++++++++++--
 lib/lacp.h           |    1 +
 vswitchd/INTERNALS   |   14 ++++++++++++++
 vswitchd/bridge.c    |   18 ++++++++++++++++++
 vswitchd/vswitch.xml |   19 +++++++++++++++++--
 7 files changed, 96 insertions(+), 20 deletions(-)

diff --git a/lib/bond.c b/lib/bond.c
index 5be1bae..107b3e5 100644
--- a/lib/bond.c
+++ b/lib/bond.c
@@ -99,6 +99,7 @@ struct bond {
 
     /* Legacy compatibility. */
     long long int next_fake_iface_update; /* LLONG_MAX if disabled. */
+    bool lacp_fallback_ab; /* fallback to active-backup on lacp failure */
 
     atomic_int ref_cnt;
 };
@@ -258,6 +259,11 @@ bond_reconfigure(struct bond *bond, const struct 
bond_settings *s)
     bond->updelay = s->up_delay;
     bond->downdelay = s->down_delay;
 
+    if (bond->lacp_fallback_ab != s->lacp_fallback_ab_cfg) {
+        bond->lacp_fallback_ab = s->lacp_fallback_ab_cfg;
+        revalidate = true;
+    }
+
     if (bond->rebalance_interval != s->rebalance_interval) {
         bond->rebalance_interval = s->rebalance_interval;
         revalidate = true;
@@ -491,8 +497,9 @@ bond_wait(struct bond *bond)
 static bool
 may_send_learning_packets(const struct bond *bond)
 {
-    return bond->lacp_status == LACP_DISABLED
-        && (bond->balance == BM_SLB || bond->balance == BM_AB)
+    return ((bond->lacp_status == LACP_DISABLED
+        && (bond->balance == BM_SLB || bond->balance == BM_AB))
+        || (bond->lacp_fallback_ab && bond->lacp_status == LACP_CONFIGURED))
         && bond->active_slave;
 }
 
@@ -585,13 +592,14 @@ bond_check_admissibility(struct bond *bond, const void 
*slave_,
      * packets to them.
      *
      * If LACP is configured, but LACP negotiations have been unsuccessful, we
-     * drop all incoming traffic. */
+     * drop all incoming traffic except if lacp_fallback_ab is enabled. */
     switch (bond->lacp_status) {
     case LACP_NEGOTIATED:
         verdict = slave->enabled ? BV_ACCEPT : BV_DROP;
         goto out;
     case LACP_CONFIGURED:
-        goto out;
+        if (!bond->lacp_fallback_ab)
+            goto out;
     case LACP_DISABLED:
         break;
     }
@@ -604,6 +612,14 @@ bond_check_admissibility(struct bond *bond, const void 
*slave_,
     }
 
     switch (bond->balance) {
+    case BM_TCP:
+        /* TCP balanced bonds require successful LACP negotiated. Based on the
+         * above check, LACP is off or lacp_fallback_ab is true on this bond.
+         * If lacp_fallback_ab is true fall through to BM_AB case else, we
+         * drop all incoming traffic. */
+        if (!bond->lacp_fallback_ab)
+            goto out;
+
     case BM_AB:
         /* Drop all packets which arrive on backup slaves.  This is similar to
          * how Linux bonding handles active-backup bonds. */
@@ -618,12 +634,6 @@ bond_check_admissibility(struct bond *bond, const void 
*slave_,
         verdict = BV_ACCEPT;
         goto out;
 
-    case BM_TCP:
-        /* TCP balanced bonds require successful LACP negotiated. Based on the
-         * above check, LACP is off on this bond.  Therfore, we drop all
-         * incoming traffic. */
-        goto out;
-
     case BM_SLB:
         /* Drop all packets for which we have learned a different input port,
          * because we probably sent the packet on one slave and got it back on
@@ -1416,14 +1426,19 @@ choose_output_slave(const struct bond *bond, const 
struct flow *flow,
                     struct flow_wildcards *wc, uint16_t vlan)
 {
     struct bond_entry *e;
+    int balance;
 
-    if (bond->lacp_status == LACP_CONFIGURED) {
-        /* LACP has been configured on this bond but negotiations were
-         * unsuccussful.  Drop all traffic. */
-        return NULL;
-    }
+    balance = (bond->lacp_status == LACP_CONFIGURED)?
+                ((bond->lacp_fallback_ab && 
+                  (bond->balance==BM_AB || bond->balance==BM_TCP))?BM_AB:-1):
+                bond->balance;
+
+    switch (balance) {
+    case -1:
+         /* LACP has been configured on this bond but negotiations were
+          * unsuccussful and fallback not configured.  Drop all traffic. */
+         return NULL;
 
-    switch (bond->balance) {
     case BM_AB:
         return bond->active_slave;
 
diff --git a/lib/bond.h b/lib/bond.h
index f80fead..e8725ee 100644
--- a/lib/bond.h
+++ b/lib/bond.h
@@ -53,6 +53,7 @@ struct bond_settings {
 
     /* Legacy compatibility. */
     bool fake_iface;            /* Update fake stats for netdev 'name'? */
+    bool lacp_fallback_ab_cfg;  /* fallback to active-backup on lacp failure */
 };
 
 /* Program startup. */
diff --git a/lib/lacp.c b/lib/lacp.c
index 5421e2a..d5c2a2a 100644
--- a/lib/lacp.c
+++ b/lib/lacp.c
@@ -102,6 +102,7 @@ struct lacp {
     bool fast;               /* True if using fast probe interval. */
     bool negotiated;         /* True if LACP negotiations were successful. */
     bool update;             /* True if lacp_update() needs to be called. */
+    bool fallback_ab; /* True if fallback to active-backup on lacp failure */
 
     atomic_int ref_cnt;
 };
@@ -283,6 +284,12 @@ lacp_configure(struct lacp *lacp, const struct 
lacp_settings *s)
 
     lacp->active = s->active;
     lacp->fast = s->fast;
+
+    if (lacp->fallback_ab != s->fallback_ab_cfg) {
+        lacp->fallback_ab = s->fallback_ab_cfg;
+        lacp->update = true;
+    }
+ 
     ovs_mutex_unlock(&mutex);
 }
 
@@ -450,7 +457,9 @@ slave_may_enable__(struct slave *slave) OVS_REQUIRES(mutex)
 {
     /* The slave may be enabled if it's attached to an aggregator and its
      * partner is synchronized.*/
-    return slave->attached && (slave->partner.state & LACP_STATE_SYNC);
+    return slave->attached && (slave->partner.state & LACP_STATE_SYNC
+            || (slave->lacp && slave->lacp->fallback_ab
+                && slave->status == LACP_DEFAULTED));
 }
 
 /* This function should be called before enabling 'slave_' to send or receive
@@ -587,6 +596,8 @@ lacp_update_attached(struct lacp *lacp) OVS_REQUIRES(mutex)
         }
 
         if (slave->status == LACP_DEFAULTED) {
+            if (lacp->fallback_ab)
+                slave->attached = true;
             continue;
         }
 
@@ -603,7 +614,8 @@ lacp_update_attached(struct lacp *lacp) OVS_REQUIRES(mutex)
 
     if (lead) {
         HMAP_FOR_EACH (slave, node, &lacp->slaves) {
-            if (lead->partner.key != slave->partner.key
+            if ((lacp->fallback_ab && slave->status == LACP_DEFAULTED)
+                || lead->partner.key != slave->partner.key
                 || !eth_addr_equals(lead->partner.sys_id,
                                     slave->partner.sys_id)) {
                 slave->attached = false;
diff --git a/lib/lacp.h b/lib/lacp.h
index 89b0e0a..330949b 100644
--- a/lib/lacp.h
+++ b/lib/lacp.h
@@ -35,6 +35,7 @@ struct lacp_settings {
     uint16_t priority;                /* System priority. */
     bool active;                      /* Active or passive mode? */
     bool fast;                        /* Fast or slow probe interval. */
+    bool fallback_ab_cfg;            /* fallback to BM_SLB on lacp failure */
 };
 
 void lacp_init(void);
diff --git a/vswitchd/INTERNALS b/vswitchd/INTERNALS
index 2b48c9b..e25cd65 100644
--- a/vswitchd/INTERNALS
+++ b/vswitchd/INTERNALS
@@ -143,6 +143,20 @@ LACP bonding requires the remote switch to implement LACP, 
but it is
 otherwise very simple in that, after LACP negotiation is complete,
 there is no need for special handling of received packets.
 
+Several of the physical switches that support LACP block all traffic
+for ports that are configured to use LACP, until LACP is negotiated with
+the host. When configuring a LACP bond on a OVS host (eg: XenServer),
+this means that there will be an interruption of the network connectivity
+between the time the ports on the physical switch and the bond on the OVS
+host are configured. The interruption may be relatively long, if different
+people are responsible for managing the switches and the OVS host. 
+
+Such network connectivity failure can be avoided if LACP can be configured
+on the OVS host before configuring the physical switch, and having
+the OVS host fall back to a bond mode (active-backup) till the physical
+switch LACP configuration is complete. An option "lacp-fallback-ab" exists to
+provide such behavior on openvswitch.
+
 Active Backup Bonding
 ---------------------
 
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index ec3633c..7d5f87d 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -235,6 +235,7 @@ static struct lacp_settings *port_configure_lacp(struct 
port *,
                                                  struct lacp_settings *);
 static void port_configure_bond(struct port *, struct bond_settings *);
 static bool port_is_synthetic(const struct port *);
+static bool set_lacp_fallback_ab_cfg(struct port *);
 
 static void reconfigure_system_stats(const struct ovsrec_open_vswitch *);
 static void run_system_stats(void);
@@ -3283,6 +3284,18 @@ enable_lacp(struct port *port, bool *activep)
     }
 }
 
+static bool
+set_lacp_fallback_ab_cfg(struct port *port)
+{
+    const char *lacp_fallback_s;
+
+    lacp_fallback_s = smap_get(&port->cfg->other_config, "lacp-fallback-ab");
+    if (lacp_fallback_s && !strcmp(lacp_fallback_s, "true"))
+       return true;
+
+    return false;
+}
+
 static struct lacp_settings *
 port_configure_lacp(struct port *port, struct lacp_settings *s)
 {
@@ -3321,6 +3334,9 @@ port_configure_lacp(struct port *port, struct 
lacp_settings *s)
 
     lacp_time = smap_get(&port->cfg->other_config, "lacp-time");
     s->fast = lacp_time && !strcasecmp(lacp_time, "fast");
+
+    s->fallback_ab_cfg = set_lacp_fallback_ab_cfg(port);
+
     return s;
 }
 
@@ -3409,6 +3425,8 @@ port_configure_bond(struct port *port, struct 
bond_settings *s)
 
     s->fake_iface = port->cfg->bond_fake_iface;
 
+    s->lacp_fallback_ab_cfg = set_lacp_fallback_ab_cfg(port);
+
     LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
         netdev_set_miimon_interval(iface->netdev, miimon_interval);
     }
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 4ad0d63..f2a1b1e 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -941,7 +941,9 @@
 
       <p>
         The following modes require the upstream switch to support 802.3ad with
-        successful LACP negotiation:
+        successful LACP negotiation. If LACP negotiation fails and
+        other-config:lacp-fallback-ab is true, then <code>active-backup</code>
+        mode is used:
       </p>
 
       <dl>
@@ -1031,7 +1033,8 @@
           in LACP negotiations initiated by a remote switch, but not allowed to
           initiate such negotiations themselves.  If LACP is enabled on a port
           whose partner switch does not support LACP, the bond will be
-          disabled.  Defaults to <code>off</code> if unset.
+          disabled, unless other-config:lacp-fallback-ab is set to true.
+          Defaults to <code>off</code> if unset.
         </column>
 
         <column name="other_config" key="lacp-system-id">
@@ -1059,6 +1062,18 @@
             rate of once every 30 seconds.
           </p>
         </column>
+
+        <column name="other_config" key="lacp-fallback-ab"
+          type='{"type": "boolean"}'>
+          <p>
+            Determines the behavior of openvswitch bond in LACP mode. If
+            the partner switch does not support LACP, setting this option
+            to <code>true</code> allows openvswitch to fallback to
+            active-backup. If the option is set to <code>false</code>, the
+            bond will be disabled. In both the cases, once the partner switch
+            is configured to LACP mode, the bond will use LACP.
+          </p>
+        </column>
       </group>
 
       <group title="Rebalancing Configuration">
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to