}
}
-/* Executes, within 'ofproto', the 'n_actions' actions in 'actions' on
- * 'packet', which arrived on 'in_port'. */
-static int
-execute_actions(struct ofproto *ofproto_, const struct flow *flow,
- struct rule_dpif *rule,
- const struct ofpact *ofpacts, size_t ofpacts_len,
- struct ofpbuf *packet)
+/* Executes, within 'ofproto', the actions in 'rule' or 'ofpacts' on 'packet'.
+ * 'flow' must reflect the data in 'packet'. */
+int
+ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto,
+ const struct flow *flow,
+ struct rule_dpif *rule,
+ const struct ofpact *ofpacts, size_t ofpacts_len,
+ struct ofpbuf *packet)
{
- struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
struct odputil_keybuf keybuf;
struct dpif_flow_stats stats;
struct xlate_out xout;
odp_flow_key_from_flow(&key, flow, ofp_port_to_odp_port(ofproto, in_port));
error = dpif_execute(ofproto->backer->dpif, key.data, key.size,
- xout.odp_actions.data, xout.odp_actions.size, packet);
+ xout.odp_actions.data, xout.odp_actions.size, packet,
+ (xout.slow & SLOW_ACTION) != 0);
xlate_out_uninit(&xout);
return error;
rule_dpif_execute(struct rule_dpif *rule, const struct flow *flow,
struct ofpbuf *packet)
{
- execute_actions(rule->up.ofproto, flow, rule, NULL, 0, packet);
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
+
+ ofproto_dpif_execute_actions(ofproto, flow, rule, NULL, 0, packet);
}
static enum ofperr
}
static enum ofperr
-packet_out(struct ofproto *ofproto, struct ofpbuf *packet,
+packet_out(struct ofproto *ofproto_, struct ofpbuf *packet,
const struct flow *flow,
const struct ofpact *ofpacts, size_t ofpacts_len)
{
- execute_actions(ofproto, flow, NULL, ofpacts, ofpacts_len, packet);
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+
+ ofproto_dpif_execute_actions(ofproto, flow, NULL, ofpacts,
+ ofpacts_len, packet);
return 0;
}
\f
trace.xout.odp_actions.size);
if (trace.xout.slow) {
+ enum slow_path_reason slow;
+
ds_put_cstr(ds, "\nThis flow is handled by the userspace "
"slow path because it:");
- switch (trace.xout.slow) {
- case SLOW_CFM:
- ds_put_cstr(ds, "\n\t- Consists of CFM packets.");
- break;
- case SLOW_LACP:
- ds_put_cstr(ds, "\n\t- Consists of LACP packets.");
- break;
- case SLOW_STP:
- ds_put_cstr(ds, "\n\t- Consists of STP packets.");
- break;
- case SLOW_BFD:
- ds_put_cstr(ds, "\n\t- Consists of BFD packets.");
- break;
- case SLOW_CONTROLLER:
- ds_put_cstr(ds, "\n\t- Sends \"packet-in\" messages "
- "to the OpenFlow controller.");
- break;
- case __SLOW_MAX:
- NOT_REACHED();
+
+ slow = trace.xout.slow;
+ while (slow) {
+ enum slow_path_reason bit = rightmost_1bit(slow);
+
+ ds_put_format(ds, "\n\t- %s.",
+ slow_path_reason_to_explanation(bit));
+
+ slow &= ~bit;
}
}