Add IPv6 support for OpenFlow, OVSDB, NetFlow, and sFlow.
[sliver-openvswitch.git] / vswitchd / bridge.c
index 4fe9d96..cde4bd0 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+/* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
 #include "bfd.h"
 #include "bitmap.h"
 #include "cfm.h"
+#include "connectivity.h"
 #include "coverage.h"
 #include "daemon.h"
 #include "dirs.h"
@@ -41,6 +42,7 @@
 #include "ofproto/bond.h"
 #include "ofproto/ofproto.h"
 #include "poll-loop.h"
+#include "seq.h"
 #include "sha1.h"
 #include "shash.h"
 #include "smap.h"
@@ -155,6 +157,9 @@ static struct ovsdb_idl_txn *daemonize_txn;
 /* Most recently processed IDL sequence number. */
 static unsigned int idl_seqno;
 
+/* Track changes to port connectivity. */
+static uint64_t connectivity_seqno = LLONG_MIN;
+
 /* Each time this timer expires, the bridge fetches interface and mirror
  * statistics and pushes them into the database. */
 #define IFACE_STATS_INTERVAL (5 * 1000) /* In milliseconds. */
@@ -171,6 +176,7 @@ static long long int iface_stats_timer = LLONG_MIN;
 #define OFP_PORT_ACTION_WINDOW 10
 
 static void add_del_bridges(const struct ovsrec_open_vswitch *);
+static void bridge_run__(void);
 static void bridge_create(const struct ovsrec_bridge *);
 static void bridge_destroy(struct bridge *);
 static struct bridge *bridge_lookup(const char *name);
@@ -246,7 +252,7 @@ static struct iface *iface_lookup(const struct bridge *, const char *name);
 static struct iface *iface_find(const char *name);
 static struct iface *iface_from_ofp_port(const struct bridge *,
                                          ofp_port_t ofp_port);
-static void iface_set_mac(struct iface *);
+static void iface_set_mac(struct iface *, const uint8_t *);
 static void iface_set_ofport(const struct ovsrec_interface *, ofp_port_t ofport);
 static void iface_clear_db_record(const struct ovsrec_interface *if_cfg);
 static void iface_configure_qos(struct iface *, const struct ovsrec_qos *);
@@ -255,6 +261,8 @@ static void iface_refresh_cfm_stats(struct iface *);
 static void iface_refresh_stats(struct iface *);
 static void iface_refresh_status(struct iface *);
 static bool iface_is_synthetic(const struct iface *);
+static ofp_port_t iface_get_requested_ofp_port(
+    const struct ovsrec_interface *);
 static ofp_port_t iface_pick_ofport(const struct ovsrec_interface *);
 
 /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
@@ -347,7 +355,6 @@ bridge_init(const char *remote)
     ovsdb_idl_omit_alert(idl, &ovsrec_port_col_status);
     ovsdb_idl_omit_alert(idl, &ovsrec_port_col_statistics);
     ovsdb_idl_omit(idl, &ovsrec_port_col_external_ids);
-    ovsdb_idl_omit(idl, &ovsrec_port_col_fake_bridge);
 
     ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_admin_state);
     ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_duplex);
