Hides mega-flow implementation in flow_table.c rather than datapath.c. This also helps next patch.
Signed-off-by: Pravin B Shelar <pshe...@nicira.com> --- datapath/datapath.c | 23 ++------- datapath/flow_table.c | 133 +++++++++++++++++++++++++++++-------------------- datapath/flow_table.h | 11 +--- 3 files changed, 85 insertions(+), 82 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index ff572ac..b4035ce 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -798,8 +798,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) /* Check if this is a duplicate flow */ flow = ovs_flow_lookup(&dp->table, &key); if (!flow) { - struct sw_flow_mask *mask_p; - /* Bail out if we're not allowed to create a new flow. */ error = -ENOENT; if (info->genlhdr->cmd == OVS_FLOW_CMD_SET) @@ -815,25 +813,14 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) flow->key = masked_key; flow->unmasked_key = key; - - /* Make sure mask is unique in the system */ - mask_p = ovs_sw_flow_mask_find(&dp->table, &mask); - if (!mask_p) { - /* Allocate a new mask if none exsits. */ - mask_p = ovs_sw_flow_mask_alloc(); - if (!mask_p) - goto err_flow_free; - mask_p->key = mask.key; - mask_p->range = mask.range; - ovs_sw_flow_mask_insert(&dp->table, mask_p); - } - - ovs_sw_flow_mask_add_ref(mask_p); - flow->mask = mask_p; rcu_assign_pointer(flow->sf_acts, acts); /* Put flow in bucket. */ - ovs_flow_insert(&dp->table, flow); + error = ovs_flow_insert(&dp->table, flow, &mask); + if (error) { + acts = NULL; + goto err_flow_free; + } reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid, info->snd_seq, OVS_FLOW_CMD_NEW); diff --git a/datapath/flow_table.c b/datapath/flow_table.c index f7655fa..9acf81f 100644 --- a/datapath/flow_table.c +++ b/datapath/flow_table.c @@ -183,12 +183,36 @@ static void rcu_free_flow_callback(struct rcu_head *rcu) __flow_free(flow); } +static void rcu_free_sw_flow_mask_cb(struct rcu_head *rcu) +{ + struct sw_flow_mask *mask = container_of(rcu, struct sw_flow_mask, rcu); + + kfree(mask); +} + +static void flow_mask_del_ref(struct sw_flow_mask *mask, bool deferred) +{ + if (!mask) + return; + + BUG_ON(!mask->ref_count); + mask->ref_count--; + + if (!mask->ref_count) { + list_del_rcu(&mask->list); + if (deferred) + call_rcu(&mask->rcu, rcu_free_sw_flow_mask_cb); + else + kfree(mask); + } +} + void ovs_flow_free(struct sw_flow *flow, bool deferred) { if (!flow) return; - ovs_sw_flow_mask_del_ref(flow->mask, deferred); + flow_mask_del_ref(flow->mask, deferred); if (deferred) call_rcu(&flow->rcu, rcu_free_flow_callback); @@ -517,31 +541,6 @@ static struct hash_table *flow_tbl_expand(struct hash_table *table) return __flow_tbl_rehash(table, table->n_buckets * 2); } -void ovs_flow_insert(struct flow_table *table, struct sw_flow *flow) -{ - struct hash_table *htable = NULL; - struct hash_table *new_htable = NULL; - - htable = ovsl_dereference(table->htable); - - /* Expand table, if necessary, to make room. */ - if (htable->count > htable->n_buckets) - new_htable = flow_tbl_expand(htable); - else if (time_after(jiffies, table->last_rehash + REHASH_INTERVAL)) - new_htable = flow_tbl_rehash(htable); - - if (new_htable && !IS_ERR(new_htable)) { - rcu_assign_pointer(table->htable, new_htable); - ovs_flow_tbl_destroy(table, true); - htable = ovsl_dereference(table->htable); - table->last_rehash = jiffies; - } - - flow->hash = flow_hash(&flow->key, flow->mask->range.start, - flow->mask->range.end); - __tbl_insert(htable, flow); -} - void ovs_flow_remove(struct flow_table *table, struct sw_flow *flow) { struct hash_table *htbl = ovsl_dereference(table->htable); @@ -551,7 +550,7 @@ void ovs_flow_remove(struct flow_table *table, struct sw_flow *flow) htbl->count--; } -struct sw_flow_mask *ovs_sw_flow_mask_alloc(void) +static struct sw_flow_mask *mask_alloc(void) { struct sw_flow_mask *mask; @@ -562,35 +561,11 @@ struct sw_flow_mask *ovs_sw_flow_mask_alloc(void) return mask; } -void ovs_sw_flow_mask_add_ref(struct sw_flow_mask *mask) +static void mask_add_ref(struct sw_flow_mask *mask) { mask->ref_count++; } -static void rcu_free_sw_flow_mask_cb(struct rcu_head *rcu) -{ - struct sw_flow_mask *mask = container_of(rcu, struct sw_flow_mask, rcu); - - kfree(mask); -} - -void ovs_sw_flow_mask_del_ref(struct sw_flow_mask *mask, bool deferred) -{ - if (!mask) - return; - - BUG_ON(!mask->ref_count); - mask->ref_count--; - - if (!mask->ref_count) { - list_del_rcu(&mask->list); - if (deferred) - call_rcu(&mask->rcu, rcu_free_sw_flow_mask_cb); - else - kfree(mask); - } -} - static bool mask_equal(const struct sw_flow_mask *a, const struct sw_flow_mask *b) { @@ -602,7 +577,7 @@ static bool mask_equal(const struct sw_flow_mask *a, && (memcmp(a_, b_, range_n_bytes(&a->range)) == 0); } -struct sw_flow_mask *ovs_sw_flow_mask_find(const struct flow_table *tbl, +static struct sw_flow_mask *flow_mask_find(const struct flow_table *tbl, const struct sw_flow_mask *mask) { struct list_head *ml; @@ -622,9 +597,57 @@ struct sw_flow_mask *ovs_sw_flow_mask_find(const struct flow_table *tbl, * The caller needs to make sure that 'mask' is not the same * as any masks that are already on the list. */ -void ovs_sw_flow_mask_insert(struct flow_table *tbl, struct sw_flow_mask *mask) +static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow, + struct sw_flow_mask *new) +{ + struct sw_flow_mask *mask; + mask = flow_mask_find(tbl, new); + if (!mask) { + /* Allocate a new mask if none exsits. */ + mask = mask_alloc(); + if (!mask) + return -ENOMEM; + mask->key = new->key; + mask->range = new->range; + list_add_rcu(&mask->list, &tbl->mask_list); + } + + mask_add_ref(mask); + flow->mask = mask; + return 0; +} + +int ovs_flow_insert(struct flow_table *table, struct sw_flow *flow, + struct sw_flow_mask *new) { - list_add_rcu(&mask->list, &tbl->mask_list); + struct hash_table *htable = NULL; + struct hash_table *new_htable = NULL; + int err; + + err = flow_mask_insert(table, flow, new); + if (err) + return err; + + htable = ovsl_dereference(table->htable); + + /* Expand table, if necessary, to make room. */ + if (htable->count > htable->n_buckets) + new_htable = flow_tbl_expand(htable); + else if (time_after(jiffies, table->last_rehash + REHASH_INTERVAL)) + new_htable = flow_tbl_rehash(htable); + + if (new_htable && !IS_ERR(new_htable)) { + rcu_assign_pointer(table->htable, new_htable); + ovs_flow_tbl_destroy(table, true); + htable = ovsl_dereference(table->htable); + table->last_rehash = jiffies; + } + + flow->hash = flow_hash(&flow->key, flow->mask->range.start, + flow->mask->range.end); + __tbl_insert(htable, flow); + + return 0; } /* Initializes the flow module. diff --git a/datapath/flow_table.h b/datapath/flow_table.h index 6c3355e..4b4f05e 100644 --- a/datapath/flow_table.h +++ b/datapath/flow_table.h @@ -73,22 +73,15 @@ struct sw_flow *ovs_flow_lookup_unmasked_key(struct flow_table *table, void ovs_flow_tbl_destroy(struct flow_table *table, bool deferred); int ovs_flow_table_init(struct flow_table *); - -void ovs_flow_insert(struct flow_table *table, struct sw_flow *flow); +int ovs_flow_insert(struct flow_table *table, struct sw_flow *flow, + struct sw_flow_mask *new); void ovs_flow_remove(struct flow_table *table, struct sw_flow *flow); struct sw_flow *ovs_flow_dump_next(struct hash_table *table, u32 *bucket, u32 *idx); bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow, const struct sw_flow_key *key, int key_end); -struct sw_flow_mask *ovs_sw_flow_mask_alloc(void); -void ovs_sw_flow_mask_add_ref(struct sw_flow_mask *); -void ovs_sw_flow_mask_del_ref(struct sw_flow_mask *, bool deferred); -void ovs_sw_flow_mask_insert(struct flow_table *, struct sw_flow_mask *); -struct sw_flow_mask *ovs_sw_flow_mask_find(const struct flow_table *, - const struct sw_flow_mask *); void ovs_flow_key_mask(struct sw_flow_key *dst, const struct sw_flow_key *src, const struct sw_flow_mask *mask); - int ovs_flush_flows(struct flow_table *flow_table); #endif /* flow_table.h */ -- 1.7.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev