From 560e802229f3028c02273435dd1c6efba33e0949 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Mon, 26 Jul 2010 18:46:27 -0700 Subject: [PATCH] datapath: Move flow allocation into a function. As the process to allocate a flow becomes more involved it becomes more cumbersome for the code to be mixed in with the general datapath so split it out into a new function. Signed-off-by: Jesse Gross Reviewed-by: Ben Pfaff --- datapath/datapath.c | 10 +++++----- datapath/flow.c | 28 +++++++++++++++++++++++----- datapath/flow.h | 14 ++++++++------ 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index b3f77b36..1677927f 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -1049,12 +1049,12 @@ static int do_put_flow(struct datapath *dp, struct odp_flow_put *uf, } /* Allocate flow. */ - error = -ENOMEM; - flow = kmem_cache_alloc(flow_cache, GFP_KERNEL); - if (flow == NULL) + flow = flow_alloc(); + if (IS_ERR(flow)) { + error = PTR_ERR(flow); goto error; + } flow->key = uf->flow.key; - spin_lock_init(&flow->lock); clear_stats(flow); /* Obtain actions. */ @@ -1109,7 +1109,7 @@ static int do_put_flow(struct datapath *dp, struct odp_flow_put *uf, error_free_flow_acts: kfree(flow->sf_acts); error_free_flow: - kmem_cache_free(flow_cache, flow); + flow_free(flow); error: return error; } diff --git a/datapath/flow.c b/datapath/flow.c index 7684c061..1f01166c 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -123,27 +123,45 @@ struct sw_flow_actions *flow_actions_alloc(size_t n_actions) return sfa; } +struct sw_flow *flow_alloc(void) +{ + struct sw_flow *flow; + + flow = kmem_cache_alloc(flow_cache, GFP_KERNEL); + if (!flow) + return ERR_PTR(-ENOMEM); + + spin_lock_init(&flow->lock); -/* Frees 'flow' immediately. */ -static void flow_free(struct sw_flow *flow) + return flow; +} + +void flow_free(struct sw_flow *flow) { if (unlikely(!flow)) return; - kfree(flow->sf_acts); + kmem_cache_free(flow_cache, flow); } +/* Frees the entire 'flow' (both base and actions) immediately. */ +static void flow_free_full(struct sw_flow *flow) +{ + kfree(flow->sf_acts); + flow_free(flow); +} + void flow_free_tbl(struct tbl_node *node) { struct sw_flow *flow = flow_cast(node); - flow_free(flow); + flow_free_full(flow); } /* RCU callback used by flow_deferred_free. */ static void rcu_free_flow_callback(struct rcu_head *rcu) { struct sw_flow *flow = container_of(rcu, struct sw_flow, rcu); - flow_free(flow); + flow_free_full(flow); } /* Schedules 'flow' to be freed after the next RCU grace period. diff --git a/datapath/flow.h b/datapath/flow.h index 80a5b66b..484ca120 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -58,20 +58,22 @@ struct arp_eth_header unsigned char ar_tip[4]; /* target IP address */ } __attribute__((packed)); -extern struct kmem_cache *flow_cache; +int flow_init(void); +void flow_exit(void); -struct sw_flow_actions *flow_actions_alloc(size_t n_actions); +struct sw_flow *flow_alloc(void); +void flow_free(struct sw_flow *flow); void flow_deferred_free(struct sw_flow *); +void flow_free_tbl(struct tbl_node *); + +struct sw_flow_actions *flow_actions_alloc(size_t n_actions); void flow_deferred_free_acts(struct sw_flow_actions *); + int flow_extract(struct sk_buff *, u16 in_port, struct odp_flow_key *); void flow_used(struct sw_flow *, struct sk_buff *); u32 flow_hash(const struct odp_flow_key *key); int flow_cmp(const struct tbl_node *, void *target); -void flow_free_tbl(struct tbl_node *); - -int flow_init(void); -void flow_exit(void); static inline struct sw_flow *flow_cast(const struct tbl_node *node) { -- 2.30.2