dpif_close(dpif);
}
}
+ svec_destroy(&dpif_names);
unixctl_command_register("bridge/dump-flows", bridge_unixctl_dump_flows);
!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;
}
}
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. */
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. */
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)
{
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. */
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",
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);
}
/* Clean up. */
+exit:
svec_destroy(&src_ports);
svec_destroy(&dst_ports);
free(pfx);