@@ -459,12 +466,12 @@ collect_in_band_managers(const struct ovsrec_open_vswitch *ovs_cfg,
 
         managers = xmalloc(sset_count(&targets) * sizeof *managers);
         SSET_FOR_EACH (target, &targets) {
-            struct sockaddr_in *sin = &managers[n_managers];
+            struct sockaddr_storage ss;
 
-            if (stream_parse_target_with_default_port(target,
-                                                      OVSDB_OLD_PORT,
-                                                      sin)) {
-                n_managers++;
+            if (stream_parse_target_with_default_port(target, OVSDB_OLD_PORT,
+                                                      &ss)
+                && ss.ss_family == AF_INET) {
+                managers[n_managers++] = *(struct sockaddr_in *) &ss;
             }
         }
     }
@@ -485,12 +492,12 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
 
     COVERAGE_INC(bridge_reconfigure);
 
-    ofproto_set_flow_eviction_threshold(
-        smap_get_int(&ovs_cfg->other_config, "flow-eviction-threshold",
-                     OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT));
+    ofproto_set_flow_limit(smap_get_int(&ovs_cfg->other_config, "flow-limit",
+                                        OFPROTO_FLOW_LIMIT_DEFAULT));
 
-    ofproto_set_n_handler_threads(
-        smap_get_int(&ovs_cfg->other_config, "n-handler-threads", 0));
+    ofproto_set_threads(
+        smap_get_int(&ovs_cfg->other_config, "n-handler-threads", 0),
+        smap_get_int(&ovs_cfg->other_config, "n-revalidator-threads", 0));
 
     bridge_configure_flow_miss_model(smap_get(&ovs_cfg->other_config,
                                               "force-miss-model"));
@@ -568,9 +575,10 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
             port_configure(port);
 
             LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
+                iface_set_ofport(iface->cfg, iface->ofp_port);
                 iface_configure_cfm(iface);
                 iface_configure_qos(iface, port->cfg->qos);
-                iface_set_mac(iface);
+                iface_set_mac(iface, port->cfg->fake_bridge ? br->ea : NULL);
                 ofproto_port_set_bfd(br->ofproto, iface->ofp_port,
                                      &iface->cfg->bfd);
             }
@@ -594,6 +602,13 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
         }
     }
     free(managers);
+
+    /* The ofproto-dpif provider does some final reconfiguration in its
+     * ->type_run() function.  We have to call it before notifying the database
+     * client that reconfiguration is complete, otherwise there is a very
+     * narrow race window in which e.g. ofproto/trace will not recognize the
+     * new configuration (sometimes this causes unit test failures). */
+    bridge_run__();
 }
 
 /* Delete ofprotos which aren't configured or have the wrong type.  Create
@@ -652,6 +667,7 @@ bridge_delete_or_reconfigure_ports(struct bridge *br)
     n = allocated = 0;
 
     OFPROTO_PORT_FOR_EACH (&ofproto_port, &dump, br->ofproto) {
+        ofp_port_t requested_ofp_port;
         struct iface *iface;
 
         iface = iface_lookup(br, ofproto_port.name);
@@ -675,6 +691,43 @@ bridge_delete_or_reconfigure_ports(struct bridge *br)
             goto delete;
         }
 
+        /* If the requested OpenFlow port for 'iface' changed, and it's not
+         * already the correct port, then we might want to temporarily delete
+         * this interface, so we can add it back again with the new OpenFlow
+         * port number. */
+        requested_ofp_port = iface_get_requested_ofp_port(iface->cfg);
+        if (iface->ofp_port != OFPP_LOCAL &&
+            requested_ofp_port != OFPP_NONE &&
+            requested_ofp_port != iface->ofp_port) {
+            ofp_port_t victim_request;
+            struct iface *victim;
+
+            /* Check for an existing OpenFlow port currently occupying
+             * 'iface''s requested port number.  If there isn't one, then
+             * delete this port.  Otherwise we need to consider further. */
+            victim = iface_from_ofp_port(br, requested_ofp_port);
+            if (!victim) {
+                goto delete;
+            }
+
+            /* 'victim' is a port currently using 'iface''s requested port
+             * number.  Unless 'victim' specifically requested that port
+             * number, too, then we can delete both 'iface' and 'victim'
+             * temporarily.  (We'll add both of them back again later with new
+             * OpenFlow port numbers.)
+             *
+             * If 'victim' did request port number 'requested_ofp_port', just
+             * like 'iface', then that's a configuration inconsistency that we
+             * can't resolve.  We might as well let it keep its current port
+             * number. */
+            victim_request = iface_get_requested_ofp_port(victim->cfg);
+            if (victim_request != requested_ofp_port) {
+                del = add_ofp_port(victim->ofp_port, del, &n, &allocated);
+                iface_destroy(victim);
+                goto delete;
+            }
+        }
+
         /* Keep it. */
         continue;
 
