uint32_t basis; /* Keeps each table's tags separate. */
};
+/* Reasons that we might need to revalidate every facet, and corresponding
+ * coverage counters.
+ *
+ * A value of 0 means that there is no need to revalidate.
+ *
+ * It would be nice to have some cleaner way to integrate with coverage
+ * counters, but with only a few reasons I guess this is good enough for
+ * now. */
+enum revalidate_reason {
+ REV_RECONFIGURE = 1, /* Switch configuration changed. */
+ REV_STP, /* Spanning tree protocol port status change. */
+ REV_PORT_TOGGLED, /* Port enabled or disabled by CFM, LACP, ...*/
+ REV_FLOW_TABLE, /* Flow table changed. */
+ REV_INCONSISTENCY /* Facet self-check failed. */
+};
+COVERAGE_DEFINE(rev_reconfigure);
+COVERAGE_DEFINE(rev_stp);
+COVERAGE_DEFINE(rev_port_toggled);
+COVERAGE_DEFINE(rev_flow_table);
+COVERAGE_DEFINE(rev_inconsistency);
+
struct ofproto_dpif {
struct hmap_node all_ofproto_dpifs_node; /* In 'all_ofproto_dpifs'. */
struct ofproto up;
/* Revalidation. */
struct table_dpif tables[N_TABLES];
- bool need_revalidate;
+ enum revalidate_reason need_revalidate;
struct tag_set revalidate_set;
/* Support for debugging async flow mods. */
table->other_table = NULL;
table->basis = random_uint32();
}
- ofproto->need_revalidate = false;
+ ofproto->need_revalidate = 0;
tag_set_init(&ofproto->revalidate_set);
list_init(&ofproto->completions);
bool revalidate_all = ofproto->need_revalidate;
struct facet *facet;
+ switch (ofproto->need_revalidate) {
+ case REV_RECONFIGURE: COVERAGE_INC(rev_reconfigure); break;
+ case REV_STP: COVERAGE_INC(rev_stp); break;
+ case REV_PORT_TOGGLED: COVERAGE_INC(rev_port_toggled); break;
+ case REV_FLOW_TABLE: COVERAGE_INC(rev_flow_table); break;
+ case REV_INCONSISTENCY: COVERAGE_INC(rev_inconsistency); break;
+ }
+
/* Clear the revalidation flags. */
tag_set_init(&ofproto->revalidate_set);
- ofproto->need_revalidate = false;
+ ofproto->need_revalidate = 0;
HMAP_FOR_EACH (facet, hmap_node, &ofproto->facets) {
if (revalidate_all
struct facet, hmap_node);
if (!tag_set_intersects(&ofproto->revalidate_set, facet->tags)) {
if (!facet_check_consistency(facet)) {
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_INCONSISTENCY;
}
}
}
struct ofport_dpif *port = ofport_dpif_cast(port_);
struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto);
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
port->odp_port = ofp_port_to_odp_port(port->up.ofp_port);
port->bundle = NULL;
port->cfm = NULL;
struct ofport_dpif *port = ofport_dpif_cast(port_);
struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto);
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
bundle_remove(port_);
set_cfm(port_, NULL);
if (ofproto->sflow) {
if (changed & (OFPUTIL_PC_NO_RECV | OFPUTIL_PC_NO_RECV_STP |
OFPUTIL_PC_NO_FWD | OFPUTIL_PC_NO_FLOOD |
OFPUTIL_PC_NO_PACKET_IN)) {
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
if (changed & OFPUTIL_PC_NO_FLOOD && port->bundle) {
bundle_update(port->bundle);
HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
dpif_sflow_add_port(ds, &ofport->up);
}
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
}
dpif_sflow_set_options(ds, sflow_options);
} else {
if (ds) {
dpif_sflow_destroy(ds);
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
ofproto->sflow = NULL;
}
}
struct ofproto_dpif *ofproto;
ofproto = ofproto_dpif_cast(ofport->up.ofproto);
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
ofport->cfm = cfm_create(netdev_get_name(ofport->up.netdev));
}
/* Only revalidate flows if the configuration changed. */
if (!s != !ofproto->stp) {
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
}
if (s) {
fwd_change = stp_forward_in_state(ofport->stp_state)
!= stp_forward_in_state(state);
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_STP;
ofport->stp_state = state;
ofport->stp_state_entered = time_msec();
pdscp = xmalloc(sizeof *pdscp);
pdscp->priority = priority;
pdscp->dscp = dscp;
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
}
if (pdscp->dscp != dscp) {
pdscp->dscp = dscp;
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
}
hmap_insert(&new, &pdscp->hmap_node, hash_int(pdscp->priority, 0));
if (!hmap_is_empty(&ofport->priorities)) {
ofport_clear_priorities(ofport);
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
}
hmap_swap(&new, &ofport->priorities);
struct mac_learning *ml = ofproto->ml;
struct mac_entry *mac, *next_mac;
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
LIST_FOR_EACH_SAFE (mac, next_mac, lru_node, &ml->lrus) {
if (mac->port.p == bundle) {
if (all_ofprotos) {
{
struct ofbundle *bundle = port->bundle;
- bundle->ofproto->need_revalidate = true;
+ bundle->ofproto->need_revalidate = REV_RECONFIGURE;
list_remove(&port->bundle_node);
port->bundle = NULL;
}
if (port->bundle != bundle) {
- bundle->ofproto->need_revalidate = true;
+ bundle->ofproto->need_revalidate = REV_RECONFIGURE;
if (port->bundle) {
bundle_del_port(port);
}
}
}
if (lacp) {
- port->bundle->ofproto->need_revalidate = true;
+ port->bundle->ofproto->need_revalidate = REV_RECONFIGURE;
lacp_slave_register(bundle->lacp, port, lacp);
}
mirror_destroy(m);
} else if (hmapx_find_and_delete(&m->srcs, bundle)
|| hmapx_find_and_delete(&m->dsts, bundle)) {
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
}
}
}
/* LACP. */
if (s->lacp) {
if (!bundle->lacp) {
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
bundle->lacp = lacp_create();
}
lacp_configure(bundle->lacp, s->lacp);
bundle->ofproto->has_bonded_bundles = true;
if (bundle->bond) {
if (bond_reconfigure(bundle->bond, s->bond)) {
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
}
} else {
bundle->bond = bond_create(s->bond);
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
}
LIST_FOR_EACH (port, bundle_node, &bundle->ports) {
}
}
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
ofproto->has_mirrors = true;
mac_learning_flush(ofproto->ml, &ofproto->revalidate_set);
mirror_update_dups(ofproto);
}
ofproto = mirror->ofproto;
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
mac_learning_flush(ofproto->ml, &ofproto->revalidate_set);
mirror_bit = MIRROR_MASK_C(1) << mirror->idx;
forward_bpdu_changed(struct ofproto *ofproto_)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
- /* Revalidate cached flows whenever forward_bpdu option changes. */
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
}
static void
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
if (ofproto->has_bundle_action) {
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_PORT_TOGGLED;
}
}
if (table->catchall_table != catchall || table->other_table != other) {
table->catchall_table = catchall;
table->other_table = other;
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_FLOW_TABLE;
}
}
if (table->other_table && rule->tag) {
tag_set_add(&ofproto->revalidate_set, rule->tag);
} else {
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_FLOW_TABLE;
}
}
}
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
if (frag_handling != OFPC_FRAG_REASM) {
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
return true;
} else {
return false;
}
}
if (errors) {
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_INCONSISTENCY;
}
if (errors) {
return 0;
}
- ofproto->need_revalidate = true;
+ ofproto->need_revalidate = REV_RECONFIGURE;
if (ofport->realdev_ofp_port) {
vsp_remove(ofport);