[ovs-dev] [PATCH v2 3/4] datapath: Simplify mega-flow APIs.
Pravin B Shelar
pshelar at nicira.com
Thu Sep 26 16:01:50 UTC 2013
Hides mega-flow implementation in flow_table.c rather than
datapath.c. This also helps next patch.
Signed-off-by: Pravin B Shelar <pshelar at nicira.com>
---
v2:
No change.
---
datapath/datapath.c | 27 +++-------
datapath/flow_table.c | 136 ++++++++++++++++++++++++++++---------------------
datapath/flow_table.h | 13 +----
3 files changed, 88 insertions(+), 88 deletions(-)
diff --git a/datapath/datapath.c b/datapath/datapath.c
index ff572ac..f7536ac 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -162,7 +162,7 @@ static void destroy_dp_rcu(struct rcu_head *rcu)
{
struct datapath *dp = container_of(rcu, struct datapath, rcu);
- ovs_flow_tbl_destroy(&dp->table, false);
+ ovs_flow_tbl_destroy(&dp->table);
free_percpu(dp->stats_percpu);
release_net(ovs_dp_get_net(dp));
kfree(dp->ports);
@@ -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);
@@ -1239,7 +1226,7 @@ err_destroy_ports_array:
err_destroy_percpu:
free_percpu(dp->stats_percpu);
err_destroy_table:
- ovs_flow_tbl_destroy(&dp->table, false);
+ ovs_flow_tbl_destroy(&dp->table);
err_free_dp:
release_net(ovs_dp_get_net(dp));
kfree(dp);
diff --git a/datapath/flow_table.c b/datapath/flow_table.c
index f7655fa..008ff5c 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);
@@ -280,11 +304,11 @@ static void __ovs_flow_tbl_destroy(struct hash_table *table, bool deferred)
__flow_tbl_destroy(table);
}
-void ovs_flow_tbl_destroy(struct flow_table *table, bool deferred)
+void ovs_flow_tbl_destroy(struct flow_table *table)
{
struct hash_table *htable = ovsl_dereference(table->htable);
- __ovs_flow_tbl_destroy(htable, deferred);
+ __ovs_flow_tbl_destroy(htable, false);
}
struct sw_flow *ovs_flow_dump_next(struct hash_table *table,
@@ -361,7 +385,7 @@ static struct hash_table *__flow_tbl_rehash(struct hash_table *table,
new_htable = __flow_tbl_alloc(n_buckets);
if (!new_htable)
- return ERR_PTR(-ENOMEM);
+ return NULL;
flow_table_copy_flows(table, new_htable);
@@ -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,54 @@ 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)
{
- list_add_rcu(&mask->list, &tbl->mask_list);
+ 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)
+{
+ struct hash_table *new_htable = NULL;
+ struct hash_table *htable;
+ int err;
+
+ err = flow_mask_insert(table, flow, new);
+ if (err)
+ return err;
+
+ flow->hash = flow_hash(&flow->key, flow->mask->range.start,
+ flow->mask->range.end);
+ htable = ovsl_dereference(table->htable);
+ __tbl_insert(htable, flow);
+
+ /* 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) {
+ rcu_assign_pointer(table->htable, new_htable);
+ __ovs_flow_tbl_destroy(htable, true);
+ table->last_rehash = jiffies;
+ }
+ return 0;
}
/* Initializes the flow module.
diff --git a/datapath/flow_table.h b/datapath/flow_table.h
index 6c3355e..0a3a0cf 100644
--- a/datapath/flow_table.h
+++ b/datapath/flow_table.h
@@ -71,24 +71,17 @@ struct sw_flow *ovs_flow_lookup(struct flow_table *,
struct sw_flow *ovs_flow_lookup_unmasked_key(struct flow_table *table,
struct sw_flow_match *match);
-void ovs_flow_tbl_destroy(struct flow_table *table, bool deferred);
+void ovs_flow_tbl_destroy(struct flow_table *table);
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
More information about the dev
mailing list