Along with flow-table rehashing OVS can compact masks array. This allows us to calculate highest index for mask array.
Signed-off-by: Pravin B Shelar <pshe...@nicira.com> --- datapath/flow_table.c | 40 ++++++++++++++++++++++++++++++---------- datapath/flow_table.h | 2 +- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/datapath/flow_table.c b/datapath/flow_table.c index c8bd9d1..f63cc2f 100644 --- a/datapath/flow_table.c +++ b/datapath/flow_table.c @@ -229,6 +229,7 @@ static struct mask_array *tbl_mask_array_alloc(int size) return NULL; new->count = 0; + new->high_mark = 0; new->max = size; return new; @@ -252,6 +253,8 @@ static int tbl_mask_array_realloc(struct flow_table *tbl, int size) new->masks[new->count++] = old->masks[i]; } } + + new->high_mark = new->count; rcu_assign_pointer(tbl->mask_array, new); if (old) @@ -260,6 +263,17 @@ static int tbl_mask_array_realloc(struct flow_table *tbl, int size) return 0; } +static void tbl_mask_array_compact(struct flow_table *tbl) +{ + struct mask_array *ma; + int size; + + ma = ovsl_dereference(tbl->mask_array); + + size = roundup(ma->count, MASK_ARRAY_SIZE_MIN); + tbl_mask_array_realloc(tbl, size); +} + int ovs_flow_tbl_init(struct flow_table *table) { struct table_instance *ti; @@ -524,7 +538,7 @@ static struct sw_flow *flow_lookup(struct flow_table *tbl, struct sw_flow *flow; int i; - for (i = 0; i < ma->max; i++) { + for (i = 0; i < ma->high_mark; i++) { struct sw_flow_mask *mask; mask = rcu_dereference_ovsl(ma->masks[i]); @@ -579,14 +593,17 @@ struct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *tbl, struct sw_flow_mask *mask; struct sw_flow *flow; - mask = rcu_dereference_ovsl(ma->masks[ce->mask_index]); - if (mask) { - flow = masked_flow_lookup(ti, key, mask, - n_mask_hit); - if (flow) /* Found */ - return flow; + if (likely(ce->mask_index < ma->high_mark)) { + mask = rcu_dereference_ovsl(ma->masks[ce->mask_index]); + if (mask) { + flow = masked_flow_lookup(ti, key, mask, + n_mask_hit); + if (flow) /* Found */ + return flow; + } } + del = ce; break; } @@ -648,7 +665,7 @@ static void flow_mask_remove(struct flow_table *tbl, struct sw_flow_mask *mask) int i; ma = ovsl_dereference(tbl->mask_array); - for (i = 0; i < ma->max; i++) { + for (i = 0; i < ma->high_mark; i++) { if (mask == ovsl_dereference(ma->masks[i])) { RCU_INIT_POINTER(ma->masks[i], NULL); ma->count--; @@ -705,7 +722,7 @@ static struct sw_flow_mask *flow_mask_find(const struct flow_table *tbl, int i; ma = ovsl_dereference(tbl->mask_array); - for (i = 0; i < ma->max; i++) { + for (i = 0; i < ma->high_mark; i++) { struct sw_flow_mask *t; t = ovsl_dereference(ma->masks[i]); @@ -753,8 +770,10 @@ static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow, t = ovsl_dereference(ma->masks[i]); if (!t) { - rcu_assign_pointer(ma->masks[i], mask); ma->count++; + if (ma->high_mark < (i + 1)) + ma->high_mark = i + 1; + rcu_assign_pointer(ma->masks[i], mask); break; } } @@ -794,6 +813,7 @@ int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow, if (new_ti) { rcu_assign_pointer(table->ti, new_ti); table_instance_destroy(ti, true); + tbl_mask_array_compact(table); table->last_rehash = jiffies; } return 0; diff --git a/datapath/flow_table.h b/datapath/flow_table.h index ee86953..267f06a 100644 --- a/datapath/flow_table.h +++ b/datapath/flow_table.h @@ -43,7 +43,7 @@ struct mask_cache_entry { struct mask_array { struct rcu_head rcu; - int count, max; + int count, max, high_mark; struct sw_flow_mask __rcu *masks[]; }; -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev