aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@redhat.com>2015-03-04 18:02:33 -0500
committerDavid S. Miller <davem@davemloft.net>2015-03-04 23:35:18 -0500
commit41b489fd6ce03e96e90fcffdb69b168065ae2e40 (patch)
tree33505efb050b5ba101dab496e8709a8c8cb71dca /net/ipv4
parentd5d6487cb8f019ab663df4c03519cd69e4362795 (diff)
fib_trie: move leaf and tnode to occupy the same spot in the key vector
If we are going to compact the leaf and tnode we first need to make sure the fields are all in the same place. In that regard I am moving the leaf pointer which represents the fib_alias hash list to occupy what is currently the first key_vector pointer. Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/fib_trie.c51
1 files changed, 27 insertions, 24 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 5be88df02b27..2233ebf2aae8 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -94,24 +94,27 @@ typedef unsigned int t_key;
94#define get_index(_key, _kv) (((_key) ^ (_kv)->key) >> (_kv)->pos) 94#define get_index(_key, _kv) (((_key) ^ (_kv)->key) >> (_kv)->pos)
95 95
96struct tnode { 96struct tnode {
97 struct rcu_head rcu;
98
99 t_key empty_children; /* KEYLENGTH bits needed */
100 t_key full_children; /* KEYLENGTH bits needed */
101 struct tnode __rcu *parent;
102
97 t_key key; 103 t_key key;
98 unsigned char bits; /* 2log(KEYLENGTH) bits needed */
99 unsigned char pos; /* 2log(KEYLENGTH) bits needed */ 104 unsigned char pos; /* 2log(KEYLENGTH) bits needed */
105 unsigned char bits; /* 2log(KEYLENGTH) bits needed */
100 unsigned char slen; 106 unsigned char slen;
101 struct tnode __rcu *parent;
102 struct rcu_head rcu;
103 union { 107 union {
104 /* The fields in this struct are valid if bits > 0 (TNODE) */ 108 /* This list pointer if valid if (pos | bits) == 0 (LEAF) */
105 struct {
106 t_key empty_children; /* KEYLENGTH bits needed */
107 t_key full_children; /* KEYLENGTH bits needed */
108 struct tnode __rcu *child[0];
109 };
110 /* This list pointer if valid if bits == 0 (LEAF) */
111 struct hlist_head leaf; 109 struct hlist_head leaf;
110 /* This array is valid if (pos | bits) > 0 (TNODE) */
111 struct tnode __rcu *tnode[0];
112 }; 112 };
113}; 113};
114 114
115#define TNODE_SIZE(n) offsetof(struct tnode, tnode[n])
116#define LEAF_SIZE TNODE_SIZE(1)
117
115#ifdef CONFIG_IP_FIB_TRIE_STATS 118#ifdef CONFIG_IP_FIB_TRIE_STATS
116struct trie_use_stats { 119struct trie_use_stats {
117 unsigned int gets; 120 unsigned int gets;
@@ -180,14 +183,14 @@ static inline unsigned long tnode_child_length(const struct tnode *tn)
180static inline struct tnode *tnode_get_child(const struct tnode *tn, 183static inline struct tnode *tnode_get_child(const struct tnode *tn,
181 unsigned long i) 184 unsigned long i)
182{ 185{
183 return rtnl_dereference(tn->child[i]); 186 return rtnl_dereference(tn->tnode[i]);
184} 187}
185 188
186/* caller must hold RCU read lock or RTNL */ 189/* caller must hold RCU read lock or RTNL */
187static inline struct tnode *tnode_get_child_rcu(const struct tnode *tn, 190static inline struct tnode *tnode_get_child_rcu(const struct tnode *tn,
188 unsigned long i) 191 unsigned long i)
189{ 192{
190 return rcu_dereference_rtnl(tn->child[i]); 193 return rcu_dereference_rtnl(tn->tnode[i]);
191} 194}
192 195
193/* To understand this stuff, an understanding of keys and all their bits is 196/* To understand this stuff, an understanding of keys and all their bits is
@@ -266,7 +269,7 @@ static inline void alias_free_mem_rcu(struct fib_alias *fa)
266} 269}
267 270
268#define TNODE_KMALLOC_MAX \ 271#define TNODE_KMALLOC_MAX \
269 ilog2((PAGE_SIZE - sizeof(struct tnode)) / sizeof(struct tnode *)) 272 ilog2((PAGE_SIZE - TNODE_SIZE(0)) / sizeof(struct tnode *))
270 273
271static void __node_free_rcu(struct rcu_head *head) 274static void __node_free_rcu(struct rcu_head *head)
272{ 275{
@@ -324,7 +327,7 @@ static struct tnode *leaf_new(t_key key, struct fib_alias *fa)
324 327
325static struct tnode *tnode_new(t_key key, int pos, int bits) 328static struct tnode *tnode_new(t_key key, int pos, int bits)
326{ 329{
327 size_t sz = offsetof(struct tnode, child[1ul << bits]); 330 size_t sz = TNODE_SIZE(1ul << bits);
328 struct tnode *tn = tnode_alloc(sz); 331 struct tnode *tn = tnode_alloc(sz);
329 unsigned int shift = pos + bits; 332 unsigned int shift = pos + bits;
330 333
@@ -343,7 +346,7 @@ static struct tnode *tnode_new(t_key key, int pos, int bits)
343 tn->empty_children = 1ul << bits; 346 tn->empty_children = 1ul << bits;
344 } 347 }
345 348
346 pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode), 349 pr_debug("AT %p s=%zu %zu\n", tn, TNODE_SIZE(0),
347 sizeof(struct tnode *) << bits); 350 sizeof(struct tnode *) << bits);
348 return tn; 351 return tn;
349} 352}
@@ -384,7 +387,7 @@ static void put_child(struct tnode *tn, unsigned long i, struct tnode *n)
384 if (n && (tn->slen < n->slen)) 387 if (n && (tn->slen < n->slen))
385 tn->slen = n->slen; 388 tn->slen = n->slen;
386 389
387 rcu_assign_pointer(tn->child[i], n); 390 rcu_assign_pointer(tn->tnode[i], n);
388} 391}
389 392
390static void update_children(struct tnode *tn) 393static void update_children(struct tnode *tn)
@@ -435,7 +438,7 @@ static void tnode_free(struct tnode *tn)
435 438
436 while (head) { 439 while (head) {
437 head = head->next; 440 head = head->next;
438 tnode_free_size += offsetof(struct tnode, child[1 << tn->bits]); 441 tnode_free_size += TNODE_SIZE(1ul << tn->bits);
439 node_free(tn); 442 node_free(tn);
440 443
441 tn = container_of(head, struct tnode, rcu); 444 tn = container_of(head, struct tnode, rcu);
@@ -788,7 +791,7 @@ static void resize(struct trie *t, struct tnode *tn)
788 * doing it ourselves. This way we can let RCU fully do its 791 * doing it ourselves. This way we can let RCU fully do its
789 * thing without us interfering 792 * thing without us interfering
790 */ 793 */
791 cptr = tp ? &tp->child[get_index(tn->key, tp)] : &t->trie; 794 cptr = tp ? &tp->tnode[get_index(tn->key, tp)] : &t->trie;
792 BUG_ON(tn != rtnl_dereference(*cptr)); 795 BUG_ON(tn != rtnl_dereference(*cptr));
793 796
794 /* Double as long as the resulting node has a number of 797 /* Double as long as the resulting node has a number of
@@ -1241,7 +1244,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
1241 /* Step 2: Sort out leaves and begin backtracing for longest prefix */ 1244 /* Step 2: Sort out leaves and begin backtracing for longest prefix */
1242 for (;;) { 1245 for (;;) {
1243 /* record the pointer where our next node pointer is stored */ 1246 /* record the pointer where our next node pointer is stored */
1244 struct tnode __rcu **cptr = n->child; 1247 struct tnode __rcu **cptr = n->tnode;
1245 1248
1246 /* This test verifies that none of the bits that differ 1249 /* This test verifies that none of the bits that differ
1247 * between the key and the prefix exist in the region of 1250 * between the key and the prefix exist in the region of
@@ -1287,7 +1290,7 @@ backtrace:
1287 cindex &= cindex - 1; 1290 cindex &= cindex - 1;
1288 1291
1289 /* grab pointer for next child node */ 1292 /* grab pointer for next child node */
1290 cptr = &pn->child[cindex]; 1293 cptr = &pn->tnode[cindex];
1291 } 1294 }
1292 } 1295 }
1293 1296
@@ -1685,7 +1688,7 @@ void __init fib_trie_init(void)
1685 0, SLAB_PANIC, NULL); 1688 0, SLAB_PANIC, NULL);
1686 1689
1687 trie_leaf_kmem = kmem_cache_create("ip_fib_trie", 1690 trie_leaf_kmem = kmem_cache_create("ip_fib_trie",
1688 sizeof(struct tnode), 1691 LEAF_SIZE,
1689 0, SLAB_PANIC, NULL); 1692 0, SLAB_PANIC, NULL);
1690} 1693}
1691 1694
@@ -1843,13 +1846,13 @@ static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
1843 seq_printf(seq, "\tMax depth: %u\n", stat->maxdepth); 1846 seq_printf(seq, "\tMax depth: %u\n", stat->maxdepth);
1844 1847
1845 seq_printf(seq, "\tLeaves: %u\n", stat->leaves); 1848 seq_printf(seq, "\tLeaves: %u\n", stat->leaves);
1846 bytes = sizeof(struct tnode) * stat->leaves; 1849 bytes = LEAF_SIZE * stat->leaves;
1847 1850
1848 seq_printf(seq, "\tPrefixes: %u\n", stat->prefixes); 1851 seq_printf(seq, "\tPrefixes: %u\n", stat->prefixes);
1849 bytes += sizeof(struct fib_alias) * stat->prefixes; 1852 bytes += sizeof(struct fib_alias) * stat->prefixes;
1850 1853
1851 seq_printf(seq, "\tInternal nodes: %u\n\t", stat->tnodes); 1854 seq_printf(seq, "\tInternal nodes: %u\n\t", stat->tnodes);
1852 bytes += sizeof(struct tnode) * stat->tnodes; 1855 bytes += TNODE_SIZE(0) * stat->tnodes;
1853 1856
1854 max = MAX_STAT_DEPTH; 1857 max = MAX_STAT_DEPTH;
1855 while (max > 0 && stat->nodesizes[max-1] == 0) 1858 while (max > 0 && stat->nodesizes[max-1] == 0)
@@ -1918,7 +1921,7 @@ static int fib_triestat_seq_show(struct seq_file *seq, void *v)
1918 seq_printf(seq, 1921 seq_printf(seq,
1919 "Basic info: size of leaf:" 1922 "Basic info: size of leaf:"
1920 " %Zd bytes, size of tnode: %Zd bytes.\n", 1923 " %Zd bytes, size of tnode: %Zd bytes.\n",
1921 sizeof(struct tnode), sizeof(struct tnode)); 1924 LEAF_SIZE, TNODE_SIZE(0));
1922 1925
1923 for (h = 0; h < FIB_TABLE_HASHSZ; h++) { 1926 for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
1924 struct hlist_head *head = &net->ipv4.fib_table_hash[h]; 1927 struct hlist_head *head = &net->ipv4.fib_table_hash[h];