If execution is performed using a helper then any recirc actions
encountered may be deferred. This change executes such actions.

Signed-off-by: Simon Horman <ho...@verge.net.au>
---
 ofproto/ofproto-dpif.c | 81 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 73 insertions(+), 8 deletions(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 6200f57..7a4f130 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -3078,12 +3078,13 @@ rule_expire(struct rule_dpif *rule)
 
 /* 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)
+static 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 list *recirc_list)
 {
     struct dpif_flow_stats stats;
     struct xlate_out xout;
@@ -3092,8 +3093,6 @@ ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto,
     struct dpif_execute execute;
     int error;
 
-    ovs_assert((rule != NULL) != (ofpacts != NULL));
-
     dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
 
     if (rule) {
@@ -3118,6 +3117,7 @@ ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto,
     execute.md.pkt_mark = flow->pkt_mark;
     execute.md.in_port.odp_port = ofp_port_to_odp_port(ofproto, in_port);
     execute.needs_help = (xout.slow & SLOW_ACTION) != 0;
+    execute.recirc_list = recirc_list;
 
     error = dpif_execute(ofproto->backer->dpif, &execute);
 
@@ -3126,6 +3126,71 @@ ofproto_dpif_execute_actions(struct ofproto_dpif 
*ofproto,
     return error;
 }
 
+#define MAX_RECIRC_DEPTH 5
+
+/* Executes, within 'ofproto', the actions in 'rule', 'ofpacts',
+ * or 'xout_' 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)
+{
+    int i, error;
+    struct list recirc_list = LIST_INITIALIZER(&recirc_list);
+    ofp_port_t in_port;
+
+    ovs_assert((rule != NULL) != (ofpacts != NULL));
+
+    error = ofproto_dpif_execute_actions__(ofproto, flow, rule, ofpacts,
+                                           ofpacts_len, packet, &recirc_list);
+    if (error || list_is_empty(&recirc_list)) {
+        return error;
+    }
+
+    in_port = flow->in_port.ofp_port;
+
+    for (i = 0; i < MAX_RECIRC_DEPTH; i++) {
+        struct list next_recirc_list = LIST_INITIALIZER(&next_recirc_list);
+        struct dpif_execute_recirc *recirc, *next_recirc;
+
+        LIST_FOR_EACH_SAFE(recirc, next_recirc, list_node, &recirc_list) {
+            struct flow new_flow;
+
+            flow_extract(recirc->packet, &recirc->md, &new_flow);
+            /* Undo port mangling in ofproto_dpif_execute_actions__() */
+            new_flow.in_port.ofp_port = in_port;
+            flow = &new_flow;
+
+            error = ofproto_dpif_execute_actions__(ofproto, flow, NULL, NULL,
+                                                   0, recirc->packet,
+                                                   &next_recirc_list);
+            if (error) {
+                break;
+            }
+            dpif_execute_recirc_destroy(recirc);
+        }
+        if (error) {
+            struct dpif_execute_recirc *recirc, *next_recirc;
+
+            list_push_back(&next_recirc_list, &recirc_list);
+            LIST_FOR_EACH_SAFE(recirc, next_recirc, list_node, &recirc_list) {
+                dpif_execute_recirc_destroy(recirc);
+            }
+
+            return error;
+        } else if (list_is_empty(&next_recirc_list)) {
+            return 0;
+        }
+
+        list_move(&recirc_list, &next_recirc_list);
+    }
+
+    VLOG_WARN_RL(&rl, "recirculated too much during action execution");
+    return EINVAL;
+}
+
 void
 rule_dpif_credit_stats(struct rule_dpif *rule,
                        const struct dpif_flow_stats *stats)
-- 
1.8.5.2

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to