lacp: New "lacp-heartbeat" mode.
[openvswitch] / vswitchd / bridge.c
index 3c9b05f3b9d195cd6d586f58eea34d315432609c..d883596de83c0e129c088974516cd4554d6495d8 100644 (file)
@@ -664,6 +664,13 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
                     dpif_port = NULL;
                 }
                 if (iface) {
+                    if (iface->port->bond) {
+                        /* The bond has a pointer to the netdev, so remove it
+                         * from the bond before closing the netdev.  The slave
+                         * will get added back to the bond later, after a new
+                         * netdev is available. */
+                        bond_slave_unregister(iface->port->bond, iface);
+                    }
                     netdev_close(iface->netdev);
                     iface->netdev = NULL;
                 }
@@ -2944,12 +2951,12 @@ port_reconfigure(struct port *port, const struct ovsrec_port *cfg)
 
     port->cfg = cfg;
 
-
     /* Add new interfaces and update 'cfg' member of existing ones. */
     sset_init(&new_ifaces);
     for (i = 0; i < cfg->n_interfaces; i++) {
         const struct ovsrec_interface *if_cfg = cfg->interfaces[i];
         struct iface *iface;
+        const char *type;
 
         if (!sset_add(&new_ifaces, if_cfg->name)) {
             VLOG_WARN("port %s: %s specified twice as port interface",
@@ -2958,8 +2965,18 @@ port_reconfigure(struct port *port, const struct ovsrec_port *cfg)
             continue;
         }
 
+        /* Determine interface type.  The local port always has type
+         * "internal".  Other ports take their type from the database and
+         * default to "system" if none is specified. */
+        type = (!strcmp(if_cfg->name, port->bridge->name) ? "internal"
+                : if_cfg->type[0] ? if_cfg->type
+                : "system");
+
         iface = iface_lookup(port->bridge, if_cfg->name);
-        if (iface) {
+        if (!strcmp(type, "null")) {
+            iface_destroy(iface);
+            continue;
+        } else if (iface) {
             if (iface->port != port) {
                 VLOG_ERR("bridge %s: %s interface is on multiple ports, "
                          "removing from %s",
@@ -2971,12 +2988,7 @@ port_reconfigure(struct port *port, const struct ovsrec_port *cfg)
             iface = iface_create(port, if_cfg);
         }
 
-        /* Determine interface type.  The local port always has type
-         * "internal".  Other ports take their type from the database and
-         * default to "system" if none is specified. */
-        iface->type = (!strcmp(if_cfg->name, port->bridge->name) ? "internal"
-                       : if_cfg->type[0] ? if_cfg->type
-                       : "system");
+        iface->type = type;
     }
     sset_destroy(&new_ifaces);
 
@@ -3124,11 +3136,13 @@ static void
 iface_reconfigure_lacp(struct iface *iface)
 {
     struct lacp_slave_settings s;
-    int priority, portid;
+    int priority, portid, key;
 
     portid = atoi(get_interface_other_config(iface->cfg, "lacp-port-id", "0"));
     priority = atoi(get_interface_other_config(iface->cfg,
                                                "lacp-port-priority", "0"));
+    key = atoi(get_interface_other_config(iface->cfg, "lacp-aggregation-key",
+                                          "0"));
 
     if (portid <= 0 || portid > UINT16_MAX) {
         portid = iface->dp_ifidx;
@@ -3138,9 +3152,14 @@ iface_reconfigure_lacp(struct iface *iface)
         priority = UINT16_MAX;
     }
 
+    if (key < 0 || key > UINT16_MAX) {
+        key = 0;
+    }
+
     s.name = iface->name;
     s.id = portid;
     s.priority = priority;
+    s.key = key;
     lacp_slave_register(iface->port->lacp, iface, &s);
 }
 
@@ -3177,9 +3196,9 @@ port_reconfigure_lacp(struct port *port)
                   ? priority
                   : UINT16_MAX - !list_is_short(&port->ifaces));
 
-    s.strict = !strcmp(get_port_other_config(port->cfg, "lacp-strict",
-                                             "false"),
-                       "true");
+    s.heartbeat = !strcmp(get_port_other_config(port->cfg,
+                                                "lacp-heartbeat",
+                                                "false"), "true");
 
     lacp_time = get_port_other_config(port->cfg, "lacp-time", "slow");
     custom_time = atoi(lacp_time);
@@ -3246,6 +3265,8 @@ port_reconfigure_bond(struct port *port)
 
     s.up_delay = MAX(0, port->cfg->bond_updelay);
     s.down_delay = MAX(0, port->cfg->bond_downdelay);
+    s.basis = atoi(get_port_other_config(port->cfg, "bond-hash-basis", "0"));
+
     s.rebalance_interval = atoi(
         get_port_other_config(port->cfg, "bond-rebalance-interval", "10000"));
     if (s.rebalance_interval < 1000) {
@@ -3263,9 +3284,15 @@ port_reconfigure_bond(struct port *port)
     }
 
     LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
-        uint16_t stable_id = (port->lacp
-                              ? lacp_slave_get_port_id(port->lacp, iface)
-                              : iface->dp_ifidx);
+        long long stable_id;
+
+        stable_id = atoll(get_interface_other_config(iface->cfg,
+                                                     "bond-stable-id", "0"));
+
+        if (stable_id <= 0 || stable_id >= UINT32_MAX) {
+            stable_id = odp_port_to_ofp_port(iface->dp_ifidx);
+        }
+
         bond_slave_register(iface->port->bond, iface, stable_id,
                             iface->netdev);
     }