@@ -690,7 +743,8 @@ bridge_delete_or_reconfigure_ports(struct bridge *br)
 }
 
 static void
-bridge_add_ports(struct bridge *br, const struct shash *wanted_ports)
+bridge_add_ports__(struct bridge *br, const struct shash *wanted_ports,
+                   bool with_requested_port)
 {
     struct shash_node *port_node;
 
@@ -700,15 +754,32 @@ bridge_add_ports(struct bridge *br, const struct shash *wanted_ports)
 
         for (i = 0; i < port_cfg->n_interfaces; i++) {
             const struct ovsrec_interface *iface_cfg = port_cfg->interfaces[i];
-            struct iface *iface = iface_lookup(br, iface_cfg->name);
+            ofp_port_t requested_ofp_port;
 
-            if (!iface) {
-                iface_create(br, iface_cfg, port_cfg);
+            requested_ofp_port = iface_get_requested_ofp_port(iface_cfg);
+            if ((requested_ofp_port != OFPP_NONE) == with_requested_port) {
+                struct iface *iface = iface_lookup(br, iface_cfg->name);
+
+                if (!iface) {
+                    iface_create(br, iface_cfg, port_cfg);
+                }
             }
         }
     }
 }
 
+static void
+bridge_add_ports(struct bridge *br, const struct shash *wanted_ports)
+{
+    /* First add interfaces that request a particular port number. */
+    bridge_add_ports__(br, wanted_ports, true);
+
+    /* Then add interfaces that want automatic port number assignment.
+     * We add these afterward to avoid accidentally taking a specifically
+     * requested port number. */
+    bridge_add_ports__(br, wanted_ports, false);
+}
+
 static void
 port_configure(struct port *port)
 {
@@ -813,9 +884,9 @@ bridge_configure_flow_miss_model(const char *opt)
     enum ofproto_flow_miss_model model = OFPROTO_HANDLE_MISS_AUTO;
 
     if (opt) {
-        if (strcmp(opt, "with-facets")) {
+        if (!strcmp(opt, "with-facets")) {
             model = OFPROTO_HANDLE_MISS_WITH_FACETS;
-        } else if (strcmp(opt, "without-facets")) {
+        } else if (!strcmp(opt, "without-facets")) {
             model = OFPROTO_HANDLE_MISS_WITHOUT_FACETS;
         }
     }
@@ -1331,10 +1402,8 @@ iface_set_netdev_config(const struct ovsrec_interface *iface_cfg,
     return netdev_set_config(netdev, &iface_cfg->options);
 }
 
-/* Opens a network device for 'if_cfg' and configures it.  If '*ofp_portp'
- * is OFPP_NONE, adds the network device to br->ofproto and stores the OpenFlow
- * port number in '*ofp_portp'; otherwise leaves br->ofproto and '*ofp_portp'
- * untouched.
+/* Opens a network device for 'if_cfg' and configures it.  Adds the network
+ * device to br->ofproto and stores the OpenFlow port number in '*ofp_portp'.
  *
  * If successful, returns 0 and stores the network device in '*netdevp'.  On
  * failure, returns a positive errno value and stores NULL in '*netdevp'. */
@@ -1406,17 +1475,10 @@ iface_create(struct bridge *br, const struct ovsrec_interface *iface_cfg,
     struct port *port;
     int error;
 
-    /* Do the bits that can fail up front.
-     *
-     * It's a bit dangerous to call bridge_run_fast() here as ofproto's
-     * internal datastructures may not be consistent.  Eventually, when port
-     * additions and deletions are cheaper, these calls should be removed. */
-    bridge_run_fast();
+    /* Do the bits that can fail up front. */
     ovs_assert(!iface_lookup(br, iface_cfg->name));
     error = iface_do_create(br, iface_cfg, port_cfg, &ofp_port, &netdev);
-    bridge_run_fast();
     if (error) {
-        iface_set_ofport(iface_cfg, OFPP_NONE);
         iface_clear_db_record(iface_cfg);
         return false;
     }
@@ -1441,8 +1503,6 @@ iface_create(struct bridge *br, const struct ovsrec_interface *iface_cfg,
     hmap_insert(&br->ifaces, &iface->ofp_port_node,
                 hash_ofp_port(ofp_port));
 
-    iface_set_ofport(iface->cfg, ofp_port);
-
     /* Populate initial status in database. */
     iface_refresh_stats(iface);
     iface_refresh_status(iface);
@@ -1458,7 +1518,7 @@ iface_create(struct bridge *br, const struct ovsrec_interface *iface_cfg,
 
             error = netdev_open(port->name, "internal", &netdev);
             if (!error) {
-                ofp_port_t fake_ofp_port = iface_pick_ofport(iface_cfg);
+                ofp_port_t fake_ofp_port = OFPP_NONE;
                 ofproto_port_add(br->ofproto, netdev, &fake_ofp_port);
                 netdev_close(netdev);
             } else {
@@ -1999,7 +2059,7 @@ run_system_stats(void)
     }
 }
 
-static inline const char *
+static const char *
 ofp12_controller_role_to_str(enum ofp12_controller_role role)
 {
     switch (role) {
@@ -2106,12 +2166,19 @@ instant_stats_run(void)
 
     if (!instant_txn) {
         struct bridge *br;
+        uint64_t seq;
 
         if (time_msec() < instant_next_txn) {
             return;
         }
         instant_next_txn = time_msec() + INSTANT_INTERVAL_MSEC;
 
+        seq = seq_read(connectivity_seq_get());
+        if (seq == connectivity_seqno) {
+            return;
+        }
+        connectivity_seqno = seq;
+
         instant_txn = ovsdb_idl_txn_create(idl);
         HMAP_FOR_EACH (br, node, &all_bridges) {
             struct iface *iface;
@@ -2188,28 +2255,24 @@ instant_stats_wait(void)
     }
 }
 \f
-/* Performs periodic activity required by bridges that needs to be done with
- * the least possible latency.
- *
- * It makes sense to call this function a couple of times per poll loop, to
- * provide a significant performance boost on some benchmarks with ofprotos
- * that use the ofproto-dpif implementation. */
-void
-bridge_run_fast(void)
+static void
+bridge_run__(void)
 {
+    struct bridge *br;
     struct sset types;
     const char *type;
-    struct bridge *br;
 
+    /* Let each datapath type do the work that it needs to do. */
     sset_init(&types);
     ofproto_enumerate_types(&types);
     SSET_FOR_EACH (type, &types) {
-        ofproto_type_run_fast(type);
+        ofproto_type_run(type);
     }
     sset_destroy(&types);
 
+    /* Let each bridge do the work that it needs to do. */
     HMAP_FOR_EACH (br, node, &all_bridges) {
-        ofproto_run_fast(br->ofproto);
+        ofproto_run(br->ofproto);
     }
 }
 
@@ -2218,8 +2281,6 @@ bridge_run(void)
 {
     static struct ovsrec_open_vswitch null_cfg;
     const struct ovsrec_open_vswitch *cfg;
-    struct sset types;
-    const char *type;
 
     bool vlan_splinters_changed;
     struct bridge *br;
@@ -2262,18 +2323,7 @@ bridge_run(void)
                                         "flow-restore-wait", false));
     }
 
-    /* Let each datapath type do the work that it needs to do. */
-    sset_init(&types);
-    ofproto_enumerate_types(&types);
-    SSET_FOR_EACH (type, &types) {
-        ofproto_type_run(type);
-    }
-    sset_destroy(&types);
-
-    /* Let each bridge do the work that it needs to do. */
-    HMAP_FOR_EACH (br, node, &all_bridges) {
-        ofproto_run(br->ofproto);
-    }
+    bridge_run__();
 
     /* Re-configure SSL.  We do this on every trip through the main loop,
      * instead of just when the database changes, because the contents of the
@@ -2414,6 +2464,15 @@ void
 bridge_get_memory_usage(struct simap *usage)
 {
     struct bridge *br;
+    struct sset types;
+    const char *type;
+
+    sset_init(&types);
+    ofproto_enumerate_types(&types);
+    SSET_FOR_EACH (type, &types) {
+        ofproto_type_get_memory_usage(type, usage);
+    }
+    sset_destroy(&types);
 
     HMAP_FOR_EACH (br, node, &all_bridges) {
         ofproto_get_memory_usage(br->ofproto, usage);
@@ -3429,21 +3488,28 @@ iface_from_ofp_port(const struct bridge *br, ofp_port_t ofp_port)
 /* Set Ethernet address of 'iface', if one is specified in the configuration
  * file. */
 static void
-iface_set_mac(struct iface *iface)
+iface_set_mac(struct iface *iface, const uint8_t *mac)
 {
     uint8_t ea[ETH_ADDR_LEN];
 
-    if (!strcmp(iface->type, "internal")
-        && iface->cfg->mac && eth_addr_from_string(iface->cfg->mac, ea)) {
+    if (strcmp(iface->type, "internal")) {
+        return;
+    }
+
+    if (iface->cfg->mac && eth_addr_from_string(iface->cfg->mac, ea)) {
+        mac = ea;
+    }
+
+    if (mac) {
         if (iface->ofp_port == OFPP_LOCAL) {
             VLOG_ERR("interface %s: ignoring mac in Interface record "
                      "(use Bridge record to set local port's mac)",
                      iface->name);
-        } else if (eth_addr_is_multicast(ea)) {
+        } else if (eth_addr_is_multicast(mac)) {
             VLOG_ERR("interface %s: cannot set MAC to multicast address",
                      iface->name);
         } else {
-            int error = netdev_set_etheraddr(iface->netdev, ea);
+            int error = netdev_set_etheraddr(iface->netdev, mac);
             if (error) {
                 VLOG_ERR("interface %s: setting MAC failed (%s)",
                          iface->name, ovs_strerror(error));
@@ -3471,6 +3537,7 @@ static void
 iface_clear_db_record(const struct ovsrec_interface *if_cfg)
 {
     if (!ovsdb_idl_row_is_synthetic(&if_cfg->header_)) {
+        iface_set_ofport(if_cfg, OFPP_NONE);
         ovsrec_interface_set_status(if_cfg, NULL);
         ovsrec_interface_set_admin_state(if_cfg, NULL);
         ovsrec_interface_set_duplex(if_cfg, NULL);
@@ -3636,14 +3703,27 @@ iface_is_synthetic(const struct iface *iface)
 }
 
 static ofp_port_t
-iface_pick_ofport(const struct ovsrec_interface *cfg)
+iface_validate_ofport__(size_t n, int64_t *ofport)
 {
-    ofp_port_t ofport = cfg->n_ofport ? u16_to_ofp(*cfg->ofport)
-                                      : OFPP_NONE;
-    return cfg->n_ofport_request ? u16_to_ofp(*cfg->ofport_request)
-                                 : ofport;
+    return (n && *ofport >= 1 && *ofport < ofp_to_u16(OFPP_MAX)
+            ? u16_to_ofp(*ofport)
+            : OFPP_NONE);
 }
 
+static ofp_port_t
+iface_get_requested_ofp_port(const struct ovsrec_interface *cfg)
+{
+    return iface_validate_ofport__(cfg->n_ofport_request, cfg->ofport_request);
+}
+
+static ofp_port_t
+iface_pick_ofport(const struct ovsrec_interface *cfg)
+{
+    ofp_port_t requested_ofport = iface_get_requested_ofp_port(cfg);
+    return (requested_ofport != OFPP_NONE
+            ? requested_ofport
+            : iface_validate_ofport__(cfg->n_ofport, cfg->ofport));
+}
 \f
 /* Port mirroring. */