diff options
| author | Arnd Bergmann <arnd@arndb.de> | 2011-10-20 15:30:55 +0200 | 
|---|---|---|
| committer | Arnd Bergmann <arnd@arndb.de> | 2011-10-20 15:30:55 +0200 | 
| commit | 29ea35969b92a4be122a58c4aceea8c5e2c388d9 (patch) | |
| tree | 8285c0e98e7bb03868d390b58180e3cab876a8db /net/core/flow.c | |
| parent | 112d17d6f75b93e1dcaec2e2232a411148b3bf71 (diff) | |
| parent | b4cbb8a4e602ea77b0525d06eff89c6a6070dab3 (diff) | |
Merge branch 'imx/devel' into next/devel
Diffstat (limited to 'net/core/flow.c')
| -rw-r--r-- | net/core/flow.c | 36 | 
1 files changed, 21 insertions, 15 deletions
diff --git a/net/core/flow.c b/net/core/flow.c index bf32c33cad3b..555a456efb07 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -30,6 +30,7 @@ struct flow_cache_entry {  		struct hlist_node	hlist;  		struct list_head	gc_list;  	} u; +	struct net			*net;  	u16				family;  	u8				dir;  	u32				genid; @@ -172,29 +173,26 @@ static void flow_new_hash_rnd(struct flow_cache *fc,  static u32 flow_hash_code(struct flow_cache *fc,  			  struct flow_cache_percpu *fcp, -			  const struct flowi *key) +			  const struct flowi *key, +			  size_t keysize)  {  	const u32 *k = (const u32 *) key; +	const u32 length = keysize * sizeof(flow_compare_t) / sizeof(u32); -	return jhash2(k, (sizeof(*key) / sizeof(u32)), fcp->hash_rnd) +	return jhash2(k, length, fcp->hash_rnd)  		& (flow_cache_hash_size(fc) - 1);  } -typedef unsigned long flow_compare_t; -  /* I hear what you're saying, use memcmp.  But memcmp cannot make - * important assumptions that we can here, such as alignment and - * constant size. + * important assumptions that we can here, such as alignment.   */ -static int flow_key_compare(const struct flowi *key1, const struct flowi *key2) +static int flow_key_compare(const struct flowi *key1, const struct flowi *key2, +			    size_t keysize)  {  	const flow_compare_t *k1, *k1_lim, *k2; -	const int n_elem = sizeof(struct flowi) / sizeof(flow_compare_t); - -	BUILD_BUG_ON(sizeof(struct flowi) % sizeof(flow_compare_t));  	k1 = (const flow_compare_t *) key1; -	k1_lim = k1 + n_elem; +	k1_lim = k1 + keysize;  	k2 = (const flow_compare_t *) key2; @@ -215,6 +213,7 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,  	struct flow_cache_entry *fle, *tfle;  	struct hlist_node *entry;  	struct flow_cache_object *flo; +	size_t keysize;  	unsigned int hash;  	local_bh_disable(); @@ -222,6 +221,11 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,  	fle = NULL;  	flo = NULL; + +	keysize = flow_key_size(family); +	if (!keysize) +		goto nocache; +  	/* Packet really early in init?  Making flow_cache_init a  	 * pre-smp initcall would solve this.  --RR */  	if (!fcp->hash_table) @@ -230,11 +234,12 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,  	if (fcp->hash_rnd_recalc)  		flow_new_hash_rnd(fc, fcp); -	hash = flow_hash_code(fc, fcp, key); +	hash = flow_hash_code(fc, fcp, key, keysize);  	hlist_for_each_entry(tfle, entry, &fcp->hash_table[hash], u.hlist) { -		if (tfle->family == family && +		if (tfle->net == net && +		    tfle->family == family &&  		    tfle->dir == dir && -		    flow_key_compare(key, &tfle->key) == 0) { +		    flow_key_compare(key, &tfle->key, keysize) == 0) {  			fle = tfle;  			break;  		} @@ -246,9 +251,10 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,  		fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC);  		if (fle) { +			fle->net = net;  			fle->family = family;  			fle->dir = dir; -			memcpy(&fle->key, key, sizeof(*key)); +			memcpy(&fle->key, key, keysize * sizeof(flow_compare_t));  			fle->object = NULL;  			hlist_add_head(&fle->u.hlist, &fcp->hash_table[hash]);  			fcp->hash_count++;  | 
