Get fix of extra struct flow copying in flow miss handling.
Signed-off-by: Jarno Rajahalme <[email protected]>
---
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
[email protected]
http://openvswitch.org/mailman/listinfo/dev