net neigh: Optimize neighbor entry size calculation.
authorYOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org>
Thu, 24 Jan 2013 00:44:23 +0000 (00:44 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 29 Jan 2013 04:17:51 +0000 (23:17 -0500)
When allocating memory for neighbour cache entry, if
tbl->entry_size is not set, we always calculate
sizeof(struct neighbour) + tbl->key_len, which is common
in the same table.

With this change, set tbl->entry_size during the table
initialization phase, if it was not set, and use it in
neigh_alloc() and neighbour_priv().

This change also allow us to have both of protocol private
data and device priate data at tha same time.

Note that the only user of prototcol private is DECnet
and the only user of device private is ATM CLIP.
Since those are exclusive, we have not been facing issues
here.

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/neighbour.h
net/core/neighbour.c

index 0dab173e27da6e8e66a8eea4913f5b0230f612bd..629ee573c6d0307a4d394dcc16e9812e955a36d4 100644 (file)
@@ -184,7 +184,7 @@ struct neigh_table {
 
 static inline void *neighbour_priv(const struct neighbour *n)
 {
-       return (char *)n + ALIGN(sizeof(*n) + n->tbl->key_len, NEIGH_PRIV_ALIGN);
+       return (char *)n + n->tbl->entry_size;
 }
 
 /* flags for neigh_update() */
index 7bd0eedb357fe0dd9e81eda5b9d7c36e2ca3e54c..3863b8f639c50827dfdf4a0c6c26bd6284f39f58 100644 (file)
@@ -290,15 +290,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device
                        goto out_entries;
        }
 
-       if (tbl->entry_size)
-               n = kzalloc(tbl->entry_size, GFP_ATOMIC);
-       else {
-               int sz = sizeof(*n) + tbl->key_len;
-
-               sz = ALIGN(sz, NEIGH_PRIV_ALIGN);
-               sz += dev->neigh_priv_len;
-               n = kzalloc(sz, GFP_ATOMIC);
-       }
+       n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
        if (!n)
                goto out_entries;
 
@@ -1546,6 +1538,12 @@ static void neigh_table_init_no_netlink(struct neigh_table *tbl)
        if (!tbl->nht || !tbl->phash_buckets)
                panic("cannot allocate neighbour cache hashes");
 
+       if (!tbl->entry_size)
+               tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
+                                       tbl->key_len, NEIGH_PRIV_ALIGN);
+       else
+               WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
+
        rwlock_init(&tbl->lock);
        INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
        schedule_delayed_work(&tbl->gc_work, tbl->parms.reachable_time);