In some cases we can avoid copying struct flow by managing the flow used
for translation outside the struct xlate_in.

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

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index d3434c3..9676a9a 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -241,9 +241,6 @@ struct xlate_out {
 struct xlate_in {
     struct ofproto_dpif *ofproto;
 
-    /* Storage for flow initialized by xlate_in_init */
-    struct flow flow_storage;
-
     struct initial_vals initial_vals;
 
     /* The packet corresponding to 'flow', or a null pointer if we are
@@ -340,7 +337,8 @@ static void xlate_out_uninit(struct xlate_out *);
 static void xlate_actions(struct xlate_in *, struct flow *,
                           struct xlate_out *);
 
-static void xlate_actions_for_side_effects(struct xlate_in *, struct flow *);
+static void xlate_actions_for_side_effects(struct xlate_in *,
+                                           const struct flow *);
 
 static void xlate_table_action(struct xlate_ctx *, struct flow *flow,
                                uint16_t in_port, uint8_t table_id,
@@ -3694,6 +3692,7 @@ handle_flow_miss_without_facet(struct flow_miss *miss,
     LIST_FOR_EACH (packet, list_node, &miss->packets) {
         struct flow_miss_op *op = &ops[*n_ops];
         struct dpif_flow_stats stats;
+        struct flow xflow = miss->flow;
 
         COVERAGE_INC(facet_suppress);
 
@@ -3705,8 +3704,8 @@ 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;
-        /* Note: Could use &miss->flow */
-        xlate_actions(&xin, &xin.flow_storage, &op->xout);
+        /* XXX: Could use miss->flow, if xlate would be called only once */
+        xlate_actions(&xin, &xflow, &op->xout);
 
         if (op->xout.odp_actions.size) {
             struct dpif_execute *execute = &op->dpif_op.u.execute;
@@ -3756,7 +3755,7 @@ handle_flow_miss_with_facet(struct flow_miss *miss, 
struct facet *facet,
 
             xlate_in_init(&xin, ofproto, &facet->flow, &facet->initial_vals,
                           facet->rule, 0, packet);
-            xlate_actions_for_side_effects(&xin, &xin.flow_storage);
+            xlate_actions_for_side_effects(&xin, &facet->flow);
         }
 
         dpif_flow_stats_extract(&facet->flow, packet, now, &stats);
@@ -4640,6 +4639,7 @@ facet_create(const struct flow_miss *miss, uint32_t hash)
     struct ofproto_dpif *ofproto = miss->ofproto;
     struct xlate_in xin;
     struct facet *facet;
+    struct flow xflow = miss->flow;
 
     facet = xzalloc(sizeof *facet);
     facet->used = time_msec();
@@ -4657,7 +4657,8 @@ facet_create(const struct flow_miss *miss, uint32_t hash)
     xlate_in_init(&xin, ofproto, &facet->flow, &facet->initial_vals,
                   facet->rule, 0, NULL);
     xin.may_learn = true;
-    xlate_actions(&xin, &xin.flow_storage, &facet->xout);
+    /* Note: Could use miss->flow */
+    xlate_actions(&xin, &xflow, &facet->xout);
     facet->nf_flow.output_iface = facet->xout.nf_output_iface;
 
     return facet;
@@ -4914,6 +4915,7 @@ facet_check_consistency(struct facet *facet)
 
     struct xlate_out xout;
     struct xlate_in xin;
+    struct flow xflow;
 
     struct rule_dpif *rule;
     bool ok;
@@ -4939,9 +4941,10 @@ facet_check_consistency(struct facet *facet)
     }
 
     /* Check the datapath actions for consistency. */
+    xflow = facet->flow;
     xlate_in_init(&xin, ofproto, &facet->flow, &facet->initial_vals, rule,
                   0, NULL);
-    xlate_actions(&xin, &xin.flow_storage, &xout);
+    xlate_actions(&xin, &xflow, &xout);
 
     ok = ofpbuf_equal(&facet->xout.odp_actions, &xout.odp_actions)
         && facet->xout.slow == xout.slow;
@@ -4992,6 +4995,7 @@ facet_revalidate(struct facet *facet)
     struct subfacet *subfacet;
     struct xlate_out xout;
     struct xlate_in xin;
+    struct flow xflow;
 
     COVERAGE_INC(facet_revalidate);
 
@@ -5021,9 +5025,10 @@ facet_revalidate(struct facet *facet)
      * We do not modify any 'facet' state yet, because we might need to, e.g.,
      * emit a NetFlow expiration and, if so, we need to have the old state
      * around to properly compose it. */
+    xflow = facet->flow;
     xlate_in_init(&xin, ofproto, &facet->flow, &facet->initial_vals, new_rule,
                   0, NULL);
-    xlate_actions(&xin, &xin.flow_storage, &xout);
+    xlate_actions(&xin, &xflow, &xout);
 
     /* A facet's slow path reason should only change under dramatic
      * circumstances.  Rather than try to update everything, it's simpler to
@@ -5581,15 +5586,17 @@ rule_dpif_execute(struct rule_dpif *rule, const struct 
flow *flow,
     struct dpif_flow_stats stats;
     struct xlate_out xout;
     struct xlate_in xin;
+    struct flow xflow;
 
     dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
     rule_credit_stats(rule, &stats);
 
     initial_vals.vlan_tci = flow->vlan_tci;
+    xflow = *flow;
     xlate_in_init(&xin, ofproto, flow, &initial_vals, rule, stats.tcp_flags,
                   packet);
     xin.resubmit_stats = &stats;
-    xlate_actions(&xin, &xin.flow_storage, &xout);
+    xlate_actions(&xin, &xflow, &xout);
 
     execute_odp_actions(ofproto, flow, xout.odp_actions.data,
                         xout.odp_actions.size, packet);
@@ -5648,7 +5655,7 @@ send_packet(const struct ofport_dpif *ofport, struct 
ofpbuf *packet)
     xin.ofpacts_len = sizeof output;
     xin.ofpacts = &output.ofpact;
     xin.resubmit_stats = &stats;
-    xlate_actions(&xin, &xin.flow_storage, &xout);
+    xlate_actions(&xin, &flow, &xout);
 
     error = dpif_execute(ofproto->backer->dpif,
                          key.data, key.size,
@@ -6846,7 +6853,6 @@ xlate_in_init(struct xlate_in *xin, struct ofproto_dpif 
*ofproto,
               const struct ofpbuf *packet)
 {
     xin->ofproto = ofproto;
-    xin->flow_storage = *flow;
     xin->packet = packet;
     xin->may_learn = packet != NULL;
     xin->rule = rule;
@@ -7045,13 +7051,17 @@ xlate_actions(struct xlate_in *xin, struct flow *flow, 
struct xlate_out *xout)
 
 /* Translates the 'ofpacts' in either 'xin' or 'xin->rule' into datapath
  * actions using 'flow', discarding the results, but "keeping" the
- * side effects, such as any special processing and controller actions. */
+ * side effects, such as any special processing and controller actions.
+ *
+ * Current use always needs a fresh copy of 'flow', so we do the copying
+ * here. */
 static void
-xlate_actions_for_side_effects(struct xlate_in *xin, struct flow *flow)
+xlate_actions_for_side_effects(struct xlate_in *xin, const struct flow *flow)
 {
     struct xlate_out xout;
+    struct flow xflow = *flow;
 
-    xlate_actions(xin, flow, &xout);
+    xlate_actions(xin, &xflow, &xout);
     xlate_out_uninit(&xout);
 }
 
@@ -7736,7 +7746,7 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf 
*packet,
     struct xlate_out xout;
     struct xlate_in xin;
     struct ofpbuf key;
-
+    struct flow xflow;
 
     ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
     odp_flow_key_from_flow(&key, flow,
@@ -7745,13 +7755,14 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf 
*packet,
     dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
 
     initial_vals.vlan_tci = flow->vlan_tci;
+    xflow = *flow;
     xlate_in_init(&xin, ofproto, flow, &initial_vals, NULL, stats.tcp_flags,
                   packet);
     xin.resubmit_stats = &stats;
     xin.ofpacts_len = ofpacts_len;
     xin.ofpacts = ofpacts;
 
-    xlate_actions(&xin, &xin.flow_storage, &xout);
+    xlate_actions(&xin, &xflow, &xout);
     dpif_execute(ofproto->backer->dpif, key.data, key.size,
                  xout.odp_actions.data, xout.odp_actions.size, packet);
     xlate_out_uninit(&xout);
@@ -7888,6 +7899,7 @@ ofproto_unixctl_fdb_show(struct unixctl_conn *conn, int 
argc OVS_UNUSED,
 struct trace_ctx {
     struct xlate_out xout;
     struct xlate_in xin;
+    struct flow xflow;
     struct flow flow;
     struct ds *result;
 };
@@ -7919,11 +7931,11 @@ trace_format_flow(struct ds *result, int level, const 
char *title,
 {
     ds_put_char_multiple(result, '\t', level);
     ds_put_format(result, "%s: ", title);
-    if (flow_equal(&trace->xin.flow_storage, &trace->flow)) {
+    if (flow_equal(&trace->xflow, &trace->flow)) {
         ds_put_cstr(result, "unchanged");
     } else {
-        flow_format(result, &trace->xin.flow_storage);
-        trace->flow = trace->xin.flow_storage;
+        flow_format(result, &trace->xflow);
+        trace->flow = trace->xflow;
     }
     ds_put_char(result, '\n');
 }
@@ -8127,14 +8139,14 @@ ofproto_trace(struct ofproto_dpif *ofproto, const 
struct flow *flow,
 
         tcp_flags = packet ? packet_get_tcp_flags(packet, flow) : 0;
         trace.result = ds;
-        trace.flow = *flow;
+        trace.flow = trace.xflow = *flow;
         ofpbuf_use_stub(&odp_actions,
                         odp_actions_stub, sizeof odp_actions_stub);
         xlate_in_init(&trace.xin, ofproto, flow, initial_vals, rule, tcp_flags,
                       packet);
         trace.xin.resubmit_hook = trace_resubmit;
         trace.xin.report_hook = trace_report;
-        xlate_actions(&trace.xin, &trace.xin.flow_storage, &trace.xout);
+        xlate_actions(&trace.xin, &trace.xflow, &trace.xout);
 
         ds_put_char(ds, '\n');
         trace_format_flow(ds, 0, "Final flow", &trace);
-- 
1.7.10.4

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

Reply via email to