/* Flow tracking. */
struct ft *ft;
struct tag_set revalidate_set;
+ bool flush;
/* Flow statistics gathering. */
struct stats_mgr *stats_mgr;
stats_mgr_wait(br->stats_mgr);
flowstats_wait(br);
bond_wait(br);
+ if (!tag_set_is_empty(&br->revalidate_set)) {
+ poll_immediate_wake();
+ }
+ }
+}
+
+/* Forces 'br' to revalidate all of its flows. This is appropriate when 'br''s
+ * configuration changes. */
+void
+bridge_flush(struct bridge *br)
+{
+ br->flush = true;
+ if (br->ml) {
+ mac_learning_flush(br->ml);
}
}
\f
port_array_init(&br->ifaces);
br->ft = ft_create();
+ tag_set_init(&br->revalidate_set);
+ br->flush = false;
br->stats_mgr = stats_mgr_create(br->rconn);
}
}
- tag_set_init(&br->revalidate_set);
-
/* Now do the things that may want to revalidate flows. */
for (iteration = 0; iteration < 50 && !bridge_is_backlogged(br);
iteration++) {
flowstats_run(br);
bond_run(br);
+ /* Start or restart secchan if necessary. */
+ run_secchan(br);
+
/* Now revalidate any flows that need it. */
- if (!tag_set_is_empty(&br->revalidate_set)) {
+ if (br->flush || !tag_set_is_empty(&br->revalidate_set)) {
struct ft_flow *f, *next;
HMAP_FOR_EACH_SAFE (f, next, struct ft_flow, node, &br->ft->flows) {
- if (tag_set_intersects(&br->revalidate_set, f->tags)) {
+ if (br->flush
+ || tag_set_intersects(&br->revalidate_set, f->tags)) {
revalidate_flow(br, f);
}
}
}
-
- /* Start or restart secchan if necessary. */
- run_secchan(br);
+ tag_set_init(&br->revalidate_set);
+ br->flush = false;
}
static void
uint16_t out_port_idx;
bool may_learn;
- /* XXX flush learning table entries when port indexes change due to
- * reconfiguration */
-
if (!pkt->buf) {
/* Don't try to learn from revalidation. */
may_learn = false;
br->ports[br->n_ports++] = port;
VLOG_WARN("created port %s on bridge %s", port->name, br->name);
+ bridge_flush(br);
}
static void
{
bool bonded = cfg_has_section("bonding.%s", port->name);
struct svec old_ifaces, new_ifaces;
+ int vlan;
size_t i;
/* Collect old and new interfaces. */
}
/* Get VLAN tag. */
- port->vlan = 0;
+ vlan = 0;
if (cfg_has("vlan.%s.tag", port->name)) {
if (!bonded) {
- int vlan = cfg_get_int(0, "vlan.%s.tag", port->name);
- if (port->vlan >= 0 && port->vlan <= 4095) {
- VLOG_DBG("port %s: assigning VLAN tag %d",
- port->name, port->vlan);
- port->vlan = vlan;
+ vlan = cfg_get_int(0, "vlan.%s.tag", port->name);
+ if (vlan >= 0 && vlan <= 4095) {
+ VLOG_DBG("port %s: assigning VLAN tag %d", port->name, vlan);
} else {
VLOG_WARN("port %s: ignoring VLAN tag %d because it is not in "
- "the valid range from 0 to 4095",
- port->name, port->vlan);
+ "the valid range from 0 to 4095", port->name, vlan);
+ vlan = 0;
}
} else {
/* It's possible that bonded, VLAN-tagged ports make sense. Maybe
port->name);
}
}
+ if (port->vlan != vlan) {
+ port->vlan = vlan;
+ bridge_flush(port->bridge);
+ }
svec_destroy(&old_ifaces);
svec_destroy(&new_ifaces);
}
}
free(port->ifaces);
free(port);
+ bridge_flush(br);
}
}
VLOG_DBG("attached network device %s to port %s", iface->name, port->name);
port_update_bonding(port);
+ bridge_flush(port->bridge);
}
static void
free(iface);
port_update_bonding(port);
+ bridge_flush(port->bridge);
}
}