Get fix of extra struct flow copying in flow miss handling.

Signed-off-by: Jarno Rajahalme <jarno.rajaha...@nsn.com>
---
 ofproto/ofproto-dpif.c |  127 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 92 insertions(+), 35 deletions(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 7c4f0e9..6598cdc 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -3522,14 +3522,14 @@ struct flow_miss {
     struct initial_vals initial_vals;
     struct list packets;
     enum dpif_upcall_type upcall_type;
+    struct xlate_out xout;
+    bool xout_garbage;           /* 'xout' needs to be uninitialized? */
 };
 
 struct flow_miss_op {
     struct dpif_op dpif_op;
 
     uint64_t slow_stub[128 / 8]; /* Buffer for compose_slow_path() */
-    struct xlate_out xout;
-    bool xout_garbage;           /* 'xout' needs to be uninitialized? */
 };
 
 /* Sends an OFPT_PACKET_IN message for 'packet' of type OFPR_NO_MATCH to each
@@ -3609,7 +3609,7 @@ flow_miss_find(struct hmap *todo, const struct 
ofproto_dpif *ofproto,
  * returned op->subfacet, and if anything needs to be freed after processing
  * the op, the caller must initialize op->garbage also. */
 static void
-init_flow_miss_execute_op(struct flow_miss *miss, struct ofpbuf *packet,
+init_flow_miss_execute_op(const struct flow_miss *miss, struct ofpbuf *packet,
                           struct flow_miss_op *op)
 {
     if (miss->flow.vlan_tci != miss->initial_vals.vlan_tci) {
@@ -3622,7 +3622,6 @@ init_flow_miss_execute_op(struct flow_miss *miss, struct 
ofpbuf *packet,
         eth_pop_vlan(packet);
     }
 
-    op->xout_garbage = false;
     op->dpif_op.type = DPIF_OP_EXECUTE;
     op->dpif_op.u.execute.key = miss->key;
     op->dpif_op.u.execute.key_len = miss->key_len;
@@ -3677,6 +3676,40 @@ flow_miss_should_make_facet(struct ofproto_dpif *ofproto,
                                         list_size(&miss->packets));
 }
 
+static inline bool
+flow_miss_add_op(const struct flow_miss *miss, struct ofpbuf *packet,
+                 struct flow_miss_op *op, const struct xlate_out *xout)
+{
+    if (xout->odp_actions.size) {
+        struct dpif_execute *execute = &op->dpif_op.u.execute;
+
+        init_flow_miss_execute_op(miss, packet, op);
+        execute->actions = xout->odp_actions.data,
+            execute->actions_len = xout->odp_actions.size;
+        return true;
+    }
+    return false;
+}
+
+static inline void
+flow_miss_side_effects(enum slow_path_reason slow,
+                       struct ofproto_dpif *ofproto, const struct flow *flow,
+                       const struct initial_vals *initial_vals,
+                       struct rule_dpif *rule, struct ofport_dpif *in_port,
+                       const struct ofpbuf *packet)
+{
+    if (slow) {
+        if (slow != SLOW_CONTROLLER) {
+            process_special(ofproto, flow, in_port, packet);
+        } else {
+            struct xlate_in xin;
+
+            xlate_in_init(&xin, ofproto, flow, initial_vals, rule, 0, packet);
+            xlate_actions_for_side_effects(&xin, flow);
+        }
+    }
+}
+
 /* Handles 'miss', which matches 'rule', without creating a facet or subfacet
  * or creating any datapath flow.  May add an "execute" operation to 'ops' and
  * increment '*n_ops'. */
@@ -3689,10 +3722,12 @@ handle_flow_miss_without_facet(struct flow_miss *miss,
     struct ofpbuf *packet;
     struct xlate_in xin;
 
-    LIST_FOR_EACH (packet, list_node, &miss->packets) {
+    if (list_is_singleton(&miss->packets)) {
         struct flow_miss_op *op = &ops[*n_ops];
         struct dpif_flow_stats stats;
-        struct flow xflow = miss->flow;
+
+        packet = CONTAINER_OF(list_front(&miss->packets), struct ofpbuf,
+                              list_node);
 
         COVERAGE_INC(facet_suppress);
 
@@ -3704,20 +3739,46 @@ handle_flow_miss_without_facet(struct flow_miss *miss,
         xlate_in_init(&xin, miss->ofproto, &miss->flow, &miss->initial_vals,
                       rule, stats.tcp_flags, packet);
         xin.resubmit_stats = &stats;
-        /* XXX: Could use miss->flow, if xlate would be called only once */
-        xlate_actions(&xin, &xflow, &op->xout);
+        miss->xout_garbage = true;
+        /* miss->flow is not needed after this */
+        xlate_actions(&xin, &miss->flow, &miss->xout);
+
+        if (flow_miss_add_op(miss, packet, op, &miss->xout)) {
+            (*n_ops)++;
+        }
+    } else {
+        /* Need to keep miss->flow for side effects handling */
+        struct flow xflow = miss->flow;
+        struct ofport_dpif *in_port;
 
-        if (op->xout.odp_actions.size) {
-            struct dpif_execute *execute = &op->dpif_op.u.execute;
+        /* Translate actions once for all the packets */
+        xlate_in_init(&xin, miss->ofproto, &miss->flow, &miss->initial_vals,
+                      rule, 0, NULL);
+        xin.may_learn = true;
+        miss->xout_garbage = true;
+        xlate_actions(&xin, &xflow, &miss->xout);
 
-            init_flow_miss_execute_op(miss, packet, op);
-            execute->actions = op->xout.odp_actions.data;
-            execute->actions_len = op->xout.odp_actions.size;
-            op->xout_garbage = true;
+        in_port = (miss->xout.slow)
+            ? get_ofp_port(miss->ofproto, miss->flow.in_port)
+            : NULL;
 
-            (*n_ops)++;
-        } else {
-            xlate_out_uninit(&op->xout);
+        LIST_FOR_EACH (packet, list_node, &miss->packets) {
+            struct flow_miss_op *op = &ops[*n_ops];
+            struct dpif_flow_stats stats;
+
+            COVERAGE_INC(facet_suppress);
+
+            handle_flow_miss_common(rule, packet, &miss->flow);
+
+            flow_miss_side_effects(miss->xout.slow, miss->ofproto, &miss->flow,
+                                   &miss->initial_vals, rule, in_port, packet);
+
+            dpif_flow_stats_extract(&miss->flow, packet, now, &stats);
+            rule_credit_stats(rule, &stats);
+
+            if (flow_miss_add_op(miss, packet, op, &miss->xout)) {
+                (*n_ops)++;
+            }
         }
     }
 }
@@ -3740,8 +3801,11 @@ handle_flow_miss_with_facet(struct flow_miss *miss, 
struct facet *facet,
     enum subfacet_path want_path;
     struct subfacet *subfacet;
     struct ofpbuf *packet;
+    struct ofport_dpif *in_port;
+
+    in_port = facet->xout.slow ? get_ofp_port(ofproto, facet->flow.in_port)
+        : NULL;
 
-    want_path = facet->xout.slow ? SF_SLOW_PATH : SF_FAST_PATH;
     subfacet = subfacet_create(facet, miss, now);
 
     LIST_FOR_EACH (packet, list_node, &miss->packets) {
@@ -3750,34 +3814,26 @@ handle_flow_miss_with_facet(struct flow_miss *miss, 
struct facet *facet,
 
         handle_flow_miss_common(facet->rule, packet, &facet->flow);
 
-        if (want_path != SF_FAST_PATH) {
-            struct xlate_in xin;
-
-            xlate_in_init(&xin, ofproto, &facet->flow, &facet->initial_vals,
-                          facet->rule, 0, packet);
-            xlate_actions_for_side_effects(&xin, &facet->flow);
-        }
+        flow_miss_side_effects(facet->xout.slow, ofproto, &facet->flow,
+                               &facet->initial_vals, facet->rule, in_port,
+                               packet);
 
         dpif_flow_stats_extract(&facet->flow, packet, now, &stats);
         subfacet_update_stats(subfacet, &stats);
 
-        if (facet->xout.odp_actions.size) {
-            struct dpif_execute *execute = &op->dpif_op.u.execute;
-
-            init_flow_miss_execute_op(miss, packet, op);
-            execute->actions = facet->xout.odp_actions.data,
-            execute->actions_len = facet->xout.odp_actions.size;
+        if (flow_miss_add_op(miss, packet, op, &facet->xout)) {
             (*n_ops)++;
         }
     }
 
+    want_path = facet->xout.slow ? SF_SLOW_PATH : SF_FAST_PATH;
+
     if (miss->upcall_type == DPIF_UC_MISS || subfacet->path != want_path) {
         struct flow_miss_op *op = &ops[(*n_ops)++];
         struct dpif_flow_put *put = &op->dpif_op.u.flow_put;
 
         subfacet->path = want_path;
 
-        op->xout_garbage = false;
         op->dpif_op.type = DPIF_OP_FLOW_PUT;
         put->flags = DPIF_FP_CREATE | DPIF_FP_MODIFY;
         put->key = miss->key;
@@ -4054,6 +4110,7 @@ handle_miss_upcalls(struct dpif_backer *backer, struct 
dpif_upcall *upcalls,
             miss->key_len = upcall->key_len;
             miss->upcall_type = upcall->type;
             list_init(&miss->packets);
+            miss->xout_garbage = false;
 
             n_misses++;
         } else {
@@ -4077,9 +4134,9 @@ handle_miss_upcalls(struct dpif_backer *backer, struct 
dpif_upcall *upcalls,
     dpif_operate(backer->dpif, dpif_ops, n_ops);
 
     /* Free memory. */
-    for (i = 0; i < n_ops; i++) {
-        if (flow_miss_ops[i].xout_garbage) {
-            xlate_out_uninit(&flow_miss_ops[i].xout);
+    for (i = 0; i < n_misses; i++) {
+        if (misses[i].xout_garbage) {
+            xlate_out_uninit(&misses[i].xout);
         }
     }
     hmap_destroy(&todo);
-- 
1.7.10.4

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

Reply via email to