Merge branch 'mainstream'
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index b8b15e3..69625cf 100644 (file)
@@ -3801,24 +3801,49 @@ facet_free(struct facet *facet)
     }
 }
 
-/* Executes, within 'ofproto', the 'n_actions' actions in 'actions' on
- * 'packet', which arrived on 'in_port'. */
-static bool
-execute_odp_actions(struct ofproto_dpif *ofproto, const struct flow *flow,
-                    const struct nlattr *odp_actions, size_t actions_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 odputil_keybuf keybuf;
+    struct dpif_flow_stats stats;
+    struct xlate_out xout;
+    struct xlate_in xin;
+    ofp_port_t in_port;
     struct ofpbuf key;
     int error;
 
+    ovs_assert((rule != NULL) != (ofpacts != NULL));
+
+    dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
+    if (rule) {
+        rule_dpif_credit_stats(rule, &stats);
+    }
+
+    xlate_in_init(&xin, ofproto, flow, rule, stats.tcp_flags, packet);
+    xin.ofpacts = ofpacts;
+    xin.ofpacts_len = ofpacts_len;
+    xin.resubmit_stats = &stats;
+    xlate_actions(&xin, &xout);
+
     ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
-    odp_flow_key_from_flow(&key, flow,
-                           ofp_port_to_odp_port(ofproto, flow->in_port.ofp_port));
+    in_port = flow->in_port.ofp_port;
+    if (in_port == OFPP_NONE) {
+        in_port = OFPP_LOCAL;
+    }
+    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,
-                         odp_actions, actions_len, packet);
-    return !error;
+                         xout.odp_actions.data, xout.odp_actions.size, packet,
+                         (xout.slow & SLOW_ACTION) != 0);
+    xlate_out_uninit(&xout);
+
+    return error;
 }
 
 /* Remove 'facet' from its ofproto and free up the associated memory:
@@ -4737,21 +4762,8 @@ rule_dpif_execute(struct rule_dpif *rule, const struct flow *flow,
                   struct ofpbuf *packet)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
-    struct dpif_flow_stats stats;
-    struct xlate_out xout;
-    struct xlate_in xin;
-
-    dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
-    rule_dpif_credit_stats(rule, &stats);
-
-    xlate_in_init(&xin, ofproto, flow, rule, stats.tcp_flags, packet);
-    xin.resubmit_stats = &stats;
-    xlate_actions(&xin, &xout);
-
-    execute_odp_actions(ofproto, flow, xout.odp_actions.data,
-                        xout.odp_actions.size, packet);
 
-    xlate_out_uninit(&xout);
+    ofproto_dpif_execute_actions(ofproto, flow, rule, NULL, 0, packet);
 }
 
 static enum ofperr
@@ -4856,30 +4868,9 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf *packet,
            const struct ofpact *ofpacts, size_t ofpacts_len)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
-    struct odputil_keybuf keybuf;
-    struct dpif_flow_stats stats;
-    struct xlate_out xout;
-    struct xlate_in xin;
-    struct ofpbuf key;
-
-
-    ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
-    odp_flow_key_from_flow(&key, flow,
-                           ofp_port_to_odp_port(ofproto,
-                                      flow->in_port.ofp_port));
-
-    dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
-
-    xlate_in_init(&xin, ofproto, flow, NULL, stats.tcp_flags, packet);
-    xin.resubmit_stats = &stats;
-    xin.ofpacts_len = ofpacts_len;
-    xin.ofpacts = ofpacts;
-
-    xlate_actions(&xin, &xout);
-    dpif_execute(ofproto->backer->dpif, key.data, key.size,
-                 xout.odp_actions.data, xout.odp_actions.size, packet);
-    xlate_out_uninit(&xout);
 
+    ofproto_dpif_execute_actions(ofproto, flow, NULL, ofpacts,
+                                 ofpacts_len, packet);
     return 0;
 }
 \f
@@ -5319,27 +5310,19 @@ ofproto_trace(struct ofproto_dpif *ofproto, const struct flow *flow,
                            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;
             }
         }