From b23cdad927a3b7f282e30d358be2c93597f8b9a3 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 6 Apr 2012 17:11:18 -0700 Subject: [PATCH] ofproto-dpif: Avoid malloc() of "struct flow_miss". In addition to avoid malloc() for struct flow_miss, this commit avoids copying "struct flow" around, which is a significant benefit because struct flow is currently 144 bytes. Signed-off-by: Ben Pfaff --- ofproto/ofproto-dpif.c | 61 +++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 62634315..99993868 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -2540,12 +2540,8 @@ process_special(struct ofproto_dpif *ofproto, const struct flow *flow, } static struct flow_miss * -flow_miss_create(struct hmap *todo, const struct flow *flow, - enum odp_key_fitness key_fitness, - const struct nlattr *key, size_t key_len, - ovs_be16 initial_tci) +flow_miss_find(struct hmap *todo, const struct flow *flow, uint32_t hash) { - uint32_t hash = flow_hash(flow, 0); struct flow_miss *miss; HMAP_FOR_EACH_WITH_HASH (miss, hmap_node, hash, todo) { @@ -2554,15 +2550,7 @@ flow_miss_create(struct hmap *todo, const struct flow *flow, } } - miss = xmalloc(sizeof *miss); - hmap_insert(todo, &miss->hmap_node, hash); - miss->flow = *flow; - miss->key_fitness = key_fitness; - miss->key = key; - miss->key_len = key_len; - miss->initial_tci = initial_tci; - list_init(&miss->packets); - return miss; + return NULL; } static void @@ -2753,10 +2741,12 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls, size_t n_upcalls) { struct dpif_upcall *upcall; - struct flow_miss *miss, *next_miss; + struct flow_miss *miss; + struct flow_miss misses[FLOW_MISS_MAX_BATCH]; struct flow_miss_op flow_miss_ops[FLOW_MISS_MAX_BATCH * 2]; struct dpif_op *dpif_ops[FLOW_MISS_MAX_BATCH * 2]; struct hmap todo; + int n_misses; size_t n_ops; size_t i; @@ -2770,26 +2760,25 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls, * the packets that have the same flow in the same "flow_miss" structure so * that we can process them together. */ hmap_init(&todo); + n_misses = 0; for (upcall = upcalls; upcall < &upcalls[n_upcalls]; upcall++) { - enum odp_key_fitness fitness; - struct flow_miss *miss; - ovs_be16 initial_tci; - struct flow flow; + struct flow_miss *miss = &misses[n_misses]; + struct flow_miss *existing_miss; + uint32_t hash; /* Obtain metadata and check userspace/kernel agreement on flow match, * then set 'flow''s header pointers. */ - fitness = ofproto_dpif_extract_flow_key(ofproto, - upcall->key, upcall->key_len, - &flow, &initial_tci, - upcall->packet); - if (fitness == ODP_FIT_ERROR) { + miss->key_fitness = ofproto_dpif_extract_flow_key( + ofproto, upcall->key, upcall->key_len, + &miss->flow, &miss->initial_tci, upcall->packet); + if (miss->key_fitness == ODP_FIT_ERROR) { continue; } - flow_extract(upcall->packet, flow.skb_priority, flow.tun_id, - flow.in_port, &flow); + flow_extract(upcall->packet, miss->flow.skb_priority, + miss->flow.tun_id, miss->flow.in_port, &miss->flow); /* Handle 802.1ag, LACP, and STP specially. */ - if (process_special(ofproto, &flow, upcall->packet)) { + if (process_special(ofproto, &miss->flow, upcall->packet)) { ofproto_update_local_port_stats(&ofproto->up, 0, upcall->packet->size); ofproto->n_matches++; @@ -2797,8 +2786,18 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls, } /* Add other packets to a to-do list. */ - miss = flow_miss_create(&todo, &flow, fitness, - upcall->key, upcall->key_len, initial_tci); + hash = flow_hash(&miss->flow, 0); + existing_miss = flow_miss_find(&todo, &miss->flow, hash); + if (!existing_miss) { + hmap_insert(&todo, &miss->hmap_node, hash); + miss->key = upcall->key; + miss->key_len = upcall->key_len; + list_init(&miss->packets); + + n_misses++; + } else { + miss = existing_miss; + } list_push_back(&miss->packets, &upcall->packet->list_node); } @@ -2839,10 +2838,6 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls, NOT_REACHED(); } } - HMAP_FOR_EACH_SAFE (miss, next_miss, hmap_node, &todo) { - hmap_remove(&todo, &miss->hmap_node); - free(miss); - } hmap_destroy(&todo); } -- 2.30.2