{
COVERAGE_INC(bridge_flush);
br->flush = true;
- mac_learning_flush(br->ml);
}
\f
/* Bridge unixctl user interface functions. */
shash_destroy(&new_ifaces);
}
+/* Expires all MAC learning entries associated with 'port' and forces ofproto
+ * to revalidate every flow. */
+static void
+port_flush_macs(struct port *port)
+{
+ struct bridge *br = port->bridge;
+ struct mac_learning *ml = br->ml;
+ struct mac_entry *mac, *next_mac;
+
+ bridge_flush(br);
+ LIST_FOR_EACH_SAFE (mac, next_mac, lru_node, &ml->lrus) {
+ if (mac->port.p == port) {
+ mac_learning_expire(ml, mac);
+ }
+ }
+}
+
static void
port_reconfigure(struct port *port, const struct ovsrec_port *cfg)
{
const char *detect_mode;
struct shash new_ifaces;
long long int next_rebalance, miimon_next_update, lacp_priority;
+ bool need_flush = false;
unsigned long *trunks;
int vlan;
size_t i;
}
if (port->vlan != vlan) {
port->vlan = vlan;
- bridge_flush(port->bridge);
+ need_flush = true;
}
/* Get trunked VLANs. */
if (trunks == NULL
? port->trunks != NULL
: port->trunks == NULL || !bitmap_equal(trunks, port->trunks, 4096)) {
- bridge_flush(port->bridge);
+ need_flush = true;
}
bitmap_free(port->trunks);
port->trunks = trunks;
+
+ if (need_flush) {
+ port_flush_macs(port);
+ }
}
static void
VLOG_INFO("destroyed port %s on bridge %s", port->name, br->name);
+ port_flush_macs(port);
+
netdev_monitor_destroy(port->monitor);
bitmap_free(port->trunks);
free(port->name);
free(port);
- bridge_flush(br);
}
}
}
if (mac_learning_set_flood_vlans(br->ml, rspan_vlans)) {
bridge_flush(br);
+ mac_learning_flush(br->ml);
}
}
VLOG_INFO("created port mirror %s on bridge %s", cfg->name, br->name);
bridge_flush(br);
+ mac_learning_flush(br->ml);
br->mirrors[i] = m = xzalloc(sizeof *m);
m->bridge = br;
free(m);
bridge_flush(br);
+ mac_learning_flush(br->ml);
}
}
|| m->out_port != out_port
|| m->out_vlan != out_vlan) {
bridge_flush(m->bridge);
+ mac_learning_flush(m->bridge->ml);
}
shash_swap(&m->src_ports, &src_ports);
shash_swap(&m->dst_ports, &dst_ports);