: NULL;
}
-static enum stp_state
+static bool
xport_stp_learn_state(const struct xport *xport)
{
struct stp_port *sp = xport_get_stp_port(xport);
return stp_forward_in_state(sp ? stp_port_get_state(sp) : STP_DISABLED);
}
+static bool
+xport_stp_listen_state(const struct xport *xport)
+{
+ struct stp_port *sp = xport_get_stp_port(xport);
+ return stp_listen_in_state(sp ? stp_port_get_state(sp) : STP_DISABLED);
+}
+
/* Returns true if STP should process 'flow'. Sets fields in 'wc' that
* were used to make the determination.*/
static bool
} else if (xport->config & OFPUTIL_PC_NO_FWD) {
xlate_report(ctx, "OFPPC_NO_FWD set, skipping output");
return;
- } else if (check_stp && !xport_stp_forward_state(xport)) {
- xlate_report(ctx, "STP not in forwarding state, skipping output");
- return;
+ } else if (check_stp) {
+ if (eth_addr_equals(ctx->base_flow.dl_dst, eth_addr_stp)) {
+ if (!xport_stp_listen_state(xport)) {
+ xlate_report(ctx, "STP not in listening state, "
+ "skipping bpdu output");
+ return;
+ }
+ } else if (!xport_stp_forward_state(xport)) {
+ xlate_report(ctx, "STP not in forwarding state, "
+ "skipping output");
+ return;
+ }
}
if (mbridge_has_mirrors(ctx->xbridge->mbridge) && xport->xbundle) {
ctx->rule = rule;
actions = rule_dpif_get_actions(rule);
do_xlate_actions(actions->ofpacts, actions->ofpacts_len, ctx);
- rule_actions_unref(actions);
ctx->rule = old_rule;
ctx->recurse--;
}
}
out:
- rule_actions_unref(actions);
rule_dpif_unref(rule);
}
struct xport *xport;
struct ofpact_output output;
struct flow flow;
- union flow_in_port in_port_;
ofpact_init(&output.ofpact, OFPACT_OUTPUT, sizeof output);
/* Use OFPP_NONE as the in_port to avoid special packet processing. */
- in_port_.ofp_port = OFPP_NONE;
- flow_extract(packet, 0, 0, NULL, &in_port_, &flow);
+ flow_extract(packet, NULL, &flow);
+ flow.in_port.ofp_port = OFPP_NONE;
ovs_rwlock_rdlock(&xlate_rwlock);
xport = xport_lookup(ofport);