vswitchd: Make the MAC entry aging time configurable.
[sliver-openvswitch.git] / vswitchd / bridge.c
index 86c5040..b2303d0 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks
+/* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -268,6 +268,7 @@ static void bridge_reconfigure_one(struct bridge *);
 static void bridge_reconfigure_remotes(struct bridge *,
                                        const struct sockaddr_in *managers,
                                        size_t n_managers);
+static void bridge_reconfigure_remotes_late(struct bridge *);
 static void bridge_get_all_ifaces(const struct bridge *, struct shash *ifaces);
 static void bridge_fetch_dp_ifaces(struct bridge *);
 static void bridge_flush(struct bridge *);
@@ -930,6 +931,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
         HMAP_FOR_EACH (iface, dp_ifidx_node, &br->ifaces) {
             iface_update_cfm(iface);
         }
+        bridge_reconfigure_remotes_late(br);
     }
 
     free(managers);
@@ -1582,7 +1584,8 @@ bridge_unixctl_fdb_show(struct unixctl_conn *conn,
         }
         ds_put_format(&ds, "%5d  %4d  "ETH_ADDR_FMT"  %3d\n",
                       br->ports[e->port]->ifaces[0]->dp_ifidx,
-                      e->vlan, ETH_ADDR_ARGS(e->mac), mac_entry_age(e));
+                      e->vlan, ETH_ADDR_ARGS(e->mac),
+                      mac_entry_age(br->ml, e));
     }
     unixctl_command_reply(conn, 200, ds_cstr(&ds));
     ds_destroy(&ds);
@@ -1712,7 +1715,7 @@ bridge_create(const struct ovsrec_bridge *br_cfg)
 
     br->name = xstrdup(br_cfg->name);
     br->cfg = br_cfg;
-    br->ml = mac_learning_create();
+    br->ml = mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME);
     eth_addr_nicira_random(br->default_ea);
 
     hmap_init(&br->ifaces);
@@ -1865,6 +1868,8 @@ bridge_reconfigure_one(struct bridge *br)
     struct svec snoops, old_snoops;
     struct shash_node *node;
     enum ofproto_fail_mode fail_mode;
+    const char *idle_time_str;
+    int idle_time;
     size_t i;
 
     /* Collect old ports. */
@@ -1944,6 +1949,13 @@ bridge_reconfigure_one(struct bridge *br)
     }
     ofproto_set_fail_mode(br->ofproto, fail_mode);
 
+    /* Set the MAC learning aging timeout. */
+    idle_time_str = bridge_get_other_config(br->cfg, "mac-aging-time");
+    idle_time = (idle_time_str && atoi(idle_time_str)
+                 ? atoi(idle_time_str)
+                 : MAC_ENTRY_DEFAULT_IDLE_TIME);
+    mac_learning_set_idle_time(br->ml, idle_time);
+
     /* Delete all flows if we're switching from connected to standalone or vice
      * versa.  (XXX Should we delete all flows if we are switching from one
      * controller to another?) */
@@ -2109,13 +2121,23 @@ bridge_reconfigure_remotes(struct bridge *br,
     if (had_primary != ofproto_has_primary_controller(br->ofproto)) {
         ofproto_flush_flows(br->ofproto);
     }
+}
 
+/* Does configuration of remotes that must happen after all of the ports and
+ * interfaces are fully configured, that is, when flow translation can be
+ * expected to succeed.  (This is because ofproto_add_flow() immediately
+ * re-translates any existing facets for the rule that it replaces, if any.)
+ * In particular, it must be called after port_update_bonding(), to ensure that
+ * 'bond_hash' is non-NULL for bonded ports. */
+static void
+bridge_reconfigure_remotes_late(struct bridge *br)
+{
     /* If there are no controllers and the bridge is in standalone
      * mode, set up a flow that matches every packet and directs
      * them to OFPP_NORMAL (which goes to us).  Otherwise, the
      * switch is in secure mode and we won't pass any traffic until
      * a controller has been defined and it tells us to do so. */
-    if (!n_controllers
+    if (!bridge_get_controllers(br, NULL)
         && ofproto_get_fail_mode(br->ofproto) == OFPROTO_FAIL_STANDALONE) {
         union ofp_action action;
         struct cls_rule rule;
@@ -3049,11 +3071,13 @@ is_admissible(struct bridge *br, const struct flow *flow, bool have_packet,
          * to the exception is if we locked the learning table to avoid
          * reflections on bond slaves.  If this is the case, just drop the
          * packet now. */
-        src_idx = mac_learning_lookup(br->ml, flow->dl_src, vlan,
-                                      &is_grat_arp_locked);
-        if (src_idx != -1 && src_idx != in_port->port_idx &&
-            (!is_gratuitous_arp(flow) || is_grat_arp_locked)) {
+        if (in_port->bond_mode != BM_AB) {
+            src_idx = mac_learning_lookup(br->ml, flow->dl_src, vlan,
+                                          &is_grat_arp_locked);
+            if (src_idx != -1 && src_idx != in_port->port_idx &&
+                (!is_gratuitous_arp(flow) || is_grat_arp_locked)) {
                 return false;
+            }
         }
     }