blob: 108a1e9c9eac388515530bb790d0e56e4dba0bfd [file] [log] [blame]
Robert Olsson19baf832005-06-21 12:43:18 -07001/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version
5 * 2 of the License, or (at your option) any later version.
6 *
7 * Robert Olsson <robert.olsson@its.uu.se> Uppsala Universitet
8 * & Swedish University of Agricultural Sciences.
9 *
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +090010 * Jens Laas <jens.laas@data.slu.se> Swedish University of
Robert Olsson19baf832005-06-21 12:43:18 -070011 * Agricultural Sciences.
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +090012 *
Robert Olsson19baf832005-06-21 12:43:18 -070013 * Hans Liss <hans.liss@its.uu.se> Uppsala Universitet
14 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -030015 * This work is based on the LPC-trie which is originally described in:
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +090016 *
Robert Olsson19baf832005-06-21 12:43:18 -070017 * An experimental study of compression methods for dynamic tries
18 * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002.
Justin P. Mattock631dd1a2010-10-18 11:03:14 +020019 * http://www.csc.kth.se/~snilsson/software/dyntrie2/
Robert Olsson19baf832005-06-21 12:43:18 -070020 *
21 *
22 * IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson
23 * IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, June 1999
24 *
Robert Olsson19baf832005-06-21 12:43:18 -070025 *
26 * Code from fib_hash has been reused which includes the following header:
27 *
28 *
29 * INET An implementation of the TCP/IP protocol suite for the LINUX
30 * operating system. INET is implemented using the BSD Socket
31 * interface as the means of communication with the user level.
32 *
33 * IPv4 FIB: lookup engine and maintenance routines.
34 *
35 *
36 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
37 *
38 * This program is free software; you can redistribute it and/or
39 * modify it under the terms of the GNU General Public License
40 * as published by the Free Software Foundation; either version
41 * 2 of the License, or (at your option) any later version.
Robert Olssonfd966252005-12-22 11:25:10 -080042 *
43 * Substantial contributions to this work comes from:
44 *
45 * David S. Miller, <davem@davemloft.net>
46 * Stephen Hemminger <shemminger@osdl.org>
47 * Paul E. McKenney <paulmck@us.ibm.com>
48 * Patrick McHardy <kaber@trash.net>
Robert Olsson19baf832005-06-21 12:43:18 -070049 */
50
Jens Låås80b71b82009-08-28 23:57:15 -070051#define VERSION "0.409"
Robert Olsson19baf832005-06-21 12:43:18 -070052
Robert Olsson19baf832005-06-21 12:43:18 -070053#include <asm/uaccess.h>
Jiri Slaby1977f032007-10-18 23:40:25 -070054#include <linux/bitops.h>
Robert Olsson19baf832005-06-21 12:43:18 -070055#include <linux/types.h>
56#include <linux/kernel.h>
Robert Olsson19baf832005-06-21 12:43:18 -070057#include <linux/mm.h>
58#include <linux/string.h>
59#include <linux/socket.h>
60#include <linux/sockios.h>
61#include <linux/errno.h>
62#include <linux/in.h>
63#include <linux/inet.h>
Stephen Hemmingercd8787a2006-01-03 14:38:34 -080064#include <linux/inetdevice.h>
Robert Olsson19baf832005-06-21 12:43:18 -070065#include <linux/netdevice.h>
66#include <linux/if_arp.h>
67#include <linux/proc_fs.h>
Robert Olsson2373ce12005-08-25 13:01:29 -070068#include <linux/rcupdate.h>
Robert Olsson19baf832005-06-21 12:43:18 -070069#include <linux/skbuff.h>
70#include <linux/netlink.h>
71#include <linux/init.h>
72#include <linux/list.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090073#include <linux/slab.h>
Paul Gortmaker70c71602011-05-22 16:47:17 -040074#include <linux/prefetch.h>
Paul Gortmakerbc3b2d72011-07-15 11:47:34 -040075#include <linux/export.h>
Eric W. Biederman457c4cb2007-09-12 12:01:34 +020076#include <net/net_namespace.h>
Robert Olsson19baf832005-06-21 12:43:18 -070077#include <net/ip.h>
78#include <net/protocol.h>
79#include <net/route.h>
80#include <net/tcp.h>
81#include <net/sock.h>
82#include <net/ip_fib.h>
83#include "fib_lookup.h"
84
Robert Olsson06ef9212006-03-20 21:35:01 -080085#define MAX_STAT_DEPTH 32
Robert Olsson19baf832005-06-21 12:43:18 -070086
Robert Olsson19baf832005-06-21 12:43:18 -070087#define KEYLENGTH (8*sizeof(t_key))
Robert Olsson19baf832005-06-21 12:43:18 -070088
Robert Olsson19baf832005-06-21 12:43:18 -070089typedef unsigned int t_key;
90
91#define T_TNODE 0
92#define T_LEAF 1
93#define NODE_TYPE_MASK 0x1UL
Robert Olsson2373ce12005-08-25 13:01:29 -070094#define NODE_TYPE(node) ((node)->parent & NODE_TYPE_MASK)
95
Olof Johansson91b9a272005-08-09 20:24:39 -070096#define IS_TNODE(n) (!(n->parent & T_LEAF))
97#define IS_LEAF(n) (n->parent & T_LEAF)
Robert Olsson19baf832005-06-21 12:43:18 -070098
David S. Millerb299e4f2011-02-02 20:48:10 -080099struct rt_trie_node {
Olof Johansson91b9a272005-08-09 20:24:39 -0700100 unsigned long parent;
Eric Dumazet8d965442008-01-13 22:31:44 -0800101 t_key key;
Robert Olsson19baf832005-06-21 12:43:18 -0700102};
103
104struct leaf {
Olof Johansson91b9a272005-08-09 20:24:39 -0700105 unsigned long parent;
Eric Dumazet8d965442008-01-13 22:31:44 -0800106 t_key key;
Robert Olsson19baf832005-06-21 12:43:18 -0700107 struct hlist_head list;
Robert Olsson2373ce12005-08-25 13:01:29 -0700108 struct rcu_head rcu;
Robert Olsson19baf832005-06-21 12:43:18 -0700109};
110
111struct leaf_info {
112 struct hlist_node hlist;
113 int plen;
Eric Dumazet5c745012011-07-18 03:16:33 +0000114 u32 mask_plen; /* ntohl(inet_make_mask(plen)) */
Robert Olsson19baf832005-06-21 12:43:18 -0700115 struct list_head falh;
Eric Dumazet5c745012011-07-18 03:16:33 +0000116 struct rcu_head rcu;
Robert Olsson19baf832005-06-21 12:43:18 -0700117};
118
119struct tnode {
Olof Johansson91b9a272005-08-09 20:24:39 -0700120 unsigned long parent;
Eric Dumazet8d965442008-01-13 22:31:44 -0800121 t_key key;
Eric Dumazet112d8cf2008-01-12 21:27:41 -0800122 unsigned char pos; /* 2log(KEYLENGTH) bits needed */
123 unsigned char bits; /* 2log(KEYLENGTH) bits needed */
Eric Dumazet8d965442008-01-13 22:31:44 -0800124 unsigned int full_children; /* KEYLENGTH bits needed */
125 unsigned int empty_children; /* KEYLENGTH bits needed */
Stephen Hemminger15be75c2008-04-10 02:56:38 -0700126 union {
127 struct rcu_head rcu;
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700128 struct tnode *tnode_free;
Stephen Hemminger15be75c2008-04-10 02:56:38 -0700129 };
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700130 struct rt_trie_node __rcu *child[0];
Robert Olsson19baf832005-06-21 12:43:18 -0700131};
132
133#ifdef CONFIG_IP_FIB_TRIE_STATS
134struct trie_use_stats {
135 unsigned int gets;
136 unsigned int backtrack;
137 unsigned int semantic_match_passed;
138 unsigned int semantic_match_miss;
139 unsigned int null_node_hit;
Robert Olsson2f368952005-07-05 15:02:40 -0700140 unsigned int resize_node_skipped;
Robert Olsson19baf832005-06-21 12:43:18 -0700141};
142#endif
143
144struct trie_stat {
145 unsigned int totdepth;
146 unsigned int maxdepth;
147 unsigned int tnodes;
148 unsigned int leaves;
149 unsigned int nullpointers;
Stephen Hemminger93672292008-01-22 21:54:05 -0800150 unsigned int prefixes;
Robert Olsson06ef9212006-03-20 21:35:01 -0800151 unsigned int nodesizes[MAX_STAT_DEPTH];
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700152};
Robert Olsson19baf832005-06-21 12:43:18 -0700153
154struct trie {
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700155 struct rt_trie_node __rcu *trie;
Robert Olsson19baf832005-06-21 12:43:18 -0700156#ifdef CONFIG_IP_FIB_TRIE_STATS
157 struct trie_use_stats stats;
158#endif
Robert Olsson19baf832005-06-21 12:43:18 -0700159};
160
David S. Millerb299e4f2011-02-02 20:48:10 -0800161static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800162 int wasfull);
David S. Millerb299e4f2011-02-02 20:48:10 -0800163static struct rt_trie_node *resize(struct trie *t, struct tnode *tn);
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700164static struct tnode *inflate(struct trie *t, struct tnode *tn);
165static struct tnode *halve(struct trie *t, struct tnode *tn);
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700166/* tnodes to free after resize(); protected by RTNL */
167static struct tnode *tnode_free_head;
Jarek Poplawskic3059472009-07-14 08:33:08 +0000168static size_t tnode_free_size;
169
170/*
171 * synchronize_rcu after call_rcu for that many pages; it should be especially
172 * useful before resizing the root node with PREEMPT_NONE configs; the value was
173 * obtained experimentally, aiming to avoid visible slowdown.
174 */
175static const int sync_pages = 128;
Robert Olsson19baf832005-06-21 12:43:18 -0700176
Christoph Lametere18b8902006-12-06 20:33:20 -0800177static struct kmem_cache *fn_alias_kmem __read_mostly;
Stephen Hemmingerbc3c8c12008-01-22 21:51:50 -0800178static struct kmem_cache *trie_leaf_kmem __read_mostly;
Robert Olsson19baf832005-06-21 12:43:18 -0700179
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700180/*
181 * caller must hold RTNL
182 */
183static inline struct tnode *node_parent(const struct rt_trie_node *node)
Stephen Hemminger06801912007-08-10 15:22:13 -0700184{
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700185 unsigned long parent;
186
187 parent = rcu_dereference_index_check(node->parent, lockdep_rtnl_is_held());
188
189 return (struct tnode *)(parent & ~NODE_TYPE_MASK);
Eric Dumazetb59cfbf2008-01-18 03:31:36 -0800190}
Stephen Hemminger06801912007-08-10 15:22:13 -0700191
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700192/*
193 * caller must hold RCU read lock or RTNL
194 */
195static inline struct tnode *node_parent_rcu(const struct rt_trie_node *node)
Eric Dumazetb59cfbf2008-01-18 03:31:36 -0800196{
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700197 unsigned long parent;
Eric Dumazetb59cfbf2008-01-18 03:31:36 -0800198
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700199 parent = rcu_dereference_index_check(node->parent, rcu_read_lock_held() ||
200 lockdep_rtnl_is_held());
201
202 return (struct tnode *)(parent & ~NODE_TYPE_MASK);
Stephen Hemminger06801912007-08-10 15:22:13 -0700203}
204
Eric Dumazetcf778b02012-01-12 04:41:32 +0000205/* Same as rcu_assign_pointer
Stephen Hemminger6440cc92008-03-22 17:59:58 -0700206 * but that macro() assumes that value is a pointer.
207 */
David S. Millerb299e4f2011-02-02 20:48:10 -0800208static inline void node_set_parent(struct rt_trie_node *node, struct tnode *ptr)
Stephen Hemminger06801912007-08-10 15:22:13 -0700209{
Stephen Hemminger6440cc92008-03-22 17:59:58 -0700210 smp_wmb();
211 node->parent = (unsigned long)ptr | NODE_TYPE(node);
Stephen Hemminger06801912007-08-10 15:22:13 -0700212}
Robert Olsson2373ce12005-08-25 13:01:29 -0700213
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700214/*
215 * caller must hold RTNL
216 */
217static inline struct rt_trie_node *tnode_get_child(const struct tnode *tn, unsigned int i)
Robert Olsson19baf832005-06-21 12:43:18 -0700218{
Eric Dumazetb59cfbf2008-01-18 03:31:36 -0800219 BUG_ON(i >= 1U << tn->bits);
Robert Olsson19baf832005-06-21 12:43:18 -0700220
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700221 return rtnl_dereference(tn->child[i]);
Eric Dumazetb59cfbf2008-01-18 03:31:36 -0800222}
223
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700224/*
225 * caller must hold RCU read lock or RTNL
226 */
227static inline struct rt_trie_node *tnode_get_child_rcu(const struct tnode *tn, unsigned int i)
Eric Dumazetb59cfbf2008-01-18 03:31:36 -0800228{
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700229 BUG_ON(i >= 1U << tn->bits);
Eric Dumazetb59cfbf2008-01-18 03:31:36 -0800230
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700231 return rcu_dereference_rtnl(tn->child[i]);
Robert Olsson19baf832005-06-21 12:43:18 -0700232}
233
Stephen Hemmignerbb435b82005-08-09 20:25:39 -0700234static inline int tnode_child_length(const struct tnode *tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700235{
Olof Johansson91b9a272005-08-09 20:24:39 -0700236 return 1 << tn->bits;
Robert Olsson19baf832005-06-21 12:43:18 -0700237}
238
David S. Miller3b004562011-02-16 14:56:22 -0800239static inline t_key mask_pfx(t_key k, unsigned int l)
Stephen Hemmingerab66b4a2007-08-10 15:22:58 -0700240{
241 return (l == 0) ? 0 : k >> (KEYLENGTH-l) << (KEYLENGTH-l);
242}
243
David S. Miller3b004562011-02-16 14:56:22 -0800244static inline t_key tkey_extract_bits(t_key a, unsigned int offset, unsigned int bits)
Robert Olsson19baf832005-06-21 12:43:18 -0700245{
Olof Johansson91b9a272005-08-09 20:24:39 -0700246 if (offset < KEYLENGTH)
Robert Olsson19baf832005-06-21 12:43:18 -0700247 return ((t_key)(a << offset)) >> (KEYLENGTH - bits);
Olof Johansson91b9a272005-08-09 20:24:39 -0700248 else
Robert Olsson19baf832005-06-21 12:43:18 -0700249 return 0;
250}
251
252static inline int tkey_equals(t_key a, t_key b)
253{
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700254 return a == b;
Robert Olsson19baf832005-06-21 12:43:18 -0700255}
256
257static inline int tkey_sub_equals(t_key a, int offset, int bits, t_key b)
258{
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700259 if (bits == 0 || offset >= KEYLENGTH)
260 return 1;
Olof Johansson91b9a272005-08-09 20:24:39 -0700261 bits = bits > KEYLENGTH ? KEYLENGTH : bits;
262 return ((a ^ b) << offset) >> (KEYLENGTH - bits) == 0;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700263}
Robert Olsson19baf832005-06-21 12:43:18 -0700264
265static inline int tkey_mismatch(t_key a, int offset, t_key b)
266{
267 t_key diff = a ^ b;
268 int i = offset;
269
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700270 if (!diff)
271 return 0;
272 while ((diff << i) >> (KEYLENGTH-1) == 0)
Robert Olsson19baf832005-06-21 12:43:18 -0700273 i++;
274 return i;
275}
276
Robert Olsson19baf832005-06-21 12:43:18 -0700277/*
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900278 To understand this stuff, an understanding of keys and all their bits is
279 necessary. Every node in the trie has a key associated with it, but not
Robert Olsson19baf832005-06-21 12:43:18 -0700280 all of the bits in that key are significant.
281
282 Consider a node 'n' and its parent 'tp'.
283
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900284 If n is a leaf, every bit in its key is significant. Its presence is
285 necessitated by path compression, since during a tree traversal (when
286 searching for a leaf - unless we are doing an insertion) we will completely
287 ignore all skipped bits we encounter. Thus we need to verify, at the end of
288 a potentially successful search, that we have indeed been walking the
Robert Olsson19baf832005-06-21 12:43:18 -0700289 correct key path.
290
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900291 Note that we can never "miss" the correct key in the tree if present by
292 following the wrong path. Path compression ensures that segments of the key
293 that are the same for all keys with a given prefix are skipped, but the
294 skipped part *is* identical for each node in the subtrie below the skipped
295 bit! trie_insert() in this implementation takes care of that - note the
Robert Olsson19baf832005-06-21 12:43:18 -0700296 call to tkey_sub_equals() in trie_insert().
297
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900298 if n is an internal node - a 'tnode' here, the various parts of its key
Robert Olsson19baf832005-06-21 12:43:18 -0700299 have many different meanings.
300
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900301 Example:
Robert Olsson19baf832005-06-21 12:43:18 -0700302 _________________________________________________________________
303 | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C |
304 -----------------------------------------------------------------
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900305 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Robert Olsson19baf832005-06-21 12:43:18 -0700306
307 _________________________________________________________________
308 | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u |
309 -----------------------------------------------------------------
310 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
311
312 tp->pos = 7
313 tp->bits = 3
314 n->pos = 15
Olof Johansson91b9a272005-08-09 20:24:39 -0700315 n->bits = 4
Robert Olsson19baf832005-06-21 12:43:18 -0700316
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900317 First, let's just ignore the bits that come before the parent tp, that is
318 the bits from 0 to (tp->pos-1). They are *known* but at this point we do
Robert Olsson19baf832005-06-21 12:43:18 -0700319 not use them for anything.
320
321 The bits from (tp->pos) to (tp->pos + tp->bits - 1) - "N", above - are the
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900322 index into the parent's child array. That is, they will be used to find
Robert Olsson19baf832005-06-21 12:43:18 -0700323 'n' among tp's children.
324
325 The bits from (tp->pos + tp->bits) to (n->pos - 1) - "S" - are skipped bits
326 for the node n.
327
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900328 All the bits we have seen so far are significant to the node n. The rest
Robert Olsson19baf832005-06-21 12:43:18 -0700329 of the bits are really not needed or indeed known in n->key.
330
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900331 The bits from (n->pos) to (n->pos + n->bits - 1) - "C" - are the index into
Robert Olsson19baf832005-06-21 12:43:18 -0700332 n's child array, and will of course be different for each child.
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900333
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700334
Robert Olsson19baf832005-06-21 12:43:18 -0700335 The rest of the bits, from (n->pos + n->bits) onward, are completely unknown
336 at this point.
337
338*/
339
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700340static inline void check_tnode(const struct tnode *tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700341{
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700342 WARN_ON(tn && tn->pos+tn->bits > 32);
Robert Olsson19baf832005-06-21 12:43:18 -0700343}
344
Denis V. Lunevf5026fa2007-12-13 09:47:57 -0800345static const int halve_threshold = 25;
346static const int inflate_threshold = 50;
Jarek Poplawski345aa032009-07-07 19:39:16 -0700347static const int halve_threshold_root = 15;
Jens Låås80b71b82009-08-28 23:57:15 -0700348static const int inflate_threshold_root = 30;
Robert Olsson2373ce12005-08-25 13:01:29 -0700349
350static void __alias_free_mem(struct rcu_head *head)
351{
352 struct fib_alias *fa = container_of(head, struct fib_alias, rcu);
353 kmem_cache_free(fn_alias_kmem, fa);
354}
355
356static inline void alias_free_mem_rcu(struct fib_alias *fa)
357{
358 call_rcu(&fa->rcu, __alias_free_mem);
359}
360
361static void __leaf_free_rcu(struct rcu_head *head)
362{
Stephen Hemmingerbc3c8c12008-01-22 21:51:50 -0800363 struct leaf *l = container_of(head, struct leaf, rcu);
364 kmem_cache_free(trie_leaf_kmem, l);
Robert Olsson2373ce12005-08-25 13:01:29 -0700365}
366
Stephen Hemminger387a5482008-04-10 03:47:34 -0700367static inline void free_leaf(struct leaf *l)
368{
Eric Dumazet0c03eca2012-08-07 00:47:11 +0000369 call_rcu(&l->rcu, __leaf_free_rcu);
Stephen Hemminger387a5482008-04-10 03:47:34 -0700370}
371
Robert Olsson2373ce12005-08-25 13:01:29 -0700372static inline void free_leaf_info(struct leaf_info *leaf)
373{
Lai Jiangshanbceb0f42011-03-18 11:42:34 +0800374 kfree_rcu(leaf, rcu);
Robert Olsson2373ce12005-08-25 13:01:29 -0700375}
376
Eric Dumazet8d965442008-01-13 22:31:44 -0800377static struct tnode *tnode_alloc(size_t size)
Robert Olsson2373ce12005-08-25 13:01:29 -0700378{
Robert Olsson2373ce12005-08-25 13:01:29 -0700379 if (size <= PAGE_SIZE)
Eric Dumazet8d965442008-01-13 22:31:44 -0800380 return kzalloc(size, GFP_KERNEL);
Stephen Hemminger15be75c2008-04-10 02:56:38 -0700381 else
Eric Dumazet7a1c8e52010-11-20 07:46:35 +0000382 return vzalloc(size);
Stephen Hemminger15be75c2008-04-10 02:56:38 -0700383}
Robert Olsson2373ce12005-08-25 13:01:29 -0700384
Robert Olsson2373ce12005-08-25 13:01:29 -0700385static void __tnode_free_rcu(struct rcu_head *head)
386{
387 struct tnode *tn = container_of(head, struct tnode, rcu);
Eric Dumazet8d965442008-01-13 22:31:44 -0800388 size_t size = sizeof(struct tnode) +
David S. Millerb299e4f2011-02-02 20:48:10 -0800389 (sizeof(struct rt_trie_node *) << tn->bits);
Robert Olsson2373ce12005-08-25 13:01:29 -0700390
391 if (size <= PAGE_SIZE)
392 kfree(tn);
Al Viro00203562013-05-05 16:03:46 +0000393 else
394 vfree(tn);
Robert Olsson2373ce12005-08-25 13:01:29 -0700395}
396
397static inline void tnode_free(struct tnode *tn)
398{
Stephen Hemminger387a5482008-04-10 03:47:34 -0700399 if (IS_LEAF(tn))
400 free_leaf((struct leaf *) tn);
401 else
Robert Olsson550e29b2006-04-04 12:53:35 -0700402 call_rcu(&tn->rcu, __tnode_free_rcu);
Robert Olsson2373ce12005-08-25 13:01:29 -0700403}
404
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700405static void tnode_free_safe(struct tnode *tn)
406{
407 BUG_ON(IS_LEAF(tn));
Jarek Poplawski7b855762009-06-18 00:28:51 -0700408 tn->tnode_free = tnode_free_head;
409 tnode_free_head = tn;
Jarek Poplawskic3059472009-07-14 08:33:08 +0000410 tnode_free_size += sizeof(struct tnode) +
David S. Millerb299e4f2011-02-02 20:48:10 -0800411 (sizeof(struct rt_trie_node *) << tn->bits);
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700412}
413
414static void tnode_free_flush(void)
415{
416 struct tnode *tn;
417
418 while ((tn = tnode_free_head)) {
419 tnode_free_head = tn->tnode_free;
420 tn->tnode_free = NULL;
421 tnode_free(tn);
422 }
Jarek Poplawskic3059472009-07-14 08:33:08 +0000423
424 if (tnode_free_size >= PAGE_SIZE * sync_pages) {
425 tnode_free_size = 0;
426 synchronize_rcu();
427 }
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700428}
429
Robert Olsson19baf832005-06-21 12:43:18 -0700430static struct leaf *leaf_new(void)
431{
Stephen Hemmingerbc3c8c12008-01-22 21:51:50 -0800432 struct leaf *l = kmem_cache_alloc(trie_leaf_kmem, GFP_KERNEL);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700433 if (l) {
Robert Olsson2373ce12005-08-25 13:01:29 -0700434 l->parent = T_LEAF;
Robert Olsson19baf832005-06-21 12:43:18 -0700435 INIT_HLIST_HEAD(&l->list);
436 }
437 return l;
438}
439
440static struct leaf_info *leaf_info_new(int plen)
441{
442 struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL);
Robert Olsson2373ce12005-08-25 13:01:29 -0700443 if (li) {
444 li->plen = plen;
Eric Dumazet5c745012011-07-18 03:16:33 +0000445 li->mask_plen = ntohl(inet_make_mask(plen));
Robert Olsson2373ce12005-08-25 13:01:29 -0700446 INIT_LIST_HEAD(&li->falh);
Patrick McHardyf0e36f82005-07-05 14:44:55 -0700447 }
Robert Olsson2373ce12005-08-25 13:01:29 -0700448 return li;
Patrick McHardyf0e36f82005-07-05 14:44:55 -0700449}
450
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800451static struct tnode *tnode_new(t_key key, int pos, int bits)
Robert Olsson19baf832005-06-21 12:43:18 -0700452{
David S. Millerb299e4f2011-02-02 20:48:10 -0800453 size_t sz = sizeof(struct tnode) + (sizeof(struct rt_trie_node *) << bits);
Patrick McHardyf0e36f82005-07-05 14:44:55 -0700454 struct tnode *tn = tnode_alloc(sz);
Robert Olsson19baf832005-06-21 12:43:18 -0700455
Olof Johansson91b9a272005-08-09 20:24:39 -0700456 if (tn) {
Robert Olsson2373ce12005-08-25 13:01:29 -0700457 tn->parent = T_TNODE;
Robert Olsson19baf832005-06-21 12:43:18 -0700458 tn->pos = pos;
459 tn->bits = bits;
460 tn->key = key;
461 tn->full_children = 0;
462 tn->empty_children = 1<<bits;
463 }
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700464
Eric Dumazeta034ee32010-09-09 23:32:28 +0000465 pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode),
Lin Ming4ea4bf72012-07-29 01:19:55 +0000466 sizeof(struct rt_trie_node *) << bits);
Robert Olsson19baf832005-06-21 12:43:18 -0700467 return tn;
468}
469
Robert Olsson19baf832005-06-21 12:43:18 -0700470/*
471 * Check whether a tnode 'n' is "full", i.e. it is an internal node
472 * and no bits are skipped. See discussion in dyntree paper p. 6
473 */
474
David S. Millerb299e4f2011-02-02 20:48:10 -0800475static inline int tnode_full(const struct tnode *tn, const struct rt_trie_node *n)
Robert Olsson19baf832005-06-21 12:43:18 -0700476{
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700477 if (n == NULL || IS_LEAF(n))
Robert Olsson19baf832005-06-21 12:43:18 -0700478 return 0;
479
480 return ((struct tnode *) n)->pos == tn->pos + tn->bits;
481}
482
Lin Ming61648d92012-07-29 02:00:03 +0000483static inline void put_child(struct tnode *tn, int i,
David S. Millerb299e4f2011-02-02 20:48:10 -0800484 struct rt_trie_node *n)
Robert Olsson19baf832005-06-21 12:43:18 -0700485{
486 tnode_put_child_reorg(tn, i, n, -1);
487}
488
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700489 /*
Robert Olsson19baf832005-06-21 12:43:18 -0700490 * Add a child at position i overwriting the old value.
491 * Update the value of full_children and empty_children.
492 */
493
David S. Millerb299e4f2011-02-02 20:48:10 -0800494static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800495 int wasfull)
Robert Olsson19baf832005-06-21 12:43:18 -0700496{
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700497 struct rt_trie_node *chi = rtnl_dereference(tn->child[i]);
Robert Olsson19baf832005-06-21 12:43:18 -0700498 int isfull;
499
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700500 BUG_ON(i >= 1<<tn->bits);
501
Robert Olsson19baf832005-06-21 12:43:18 -0700502 /* update emptyChildren */
503 if (n == NULL && chi != NULL)
504 tn->empty_children++;
505 else if (n != NULL && chi == NULL)
506 tn->empty_children--;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700507
Robert Olsson19baf832005-06-21 12:43:18 -0700508 /* update fullChildren */
Olof Johansson91b9a272005-08-09 20:24:39 -0700509 if (wasfull == -1)
Robert Olsson19baf832005-06-21 12:43:18 -0700510 wasfull = tnode_full(tn, chi);
511
512 isfull = tnode_full(tn, n);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700513 if (wasfull && !isfull)
Robert Olsson19baf832005-06-21 12:43:18 -0700514 tn->full_children--;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700515 else if (!wasfull && isfull)
Robert Olsson19baf832005-06-21 12:43:18 -0700516 tn->full_children++;
Olof Johansson91b9a272005-08-09 20:24:39 -0700517
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700518 if (n)
Stephen Hemminger06801912007-08-10 15:22:13 -0700519 node_set_parent(n, tn);
Robert Olsson19baf832005-06-21 12:43:18 -0700520
Eric Dumazetcf778b02012-01-12 04:41:32 +0000521 rcu_assign_pointer(tn->child[i], n);
Robert Olsson19baf832005-06-21 12:43:18 -0700522}
523
Jens Låås80b71b82009-08-28 23:57:15 -0700524#define MAX_WORK 10
David S. Millerb299e4f2011-02-02 20:48:10 -0800525static struct rt_trie_node *resize(struct trie *t, struct tnode *tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700526{
527 int i;
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700528 struct tnode *old_tn;
Robert Olssone6308be2005-10-04 13:01:58 -0700529 int inflate_threshold_use;
530 int halve_threshold_use;
Jens Låås80b71b82009-08-28 23:57:15 -0700531 int max_work;
Robert Olsson19baf832005-06-21 12:43:18 -0700532
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900533 if (!tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700534 return NULL;
535
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700536 pr_debug("In tnode_resize %p inflate_threshold=%d threshold=%d\n",
537 tn, inflate_threshold, halve_threshold);
Robert Olsson19baf832005-06-21 12:43:18 -0700538
539 /* No children */
540 if (tn->empty_children == tnode_child_length(tn)) {
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700541 tnode_free_safe(tn);
Robert Olsson19baf832005-06-21 12:43:18 -0700542 return NULL;
543 }
544 /* One child */
545 if (tn->empty_children == tnode_child_length(tn) - 1)
Jens Låås80b71b82009-08-28 23:57:15 -0700546 goto one_child;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700547 /*
Robert Olsson19baf832005-06-21 12:43:18 -0700548 * Double as long as the resulting node has a number of
549 * nonempty nodes that are above the threshold.
550 */
551
552 /*
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700553 * From "Implementing a dynamic compressed trie" by Stefan Nilsson of
554 * the Helsinki University of Technology and Matti Tikkanen of Nokia
Robert Olsson19baf832005-06-21 12:43:18 -0700555 * Telecommunications, page 6:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700556 * "A node is doubled if the ratio of non-empty children to all
Robert Olsson19baf832005-06-21 12:43:18 -0700557 * children in the *doubled* node is at least 'high'."
558 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700559 * 'high' in this instance is the variable 'inflate_threshold'. It
560 * is expressed as a percentage, so we multiply it with
561 * tnode_child_length() and instead of multiplying by 2 (since the
562 * child array will be doubled by inflate()) and multiplying
563 * the left-hand side by 100 (to handle the percentage thing) we
Robert Olsson19baf832005-06-21 12:43:18 -0700564 * multiply the left-hand side by 50.
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700565 *
566 * The left-hand side may look a bit weird: tnode_child_length(tn)
567 * - tn->empty_children is of course the number of non-null children
568 * in the current node. tn->full_children is the number of "full"
Robert Olsson19baf832005-06-21 12:43:18 -0700569 * children, that is non-null tnodes with a skip value of 0.
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700570 * All of those will be doubled in the resulting inflated tnode, so
Robert Olsson19baf832005-06-21 12:43:18 -0700571 * we just count them one extra time here.
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700572 *
Robert Olsson19baf832005-06-21 12:43:18 -0700573 * A clearer way to write this would be:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700574 *
Robert Olsson19baf832005-06-21 12:43:18 -0700575 * to_be_doubled = tn->full_children;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700576 * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children -
Robert Olsson19baf832005-06-21 12:43:18 -0700577 * tn->full_children;
578 *
579 * new_child_length = tnode_child_length(tn) * 2;
580 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700581 * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) /
Robert Olsson19baf832005-06-21 12:43:18 -0700582 * new_child_length;
583 * if (new_fill_factor >= inflate_threshold)
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700584 *
585 * ...and so on, tho it would mess up the while () loop.
586 *
Robert Olsson19baf832005-06-21 12:43:18 -0700587 * anyway,
588 * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >=
589 * inflate_threshold
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700590 *
Robert Olsson19baf832005-06-21 12:43:18 -0700591 * avoid a division:
592 * 100 * (not_to_be_doubled + 2*to_be_doubled) >=
593 * inflate_threshold * new_child_length
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700594 *
Robert Olsson19baf832005-06-21 12:43:18 -0700595 * expand not_to_be_doubled and to_be_doubled, and shorten:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700596 * 100 * (tnode_child_length(tn) - tn->empty_children +
Olof Johansson91b9a272005-08-09 20:24:39 -0700597 * tn->full_children) >= inflate_threshold * new_child_length
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700598 *
Robert Olsson19baf832005-06-21 12:43:18 -0700599 * expand new_child_length:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700600 * 100 * (tnode_child_length(tn) - tn->empty_children +
Olof Johansson91b9a272005-08-09 20:24:39 -0700601 * tn->full_children) >=
Robert Olsson19baf832005-06-21 12:43:18 -0700602 * inflate_threshold * tnode_child_length(tn) * 2
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700603 *
Robert Olsson19baf832005-06-21 12:43:18 -0700604 * shorten again:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700605 * 50 * (tn->full_children + tnode_child_length(tn) -
Olof Johansson91b9a272005-08-09 20:24:39 -0700606 * tn->empty_children) >= inflate_threshold *
Robert Olsson19baf832005-06-21 12:43:18 -0700607 * tnode_child_length(tn)
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700608 *
Robert Olsson19baf832005-06-21 12:43:18 -0700609 */
610
611 check_tnode(tn);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700612
Robert Olssone6308be2005-10-04 13:01:58 -0700613 /* Keep root node larger */
614
David S. Millerb299e4f2011-02-02 20:48:10 -0800615 if (!node_parent((struct rt_trie_node *)tn)) {
Jens Låås80b71b82009-08-28 23:57:15 -0700616 inflate_threshold_use = inflate_threshold_root;
617 halve_threshold_use = halve_threshold_root;
Eric Dumazeta034ee32010-09-09 23:32:28 +0000618 } else {
Robert Olssone6308be2005-10-04 13:01:58 -0700619 inflate_threshold_use = inflate_threshold;
Jens Låås80b71b82009-08-28 23:57:15 -0700620 halve_threshold_use = halve_threshold;
621 }
Robert Olssone6308be2005-10-04 13:01:58 -0700622
Jens Låås80b71b82009-08-28 23:57:15 -0700623 max_work = MAX_WORK;
624 while ((tn->full_children > 0 && max_work-- &&
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800625 50 * (tn->full_children + tnode_child_length(tn)
626 - tn->empty_children)
627 >= inflate_threshold_use * tnode_child_length(tn))) {
Robert Olsson19baf832005-06-21 12:43:18 -0700628
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700629 old_tn = tn;
630 tn = inflate(t, tn);
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800631
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700632 if (IS_ERR(tn)) {
633 tn = old_tn;
Robert Olsson2f368952005-07-05 15:02:40 -0700634#ifdef CONFIG_IP_FIB_TRIE_STATS
635 t->stats.resize_node_skipped++;
636#endif
637 break;
638 }
Robert Olsson19baf832005-06-21 12:43:18 -0700639 }
640
641 check_tnode(tn);
642
Jens Låås80b71b82009-08-28 23:57:15 -0700643 /* Return if at least one inflate is run */
Eric Dumazeta034ee32010-09-09 23:32:28 +0000644 if (max_work != MAX_WORK)
David S. Millerb299e4f2011-02-02 20:48:10 -0800645 return (struct rt_trie_node *) tn;
Jens Låås80b71b82009-08-28 23:57:15 -0700646
Robert Olsson19baf832005-06-21 12:43:18 -0700647 /*
648 * Halve as long as the number of empty children in this
649 * node is above threshold.
650 */
Robert Olsson2f368952005-07-05 15:02:40 -0700651
Jens Låås80b71b82009-08-28 23:57:15 -0700652 max_work = MAX_WORK;
653 while (tn->bits > 1 && max_work-- &&
Robert Olsson19baf832005-06-21 12:43:18 -0700654 100 * (tnode_child_length(tn) - tn->empty_children) <
Robert Olssone6308be2005-10-04 13:01:58 -0700655 halve_threshold_use * tnode_child_length(tn)) {
Robert Olsson19baf832005-06-21 12:43:18 -0700656
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700657 old_tn = tn;
658 tn = halve(t, tn);
659 if (IS_ERR(tn)) {
660 tn = old_tn;
Robert Olsson2f368952005-07-05 15:02:40 -0700661#ifdef CONFIG_IP_FIB_TRIE_STATS
662 t->stats.resize_node_skipped++;
663#endif
664 break;
665 }
666 }
667
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700668
Robert Olsson19baf832005-06-21 12:43:18 -0700669 /* Only one child remains */
Jens Låås80b71b82009-08-28 23:57:15 -0700670 if (tn->empty_children == tnode_child_length(tn) - 1) {
671one_child:
Robert Olsson19baf832005-06-21 12:43:18 -0700672 for (i = 0; i < tnode_child_length(tn); i++) {
David S. Millerb299e4f2011-02-02 20:48:10 -0800673 struct rt_trie_node *n;
Olof Johansson91b9a272005-08-09 20:24:39 -0700674
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700675 n = rtnl_dereference(tn->child[i]);
Robert Olsson2373ce12005-08-25 13:01:29 -0700676 if (!n)
Olof Johansson91b9a272005-08-09 20:24:39 -0700677 continue;
Olof Johansson91b9a272005-08-09 20:24:39 -0700678
679 /* compress one level */
680
Stephen Hemminger06801912007-08-10 15:22:13 -0700681 node_set_parent(n, NULL);
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700682 tnode_free_safe(tn);
Olof Johansson91b9a272005-08-09 20:24:39 -0700683 return n;
Robert Olsson19baf832005-06-21 12:43:18 -0700684 }
Jens Låås80b71b82009-08-28 23:57:15 -0700685 }
David S. Millerb299e4f2011-02-02 20:48:10 -0800686 return (struct rt_trie_node *) tn;
Robert Olsson19baf832005-06-21 12:43:18 -0700687}
688
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700689
690static void tnode_clean_free(struct tnode *tn)
691{
692 int i;
693 struct tnode *tofree;
694
695 for (i = 0; i < tnode_child_length(tn); i++) {
696 tofree = (struct tnode *)rtnl_dereference(tn->child[i]);
697 if (tofree)
698 tnode_free(tofree);
699 }
700 tnode_free(tn);
701}
702
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700703static struct tnode *inflate(struct trie *t, struct tnode *tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700704{
Robert Olsson19baf832005-06-21 12:43:18 -0700705 struct tnode *oldtnode = tn;
706 int olen = tnode_child_length(tn);
707 int i;
708
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700709 pr_debug("In inflate\n");
Robert Olsson19baf832005-06-21 12:43:18 -0700710
711 tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits + 1);
712
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700713 if (!tn)
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700714 return ERR_PTR(-ENOMEM);
Robert Olsson2f368952005-07-05 15:02:40 -0700715
716 /*
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700717 * Preallocate and store tnodes before the actual work so we
718 * don't get into an inconsistent state if memory allocation
719 * fails. In case of failure we return the oldnode and inflate
Robert Olsson2f368952005-07-05 15:02:40 -0700720 * of tnode is ignored.
721 */
Olof Johansson91b9a272005-08-09 20:24:39 -0700722
723 for (i = 0; i < olen; i++) {
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800724 struct tnode *inode;
Robert Olsson2f368952005-07-05 15:02:40 -0700725
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800726 inode = (struct tnode *) tnode_get_child(oldtnode, i);
Robert Olsson2f368952005-07-05 15:02:40 -0700727 if (inode &&
728 IS_TNODE(inode) &&
729 inode->pos == oldtnode->pos + oldtnode->bits &&
730 inode->bits > 1) {
731 struct tnode *left, *right;
Stephen Hemmingerab66b4a2007-08-10 15:22:58 -0700732 t_key m = ~0U << (KEYLENGTH - 1) >> inode->pos;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700733
Robert Olsson2f368952005-07-05 15:02:40 -0700734 left = tnode_new(inode->key&(~m), inode->pos + 1,
735 inode->bits - 1);
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700736 if (!left)
737 goto nomem;
Olof Johansson91b9a272005-08-09 20:24:39 -0700738
Robert Olsson2f368952005-07-05 15:02:40 -0700739 right = tnode_new(inode->key|m, inode->pos + 1,
740 inode->bits - 1);
741
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900742 if (!right) {
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700743 tnode_free(left);
744 goto nomem;
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900745 }
Robert Olsson2f368952005-07-05 15:02:40 -0700746
Lin Ming61648d92012-07-29 02:00:03 +0000747 put_child(tn, 2*i, (struct rt_trie_node *) left);
748 put_child(tn, 2*i+1, (struct rt_trie_node *) right);
Robert Olsson2f368952005-07-05 15:02:40 -0700749 }
750 }
751
Olof Johansson91b9a272005-08-09 20:24:39 -0700752 for (i = 0; i < olen; i++) {
Stephen Hemmingerc95aaf92008-01-12 21:25:02 -0800753 struct tnode *inode;
David S. Millerb299e4f2011-02-02 20:48:10 -0800754 struct rt_trie_node *node = tnode_get_child(oldtnode, i);
Olof Johansson91b9a272005-08-09 20:24:39 -0700755 struct tnode *left, *right;
756 int size, j;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700757
Robert Olsson19baf832005-06-21 12:43:18 -0700758 /* An empty child */
759 if (node == NULL)
760 continue;
761
762 /* A leaf or an internal node with skipped bits */
763
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700764 if (IS_LEAF(node) || ((struct tnode *) node)->pos >
Robert Olsson19baf832005-06-21 12:43:18 -0700765 tn->pos + tn->bits - 1) {
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800766 if (tkey_extract_bits(node->key,
767 oldtnode->pos + oldtnode->bits,
768 1) == 0)
Lin Ming61648d92012-07-29 02:00:03 +0000769 put_child(tn, 2*i, node);
Robert Olsson19baf832005-06-21 12:43:18 -0700770 else
Lin Ming61648d92012-07-29 02:00:03 +0000771 put_child(tn, 2*i+1, node);
Robert Olsson19baf832005-06-21 12:43:18 -0700772 continue;
773 }
774
775 /* An internal node with two children */
776 inode = (struct tnode *) node;
777
778 if (inode->bits == 1) {
Lin Ming61648d92012-07-29 02:00:03 +0000779 put_child(tn, 2*i, rtnl_dereference(inode->child[0]));
780 put_child(tn, 2*i+1, rtnl_dereference(inode->child[1]));
Robert Olsson19baf832005-06-21 12:43:18 -0700781
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700782 tnode_free_safe(inode);
Olof Johansson91b9a272005-08-09 20:24:39 -0700783 continue;
Robert Olsson19baf832005-06-21 12:43:18 -0700784 }
785
Olof Johansson91b9a272005-08-09 20:24:39 -0700786 /* An internal node with more than two children */
Robert Olsson19baf832005-06-21 12:43:18 -0700787
Olof Johansson91b9a272005-08-09 20:24:39 -0700788 /* We will replace this node 'inode' with two new
789 * ones, 'left' and 'right', each with half of the
790 * original children. The two new nodes will have
791 * a position one bit further down the key and this
792 * means that the "significant" part of their keys
793 * (see the discussion near the top of this file)
794 * will differ by one bit, which will be "0" in
795 * left's key and "1" in right's key. Since we are
796 * moving the key position by one step, the bit that
797 * we are moving away from - the bit at position
798 * (inode->pos) - is the one that will differ between
799 * left and right. So... we synthesize that bit in the
800 * two new keys.
801 * The mask 'm' below will be a single "one" bit at
802 * the position (inode->pos)
803 */
Robert Olsson19baf832005-06-21 12:43:18 -0700804
Olof Johansson91b9a272005-08-09 20:24:39 -0700805 /* Use the old key, but set the new significant
806 * bit to zero.
807 */
Robert Olsson19baf832005-06-21 12:43:18 -0700808
Olof Johansson91b9a272005-08-09 20:24:39 -0700809 left = (struct tnode *) tnode_get_child(tn, 2*i);
Lin Ming61648d92012-07-29 02:00:03 +0000810 put_child(tn, 2*i, NULL);
Robert Olsson19baf832005-06-21 12:43:18 -0700811
Olof Johansson91b9a272005-08-09 20:24:39 -0700812 BUG_ON(!left);
Robert Olsson2f368952005-07-05 15:02:40 -0700813
Olof Johansson91b9a272005-08-09 20:24:39 -0700814 right = (struct tnode *) tnode_get_child(tn, 2*i+1);
Lin Ming61648d92012-07-29 02:00:03 +0000815 put_child(tn, 2*i+1, NULL);
Robert Olsson2f368952005-07-05 15:02:40 -0700816
Olof Johansson91b9a272005-08-09 20:24:39 -0700817 BUG_ON(!right);
Robert Olsson2f368952005-07-05 15:02:40 -0700818
Olof Johansson91b9a272005-08-09 20:24:39 -0700819 size = tnode_child_length(left);
820 for (j = 0; j < size; j++) {
Lin Ming61648d92012-07-29 02:00:03 +0000821 put_child(left, j, rtnl_dereference(inode->child[j]));
822 put_child(right, j, rtnl_dereference(inode->child[j + size]));
Robert Olsson19baf832005-06-21 12:43:18 -0700823 }
Lin Ming61648d92012-07-29 02:00:03 +0000824 put_child(tn, 2*i, resize(t, left));
825 put_child(tn, 2*i+1, resize(t, right));
Olof Johansson91b9a272005-08-09 20:24:39 -0700826
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700827 tnode_free_safe(inode);
Robert Olsson19baf832005-06-21 12:43:18 -0700828 }
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700829 tnode_free_safe(oldtnode);
Robert Olsson19baf832005-06-21 12:43:18 -0700830 return tn;
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700831nomem:
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700832 tnode_clean_free(tn);
833 return ERR_PTR(-ENOMEM);
Robert Olsson19baf832005-06-21 12:43:18 -0700834}
835
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700836static struct tnode *halve(struct trie *t, struct tnode *tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700837{
838 struct tnode *oldtnode = tn;
David S. Millerb299e4f2011-02-02 20:48:10 -0800839 struct rt_trie_node *left, *right;
Robert Olsson19baf832005-06-21 12:43:18 -0700840 int i;
841 int olen = tnode_child_length(tn);
842
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700843 pr_debug("In halve\n");
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700844
845 tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits - 1);
Robert Olsson19baf832005-06-21 12:43:18 -0700846
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700847 if (!tn)
848 return ERR_PTR(-ENOMEM);
Robert Olsson2f368952005-07-05 15:02:40 -0700849
850 /*
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700851 * Preallocate and store tnodes before the actual work so we
852 * don't get into an inconsistent state if memory allocation
853 * fails. In case of failure we return the oldnode and halve
Robert Olsson2f368952005-07-05 15:02:40 -0700854 * of tnode is ignored.
855 */
856
Olof Johansson91b9a272005-08-09 20:24:39 -0700857 for (i = 0; i < olen; i += 2) {
Robert Olsson2f368952005-07-05 15:02:40 -0700858 left = tnode_get_child(oldtnode, i);
859 right = tnode_get_child(oldtnode, i+1);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700860
Robert Olsson2f368952005-07-05 15:02:40 -0700861 /* Two nonempty children */
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700862 if (left && right) {
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700863 struct tnode *newn;
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700864
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700865 newn = tnode_new(left->key, tn->pos + tn->bits, 1);
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700866
867 if (!newn)
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700868 goto nomem;
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700869
Lin Ming61648d92012-07-29 02:00:03 +0000870 put_child(tn, i/2, (struct rt_trie_node *)newn);
Robert Olsson2f368952005-07-05 15:02:40 -0700871 }
Robert Olsson2f368952005-07-05 15:02:40 -0700872
Robert Olsson2f368952005-07-05 15:02:40 -0700873 }
Robert Olsson19baf832005-06-21 12:43:18 -0700874
Olof Johansson91b9a272005-08-09 20:24:39 -0700875 for (i = 0; i < olen; i += 2) {
876 struct tnode *newBinNode;
877
Robert Olsson19baf832005-06-21 12:43:18 -0700878 left = tnode_get_child(oldtnode, i);
879 right = tnode_get_child(oldtnode, i+1);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700880
Robert Olsson19baf832005-06-21 12:43:18 -0700881 /* At least one of the children is empty */
882 if (left == NULL) {
883 if (right == NULL) /* Both are empty */
884 continue;
Lin Ming61648d92012-07-29 02:00:03 +0000885 put_child(tn, i/2, right);
Olof Johansson91b9a272005-08-09 20:24:39 -0700886 continue;
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700887 }
Olof Johansson91b9a272005-08-09 20:24:39 -0700888
889 if (right == NULL) {
Lin Ming61648d92012-07-29 02:00:03 +0000890 put_child(tn, i/2, left);
Olof Johansson91b9a272005-08-09 20:24:39 -0700891 continue;
892 }
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700893
Robert Olsson19baf832005-06-21 12:43:18 -0700894 /* Two nonempty children */
Olof Johansson91b9a272005-08-09 20:24:39 -0700895 newBinNode = (struct tnode *) tnode_get_child(tn, i/2);
Lin Ming61648d92012-07-29 02:00:03 +0000896 put_child(tn, i/2, NULL);
897 put_child(newBinNode, 0, left);
898 put_child(newBinNode, 1, right);
899 put_child(tn, i/2, resize(t, newBinNode));
Robert Olsson19baf832005-06-21 12:43:18 -0700900 }
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700901 tnode_free_safe(oldtnode);
Robert Olsson19baf832005-06-21 12:43:18 -0700902 return tn;
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700903nomem:
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700904 tnode_clean_free(tn);
905 return ERR_PTR(-ENOMEM);
Robert Olsson19baf832005-06-21 12:43:18 -0700906}
907
Robert Olsson772cb712005-09-19 15:31:18 -0700908/* readside must use rcu_read_lock currently dump routines
Robert Olsson2373ce12005-08-25 13:01:29 -0700909 via get_fa_head and dump */
910
Robert Olsson772cb712005-09-19 15:31:18 -0700911static struct leaf_info *find_leaf_info(struct leaf *l, int plen)
Robert Olsson19baf832005-06-21 12:43:18 -0700912{
Robert Olsson772cb712005-09-19 15:31:18 -0700913 struct hlist_head *head = &l->list;
Robert Olsson19baf832005-06-21 12:43:18 -0700914 struct leaf_info *li;
915
Sasha Levinb67bfe02013-02-27 17:06:00 -0800916 hlist_for_each_entry_rcu(li, head, hlist)
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700917 if (li->plen == plen)
Robert Olsson19baf832005-06-21 12:43:18 -0700918 return li;
Olof Johansson91b9a272005-08-09 20:24:39 -0700919
Robert Olsson19baf832005-06-21 12:43:18 -0700920 return NULL;
921}
922
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800923static inline struct list_head *get_fa_head(struct leaf *l, int plen)
Robert Olsson19baf832005-06-21 12:43:18 -0700924{
Robert Olsson772cb712005-09-19 15:31:18 -0700925 struct leaf_info *li = find_leaf_info(l, plen);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700926
Olof Johansson91b9a272005-08-09 20:24:39 -0700927 if (!li)
928 return NULL;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700929
Olof Johansson91b9a272005-08-09 20:24:39 -0700930 return &li->falh;
Robert Olsson19baf832005-06-21 12:43:18 -0700931}
932
933static void insert_leaf_info(struct hlist_head *head, struct leaf_info *new)
934{
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900935 struct leaf_info *li = NULL, *last = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -0700936
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900937 if (hlist_empty(head)) {
938 hlist_add_head_rcu(&new->hlist, head);
939 } else {
Sasha Levinb67bfe02013-02-27 17:06:00 -0800940 hlist_for_each_entry(li, head, hlist) {
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900941 if (new->plen > li->plen)
942 break;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700943
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900944 last = li;
945 }
946 if (last)
947 hlist_add_after_rcu(&last->hlist, &new->hlist);
948 else
949 hlist_add_before_rcu(&new->hlist, &li->hlist);
950 }
Robert Olsson19baf832005-06-21 12:43:18 -0700951}
952
Robert Olsson2373ce12005-08-25 13:01:29 -0700953/* rcu_read_lock needs to be hold by caller from readside */
954
Robert Olsson19baf832005-06-21 12:43:18 -0700955static struct leaf *
956fib_find_node(struct trie *t, u32 key)
957{
958 int pos;
959 struct tnode *tn;
David S. Millerb299e4f2011-02-02 20:48:10 -0800960 struct rt_trie_node *n;
Robert Olsson19baf832005-06-21 12:43:18 -0700961
962 pos = 0;
Eric Dumazeta034ee32010-09-09 23:32:28 +0000963 n = rcu_dereference_rtnl(t->trie);
Robert Olsson19baf832005-06-21 12:43:18 -0700964
965 while (n != NULL && NODE_TYPE(n) == T_TNODE) {
966 tn = (struct tnode *) n;
Olof Johansson91b9a272005-08-09 20:24:39 -0700967
Robert Olsson19baf832005-06-21 12:43:18 -0700968 check_tnode(tn);
Olof Johansson91b9a272005-08-09 20:24:39 -0700969
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700970 if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
Olof Johansson91b9a272005-08-09 20:24:39 -0700971 pos = tn->pos + tn->bits;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800972 n = tnode_get_child_rcu(tn,
973 tkey_extract_bits(key,
974 tn->pos,
975 tn->bits));
Olof Johansson91b9a272005-08-09 20:24:39 -0700976 } else
Robert Olsson19baf832005-06-21 12:43:18 -0700977 break;
978 }
979 /* Case we have found a leaf. Compare prefixes */
980
Olof Johansson91b9a272005-08-09 20:24:39 -0700981 if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key))
982 return (struct leaf *)n;
983
Robert Olsson19baf832005-06-21 12:43:18 -0700984 return NULL;
985}
986
Jarek Poplawski7b855762009-06-18 00:28:51 -0700987static void trie_rebalance(struct trie *t, struct tnode *tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700988{
Robert Olsson19baf832005-06-21 12:43:18 -0700989 int wasfull;
Robert Olsson3ed18d72009-05-21 15:20:59 -0700990 t_key cindex, key;
Stephen Hemminger06801912007-08-10 15:22:13 -0700991 struct tnode *tp;
Robert Olsson19baf832005-06-21 12:43:18 -0700992
Robert Olsson3ed18d72009-05-21 15:20:59 -0700993 key = tn->key;
994
David S. Millerb299e4f2011-02-02 20:48:10 -0800995 while (tn != NULL && (tp = node_parent((struct rt_trie_node *)tn)) != NULL) {
Robert Olsson19baf832005-06-21 12:43:18 -0700996 cindex = tkey_extract_bits(key, tp->pos, tp->bits);
997 wasfull = tnode_full(tp, tnode_get_child(tp, cindex));
Joe Perchese3192692012-06-03 17:41:40 +0000998 tn = (struct tnode *)resize(t, tn);
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800999
Joe Perchese3192692012-06-03 17:41:40 +00001000 tnode_put_child_reorg(tp, cindex,
David S. Millerb299e4f2011-02-02 20:48:10 -08001001 (struct rt_trie_node *)tn, wasfull);
Olof Johansson91b9a272005-08-09 20:24:39 -07001002
David S. Millerb299e4f2011-02-02 20:48:10 -08001003 tp = node_parent((struct rt_trie_node *) tn);
Jarek Poplawski008440e2009-06-30 12:47:19 -07001004 if (!tp)
Eric Dumazetcf778b02012-01-12 04:41:32 +00001005 rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
Jarek Poplawski008440e2009-06-30 12:47:19 -07001006
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -07001007 tnode_free_flush();
Stephen Hemminger06801912007-08-10 15:22:13 -07001008 if (!tp)
Robert Olsson19baf832005-06-21 12:43:18 -07001009 break;
Stephen Hemminger06801912007-08-10 15:22:13 -07001010 tn = tp;
Robert Olsson19baf832005-06-21 12:43:18 -07001011 }
Stephen Hemminger06801912007-08-10 15:22:13 -07001012
Robert Olsson19baf832005-06-21 12:43:18 -07001013 /* Handle last (top) tnode */
Jarek Poplawski7b855762009-06-18 00:28:51 -07001014 if (IS_TNODE(tn))
Joe Perchese3192692012-06-03 17:41:40 +00001015 tn = (struct tnode *)resize(t, tn);
Robert Olsson19baf832005-06-21 12:43:18 -07001016
Eric Dumazetcf778b02012-01-12 04:41:32 +00001017 rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
Jarek Poplawski7b855762009-06-18 00:28:51 -07001018 tnode_free_flush();
Robert Olsson19baf832005-06-21 12:43:18 -07001019}
1020
Robert Olsson2373ce12005-08-25 13:01:29 -07001021/* only used from updater-side */
1022
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001023static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
Robert Olsson19baf832005-06-21 12:43:18 -07001024{
1025 int pos, newpos;
1026 struct tnode *tp = NULL, *tn = NULL;
David S. Millerb299e4f2011-02-02 20:48:10 -08001027 struct rt_trie_node *n;
Robert Olsson19baf832005-06-21 12:43:18 -07001028 struct leaf *l;
1029 int missbit;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001030 struct list_head *fa_head = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001031 struct leaf_info *li;
1032 t_key cindex;
1033
1034 pos = 0;
Eric Dumazet0a5c0472011-03-31 01:51:35 -07001035 n = rtnl_dereference(t->trie);
Robert Olsson19baf832005-06-21 12:43:18 -07001036
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001037 /* If we point to NULL, stop. Either the tree is empty and we should
1038 * just put a new leaf in if, or we have reached an empty child slot,
Robert Olsson19baf832005-06-21 12:43:18 -07001039 * and we should just put our new leaf in that.
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001040 * If we point to a T_TNODE, check if it matches our key. Note that
1041 * a T_TNODE might be skipping any number of bits - its 'pos' need
Robert Olsson19baf832005-06-21 12:43:18 -07001042 * not be the parent's 'pos'+'bits'!
1043 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001044 * If it does match the current key, get pos/bits from it, extract
Robert Olsson19baf832005-06-21 12:43:18 -07001045 * the index from our key, push the T_TNODE and walk the tree.
1046 *
1047 * If it doesn't, we have to replace it with a new T_TNODE.
1048 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001049 * If we point to a T_LEAF, it might or might not have the same key
1050 * as we do. If it does, just change the value, update the T_LEAF's
1051 * value, and return it.
Robert Olsson19baf832005-06-21 12:43:18 -07001052 * If it doesn't, we need to replace it with a T_TNODE.
1053 */
1054
1055 while (n != NULL && NODE_TYPE(n) == T_TNODE) {
1056 tn = (struct tnode *) n;
Olof Johansson91b9a272005-08-09 20:24:39 -07001057
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001058 check_tnode(tn);
Olof Johansson91b9a272005-08-09 20:24:39 -07001059
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001060 if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
Robert Olsson19baf832005-06-21 12:43:18 -07001061 tp = tn;
Olof Johansson91b9a272005-08-09 20:24:39 -07001062 pos = tn->pos + tn->bits;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001063 n = tnode_get_child(tn,
1064 tkey_extract_bits(key,
1065 tn->pos,
1066 tn->bits));
Robert Olsson19baf832005-06-21 12:43:18 -07001067
Stephen Hemminger06801912007-08-10 15:22:13 -07001068 BUG_ON(n && node_parent(n) != tn);
Olof Johansson91b9a272005-08-09 20:24:39 -07001069 } else
Robert Olsson19baf832005-06-21 12:43:18 -07001070 break;
1071 }
1072
1073 /*
1074 * n ----> NULL, LEAF or TNODE
1075 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001076 * tp is n's (parent) ----> NULL or TNODE
Robert Olsson19baf832005-06-21 12:43:18 -07001077 */
1078
Olof Johansson91b9a272005-08-09 20:24:39 -07001079 BUG_ON(tp && IS_LEAF(tp));
Robert Olsson19baf832005-06-21 12:43:18 -07001080
1081 /* Case 1: n is a leaf. Compare prefixes */
1082
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001083 if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) {
Stephen Hemmingerc95aaf92008-01-12 21:25:02 -08001084 l = (struct leaf *) n;
Robert Olsson19baf832005-06-21 12:43:18 -07001085 li = leaf_info_new(plen);
Olof Johansson91b9a272005-08-09 20:24:39 -07001086
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001087 if (!li)
1088 return NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001089
1090 fa_head = &li->falh;
1091 insert_leaf_info(&l->list, li);
1092 goto done;
1093 }
Robert Olsson19baf832005-06-21 12:43:18 -07001094 l = leaf_new();
1095
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001096 if (!l)
1097 return NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001098
1099 l->key = key;
1100 li = leaf_info_new(plen);
1101
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001102 if (!li) {
Stephen Hemminger387a5482008-04-10 03:47:34 -07001103 free_leaf(l);
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001104 return NULL;
Robert Olssonf835e472005-06-28 15:00:39 -07001105 }
Robert Olsson19baf832005-06-21 12:43:18 -07001106
1107 fa_head = &li->falh;
1108 insert_leaf_info(&l->list, li);
1109
Robert Olsson19baf832005-06-21 12:43:18 -07001110 if (t->trie && n == NULL) {
Olof Johansson91b9a272005-08-09 20:24:39 -07001111 /* Case 2: n is NULL, and will just insert a new leaf */
Robert Olsson19baf832005-06-21 12:43:18 -07001112
David S. Millerb299e4f2011-02-02 20:48:10 -08001113 node_set_parent((struct rt_trie_node *)l, tp);
Robert Olsson19baf832005-06-21 12:43:18 -07001114
Olof Johansson91b9a272005-08-09 20:24:39 -07001115 cindex = tkey_extract_bits(key, tp->pos, tp->bits);
Lin Ming61648d92012-07-29 02:00:03 +00001116 put_child(tp, cindex, (struct rt_trie_node *)l);
Olof Johansson91b9a272005-08-09 20:24:39 -07001117 } else {
1118 /* Case 3: n is a LEAF or a TNODE and the key doesn't match. */
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001119 /*
1120 * Add a new tnode here
Robert Olsson19baf832005-06-21 12:43:18 -07001121 * first tnode need some special handling
1122 */
1123
1124 if (tp)
Olof Johansson91b9a272005-08-09 20:24:39 -07001125 pos = tp->pos+tp->bits;
Robert Olsson19baf832005-06-21 12:43:18 -07001126 else
Olof Johansson91b9a272005-08-09 20:24:39 -07001127 pos = 0;
1128
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001129 if (n) {
Robert Olsson19baf832005-06-21 12:43:18 -07001130 newpos = tkey_mismatch(key, pos, n->key);
1131 tn = tnode_new(n->key, newpos, 1);
Olof Johansson91b9a272005-08-09 20:24:39 -07001132 } else {
Robert Olsson19baf832005-06-21 12:43:18 -07001133 newpos = 0;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001134 tn = tnode_new(key, newpos, 1); /* First tnode */
Robert Olsson19baf832005-06-21 12:43:18 -07001135 }
Robert Olsson19baf832005-06-21 12:43:18 -07001136
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001137 if (!tn) {
Robert Olssonf835e472005-06-28 15:00:39 -07001138 free_leaf_info(li);
Stephen Hemminger387a5482008-04-10 03:47:34 -07001139 free_leaf(l);
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001140 return NULL;
Olof Johansson91b9a272005-08-09 20:24:39 -07001141 }
1142
David S. Millerb299e4f2011-02-02 20:48:10 -08001143 node_set_parent((struct rt_trie_node *)tn, tp);
Robert Olsson19baf832005-06-21 12:43:18 -07001144
Olof Johansson91b9a272005-08-09 20:24:39 -07001145 missbit = tkey_extract_bits(key, newpos, 1);
Lin Ming61648d92012-07-29 02:00:03 +00001146 put_child(tn, missbit, (struct rt_trie_node *)l);
1147 put_child(tn, 1-missbit, n);
Robert Olsson19baf832005-06-21 12:43:18 -07001148
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001149 if (tp) {
Robert Olsson19baf832005-06-21 12:43:18 -07001150 cindex = tkey_extract_bits(key, tp->pos, tp->bits);
Lin Ming61648d92012-07-29 02:00:03 +00001151 put_child(tp, cindex, (struct rt_trie_node *)tn);
Olof Johansson91b9a272005-08-09 20:24:39 -07001152 } else {
Eric Dumazetcf778b02012-01-12 04:41:32 +00001153 rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
Robert Olsson19baf832005-06-21 12:43:18 -07001154 tp = tn;
1155 }
1156 }
Olof Johansson91b9a272005-08-09 20:24:39 -07001157
1158 if (tp && tp->pos + tp->bits > 32)
Joe Perches058bd4d2012-03-11 18:36:11 +00001159 pr_warn("fib_trie tp=%p pos=%d, bits=%d, key=%0x plen=%d\n",
1160 tp, tp->pos, tp->bits, key, plen);
Olof Johansson91b9a272005-08-09 20:24:39 -07001161
Robert Olsson19baf832005-06-21 12:43:18 -07001162 /* Rebalance the trie */
Robert Olsson2373ce12005-08-25 13:01:29 -07001163
Jarek Poplawski7b855762009-06-18 00:28:51 -07001164 trie_rebalance(t, tp);
Robert Olssonf835e472005-06-28 15:00:39 -07001165done:
Robert Olsson19baf832005-06-21 12:43:18 -07001166 return fa_head;
1167}
1168
Robert Olssond562f1f2007-03-26 14:22:22 -07001169/*
1170 * Caller must hold RTNL.
1171 */
Stephen Hemminger16c6cf82009-09-20 10:35:36 +00001172int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
Robert Olsson19baf832005-06-21 12:43:18 -07001173{
1174 struct trie *t = (struct trie *) tb->tb_data;
1175 struct fib_alias *fa, *new_fa;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001176 struct list_head *fa_head = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001177 struct fib_info *fi;
Thomas Graf4e902c52006-08-17 18:14:52 -07001178 int plen = cfg->fc_dst_len;
1179 u8 tos = cfg->fc_tos;
Robert Olsson19baf832005-06-21 12:43:18 -07001180 u32 key, mask;
1181 int err;
1182 struct leaf *l;
1183
1184 if (plen > 32)
1185 return -EINVAL;
1186
Thomas Graf4e902c52006-08-17 18:14:52 -07001187 key = ntohl(cfg->fc_dst);
Robert Olsson19baf832005-06-21 12:43:18 -07001188
Patrick McHardy2dfe55b2006-08-10 23:08:33 -07001189 pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen);
Robert Olsson19baf832005-06-21 12:43:18 -07001190
Olof Johansson91b9a272005-08-09 20:24:39 -07001191 mask = ntohl(inet_make_mask(plen));
Robert Olsson19baf832005-06-21 12:43:18 -07001192
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001193 if (key & ~mask)
Robert Olsson19baf832005-06-21 12:43:18 -07001194 return -EINVAL;
1195
1196 key = key & mask;
1197
Thomas Graf4e902c52006-08-17 18:14:52 -07001198 fi = fib_create_info(cfg);
1199 if (IS_ERR(fi)) {
1200 err = PTR_ERR(fi);
Robert Olsson19baf832005-06-21 12:43:18 -07001201 goto err;
Thomas Graf4e902c52006-08-17 18:14:52 -07001202 }
Robert Olsson19baf832005-06-21 12:43:18 -07001203
1204 l = fib_find_node(t, key);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001205 fa = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001206
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001207 if (l) {
Robert Olsson19baf832005-06-21 12:43:18 -07001208 fa_head = get_fa_head(l, plen);
1209 fa = fib_find_alias(fa_head, tos, fi->fib_priority);
1210 }
1211
1212 /* Now fa, if non-NULL, points to the first fib alias
1213 * with the same keys [prefix,tos,priority], if such key already
1214 * exists or to the node before which we will insert new one.
1215 *
1216 * If fa is NULL, we will need to allocate a new one and
1217 * insert to the head of f.
1218 *
1219 * If f is NULL, no fib node matched the destination key
1220 * and we need to allocate a new one of those as well.
1221 */
1222
Julian Anastasov936f6f82008-01-28 21:18:06 -08001223 if (fa && fa->fa_tos == tos &&
1224 fa->fa_info->fib_priority == fi->fib_priority) {
1225 struct fib_alias *fa_first, *fa_match;
Robert Olsson19baf832005-06-21 12:43:18 -07001226
1227 err = -EEXIST;
Thomas Graf4e902c52006-08-17 18:14:52 -07001228 if (cfg->fc_nlflags & NLM_F_EXCL)
Robert Olsson19baf832005-06-21 12:43:18 -07001229 goto out;
1230
Julian Anastasov936f6f82008-01-28 21:18:06 -08001231 /* We have 2 goals:
1232 * 1. Find exact match for type, scope, fib_info to avoid
1233 * duplicate routes
1234 * 2. Find next 'fa' (or head), NLM_F_APPEND inserts before it
1235 */
1236 fa_match = NULL;
1237 fa_first = fa;
1238 fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
1239 list_for_each_entry_continue(fa, fa_head, fa_list) {
1240 if (fa->fa_tos != tos)
1241 break;
1242 if (fa->fa_info->fib_priority != fi->fib_priority)
1243 break;
1244 if (fa->fa_type == cfg->fc_type &&
Julian Anastasov936f6f82008-01-28 21:18:06 -08001245 fa->fa_info == fi) {
1246 fa_match = fa;
1247 break;
1248 }
1249 }
1250
Thomas Graf4e902c52006-08-17 18:14:52 -07001251 if (cfg->fc_nlflags & NLM_F_REPLACE) {
Robert Olsson19baf832005-06-21 12:43:18 -07001252 struct fib_info *fi_drop;
1253 u8 state;
1254
Julian Anastasov936f6f82008-01-28 21:18:06 -08001255 fa = fa_first;
1256 if (fa_match) {
1257 if (fa == fa_match)
1258 err = 0;
Joonwoo Park67250332008-01-18 03:45:18 -08001259 goto out;
Julian Anastasov936f6f82008-01-28 21:18:06 -08001260 }
Robert Olsson2373ce12005-08-25 13:01:29 -07001261 err = -ENOBUFS;
Christoph Lametere94b1762006-12-06 20:33:17 -08001262 new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
Robert Olsson2373ce12005-08-25 13:01:29 -07001263 if (new_fa == NULL)
1264 goto out;
Robert Olsson19baf832005-06-21 12:43:18 -07001265
1266 fi_drop = fa->fa_info;
Robert Olsson2373ce12005-08-25 13:01:29 -07001267 new_fa->fa_tos = fa->fa_tos;
1268 new_fa->fa_info = fi;
Thomas Graf4e902c52006-08-17 18:14:52 -07001269 new_fa->fa_type = cfg->fc_type;
Robert Olsson19baf832005-06-21 12:43:18 -07001270 state = fa->fa_state;
Julian Anastasov936f6f82008-01-28 21:18:06 -08001271 new_fa->fa_state = state & ~FA_S_ACCESSED;
Robert Olsson19baf832005-06-21 12:43:18 -07001272
Robert Olsson2373ce12005-08-25 13:01:29 -07001273 list_replace_rcu(&fa->fa_list, &new_fa->fa_list);
1274 alias_free_mem_rcu(fa);
Robert Olsson19baf832005-06-21 12:43:18 -07001275
1276 fib_release_info(fi_drop);
1277 if (state & FA_S_ACCESSED)
Nicolas Dichtel4ccfe6d2012-09-07 00:45:29 +00001278 rt_cache_flush(cfg->fc_nlinfo.nl_net);
Milan Kocianb8f55832007-05-23 14:55:06 -07001279 rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
1280 tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
Robert Olsson19baf832005-06-21 12:43:18 -07001281
Olof Johansson91b9a272005-08-09 20:24:39 -07001282 goto succeeded;
Robert Olsson19baf832005-06-21 12:43:18 -07001283 }
1284 /* Error if we find a perfect match which
1285 * uses the same scope, type, and nexthop
1286 * information.
1287 */
Julian Anastasov936f6f82008-01-28 21:18:06 -08001288 if (fa_match)
1289 goto out;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001290
Thomas Graf4e902c52006-08-17 18:14:52 -07001291 if (!(cfg->fc_nlflags & NLM_F_APPEND))
Julian Anastasov936f6f82008-01-28 21:18:06 -08001292 fa = fa_first;
Robert Olsson19baf832005-06-21 12:43:18 -07001293 }
1294 err = -ENOENT;
Thomas Graf4e902c52006-08-17 18:14:52 -07001295 if (!(cfg->fc_nlflags & NLM_F_CREATE))
Robert Olsson19baf832005-06-21 12:43:18 -07001296 goto out;
1297
1298 err = -ENOBUFS;
Christoph Lametere94b1762006-12-06 20:33:17 -08001299 new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
Robert Olsson19baf832005-06-21 12:43:18 -07001300 if (new_fa == NULL)
1301 goto out;
1302
1303 new_fa->fa_info = fi;
1304 new_fa->fa_tos = tos;
Thomas Graf4e902c52006-08-17 18:14:52 -07001305 new_fa->fa_type = cfg->fc_type;
Robert Olsson19baf832005-06-21 12:43:18 -07001306 new_fa->fa_state = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001307 /*
1308 * Insert new entry to the list.
1309 */
1310
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001311 if (!fa_head) {
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001312 fa_head = fib_insert_node(t, key, plen);
1313 if (unlikely(!fa_head)) {
1314 err = -ENOMEM;
Robert Olssonf835e472005-06-28 15:00:39 -07001315 goto out_free_new_fa;
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001316 }
Robert Olssonf835e472005-06-28 15:00:39 -07001317 }
Robert Olsson19baf832005-06-21 12:43:18 -07001318
David S. Miller21d8c492011-04-14 14:49:37 -07001319 if (!plen)
1320 tb->tb_num_default++;
1321
Robert Olsson2373ce12005-08-25 13:01:29 -07001322 list_add_tail_rcu(&new_fa->fa_list,
1323 (fa ? &fa->fa_list : fa_head));
Robert Olsson19baf832005-06-21 12:43:18 -07001324
Nicolas Dichtel4ccfe6d2012-09-07 00:45:29 +00001325 rt_cache_flush(cfg->fc_nlinfo.nl_net);
Thomas Graf4e902c52006-08-17 18:14:52 -07001326 rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id,
Milan Kocianb8f55832007-05-23 14:55:06 -07001327 &cfg->fc_nlinfo, 0);
Robert Olsson19baf832005-06-21 12:43:18 -07001328succeeded:
1329 return 0;
Robert Olssonf835e472005-06-28 15:00:39 -07001330
1331out_free_new_fa:
1332 kmem_cache_free(fn_alias_kmem, new_fa);
Robert Olsson19baf832005-06-21 12:43:18 -07001333out:
1334 fib_release_info(fi);
Olof Johansson91b9a272005-08-09 20:24:39 -07001335err:
Robert Olsson19baf832005-06-21 12:43:18 -07001336 return err;
1337}
1338
Robert Olsson772cb712005-09-19 15:31:18 -07001339/* should be called with rcu_read_lock */
David S. Miller5b470442011-01-31 16:10:03 -08001340static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
David S. Miller22bd5b92011-03-11 19:54:08 -05001341 t_key key, const struct flowi4 *flp,
Eric Dumazetebc0ffa2010-10-05 10:41:36 +00001342 struct fib_result *res, int fib_flags)
Robert Olsson19baf832005-06-21 12:43:18 -07001343{
Robert Olsson19baf832005-06-21 12:43:18 -07001344 struct leaf_info *li;
1345 struct hlist_head *hhead = &l->list;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001346
Sasha Levinb67bfe02013-02-27 17:06:00 -08001347 hlist_for_each_entry_rcu(li, hhead, hlist) {
David S. Miller3be06862011-03-07 15:01:10 -08001348 struct fib_alias *fa;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001349
Eric Dumazet5c745012011-07-18 03:16:33 +00001350 if (l->key != (key & li->mask_plen))
Robert Olsson19baf832005-06-21 12:43:18 -07001351 continue;
1352
David S. Miller3be06862011-03-07 15:01:10 -08001353 list_for_each_entry_rcu(fa, &li->falh, fa_list) {
1354 struct fib_info *fi = fa->fa_info;
1355 int nhsel, err;
1356
David S. Miller22bd5b92011-03-11 19:54:08 -05001357 if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
David S. Miller3be06862011-03-07 15:01:10 -08001358 continue;
David S. Millerdccd9ecc2012-05-10 22:16:32 -04001359 if (fi->fib_dead)
1360 continue;
David S. Miller37e826c2011-03-24 18:06:47 -07001361 if (fa->fa_info->fib_scope < flp->flowi4_scope)
David S. Miller3be06862011-03-07 15:01:10 -08001362 continue;
1363 fib_alias_accessed(fa);
1364 err = fib_props[fa->fa_type].error;
1365 if (err) {
1366#ifdef CONFIG_IP_FIB_TRIE_STATS
Julian Anastasov1fbc7842011-03-25 20:33:23 -07001367 t->stats.semantic_match_passed++;
David S. Miller3be06862011-03-07 15:01:10 -08001368#endif
Julian Anastasov1fbc7842011-03-25 20:33:23 -07001369 return err;
David S. Miller3be06862011-03-07 15:01:10 -08001370 }
1371 if (fi->fib_flags & RTNH_F_DEAD)
1372 continue;
1373 for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
1374 const struct fib_nh *nh = &fi->fib_nh[nhsel];
1375
1376 if (nh->nh_flags & RTNH_F_DEAD)
1377 continue;
David S. Miller22bd5b92011-03-11 19:54:08 -05001378 if (flp->flowi4_oif && flp->flowi4_oif != nh->nh_oif)
David S. Miller3be06862011-03-07 15:01:10 -08001379 continue;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001380
Robert Olsson19baf832005-06-21 12:43:18 -07001381#ifdef CONFIG_IP_FIB_TRIE_STATS
David S. Miller3be06862011-03-07 15:01:10 -08001382 t->stats.semantic_match_passed++;
Robert Olsson19baf832005-06-21 12:43:18 -07001383#endif
Eric Dumazet5c745012011-07-18 03:16:33 +00001384 res->prefixlen = li->plen;
David S. Miller3be06862011-03-07 15:01:10 -08001385 res->nh_sel = nhsel;
1386 res->type = fa->fa_type;
David S. Miller37e826c2011-03-24 18:06:47 -07001387 res->scope = fa->fa_info->fib_scope;
David S. Miller3be06862011-03-07 15:01:10 -08001388 res->fi = fi;
1389 res->table = tb;
1390 res->fa_head = &li->falh;
1391 if (!(fib_flags & FIB_LOOKUP_NOREF))
Eric Dumazet5c745012011-07-18 03:16:33 +00001392 atomic_inc(&fi->fib_clntref);
David S. Miller3be06862011-03-07 15:01:10 -08001393 return 0;
1394 }
1395 }
1396
1397#ifdef CONFIG_IP_FIB_TRIE_STATS
1398 t->stats.semantic_match_miss++;
1399#endif
Robert Olsson19baf832005-06-21 12:43:18 -07001400 }
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001401
Ben Hutchings2e655572008-07-10 16:52:52 -07001402 return 1;
Robert Olsson19baf832005-06-21 12:43:18 -07001403}
1404
David S. Miller22bd5b92011-03-11 19:54:08 -05001405int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
Eric Dumazetebc0ffa2010-10-05 10:41:36 +00001406 struct fib_result *res, int fib_flags)
Robert Olsson19baf832005-06-21 12:43:18 -07001407{
1408 struct trie *t = (struct trie *) tb->tb_data;
Ben Hutchings2e655572008-07-10 16:52:52 -07001409 int ret;
David S. Millerb299e4f2011-02-02 20:48:10 -08001410 struct rt_trie_node *n;
Robert Olsson19baf832005-06-21 12:43:18 -07001411 struct tnode *pn;
David S. Miller3b004562011-02-16 14:56:22 -08001412 unsigned int pos, bits;
David S. Miller22bd5b92011-03-11 19:54:08 -05001413 t_key key = ntohl(flp->daddr);
David S. Miller3b004562011-02-16 14:56:22 -08001414 unsigned int chopped_off;
Robert Olsson19baf832005-06-21 12:43:18 -07001415 t_key cindex = 0;
David S. Miller3b004562011-02-16 14:56:22 -08001416 unsigned int current_prefix_length = KEYLENGTH;
Olof Johansson91b9a272005-08-09 20:24:39 -07001417 struct tnode *cn;
Eric Dumazet874ffa82010-10-13 06:56:11 +00001418 t_key pref_mismatch;
Olof Johansson91b9a272005-08-09 20:24:39 -07001419
Robert Olsson2373ce12005-08-25 13:01:29 -07001420 rcu_read_lock();
Robert Olsson19baf832005-06-21 12:43:18 -07001421
Robert Olsson2373ce12005-08-25 13:01:29 -07001422 n = rcu_dereference(t->trie);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001423 if (!n)
Robert Olsson19baf832005-06-21 12:43:18 -07001424 goto failed;
1425
1426#ifdef CONFIG_IP_FIB_TRIE_STATS
1427 t->stats.gets++;
1428#endif
1429
1430 /* Just a leaf? */
1431 if (IS_LEAF(n)) {
David S. Miller5b470442011-01-31 16:10:03 -08001432 ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags);
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001433 goto found;
Robert Olsson19baf832005-06-21 12:43:18 -07001434 }
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001435
Robert Olsson19baf832005-06-21 12:43:18 -07001436 pn = (struct tnode *) n;
1437 chopped_off = 0;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001438
Olof Johansson91b9a272005-08-09 20:24:39 -07001439 while (pn) {
Robert Olsson19baf832005-06-21 12:43:18 -07001440 pos = pn->pos;
1441 bits = pn->bits;
1442
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001443 if (!chopped_off)
Stephen Hemmingerab66b4a2007-08-10 15:22:58 -07001444 cindex = tkey_extract_bits(mask_pfx(key, current_prefix_length),
1445 pos, bits);
Robert Olsson19baf832005-06-21 12:43:18 -07001446
Jarek Poplawskib902e572009-07-14 11:20:32 +00001447 n = tnode_get_child_rcu(pn, cindex);
Robert Olsson19baf832005-06-21 12:43:18 -07001448
1449 if (n == NULL) {
1450#ifdef CONFIG_IP_FIB_TRIE_STATS
1451 t->stats.null_node_hit++;
1452#endif
1453 goto backtrace;
1454 }
1455
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001456 if (IS_LEAF(n)) {
David S. Miller5b470442011-01-31 16:10:03 -08001457 ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags);
Ben Hutchings2e655572008-07-10 16:52:52 -07001458 if (ret > 0)
Olof Johansson91b9a272005-08-09 20:24:39 -07001459 goto backtrace;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001460 goto found;
Olof Johansson91b9a272005-08-09 20:24:39 -07001461 }
1462
Olof Johansson91b9a272005-08-09 20:24:39 -07001463 cn = (struct tnode *)n;
1464
1465 /*
1466 * It's a tnode, and we can do some extra checks here if we
1467 * like, to avoid descending into a dead-end branch.
1468 * This tnode is in the parent's child array at index
1469 * key[p_pos..p_pos+p_bits] but potentially with some bits
1470 * chopped off, so in reality the index may be just a
1471 * subprefix, padded with zero at the end.
1472 * We can also take a look at any skipped bits in this
1473 * tnode - everything up to p_pos is supposed to be ok,
1474 * and the non-chopped bits of the index (se previous
1475 * paragraph) are also guaranteed ok, but the rest is
1476 * considered unknown.
1477 *
1478 * The skipped bits are key[pos+bits..cn->pos].
1479 */
1480
1481 /* If current_prefix_length < pos+bits, we are already doing
1482 * actual prefix matching, which means everything from
1483 * pos+(bits-chopped_off) onward must be zero along some
1484 * branch of this subtree - otherwise there is *no* valid
1485 * prefix present. Here we can only check the skipped
1486 * bits. Remember, since we have already indexed into the
1487 * parent's child array, we know that the bits we chopped of
1488 * *are* zero.
1489 */
1490
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001491 /* NOTA BENE: Checking only skipped bits
1492 for the new node here */
Olof Johansson91b9a272005-08-09 20:24:39 -07001493
1494 if (current_prefix_length < pos+bits) {
1495 if (tkey_extract_bits(cn->key, current_prefix_length,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001496 cn->pos - current_prefix_length)
1497 || !(cn->child[0]))
Olof Johansson91b9a272005-08-09 20:24:39 -07001498 goto backtrace;
1499 }
1500
1501 /*
1502 * If chopped_off=0, the index is fully validated and we
1503 * only need to look at the skipped bits for this, the new,
1504 * tnode. What we actually want to do is to find out if
1505 * these skipped bits match our key perfectly, or if we will
1506 * have to count on finding a matching prefix further down,
1507 * because if we do, we would like to have some way of
1508 * verifying the existence of such a prefix at this point.
1509 */
1510
1511 /* The only thing we can do at this point is to verify that
1512 * any such matching prefix can indeed be a prefix to our
1513 * key, and if the bits in the node we are inspecting that
1514 * do not match our key are not ZERO, this cannot be true.
1515 * Thus, find out where there is a mismatch (before cn->pos)
1516 * and verify that all the mismatching bits are zero in the
1517 * new tnode's key.
1518 */
1519
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001520 /*
1521 * Note: We aren't very concerned about the piece of
1522 * the key that precede pn->pos+pn->bits, since these
1523 * have already been checked. The bits after cn->pos
1524 * aren't checked since these are by definition
1525 * "unknown" at this point. Thus, what we want to see
1526 * is if we are about to enter the "prefix matching"
1527 * state, and in that case verify that the skipped
1528 * bits that will prevail throughout this subtree are
1529 * zero, as they have to be if we are to find a
1530 * matching prefix.
Olof Johansson91b9a272005-08-09 20:24:39 -07001531 */
1532
Eric Dumazet874ffa82010-10-13 06:56:11 +00001533 pref_mismatch = mask_pfx(cn->key ^ key, cn->pos);
Olof Johansson91b9a272005-08-09 20:24:39 -07001534
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001535 /*
1536 * In short: If skipped bits in this node do not match
1537 * the search key, enter the "prefix matching"
1538 * state.directly.
Olof Johansson91b9a272005-08-09 20:24:39 -07001539 */
1540 if (pref_mismatch) {
Eric Dumazet79cda752012-08-07 10:45:47 +00001541 /* fls(x) = __fls(x) + 1 */
1542 int mp = KEYLENGTH - __fls(pref_mismatch) - 1;
Olof Johansson91b9a272005-08-09 20:24:39 -07001543
Eric Dumazet874ffa82010-10-13 06:56:11 +00001544 if (tkey_extract_bits(cn->key, mp, cn->pos - mp) != 0)
Olof Johansson91b9a272005-08-09 20:24:39 -07001545 goto backtrace;
1546
1547 if (current_prefix_length >= cn->pos)
1548 current_prefix_length = mp;
1549 }
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001550
Olof Johansson91b9a272005-08-09 20:24:39 -07001551 pn = (struct tnode *)n; /* Descend */
1552 chopped_off = 0;
1553 continue;
1554
Robert Olsson19baf832005-06-21 12:43:18 -07001555backtrace:
1556 chopped_off++;
1557
1558 /* As zero don't change the child key (cindex) */
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001559 while ((chopped_off <= pn->bits)
1560 && !(cindex & (1<<(chopped_off-1))))
Robert Olsson19baf832005-06-21 12:43:18 -07001561 chopped_off++;
Robert Olsson19baf832005-06-21 12:43:18 -07001562
1563 /* Decrease current_... with bits chopped off */
1564 if (current_prefix_length > pn->pos + pn->bits - chopped_off)
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001565 current_prefix_length = pn->pos + pn->bits
1566 - chopped_off;
Olof Johansson91b9a272005-08-09 20:24:39 -07001567
Robert Olsson19baf832005-06-21 12:43:18 -07001568 /*
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001569 * Either we do the actual chop off according or if we have
Robert Olsson19baf832005-06-21 12:43:18 -07001570 * chopped off all bits in this tnode walk up to our parent.
1571 */
1572
Olof Johansson91b9a272005-08-09 20:24:39 -07001573 if (chopped_off <= pn->bits) {
Robert Olsson19baf832005-06-21 12:43:18 -07001574 cindex &= ~(1 << (chopped_off-1));
Olof Johansson91b9a272005-08-09 20:24:39 -07001575 } else {
David S. Millerb299e4f2011-02-02 20:48:10 -08001576 struct tnode *parent = node_parent_rcu((struct rt_trie_node *) pn);
Stephen Hemminger06801912007-08-10 15:22:13 -07001577 if (!parent)
Robert Olsson19baf832005-06-21 12:43:18 -07001578 goto failed;
Olof Johansson91b9a272005-08-09 20:24:39 -07001579
Robert Olsson19baf832005-06-21 12:43:18 -07001580 /* Get Child's index */
Stephen Hemminger06801912007-08-10 15:22:13 -07001581 cindex = tkey_extract_bits(pn->key, parent->pos, parent->bits);
1582 pn = parent;
Robert Olsson19baf832005-06-21 12:43:18 -07001583 chopped_off = 0;
1584
1585#ifdef CONFIG_IP_FIB_TRIE_STATS
1586 t->stats.backtrack++;
1587#endif
1588 goto backtrace;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001589 }
Robert Olsson19baf832005-06-21 12:43:18 -07001590 }
1591failed:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001592 ret = 1;
Robert Olsson19baf832005-06-21 12:43:18 -07001593found:
Robert Olsson2373ce12005-08-25 13:01:29 -07001594 rcu_read_unlock();
Robert Olsson19baf832005-06-21 12:43:18 -07001595 return ret;
1596}
Florian Westphal6fc01432011-08-25 13:46:12 +02001597EXPORT_SYMBOL_GPL(fib_table_lookup);
Robert Olsson19baf832005-06-21 12:43:18 -07001598
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001599/*
1600 * Remove the leaf and return parent.
1601 */
1602static void trie_leaf_remove(struct trie *t, struct leaf *l)
Robert Olsson19baf832005-06-21 12:43:18 -07001603{
David S. Millerb299e4f2011-02-02 20:48:10 -08001604 struct tnode *tp = node_parent((struct rt_trie_node *) l);
Robert Olsson19baf832005-06-21 12:43:18 -07001605
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001606 pr_debug("entering trie_leaf_remove(%p)\n", l);
Robert Olsson19baf832005-06-21 12:43:18 -07001607
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001608 if (tp) {
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001609 t_key cindex = tkey_extract_bits(l->key, tp->pos, tp->bits);
Lin Ming61648d92012-07-29 02:00:03 +00001610 put_child(tp, cindex, NULL);
Jarek Poplawski7b855762009-06-18 00:28:51 -07001611 trie_rebalance(t, tp);
Olof Johansson91b9a272005-08-09 20:24:39 -07001612 } else
Stephen Hemmingera9b3cd72011-08-01 16:19:00 +00001613 RCU_INIT_POINTER(t->trie, NULL);
Robert Olsson19baf832005-06-21 12:43:18 -07001614
Stephen Hemminger387a5482008-04-10 03:47:34 -07001615 free_leaf(l);
Robert Olsson19baf832005-06-21 12:43:18 -07001616}
1617
Robert Olssond562f1f2007-03-26 14:22:22 -07001618/*
1619 * Caller must hold RTNL.
1620 */
Stephen Hemminger16c6cf82009-09-20 10:35:36 +00001621int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
Robert Olsson19baf832005-06-21 12:43:18 -07001622{
1623 struct trie *t = (struct trie *) tb->tb_data;
1624 u32 key, mask;
Thomas Graf4e902c52006-08-17 18:14:52 -07001625 int plen = cfg->fc_dst_len;
1626 u8 tos = cfg->fc_tos;
Robert Olsson19baf832005-06-21 12:43:18 -07001627 struct fib_alias *fa, *fa_to_delete;
1628 struct list_head *fa_head;
1629 struct leaf *l;
Olof Johansson91b9a272005-08-09 20:24:39 -07001630 struct leaf_info *li;
1631
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001632 if (plen > 32)
Robert Olsson19baf832005-06-21 12:43:18 -07001633 return -EINVAL;
1634
Thomas Graf4e902c52006-08-17 18:14:52 -07001635 key = ntohl(cfg->fc_dst);
Olof Johansson91b9a272005-08-09 20:24:39 -07001636 mask = ntohl(inet_make_mask(plen));
Robert Olsson19baf832005-06-21 12:43:18 -07001637
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001638 if (key & ~mask)
Robert Olsson19baf832005-06-21 12:43:18 -07001639 return -EINVAL;
1640
1641 key = key & mask;
1642 l = fib_find_node(t, key);
1643
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001644 if (!l)
Robert Olsson19baf832005-06-21 12:43:18 -07001645 return -ESRCH;
1646
Igor Maravicad5b3102012-08-13 10:26:08 +02001647 li = find_leaf_info(l, plen);
1648
1649 if (!li)
1650 return -ESRCH;
1651
1652 fa_head = &li->falh;
Robert Olsson19baf832005-06-21 12:43:18 -07001653 fa = fib_find_alias(fa_head, tos, 0);
1654
1655 if (!fa)
1656 return -ESRCH;
1657
Stephen Hemminger0c7770c2005-08-23 21:59:41 -07001658 pr_debug("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t);
Robert Olsson19baf832005-06-21 12:43:18 -07001659
1660 fa_to_delete = NULL;
Julian Anastasov936f6f82008-01-28 21:18:06 -08001661 fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
1662 list_for_each_entry_continue(fa, fa_head, fa_list) {
Robert Olsson19baf832005-06-21 12:43:18 -07001663 struct fib_info *fi = fa->fa_info;
1664
1665 if (fa->fa_tos != tos)
1666 break;
1667
Thomas Graf4e902c52006-08-17 18:14:52 -07001668 if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) &&
1669 (cfg->fc_scope == RT_SCOPE_NOWHERE ||
David S. Miller37e826c2011-03-24 18:06:47 -07001670 fa->fa_info->fib_scope == cfg->fc_scope) &&
Julian Anastasov74cb3c12011-03-19 12:13:46 +00001671 (!cfg->fc_prefsrc ||
1672 fi->fib_prefsrc == cfg->fc_prefsrc) &&
Thomas Graf4e902c52006-08-17 18:14:52 -07001673 (!cfg->fc_protocol ||
1674 fi->fib_protocol == cfg->fc_protocol) &&
1675 fib_nh_match(cfg, fi) == 0) {
Robert Olsson19baf832005-06-21 12:43:18 -07001676 fa_to_delete = fa;
1677 break;
1678 }
1679 }
1680
Olof Johansson91b9a272005-08-09 20:24:39 -07001681 if (!fa_to_delete)
1682 return -ESRCH;
Robert Olsson19baf832005-06-21 12:43:18 -07001683
Olof Johansson91b9a272005-08-09 20:24:39 -07001684 fa = fa_to_delete;
Thomas Graf4e902c52006-08-17 18:14:52 -07001685 rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id,
Milan Kocianb8f55832007-05-23 14:55:06 -07001686 &cfg->fc_nlinfo, 0);
Robert Olsson19baf832005-06-21 12:43:18 -07001687
Robert Olsson2373ce12005-08-25 13:01:29 -07001688 list_del_rcu(&fa->fa_list);
Robert Olsson19baf832005-06-21 12:43:18 -07001689
David S. Miller21d8c492011-04-14 14:49:37 -07001690 if (!plen)
1691 tb->tb_num_default--;
1692
Olof Johansson91b9a272005-08-09 20:24:39 -07001693 if (list_empty(fa_head)) {
Robert Olsson2373ce12005-08-25 13:01:29 -07001694 hlist_del_rcu(&li->hlist);
Olof Johansson91b9a272005-08-09 20:24:39 -07001695 free_leaf_info(li);
Robert Olsson2373ce12005-08-25 13:01:29 -07001696 }
Olof Johansson91b9a272005-08-09 20:24:39 -07001697
1698 if (hlist_empty(&l->list))
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001699 trie_leaf_remove(t, l);
Olof Johansson91b9a272005-08-09 20:24:39 -07001700
1701 if (fa->fa_state & FA_S_ACCESSED)
Nicolas Dichtel4ccfe6d2012-09-07 00:45:29 +00001702 rt_cache_flush(cfg->fc_nlinfo.nl_net);
Olof Johansson91b9a272005-08-09 20:24:39 -07001703
Robert Olsson2373ce12005-08-25 13:01:29 -07001704 fib_release_info(fa->fa_info);
1705 alias_free_mem_rcu(fa);
Olof Johansson91b9a272005-08-09 20:24:39 -07001706 return 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001707}
1708
Stephen Hemmingeref3660c2008-04-10 03:46:12 -07001709static int trie_flush_list(struct list_head *head)
Robert Olsson19baf832005-06-21 12:43:18 -07001710{
1711 struct fib_alias *fa, *fa_node;
1712 int found = 0;
1713
1714 list_for_each_entry_safe(fa, fa_node, head, fa_list) {
1715 struct fib_info *fi = fa->fa_info;
Robert Olsson19baf832005-06-21 12:43:18 -07001716
Robert Olsson2373ce12005-08-25 13:01:29 -07001717 if (fi && (fi->fib_flags & RTNH_F_DEAD)) {
1718 list_del_rcu(&fa->fa_list);
1719 fib_release_info(fa->fa_info);
1720 alias_free_mem_rcu(fa);
Robert Olsson19baf832005-06-21 12:43:18 -07001721 found++;
1722 }
1723 }
1724 return found;
1725}
1726
Stephen Hemmingeref3660c2008-04-10 03:46:12 -07001727static int trie_flush_leaf(struct leaf *l)
Robert Olsson19baf832005-06-21 12:43:18 -07001728{
1729 int found = 0;
1730 struct hlist_head *lih = &l->list;
Sasha Levinb67bfe02013-02-27 17:06:00 -08001731 struct hlist_node *tmp;
Robert Olsson19baf832005-06-21 12:43:18 -07001732 struct leaf_info *li = NULL;
1733
Sasha Levinb67bfe02013-02-27 17:06:00 -08001734 hlist_for_each_entry_safe(li, tmp, lih, hlist) {
Stephen Hemmingeref3660c2008-04-10 03:46:12 -07001735 found += trie_flush_list(&li->falh);
Robert Olsson19baf832005-06-21 12:43:18 -07001736
1737 if (list_empty(&li->falh)) {
Robert Olsson2373ce12005-08-25 13:01:29 -07001738 hlist_del_rcu(&li->hlist);
Robert Olsson19baf832005-06-21 12:43:18 -07001739 free_leaf_info(li);
1740 }
1741 }
1742 return found;
1743}
1744
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001745/*
1746 * Scan for the next right leaf starting at node p->child[idx]
1747 * Since we have back pointer, no recursion necessary.
1748 */
David S. Millerb299e4f2011-02-02 20:48:10 -08001749static struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c)
Robert Olsson19baf832005-06-21 12:43:18 -07001750{
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001751 do {
1752 t_key idx;
Robert Olsson19baf832005-06-21 12:43:18 -07001753
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001754 if (c)
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001755 idx = tkey_extract_bits(c->key, p->pos, p->bits) + 1;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001756 else
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001757 idx = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001758
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001759 while (idx < 1u << p->bits) {
1760 c = tnode_get_child_rcu(p, idx++);
Robert Olsson2373ce12005-08-25 13:01:29 -07001761 if (!c)
Olof Johansson91b9a272005-08-09 20:24:39 -07001762 continue;
Robert Olsson19baf832005-06-21 12:43:18 -07001763
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001764 if (IS_LEAF(c)) {
Eric Dumazet0a5c0472011-03-31 01:51:35 -07001765 prefetch(rcu_dereference_rtnl(p->child[idx]));
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001766 return (struct leaf *) c;
Robert Olsson19baf832005-06-21 12:43:18 -07001767 }
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001768
1769 /* Rescan start scanning in new node */
1770 p = (struct tnode *) c;
1771 idx = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001772 }
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001773
1774 /* Node empty, walk back up to parent */
David S. Millerb299e4f2011-02-02 20:48:10 -08001775 c = (struct rt_trie_node *) p;
Eric Dumazeta034ee32010-09-09 23:32:28 +00001776 } while ((p = node_parent_rcu(c)) != NULL);
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001777
1778 return NULL; /* Root of trie */
1779}
1780
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001781static struct leaf *trie_firstleaf(struct trie *t)
1782{
Eric Dumazeta034ee32010-09-09 23:32:28 +00001783 struct tnode *n = (struct tnode *)rcu_dereference_rtnl(t->trie);
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001784
1785 if (!n)
1786 return NULL;
1787
1788 if (IS_LEAF(n)) /* trie is just a leaf */
1789 return (struct leaf *) n;
1790
1791 return leaf_walk_rcu(n, NULL);
1792}
1793
1794static struct leaf *trie_nextleaf(struct leaf *l)
1795{
David S. Millerb299e4f2011-02-02 20:48:10 -08001796 struct rt_trie_node *c = (struct rt_trie_node *) l;
Jarek Poplawskib902e572009-07-14 11:20:32 +00001797 struct tnode *p = node_parent_rcu(c);
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001798
1799 if (!p)
1800 return NULL; /* trie with just one leaf */
1801
1802 return leaf_walk_rcu(p, c);
Robert Olsson19baf832005-06-21 12:43:18 -07001803}
1804
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001805static struct leaf *trie_leafindex(struct trie *t, int index)
1806{
1807 struct leaf *l = trie_firstleaf(t);
1808
Stephen Hemmingerec28cf72008-02-11 21:12:49 -08001809 while (l && index-- > 0)
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001810 l = trie_nextleaf(l);
Stephen Hemmingerec28cf72008-02-11 21:12:49 -08001811
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001812 return l;
1813}
1814
1815
Robert Olssond562f1f2007-03-26 14:22:22 -07001816/*
1817 * Caller must hold RTNL.
1818 */
Stephen Hemminger16c6cf82009-09-20 10:35:36 +00001819int fib_table_flush(struct fib_table *tb)
Robert Olsson19baf832005-06-21 12:43:18 -07001820{
1821 struct trie *t = (struct trie *) tb->tb_data;
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001822 struct leaf *l, *ll = NULL;
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001823 int found = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001824
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001825 for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) {
Stephen Hemmingeref3660c2008-04-10 03:46:12 -07001826 found += trie_flush_leaf(l);
Robert Olsson19baf832005-06-21 12:43:18 -07001827
1828 if (ll && hlist_empty(&ll->list))
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001829 trie_leaf_remove(t, ll);
Robert Olsson19baf832005-06-21 12:43:18 -07001830 ll = l;
1831 }
1832
1833 if (ll && hlist_empty(&ll->list))
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001834 trie_leaf_remove(t, ll);
Robert Olsson19baf832005-06-21 12:43:18 -07001835
Stephen Hemminger0c7770c2005-08-23 21:59:41 -07001836 pr_debug("trie_flush found=%d\n", found);
Robert Olsson19baf832005-06-21 12:43:18 -07001837 return found;
1838}
1839
Pavel Emelyanov4aa2c462010-10-28 02:00:43 +00001840void fib_free_table(struct fib_table *tb)
1841{
1842 kfree(tb);
1843}
1844
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001845static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
1846 struct fib_table *tb,
Robert Olsson19baf832005-06-21 12:43:18 -07001847 struct sk_buff *skb, struct netlink_callback *cb)
1848{
1849 int i, s_i;
1850 struct fib_alias *fa;
Al Viro32ab5f82006-09-26 22:21:45 -07001851 __be32 xkey = htonl(key);
Robert Olsson19baf832005-06-21 12:43:18 -07001852
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001853 s_i = cb->args[5];
Robert Olsson19baf832005-06-21 12:43:18 -07001854 i = 0;
1855
Robert Olsson2373ce12005-08-25 13:01:29 -07001856 /* rcu_read_lock is hold by caller */
1857
1858 list_for_each_entry_rcu(fa, fah, fa_list) {
Robert Olsson19baf832005-06-21 12:43:18 -07001859 if (i < s_i) {
1860 i++;
1861 continue;
1862 }
Robert Olsson19baf832005-06-21 12:43:18 -07001863
Eric W. Biederman15e47302012-09-07 20:12:54 +00001864 if (fib_dump_info(skb, NETLINK_CB(cb->skb).portid,
Robert Olsson19baf832005-06-21 12:43:18 -07001865 cb->nlh->nlmsg_seq,
1866 RTM_NEWROUTE,
1867 tb->tb_id,
1868 fa->fa_type,
Thomas Grafbe403ea2006-08-17 18:15:17 -07001869 xkey,
Robert Olsson19baf832005-06-21 12:43:18 -07001870 plen,
1871 fa->fa_tos,
Stephen Hemminger64347f72008-01-22 21:55:01 -08001872 fa->fa_info, NLM_F_MULTI) < 0) {
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001873 cb->args[5] = i;
Robert Olsson19baf832005-06-21 12:43:18 -07001874 return -1;
Olof Johansson91b9a272005-08-09 20:24:39 -07001875 }
Robert Olsson19baf832005-06-21 12:43:18 -07001876 i++;
1877 }
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001878 cb->args[5] = i;
Robert Olsson19baf832005-06-21 12:43:18 -07001879 return skb->len;
1880}
1881
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001882static int fn_trie_dump_leaf(struct leaf *l, struct fib_table *tb,
1883 struct sk_buff *skb, struct netlink_callback *cb)
Robert Olsson19baf832005-06-21 12:43:18 -07001884{
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001885 struct leaf_info *li;
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001886 int i, s_i;
Robert Olsson19baf832005-06-21 12:43:18 -07001887
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001888 s_i = cb->args[4];
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001889 i = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001890
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001891 /* rcu_read_lock is hold by caller */
Sasha Levinb67bfe02013-02-27 17:06:00 -08001892 hlist_for_each_entry_rcu(li, &l->list, hlist) {
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001893 if (i < s_i) {
1894 i++;
Robert Olsson19baf832005-06-21 12:43:18 -07001895 continue;
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001896 }
Robert Olsson19baf832005-06-21 12:43:18 -07001897
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001898 if (i > s_i)
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001899 cb->args[5] = 0;
Olof Johansson91b9a272005-08-09 20:24:39 -07001900
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001901 if (list_empty(&li->falh))
Robert Olsson19baf832005-06-21 12:43:18 -07001902 continue;
1903
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001904 if (fn_trie_dump_fa(l->key, li->plen, &li->falh, tb, skb, cb) < 0) {
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001905 cb->args[4] = i;
Robert Olsson19baf832005-06-21 12:43:18 -07001906 return -1;
1907 }
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001908 i++;
Robert Olsson19baf832005-06-21 12:43:18 -07001909 }
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001910
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001911 cb->args[4] = i;
Robert Olsson19baf832005-06-21 12:43:18 -07001912 return skb->len;
1913}
1914
Stephen Hemminger16c6cf82009-09-20 10:35:36 +00001915int fib_table_dump(struct fib_table *tb, struct sk_buff *skb,
1916 struct netlink_callback *cb)
Robert Olsson19baf832005-06-21 12:43:18 -07001917{
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001918 struct leaf *l;
Robert Olsson19baf832005-06-21 12:43:18 -07001919 struct trie *t = (struct trie *) tb->tb_data;
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001920 t_key key = cb->args[2];
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001921 int count = cb->args[3];
Robert Olsson19baf832005-06-21 12:43:18 -07001922
Robert Olsson2373ce12005-08-25 13:01:29 -07001923 rcu_read_lock();
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001924 /* Dump starting at last key.
1925 * Note: 0.0.0.0/0 (ie default) is first key.
1926 */
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001927 if (count == 0)
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001928 l = trie_firstleaf(t);
1929 else {
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001930 /* Normally, continue from last key, but if that is missing
1931 * fallback to using slow rescan
1932 */
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001933 l = fib_find_node(t, key);
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001934 if (!l)
1935 l = trie_leafindex(t, count);
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001936 }
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001937
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001938 while (l) {
1939 cb->args[2] = l->key;
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001940 if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) {
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001941 cb->args[3] = count;
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001942 rcu_read_unlock();
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001943 return -1;
Robert Olsson19baf832005-06-21 12:43:18 -07001944 }
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001945
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001946 ++count;
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001947 l = trie_nextleaf(l);
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001948 memset(&cb->args[4], 0,
1949 sizeof(cb->args) - 4*sizeof(cb->args[0]));
Robert Olsson19baf832005-06-21 12:43:18 -07001950 }
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001951 cb->args[3] = count;
Robert Olsson2373ce12005-08-25 13:01:29 -07001952 rcu_read_unlock();
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001953
Robert Olsson19baf832005-06-21 12:43:18 -07001954 return skb->len;
Robert Olsson19baf832005-06-21 12:43:18 -07001955}
1956
David S. Miller5348ba82011-02-01 15:30:56 -08001957void __init fib_trie_init(void)
Stephen Hemminger7f9b8052008-01-14 23:14:20 -08001958{
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001959 fn_alias_kmem = kmem_cache_create("ip_fib_alias",
1960 sizeof(struct fib_alias),
Stephen Hemmingerbc3c8c12008-01-22 21:51:50 -08001961 0, SLAB_PANIC, NULL);
1962
1963 trie_leaf_kmem = kmem_cache_create("ip_fib_trie",
1964 max(sizeof(struct leaf),
1965 sizeof(struct leaf_info)),
1966 0, SLAB_PANIC, NULL);
Stephen Hemminger7f9b8052008-01-14 23:14:20 -08001967}
Robert Olsson19baf832005-06-21 12:43:18 -07001968
Stephen Hemminger7f9b8052008-01-14 23:14:20 -08001969
David S. Miller5348ba82011-02-01 15:30:56 -08001970struct fib_table *fib_trie_table(u32 id)
Robert Olsson19baf832005-06-21 12:43:18 -07001971{
1972 struct fib_table *tb;
1973 struct trie *t;
1974
Robert Olsson19baf832005-06-21 12:43:18 -07001975 tb = kmalloc(sizeof(struct fib_table) + sizeof(struct trie),
1976 GFP_KERNEL);
1977 if (tb == NULL)
1978 return NULL;
1979
1980 tb->tb_id = id;
Denis V. Lunev971b8932007-12-08 00:32:23 -08001981 tb->tb_default = -1;
David S. Miller21d8c492011-04-14 14:49:37 -07001982 tb->tb_num_default = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001983
1984 t = (struct trie *) tb->tb_data;
Stephen Hemmingerc28a1cf2008-01-12 20:49:13 -08001985 memset(t, 0, sizeof(*t));
Robert Olsson19baf832005-06-21 12:43:18 -07001986
Robert Olsson19baf832005-06-21 12:43:18 -07001987 return tb;
1988}
1989
Robert Olsson19baf832005-06-21 12:43:18 -07001990#ifdef CONFIG_PROC_FS
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001991/* Depth first Trie walk iterator */
1992struct fib_trie_iter {
Denis V. Lunev1c340b22008-01-10 03:27:17 -08001993 struct seq_net_private p;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07001994 struct fib_table *tb;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001995 struct tnode *tnode;
Eric Dumazeta034ee32010-09-09 23:32:28 +00001996 unsigned int index;
1997 unsigned int depth;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001998};
Robert Olsson19baf832005-06-21 12:43:18 -07001999
David S. Millerb299e4f2011-02-02 20:48:10 -08002000static struct rt_trie_node *fib_trie_get_next(struct fib_trie_iter *iter)
Robert Olsson19baf832005-06-21 12:43:18 -07002001{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002002 struct tnode *tn = iter->tnode;
Eric Dumazeta034ee32010-09-09 23:32:28 +00002003 unsigned int cindex = iter->index;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002004 struct tnode *p;
2005
Eric W. Biederman6640e692007-01-24 14:42:04 -08002006 /* A single entry routing table */
2007 if (!tn)
2008 return NULL;
2009
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002010 pr_debug("get_next iter={node=%p index=%d depth=%d}\n",
2011 iter->tnode, iter->index, iter->depth);
2012rescan:
2013 while (cindex < (1<<tn->bits)) {
David S. Millerb299e4f2011-02-02 20:48:10 -08002014 struct rt_trie_node *n = tnode_get_child_rcu(tn, cindex);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002015
2016 if (n) {
2017 if (IS_LEAF(n)) {
2018 iter->tnode = tn;
2019 iter->index = cindex + 1;
2020 } else {
2021 /* push down one level */
2022 iter->tnode = (struct tnode *) n;
2023 iter->index = 0;
2024 ++iter->depth;
2025 }
2026 return n;
2027 }
2028
2029 ++cindex;
2030 }
2031
2032 /* Current node exhausted, pop back up */
David S. Millerb299e4f2011-02-02 20:48:10 -08002033 p = node_parent_rcu((struct rt_trie_node *)tn);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002034 if (p) {
2035 cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1;
2036 tn = p;
2037 --iter->depth;
2038 goto rescan;
2039 }
2040
2041 /* got root? */
Robert Olsson19baf832005-06-21 12:43:18 -07002042 return NULL;
2043}
2044
David S. Millerb299e4f2011-02-02 20:48:10 -08002045static struct rt_trie_node *fib_trie_get_first(struct fib_trie_iter *iter,
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002046 struct trie *t)
Robert Olsson19baf832005-06-21 12:43:18 -07002047{
David S. Millerb299e4f2011-02-02 20:48:10 -08002048 struct rt_trie_node *n;
Robert Olsson5ddf0eb2006-03-20 21:34:12 -08002049
Stephen Hemminger132adf52007-03-08 20:44:43 -08002050 if (!t)
Robert Olsson5ddf0eb2006-03-20 21:34:12 -08002051 return NULL;
2052
2053 n = rcu_dereference(t->trie);
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002054 if (!n)
Robert Olsson5ddf0eb2006-03-20 21:34:12 -08002055 return NULL;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002056
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002057 if (IS_TNODE(n)) {
2058 iter->tnode = (struct tnode *) n;
2059 iter->index = 0;
2060 iter->depth = 1;
2061 } else {
2062 iter->tnode = NULL;
2063 iter->index = 0;
2064 iter->depth = 0;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002065 }
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002066
2067 return n;
Robert Olsson19baf832005-06-21 12:43:18 -07002068}
2069
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002070static void trie_collect_stats(struct trie *t, struct trie_stat *s)
Robert Olsson19baf832005-06-21 12:43:18 -07002071{
David S. Millerb299e4f2011-02-02 20:48:10 -08002072 struct rt_trie_node *n;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002073 struct fib_trie_iter iter;
Robert Olsson19baf832005-06-21 12:43:18 -07002074
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002075 memset(s, 0, sizeof(*s));
Robert Olsson19baf832005-06-21 12:43:18 -07002076
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002077 rcu_read_lock();
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002078 for (n = fib_trie_get_first(&iter, t); n; n = fib_trie_get_next(&iter)) {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002079 if (IS_LEAF(n)) {
Stephen Hemminger93672292008-01-22 21:54:05 -08002080 struct leaf *l = (struct leaf *)n;
2081 struct leaf_info *li;
Stephen Hemminger93672292008-01-22 21:54:05 -08002082
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002083 s->leaves++;
2084 s->totdepth += iter.depth;
2085 if (iter.depth > s->maxdepth)
2086 s->maxdepth = iter.depth;
Stephen Hemminger93672292008-01-22 21:54:05 -08002087
Sasha Levinb67bfe02013-02-27 17:06:00 -08002088 hlist_for_each_entry_rcu(li, &l->list, hlist)
Stephen Hemminger93672292008-01-22 21:54:05 -08002089 ++s->prefixes;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002090 } else {
2091 const struct tnode *tn = (const struct tnode *) n;
2092 int i;
Robert Olsson19baf832005-06-21 12:43:18 -07002093
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002094 s->tnodes++;
Stephen Hemminger132adf52007-03-08 20:44:43 -08002095 if (tn->bits < MAX_STAT_DEPTH)
Robert Olsson06ef9212006-03-20 21:35:01 -08002096 s->nodesizes[tn->bits]++;
2097
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002098 for (i = 0; i < (1<<tn->bits); i++)
2099 if (!tn->child[i])
2100 s->nullpointers++;
2101 }
2102 }
2103 rcu_read_unlock();
Robert Olsson19baf832005-06-21 12:43:18 -07002104}
2105
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07002106/*
Robert Olsson19baf832005-06-21 12:43:18 -07002107 * This outputs /proc/net/fib_triestats
Robert Olsson19baf832005-06-21 12:43:18 -07002108 */
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002109static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
Robert Olsson19baf832005-06-21 12:43:18 -07002110{
Eric Dumazeta034ee32010-09-09 23:32:28 +00002111 unsigned int i, max, pointers, bytes, avdepth;
Robert Olsson19baf832005-06-21 12:43:18 -07002112
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002113 if (stat->leaves)
2114 avdepth = stat->totdepth*100 / stat->leaves;
2115 else
2116 avdepth = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07002117
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08002118 seq_printf(seq, "\tAver depth: %u.%02d\n",
2119 avdepth / 100, avdepth % 100);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002120 seq_printf(seq, "\tMax depth: %u\n", stat->maxdepth);
Robert Olsson19baf832005-06-21 12:43:18 -07002121
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002122 seq_printf(seq, "\tLeaves: %u\n", stat->leaves);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002123 bytes = sizeof(struct leaf) * stat->leaves;
Stephen Hemminger93672292008-01-22 21:54:05 -08002124
2125 seq_printf(seq, "\tPrefixes: %u\n", stat->prefixes);
2126 bytes += sizeof(struct leaf_info) * stat->prefixes;
2127
Stephen Hemminger187b5182008-01-12 20:55:55 -08002128 seq_printf(seq, "\tInternal nodes: %u\n\t", stat->tnodes);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002129 bytes += sizeof(struct tnode) * stat->tnodes;
Robert Olsson19baf832005-06-21 12:43:18 -07002130
Robert Olsson06ef9212006-03-20 21:35:01 -08002131 max = MAX_STAT_DEPTH;
2132 while (max > 0 && stat->nodesizes[max-1] == 0)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002133 max--;
Robert Olsson19baf832005-06-21 12:43:18 -07002134
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002135 pointers = 0;
Jerry Snitselaarf585a992013-07-22 12:01:58 -07002136 for (i = 1; i < max; i++)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002137 if (stat->nodesizes[i] != 0) {
Stephen Hemminger187b5182008-01-12 20:55:55 -08002138 seq_printf(seq, " %u: %u", i, stat->nodesizes[i]);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002139 pointers += (1<<i) * stat->nodesizes[i];
2140 }
2141 seq_putc(seq, '\n');
Stephen Hemminger187b5182008-01-12 20:55:55 -08002142 seq_printf(seq, "\tPointers: %u\n", pointers);
Robert Olsson19baf832005-06-21 12:43:18 -07002143
David S. Millerb299e4f2011-02-02 20:48:10 -08002144 bytes += sizeof(struct rt_trie_node *) * pointers;
Stephen Hemminger187b5182008-01-12 20:55:55 -08002145 seq_printf(seq, "Null ptrs: %u\n", stat->nullpointers);
2146 seq_printf(seq, "Total size: %u kB\n", (bytes + 1023) / 1024);
Stephen Hemminger66a2f7f2008-01-12 21:23:17 -08002147}
Robert Olsson19baf832005-06-21 12:43:18 -07002148
2149#ifdef CONFIG_IP_FIB_TRIE_STATS
Stephen Hemminger66a2f7f2008-01-12 21:23:17 -08002150static void trie_show_usage(struct seq_file *seq,
2151 const struct trie_use_stats *stats)
2152{
2153 seq_printf(seq, "\nCounters:\n---------\n");
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08002154 seq_printf(seq, "gets = %u\n", stats->gets);
2155 seq_printf(seq, "backtracks = %u\n", stats->backtrack);
2156 seq_printf(seq, "semantic match passed = %u\n",
2157 stats->semantic_match_passed);
2158 seq_printf(seq, "semantic match miss = %u\n",
2159 stats->semantic_match_miss);
2160 seq_printf(seq, "null node hit= %u\n", stats->null_node_hit);
2161 seq_printf(seq, "skipped node resize = %u\n\n",
2162 stats->resize_node_skipped);
Robert Olsson19baf832005-06-21 12:43:18 -07002163}
Stephen Hemminger66a2f7f2008-01-12 21:23:17 -08002164#endif /* CONFIG_IP_FIB_TRIE_STATS */
2165
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002166static void fib_table_print(struct seq_file *seq, struct fib_table *tb)
Stephen Hemmingerd717a9a2008-01-14 23:11:54 -08002167{
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002168 if (tb->tb_id == RT_TABLE_LOCAL)
2169 seq_puts(seq, "Local:\n");
2170 else if (tb->tb_id == RT_TABLE_MAIN)
2171 seq_puts(seq, "Main:\n");
2172 else
2173 seq_printf(seq, "Id %d:\n", tb->tb_id);
Stephen Hemmingerd717a9a2008-01-14 23:11:54 -08002174}
Robert Olsson19baf832005-06-21 12:43:18 -07002175
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002176
Robert Olsson19baf832005-06-21 12:43:18 -07002177static int fib_triestat_seq_show(struct seq_file *seq, void *v)
2178{
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002179 struct net *net = (struct net *)seq->private;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002180 unsigned int h;
Eric W. Biederman877a9bf2007-12-07 00:47:47 -08002181
Stephen Hemmingerd717a9a2008-01-14 23:11:54 -08002182 seq_printf(seq,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08002183 "Basic info: size of leaf:"
2184 " %Zd bytes, size of tnode: %Zd bytes.\n",
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002185 sizeof(struct leaf), sizeof(struct tnode));
Olof Johansson91b9a272005-08-09 20:24:39 -07002186
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002187 for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
2188 struct hlist_head *head = &net->ipv4.fib_table_hash[h];
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002189 struct fib_table *tb;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002190
Sasha Levinb67bfe02013-02-27 17:06:00 -08002191 hlist_for_each_entry_rcu(tb, head, tb_hlist) {
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002192 struct trie *t = (struct trie *) tb->tb_data;
2193 struct trie_stat stat;
2194
2195 if (!t)
2196 continue;
2197
2198 fib_table_print(seq, tb);
2199
2200 trie_collect_stats(t, &stat);
2201 trie_show_stats(seq, &stat);
2202#ifdef CONFIG_IP_FIB_TRIE_STATS
2203 trie_show_usage(seq, &t->stats);
2204#endif
2205 }
2206 }
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002207
Robert Olsson19baf832005-06-21 12:43:18 -07002208 return 0;
2209}
2210
Robert Olsson19baf832005-06-21 12:43:18 -07002211static int fib_triestat_seq_open(struct inode *inode, struct file *file)
2212{
Pavel Emelyanovde05c552008-07-18 04:07:21 -07002213 return single_open_net(inode, file, fib_triestat_seq_show);
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002214}
2215
Arjan van de Ven9a321442007-02-12 00:55:35 -08002216static const struct file_operations fib_triestat_fops = {
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07002217 .owner = THIS_MODULE,
2218 .open = fib_triestat_seq_open,
2219 .read = seq_read,
2220 .llseek = seq_lseek,
Pavel Emelyanovb6fcbdb2008-07-18 04:07:44 -07002221 .release = single_release_net,
Robert Olsson19baf832005-06-21 12:43:18 -07002222};
2223
David S. Millerb299e4f2011-02-02 20:48:10 -08002224static struct rt_trie_node *fib_trie_get_idx(struct seq_file *seq, loff_t pos)
Robert Olsson19baf832005-06-21 12:43:18 -07002225{
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002226 struct fib_trie_iter *iter = seq->private;
2227 struct net *net = seq_file_net(seq);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002228 loff_t idx = 0;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002229 unsigned int h;
Robert Olsson19baf832005-06-21 12:43:18 -07002230
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002231 for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
2232 struct hlist_head *head = &net->ipv4.fib_table_hash[h];
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002233 struct fib_table *tb;
2234
Sasha Levinb67bfe02013-02-27 17:06:00 -08002235 hlist_for_each_entry_rcu(tb, head, tb_hlist) {
David S. Millerb299e4f2011-02-02 20:48:10 -08002236 struct rt_trie_node *n;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002237
2238 for (n = fib_trie_get_first(iter,
2239 (struct trie *) tb->tb_data);
2240 n; n = fib_trie_get_next(iter))
2241 if (pos == idx++) {
2242 iter->tb = tb;
2243 return n;
2244 }
2245 }
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002246 }
Robert Olsson19baf832005-06-21 12:43:18 -07002247
Robert Olsson19baf832005-06-21 12:43:18 -07002248 return NULL;
2249}
2250
2251static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
Stephen Hemmingerc95aaf92008-01-12 21:25:02 -08002252 __acquires(RCU)
Robert Olsson19baf832005-06-21 12:43:18 -07002253{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002254 rcu_read_lock();
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002255 return fib_trie_get_idx(seq, *pos);
Robert Olsson19baf832005-06-21 12:43:18 -07002256}
2257
2258static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2259{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002260 struct fib_trie_iter *iter = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002261 struct net *net = seq_file_net(seq);
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002262 struct fib_table *tb = iter->tb;
2263 struct hlist_node *tb_node;
2264 unsigned int h;
David S. Millerb299e4f2011-02-02 20:48:10 -08002265 struct rt_trie_node *n;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002266
Robert Olsson19baf832005-06-21 12:43:18 -07002267 ++*pos;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002268 /* next node in same table */
2269 n = fib_trie_get_next(iter);
2270 if (n)
2271 return n;
Olof Johansson91b9a272005-08-09 20:24:39 -07002272
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002273 /* walk rest of this hash chain */
2274 h = tb->tb_id & (FIB_TABLE_HASHSZ - 1);
Eric Dumazet0a5c0472011-03-31 01:51:35 -07002275 while ((tb_node = rcu_dereference(hlist_next_rcu(&tb->tb_hlist)))) {
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002276 tb = hlist_entry(tb_node, struct fib_table, tb_hlist);
2277 n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
2278 if (n)
2279 goto found;
2280 }
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002281
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002282 /* new hash chain */
2283 while (++h < FIB_TABLE_HASHSZ) {
2284 struct hlist_head *head = &net->ipv4.fib_table_hash[h];
Sasha Levinb67bfe02013-02-27 17:06:00 -08002285 hlist_for_each_entry_rcu(tb, head, tb_hlist) {
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002286 n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
2287 if (n)
2288 goto found;
2289 }
2290 }
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002291 return NULL;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002292
2293found:
2294 iter->tb = tb;
2295 return n;
Robert Olsson19baf832005-06-21 12:43:18 -07002296}
2297
2298static void fib_trie_seq_stop(struct seq_file *seq, void *v)
Stephen Hemmingerc95aaf92008-01-12 21:25:02 -08002299 __releases(RCU)
Robert Olsson19baf832005-06-21 12:43:18 -07002300{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002301 rcu_read_unlock();
Robert Olsson19baf832005-06-21 12:43:18 -07002302}
2303
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002304static void seq_indent(struct seq_file *seq, int n)
2305{
Eric Dumazeta034ee32010-09-09 23:32:28 +00002306 while (n-- > 0)
2307 seq_puts(seq, " ");
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002308}
Robert Olsson19baf832005-06-21 12:43:18 -07002309
Eric Dumazet28d36e32008-01-14 23:09:56 -08002310static inline const char *rtn_scope(char *buf, size_t len, enum rt_scope_t s)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002311{
Stephen Hemminger132adf52007-03-08 20:44:43 -08002312 switch (s) {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002313 case RT_SCOPE_UNIVERSE: return "universe";
2314 case RT_SCOPE_SITE: return "site";
2315 case RT_SCOPE_LINK: return "link";
2316 case RT_SCOPE_HOST: return "host";
2317 case RT_SCOPE_NOWHERE: return "nowhere";
2318 default:
Eric Dumazet28d36e32008-01-14 23:09:56 -08002319 snprintf(buf, len, "scope=%d", s);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002320 return buf;
2321 }
2322}
2323
Jan Engelhardt36cbd3d2009-08-05 10:42:58 -07002324static const char *const rtn_type_names[__RTN_MAX] = {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002325 [RTN_UNSPEC] = "UNSPEC",
2326 [RTN_UNICAST] = "UNICAST",
2327 [RTN_LOCAL] = "LOCAL",
2328 [RTN_BROADCAST] = "BROADCAST",
2329 [RTN_ANYCAST] = "ANYCAST",
2330 [RTN_MULTICAST] = "MULTICAST",
2331 [RTN_BLACKHOLE] = "BLACKHOLE",
2332 [RTN_UNREACHABLE] = "UNREACHABLE",
2333 [RTN_PROHIBIT] = "PROHIBIT",
2334 [RTN_THROW] = "THROW",
2335 [RTN_NAT] = "NAT",
2336 [RTN_XRESOLVE] = "XRESOLVE",
2337};
2338
Eric Dumazeta034ee32010-09-09 23:32:28 +00002339static inline const char *rtn_type(char *buf, size_t len, unsigned int t)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002340{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002341 if (t < __RTN_MAX && rtn_type_names[t])
2342 return rtn_type_names[t];
Eric Dumazet28d36e32008-01-14 23:09:56 -08002343 snprintf(buf, len, "type %u", t);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002344 return buf;
2345}
2346
2347/* Pretty print the trie */
Robert Olsson19baf832005-06-21 12:43:18 -07002348static int fib_trie_seq_show(struct seq_file *seq, void *v)
2349{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002350 const struct fib_trie_iter *iter = seq->private;
David S. Millerb299e4f2011-02-02 20:48:10 -08002351 struct rt_trie_node *n = v;
Robert Olsson19baf832005-06-21 12:43:18 -07002352
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002353 if (!node_parent_rcu(n))
2354 fib_table_print(seq, iter->tb);
Robert Olsson095b8502007-01-26 19:06:01 -08002355
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002356 if (IS_TNODE(n)) {
2357 struct tnode *tn = (struct tnode *) n;
Stephen Hemmingerab66b4a2007-08-10 15:22:58 -07002358 __be32 prf = htonl(mask_pfx(tn->key, tn->pos));
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002359
Robert Olsson1d25cd62005-09-19 15:29:52 -07002360 seq_indent(seq, iter->depth-1);
Harvey Harrison673d57e2008-10-31 00:53:57 -07002361 seq_printf(seq, " +-- %pI4/%d %d %d %d\n",
2362 &prf, tn->pos, tn->bits, tn->full_children,
Robert Olsson1d25cd62005-09-19 15:29:52 -07002363 tn->empty_children);
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09002364
Olof Johansson91b9a272005-08-09 20:24:39 -07002365 } else {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002366 struct leaf *l = (struct leaf *) n;
Stephen Hemminger13280422008-01-22 21:54:37 -08002367 struct leaf_info *li;
Al Viro32ab5f82006-09-26 22:21:45 -07002368 __be32 val = htonl(l->key);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002369
2370 seq_indent(seq, iter->depth);
Harvey Harrison673d57e2008-10-31 00:53:57 -07002371 seq_printf(seq, " |-- %pI4\n", &val);
Eric Dumazet28d36e32008-01-14 23:09:56 -08002372
Sasha Levinb67bfe02013-02-27 17:06:00 -08002373 hlist_for_each_entry_rcu(li, &l->list, hlist) {
Stephen Hemminger13280422008-01-22 21:54:37 -08002374 struct fib_alias *fa;
Eric Dumazet28d36e32008-01-14 23:09:56 -08002375
Stephen Hemminger13280422008-01-22 21:54:37 -08002376 list_for_each_entry_rcu(fa, &li->falh, fa_list) {
2377 char buf1[32], buf2[32];
Eric Dumazet28d36e32008-01-14 23:09:56 -08002378
Stephen Hemminger13280422008-01-22 21:54:37 -08002379 seq_indent(seq, iter->depth+1);
2380 seq_printf(seq, " /%d %s %s", li->plen,
2381 rtn_scope(buf1, sizeof(buf1),
David S. Miller37e826c2011-03-24 18:06:47 -07002382 fa->fa_info->fib_scope),
Stephen Hemminger13280422008-01-22 21:54:37 -08002383 rtn_type(buf2, sizeof(buf2),
2384 fa->fa_type));
2385 if (fa->fa_tos)
Denis V. Lunevb9c4d822008-02-05 02:58:45 -08002386 seq_printf(seq, " tos=%d", fa->fa_tos);
Stephen Hemminger13280422008-01-22 21:54:37 -08002387 seq_putc(seq, '\n');
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002388 }
2389 }
Robert Olsson19baf832005-06-21 12:43:18 -07002390 }
2391
2392 return 0;
2393}
2394
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002395static const struct seq_operations fib_trie_seq_ops = {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002396 .start = fib_trie_seq_start,
2397 .next = fib_trie_seq_next,
2398 .stop = fib_trie_seq_stop,
2399 .show = fib_trie_seq_show,
Robert Olsson19baf832005-06-21 12:43:18 -07002400};
2401
2402static int fib_trie_seq_open(struct inode *inode, struct file *file)
2403{
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002404 return seq_open_net(inode, file, &fib_trie_seq_ops,
2405 sizeof(struct fib_trie_iter));
Robert Olsson19baf832005-06-21 12:43:18 -07002406}
2407
Arjan van de Ven9a321442007-02-12 00:55:35 -08002408static const struct file_operations fib_trie_fops = {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002409 .owner = THIS_MODULE,
2410 .open = fib_trie_seq_open,
2411 .read = seq_read,
2412 .llseek = seq_lseek,
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002413 .release = seq_release_net,
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002414};
2415
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002416struct fib_route_iter {
2417 struct seq_net_private p;
2418 struct trie *main_trie;
2419 loff_t pos;
2420 t_key key;
2421};
2422
2423static struct leaf *fib_route_get_idx(struct fib_route_iter *iter, loff_t pos)
2424{
2425 struct leaf *l = NULL;
2426 struct trie *t = iter->main_trie;
2427
2428 /* use cache location of last found key */
2429 if (iter->pos > 0 && pos >= iter->pos && (l = fib_find_node(t, iter->key)))
2430 pos -= iter->pos;
2431 else {
2432 iter->pos = 0;
2433 l = trie_firstleaf(t);
2434 }
2435
2436 while (l && pos-- > 0) {
2437 iter->pos++;
2438 l = trie_nextleaf(l);
2439 }
2440
2441 if (l)
2442 iter->key = pos; /* remember it */
2443 else
2444 iter->pos = 0; /* forget it */
2445
2446 return l;
2447}
2448
2449static void *fib_route_seq_start(struct seq_file *seq, loff_t *pos)
2450 __acquires(RCU)
2451{
2452 struct fib_route_iter *iter = seq->private;
2453 struct fib_table *tb;
2454
2455 rcu_read_lock();
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002456 tb = fib_get_table(seq_file_net(seq), RT_TABLE_MAIN);
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002457 if (!tb)
2458 return NULL;
2459
2460 iter->main_trie = (struct trie *) tb->tb_data;
2461 if (*pos == 0)
2462 return SEQ_START_TOKEN;
2463 else
2464 return fib_route_get_idx(iter, *pos - 1);
2465}
2466
2467static void *fib_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2468{
2469 struct fib_route_iter *iter = seq->private;
2470 struct leaf *l = v;
2471
2472 ++*pos;
2473 if (v == SEQ_START_TOKEN) {
2474 iter->pos = 0;
2475 l = trie_firstleaf(iter->main_trie);
2476 } else {
2477 iter->pos++;
2478 l = trie_nextleaf(l);
2479 }
2480
2481 if (l)
2482 iter->key = l->key;
2483 else
2484 iter->pos = 0;
2485 return l;
2486}
2487
2488static void fib_route_seq_stop(struct seq_file *seq, void *v)
2489 __releases(RCU)
2490{
2491 rcu_read_unlock();
2492}
2493
Eric Dumazeta034ee32010-09-09 23:32:28 +00002494static unsigned int fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002495{
Eric Dumazeta034ee32010-09-09 23:32:28 +00002496 unsigned int flags = 0;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002497
Eric Dumazeta034ee32010-09-09 23:32:28 +00002498 if (type == RTN_UNREACHABLE || type == RTN_PROHIBIT)
2499 flags = RTF_REJECT;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002500 if (fi && fi->fib_nh->nh_gw)
2501 flags |= RTF_GATEWAY;
Al Viro32ab5f82006-09-26 22:21:45 -07002502 if (mask == htonl(0xFFFFFFFF))
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002503 flags |= RTF_HOST;
2504 flags |= RTF_UP;
2505 return flags;
2506}
2507
2508/*
2509 * This outputs /proc/net/route.
2510 * The format of the file is not supposed to be changed
Eric Dumazeta034ee32010-09-09 23:32:28 +00002511 * and needs to be same as fib_hash output to avoid breaking
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002512 * legacy utilities
2513 */
2514static int fib_route_seq_show(struct seq_file *seq, void *v)
2515{
2516 struct leaf *l = v;
Stephen Hemminger13280422008-01-22 21:54:37 -08002517 struct leaf_info *li;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002518
2519 if (v == SEQ_START_TOKEN) {
2520 seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
2521 "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
2522 "\tWindow\tIRTT");
2523 return 0;
2524 }
2525
Sasha Levinb67bfe02013-02-27 17:06:00 -08002526 hlist_for_each_entry_rcu(li, &l->list, hlist) {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002527 struct fib_alias *fa;
Al Viro32ab5f82006-09-26 22:21:45 -07002528 __be32 mask, prefix;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002529
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002530 mask = inet_make_mask(li->plen);
2531 prefix = htonl(l->key);
2532
2533 list_for_each_entry_rcu(fa, &li->falh, fa_list) {
Herbert Xu1371e372005-10-15 09:42:39 +10002534 const struct fib_info *fi = fa->fa_info;
Eric Dumazeta034ee32010-09-09 23:32:28 +00002535 unsigned int flags = fib_flag_trans(fa->fa_type, mask, fi);
Pavel Emelyanov5e659e42008-04-24 01:02:16 -07002536 int len;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002537
2538 if (fa->fa_type == RTN_BROADCAST
2539 || fa->fa_type == RTN_MULTICAST)
2540 continue;
2541
2542 if (fi)
Pavel Emelyanov5e659e42008-04-24 01:02:16 -07002543 seq_printf(seq,
2544 "%s\t%08X\t%08X\t%04X\t%d\t%u\t"
2545 "%d\t%08X\t%d\t%u\t%u%n",
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002546 fi->fib_dev ? fi->fib_dev->name : "*",
2547 prefix,
2548 fi->fib_nh->nh_gw, flags, 0, 0,
2549 fi->fib_priority,
2550 mask,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08002551 (fi->fib_advmss ?
2552 fi->fib_advmss + 40 : 0),
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002553 fi->fib_window,
Pavel Emelyanov5e659e42008-04-24 01:02:16 -07002554 fi->fib_rtt >> 3, &len);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002555 else
Pavel Emelyanov5e659e42008-04-24 01:02:16 -07002556 seq_printf(seq,
2557 "*\t%08X\t%08X\t%04X\t%d\t%u\t"
2558 "%d\t%08X\t%d\t%u\t%u%n",
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002559 prefix, 0, flags, 0, 0, 0,
Pavel Emelyanov5e659e42008-04-24 01:02:16 -07002560 mask, 0, 0, 0, &len);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002561
Pavel Emelyanov5e659e42008-04-24 01:02:16 -07002562 seq_printf(seq, "%*s\n", 127 - len, "");
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002563 }
2564 }
2565
2566 return 0;
2567}
2568
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002569static const struct seq_operations fib_route_seq_ops = {
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002570 .start = fib_route_seq_start,
2571 .next = fib_route_seq_next,
2572 .stop = fib_route_seq_stop,
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002573 .show = fib_route_seq_show,
2574};
2575
2576static int fib_route_seq_open(struct inode *inode, struct file *file)
2577{
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002578 return seq_open_net(inode, file, &fib_route_seq_ops,
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002579 sizeof(struct fib_route_iter));
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002580}
2581
Arjan van de Ven9a321442007-02-12 00:55:35 -08002582static const struct file_operations fib_route_fops = {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002583 .owner = THIS_MODULE,
2584 .open = fib_route_seq_open,
2585 .read = seq_read,
2586 .llseek = seq_lseek,
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002587 .release = seq_release_net,
Robert Olsson19baf832005-06-21 12:43:18 -07002588};
2589
Denis V. Lunev61a02652008-01-10 03:21:09 -08002590int __net_init fib_proc_init(struct net *net)
Robert Olsson19baf832005-06-21 12:43:18 -07002591{
Gao fengd4beaa62013-02-18 01:34:54 +00002592 if (!proc_create("fib_trie", S_IRUGO, net->proc_net, &fib_trie_fops))
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002593 goto out1;
2594
Gao fengd4beaa62013-02-18 01:34:54 +00002595 if (!proc_create("fib_triestat", S_IRUGO, net->proc_net,
2596 &fib_triestat_fops))
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002597 goto out2;
2598
Gao fengd4beaa62013-02-18 01:34:54 +00002599 if (!proc_create("route", S_IRUGO, net->proc_net, &fib_route_fops))
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002600 goto out3;
2601
Robert Olsson19baf832005-06-21 12:43:18 -07002602 return 0;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002603
2604out3:
Gao fengece31ff2013-02-18 01:34:56 +00002605 remove_proc_entry("fib_triestat", net->proc_net);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002606out2:
Gao fengece31ff2013-02-18 01:34:56 +00002607 remove_proc_entry("fib_trie", net->proc_net);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002608out1:
2609 return -ENOMEM;
Robert Olsson19baf832005-06-21 12:43:18 -07002610}
2611
Denis V. Lunev61a02652008-01-10 03:21:09 -08002612void __net_exit fib_proc_exit(struct net *net)
Robert Olsson19baf832005-06-21 12:43:18 -07002613{
Gao fengece31ff2013-02-18 01:34:56 +00002614 remove_proc_entry("fib_trie", net->proc_net);
2615 remove_proc_entry("fib_triestat", net->proc_net);
2616 remove_proc_entry("route", net->proc_net);
Robert Olsson19baf832005-06-21 12:43:18 -07002617}
2618
2619#endif /* CONFIG_PROC_FS */