vswitchd: Add missing argument to check for update-resolv.conf config
[openvswitch] / vswitchd / bridge.c
index b266c1056d94e5421b67676df930cfa80e2493ad..febf63bea52b1e1e4a037c4fbd093b4043382617 100644 (file)
@@ -1,28 +1,16 @@
 /* Copyright (c) 2008, 2009 Nicira Networks
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
  *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * In addition, as a special exception, Nicira Networks gives permission
- * to link the code of its release of vswitchd with the OpenSSL project's
- * "OpenSSL" library (or with modified versions of it that use the same
- * license as the "OpenSSL" library), and distribute the linked
- * executables.  You must obey the GNU General Public License in all
- * respects for all of the code used other than "OpenSSL".  If you modify
- * this file, you may extend this exception to your version of the file,
- * but you are not obligated to do so.  If you do not wish to do so,
- * delete this exception statement from your version.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #include <config.h>
@@ -39,6 +27,7 @@
 #include <strings.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
+#include <sys/types.h>
 #include <unistd.h>
 #include "bitmap.h"
 #include "cfg.h"
@@ -335,6 +324,7 @@ bridge_configure_ssl(void)
     static char *private_key_file;
     static char *certificate_file;
     static char *cacert_file;
+    struct stat s;
 
     if (config_string_change("ssl.private-key", &private_key_file)) {
         vconn_ssl_set_private_key_file(private_key_file);
@@ -344,7 +334,13 @@ bridge_configure_ssl(void)
         vconn_ssl_set_certificate_file(certificate_file);
     }
 
-    if (config_string_change("ssl.ca-cert", &cacert_file)) {
+    /* We assume that even if the filename hasn't changed, if the CA cert 
+     * file has been removed, that we want to move back into
+     * boot-strapping mode.  This opens a small security hole, because
+     * the old certificate will still be trusted until vSwitch is
+     * restarted.  We may want to address this in vconn's SSL library. */
+    if (config_string_change("ssl.ca-cert", &cacert_file)
+            || (stat(cacert_file, &s) && errno == ENOENT)) {
         vconn_ssl_set_ca_cert_file(cacert_file,
                                    cfg_get_bool(0, "ssl.bootstrap-ca-cert"));
     }
@@ -732,10 +728,10 @@ bridge_pick_datapath_id(struct bridge *br,
 static uint64_t
 dpid_from_hash(const void *data, size_t n)
 {
-    uint8_t hash[SHA1HashSize];
+    uint8_t hash[SHA1_DIGEST_SIZE];
 
     BUILD_ASSERT_DECL(sizeof hash >= ETH_ADDR_LEN);
-    SHA1Bytes(data, n, hash);
+    sha1_bytes(data, n, hash);
     eth_addr_mark_random(hash);
     return eth_addr_to_uint64(hash);
 }
@@ -1080,10 +1076,15 @@ bridge_reconfigure_controller(struct bridge *br)
         int rate_limit, burst_limit;
 
         if (!strcmp(controller, "discover")) {
+            bool update_resolv_conf = true;
+
+            if (cfg_has("%s.update-resolv.conf", pfx)) {
+                update_resolv_conf = cfg_get_bool(0, "%s.update-resolv.conf",
+                        pfx);
+            }
             ofproto_set_discovery(br->ofproto, true,
                                   cfg_get_string(0, "%s.accept-regex", pfx),
-                                  cfg_get_bool(0, "%s.update-resolv.conf",
-                                               pfx));
+                                  update_resolv_conf);
         } else {
             struct netdev *netdev;
             bool in_band;
@@ -1135,8 +1136,13 @@ bridge_reconfigure_controller(struct bridge *br)
                              || !strcmp(fail_mode, "open")));
 
         probe = cfg_get_int(0, "%s.inactivity-probe", pfx);
-        ofproto_set_probe_interval(br->ofproto,
-                                   probe ? probe : cfg_get_int(0, "mgmt.inactivity-probe"));
+        if (probe < 5) {
+            probe = cfg_get_int(0, "mgmt.inactivity-probe");
+            if (probe < 5) {
+                probe = 15;
+            }
+        }
+        ofproto_set_probe_interval(br->ofproto, probe);
 
         max_backoff = cfg_get_int(0, "%s.max-backoff", pfx);
         if (!max_backoff) {
@@ -1744,12 +1750,32 @@ process_flow(struct bridge *br, const flow_t *flow,
         goto done;
     }
 
-    /* Drop multicast and broadcast packets on inactive bonded interfaces, to
+    /* Multicast (and broadcast) packets on bonds need special attention, to
      * avoid receiving duplicates. */
     if (in_port->n_ifaces > 1 && eth_addr_is_multicast(flow->dl_dst)) {
         *tags |= in_port->active_iface_tag;
         if (in_port->active_iface != in_iface->port_ifidx) {
+            /* Drop all multicast packets on inactive slaves. */
             goto done;
+        } else {
+            /* Drop all multicast packets for which we have learned a different
+             * input port, because we probably sent the packet on one slaves
+             * and got it back on the active slave.  Broadcast ARP replies are
+             * an exception to this rule: the host has moved to another
+             * switch. */
+            int src_idx = mac_learning_lookup(br->ml, flow->dl_src, vlan);
+            if (src_idx != -1 && src_idx != in_port->port_idx) {
+                if (packet) {
+                    if (!is_bcast_arp_reply(flow, packet)) {
+                        goto done;
+                    }
+                } else {
+                    /* No way to know whether it's an ARP reply, because the
+                     * flow entry doesn't include enough information and we
+                     * don't have a packet.  Punt. */
+                    return false;
+                }
+            }
         }
     }
 
@@ -1757,27 +1783,9 @@ process_flow(struct bridge *br, const flow_t *flow,
     out_port = FLOOD_PORT;
     if (br->ml) {
         int out_port_idx;
-        bool may_learn;
-
-        if (!packet) {
-            /* Don't try to learn from revalidation. */
-            may_learn = false;
-        } else if (in_port->n_ifaces > 1) {
-            /* If the packet arrived on a bonded port, don't learn from it
-             * unless we haven't learned any port at all for that address
-             * (because we probably sent the packet on one bonded interface and
-             * got it back on the other).  Broadcast ARP replies are an
-             * exception to this rule: the host has moved to another switch. */
-            int src_idx = mac_learning_lookup(br->ml, flow->dl_src, vlan);
-            may_learn = (src_idx < 0
-                         || src_idx == in_port->port_idx
-                         || is_bcast_arp_reply(flow, packet));
-        } else {
-            may_learn = true;
-        }
 
-        /* Learn source MAC. */
-        if (may_learn) {
+        /* Learn source MAC (but don't try to learn from revalidation). */
+        if (packet) {
             tag_type rev_tag = mac_learning_learn(br->ml, flow->dl_src,
                                                   vlan, in_port->port_idx);
             if (rev_tag) {