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