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