VLOG_DEFINE_THIS_MODULE(ofproto_dpif);
-COVERAGE_DEFINE(ofproto_dpif_ctlr_action);
COVERAGE_DEFINE(ofproto_dpif_expired);
COVERAGE_DEFINE(ofproto_dpif_xlate);
COVERAGE_DEFINE(facet_changed_rule);
-COVERAGE_DEFINE(facet_invalidated);
COVERAGE_DEFINE(facet_revalidate);
COVERAGE_DEFINE(facet_unexpected);
COVERAGE_DEFINE(facet_suppress);
}
static void port_run(struct ofport_dpif *);
+static void port_run_fast(struct ofport_dpif *);
static void port_wait(struct ofport_dpif *);
static int set_cfm(struct ofport *, const struct cfm_settings *);
static void ofport_clear_priorities(struct ofport_dpif *);
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);
run_fast(struct ofproto *ofproto_)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+ struct ofport_dpif *ofport;
unsigned int work;
+ HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
+ port_run_fast(ofport);
+ }
+
/* Handle one or more batches of upcalls, until there's nothing left to do
* or until we do a fixed total amount of work.
*
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
ofproto_port->ofp_port = odp_port_to_ofp_port(dpif_port->port_no);
}
+static void
+port_run_fast(struct ofport_dpif *ofport)
+{
+ if (ofport->cfm && cfm_should_send_ccm(ofport->cfm)) {
+ struct ofpbuf packet;
+
+ ofpbuf_init(&packet, 0);
+ cfm_compose_ccm(ofport->cfm, &packet, ofport->up.pp.hw_addr);
+ send_packet(ofport, &packet);
+ ofpbuf_uninit(&packet);
+ }
+}
+
static void
port_run(struct ofport_dpif *ofport)
{
ofport->carrier_seq = carrier_seq;
+ port_run_fast(ofport);
if (ofport->cfm) {
cfm_run(ofport->cfm);
-
- if (cfm_should_send_ccm(ofport->cfm)) {
- struct ofpbuf packet;
-
- ofpbuf_init(&packet, 0);
- cfm_compose_ccm(ofport->cfm, &packet, ofport->up.pp.hw_addr);
- send_packet(ofport, &packet);
- ofpbuf_uninit(&packet);
- }
-
enable = enable && !cfm_get_fault(ofport->cfm)
&& cfm_get_opup(ofport->cfm);
}
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;
}
}
code = ofputil_decode_action_unsafe(ia);
switch (code) {
+ case OFPUTIL_ACTION_INVALID:
+ NOT_REACHED();
+
case OFPUTIL_OFPAT10_OUTPUT:
xlate_output_action(ctx, &ia->output);
break;
ctx->mirrors |= m->dup_mirrors;
if (m->out) {
output_normal(ctx, m->out, vlan);
- } else if (!eth_addr_is_reserved(orig_flow->dl_dst)
- && vlan != m->out_vlan) {
+ } else if (vlan != m->out_vlan
+ && !eth_addr_is_reserved(orig_flow->dl_dst)) {
struct ofbundle *bundle;
HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
* we don't know about.
*
* - The ofproto client didn't configure the port as part of a bundle.
+ * This is particularly likely to happen if a packet was received on the
+ * port after it was created, but before the client had a chance to
+ * configure its bundle.
*/
if (warn) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
/* Drop frames for reserved multicast addresses
* only if forward_bpdu option is absent. */
- if (eth_addr_is_reserved(flow->dl_dst) && !ofproto->up.forward_bpdu) {
+ if (!ofproto->up.forward_bpdu && eth_addr_is_reserved(flow->dl_dst)) {
return false;
}
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);