vswitchd: Fix unimportant memory leak.
[openvswitch] / vswitchd / bridge.c
index 25df8d48e443007c45bc45c0b160b0b8233e67b8..ac993bfce05c0036ca5d7ddba761769374630787 100644 (file)
@@ -312,6 +312,7 @@ bridge_init(void)
             dpif_close(dpif);
         }
     }
+    svec_destroy(&dpif_names);
 
     unixctl_command_register("bridge/dump-flows", bridge_unixctl_dump_flows);
 
@@ -741,6 +742,7 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN],
             !eth_addr_is_zero(iface_ea) &&
             memcmp(iface_ea, ea, ETH_ADDR_LEN) < 0)
         {
+            memcpy(ea, iface_ea, ETH_ADDR_LEN);
             *hw_addr_iface = iface;
         }
     }
@@ -1773,12 +1775,14 @@ compose_dsts(const struct bridge *br, const flow_t *flow, uint16_t vlan,
                 for (i = 0; i < br->n_ports; i++) {
                     struct port *port = br->ports[i];
                     if (port_includes_vlan(port, m->out_vlan)
-                        && set_dst(dst, flow, in_port, port, tags)
-                        && !dst_is_duplicate(dsts, dst - dsts, dst))
+                        && set_dst(dst, flow, in_port, port, tags))
                     {
                         if (port->vlan < 0) {
                             dst->vlan = m->out_vlan;
                         }
+                        if (dst_is_duplicate(dsts, dst - dsts, dst)) {
+                            continue;
+                        }
                         if (dst->dp_ifidx == flow->in_port
                             && dst->vlan == vlan) {
                             /* Don't send out input port on same VLAN. */
@@ -1952,7 +1956,7 @@ process_flow(struct bridge *br, const flow_t *flow,
             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
+             * input port, because we probably sent the packet on one slave
              * and got it back on the active slave.  Broadcast ARP replies are
              * an exception to this rule: the host has moved to another
              * switch. */
@@ -2747,6 +2751,25 @@ bond_unixctl_disable_slave(struct unixctl_conn *conn, const char *args)
     enable_slave(conn, args, false);
 }
 
+static void
+bond_unixctl_hash(struct unixctl_conn *conn, const char *args)
+{
+       uint8_t mac[ETH_ADDR_LEN];
+       uint8_t hash;
+       char *hash_cstr;
+
+       if (sscanf(args, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
+           == ETH_ADDR_SCAN_COUNT) {
+               hash = bond_hash(mac);
+
+               hash_cstr = xasprintf("%u", hash);
+               unixctl_command_reply(conn, 200, hash_cstr);
+               free(hash_cstr);
+       } else {
+               unixctl_command_reply(conn, 501, "invalid mac");
+       }
+}
+
 static void
 bond_init(void)
 {
@@ -2757,6 +2780,7 @@ bond_init(void)
                              bond_unixctl_set_active_slave);
     unixctl_command_register("bond/enable-slave", bond_unixctl_enable_slave);
     unixctl_command_register("bond/disable-slave", bond_unixctl_disable_slave);
+    unixctl_command_register("bond/hash", bond_unixctl_hash);
 }
 \f
 /* Port functions. */
@@ -3368,6 +3392,7 @@ mirror_reconfigure_one(struct mirror *m)
     int *vlans;
     size_t i;
     bool mirror_all_ports;
+    bool any_ports_specified;
 
     /* Get output port. */
     out_port_name = cfg_get_key(0, "mirror.%s.%s.output.port",
@@ -3406,11 +3431,18 @@ mirror_reconfigure_one(struct mirror *m)
     cfg_get_all_keys(&src_ports, "%s.select.src-port", pfx);
     cfg_get_all_keys(&dst_ports, "%s.select.dst-port", pfx);
     cfg_get_all_keys(&ports, "%s.select.port", pfx);
+    any_ports_specified = src_ports.n || dst_ports.n || ports.n;
     svec_append(&src_ports, &ports);
     svec_append(&dst_ports, &ports);
     svec_destroy(&ports);
     prune_ports(m, &src_ports);
     prune_ports(m, &dst_ports);
+    if (any_ports_specified && !src_ports.n && !dst_ports.n) {
+        VLOG_ERR("%s: none of the specified ports exist; "
+                 "disabling port mirror %s", pfx, pfx);
+        mirror_destroy(m);
+        goto exit;
+    }
 
     /* Get all the vlans, and drop duplicate and invalid vlans. */
     svec_init(&vlan_strings);
@@ -3462,6 +3494,7 @@ mirror_reconfigure_one(struct mirror *m)
     }
 
     /* Clean up. */
+exit:
     svec_destroy(&src_ports);
     svec_destroy(&dst_ports);
     free(pfx);