blob: 2b7220728b242efe43952150423d525f94497a6e [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 Gortmakerbc3b2d72011-07-15 11:47:34 -040074#include <linux/export.h>
Eric W. Biederman457c4cb2007-09-12 12:01:34 +020075#include <net/net_namespace.h>
Robert Olsson19baf832005-06-21 12:43:18 -070076#include <net/ip.h>
77#include <net/protocol.h>
78#include <net/route.h>
79#include <net/tcp.h>
80#include <net/sock.h>
81#include <net/ip_fib.h>
82#include "fib_lookup.h"
83
Robert Olsson06ef9212006-03-20 21:35:01 -080084#define MAX_STAT_DEPTH 32
Robert Olsson19baf832005-06-21 12:43:18 -070085
Robert Olsson19baf832005-06-21 12:43:18 -070086#define KEYLENGTH (8*sizeof(t_key))
Robert Olsson19baf832005-06-21 12:43:18 -070087
Robert Olsson19baf832005-06-21 12:43:18 -070088typedef unsigned int t_key;
89
Alexander Duyck64c9b6f2014-12-31 10:55:35 -080090#define IS_TNODE(n) ((n)->bits)
91#define IS_LEAF(n) (!(n)->bits)
Robert Olsson2373ce12005-08-25 13:01:29 -070092
Alexander Duyck64c9b6f2014-12-31 10:55:35 -080093struct tnode {
94 t_key key;
95 unsigned char bits; /* 2log(KEYLENGTH) bits needed */
96 unsigned char pos; /* 2log(KEYLENGTH) bits needed */
97 struct tnode __rcu *parent;
98 union {
99 struct rcu_head rcu;
100 struct tnode *tnode_free;
101 };
102 unsigned int full_children; /* KEYLENGTH bits needed */
103 unsigned int empty_children; /* KEYLENGTH bits needed */
104 struct rt_trie_node __rcu *child[0];
105};
Robert Olsson19baf832005-06-21 12:43:18 -0700106
David S. Millerb299e4f2011-02-02 20:48:10 -0800107struct rt_trie_node {
Eric Dumazet8d965442008-01-13 22:31:44 -0800108 t_key key;
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800109 unsigned char bits;
110 unsigned char pos;
111 struct tnode __rcu *parent;
112 struct rcu_head rcu;
Robert Olsson19baf832005-06-21 12:43:18 -0700113};
114
115struct leaf {
Eric Dumazet8d965442008-01-13 22:31:44 -0800116 t_key key;
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800117 unsigned char bits;
118 unsigned char pos;
119 struct tnode __rcu *parent;
Robert Olsson2373ce12005-08-25 13:01:29 -0700120 struct rcu_head rcu;
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800121 struct hlist_head list;
Robert Olsson19baf832005-06-21 12:43:18 -0700122};
123
124struct leaf_info {
125 struct hlist_node hlist;
126 int plen;
Eric Dumazet5c745012011-07-18 03:16:33 +0000127 u32 mask_plen; /* ntohl(inet_make_mask(plen)) */
Robert Olsson19baf832005-06-21 12:43:18 -0700128 struct list_head falh;
Eric Dumazet5c745012011-07-18 03:16:33 +0000129 struct rcu_head rcu;
Robert Olsson19baf832005-06-21 12:43:18 -0700130};
131
Robert Olsson19baf832005-06-21 12:43:18 -0700132#ifdef CONFIG_IP_FIB_TRIE_STATS
133struct trie_use_stats {
134 unsigned int gets;
135 unsigned int backtrack;
136 unsigned int semantic_match_passed;
137 unsigned int semantic_match_miss;
138 unsigned int null_node_hit;
Robert Olsson2f368952005-07-05 15:02:40 -0700139 unsigned int resize_node_skipped;
Robert Olsson19baf832005-06-21 12:43:18 -0700140};
141#endif
142
143struct trie_stat {
144 unsigned int totdepth;
145 unsigned int maxdepth;
146 unsigned int tnodes;
147 unsigned int leaves;
148 unsigned int nullpointers;
Stephen Hemminger93672292008-01-22 21:54:05 -0800149 unsigned int prefixes;
Robert Olsson06ef9212006-03-20 21:35:01 -0800150 unsigned int nodesizes[MAX_STAT_DEPTH];
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700151};
Robert Olsson19baf832005-06-21 12:43:18 -0700152
153struct trie {
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700154 struct rt_trie_node __rcu *trie;
Robert Olsson19baf832005-06-21 12:43:18 -0700155#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -0800156 struct trie_use_stats __percpu *stats;
Robert Olsson19baf832005-06-21 12:43:18 -0700157#endif
Robert Olsson19baf832005-06-21 12:43:18 -0700158};
159
David S. Millerb299e4f2011-02-02 20:48:10 -0800160static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800161 int wasfull);
David S. Millerb299e4f2011-02-02 20:48:10 -0800162static struct rt_trie_node *resize(struct trie *t, struct tnode *tn);
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700163static struct tnode *inflate(struct trie *t, struct tnode *tn);
164static struct tnode *halve(struct trie *t, struct tnode *tn);
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700165/* tnodes to free after resize(); protected by RTNL */
166static struct tnode *tnode_free_head;
Jarek Poplawskic3059472009-07-14 08:33:08 +0000167static size_t tnode_free_size;
168
169/*
170 * synchronize_rcu after call_rcu for that many pages; it should be especially
171 * useful before resizing the root node with PREEMPT_NONE configs; the value was
172 * obtained experimentally, aiming to avoid visible slowdown.
173 */
174static const int sync_pages = 128;
Robert Olsson19baf832005-06-21 12:43:18 -0700175
Christoph Lametere18b8902006-12-06 20:33:20 -0800176static struct kmem_cache *fn_alias_kmem __read_mostly;
Stephen Hemmingerbc3c8c12008-01-22 21:51:50 -0800177static struct kmem_cache *trie_leaf_kmem __read_mostly;
Robert Olsson19baf832005-06-21 12:43:18 -0700178
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800179/* caller must hold RTNL */
180#define node_parent(n) rtnl_dereference((n)->parent)
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700181
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800182/* caller must hold RCU read lock or RTNL */
183#define node_parent_rcu(n) rcu_dereference_rtnl((n)->parent)
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700184
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800185/* wrapper for rcu_assign_pointer */
David S. Millerb299e4f2011-02-02 20:48:10 -0800186static inline void node_set_parent(struct rt_trie_node *node, struct tnode *ptr)
Stephen Hemminger06801912007-08-10 15:22:13 -0700187{
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800188 if (node)
189 rcu_assign_pointer(node->parent, ptr);
190}
191
192#define NODE_INIT_PARENT(n, p) RCU_INIT_POINTER((n)->parent, p)
193
194/* This provides us with the number of children in this node, in the case of a
195 * leaf this will return 0 meaning none of the children are accessible.
196 */
197static inline int tnode_child_length(const struct tnode *tn)
198{
199 return (1ul << tn->bits) & ~(1ul);
Stephen Hemminger06801912007-08-10 15:22:13 -0700200}
Robert Olsson2373ce12005-08-25 13:01:29 -0700201
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700202/*
203 * caller must hold RTNL
204 */
205static inline struct rt_trie_node *tnode_get_child(const struct tnode *tn, unsigned int i)
Robert Olsson19baf832005-06-21 12:43:18 -0700206{
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800207 BUG_ON(i >= tnode_child_length(tn));
Robert Olsson19baf832005-06-21 12:43:18 -0700208
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700209 return rtnl_dereference(tn->child[i]);
Eric Dumazetb59cfbf2008-01-18 03:31:36 -0800210}
211
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700212/*
213 * caller must hold RCU read lock or RTNL
214 */
215static inline struct rt_trie_node *tnode_get_child_rcu(const struct tnode *tn, unsigned int i)
Eric Dumazetb59cfbf2008-01-18 03:31:36 -0800216{
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800217 BUG_ON(i >= tnode_child_length(tn));
Eric Dumazetb59cfbf2008-01-18 03:31:36 -0800218
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700219 return rcu_dereference_rtnl(tn->child[i]);
Robert Olsson19baf832005-06-21 12:43:18 -0700220}
221
David S. Miller3b004562011-02-16 14:56:22 -0800222static inline t_key mask_pfx(t_key k, unsigned int l)
Stephen Hemmingerab66b4a2007-08-10 15:22:58 -0700223{
224 return (l == 0) ? 0 : k >> (KEYLENGTH-l) << (KEYLENGTH-l);
225}
226
David S. Miller3b004562011-02-16 14:56:22 -0800227static inline t_key tkey_extract_bits(t_key a, unsigned int offset, unsigned int bits)
Robert Olsson19baf832005-06-21 12:43:18 -0700228{
Olof Johansson91b9a272005-08-09 20:24:39 -0700229 if (offset < KEYLENGTH)
Robert Olsson19baf832005-06-21 12:43:18 -0700230 return ((t_key)(a << offset)) >> (KEYLENGTH - bits);
Olof Johansson91b9a272005-08-09 20:24:39 -0700231 else
Robert Olsson19baf832005-06-21 12:43:18 -0700232 return 0;
233}
234
235static inline int tkey_equals(t_key a, t_key b)
236{
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700237 return a == b;
Robert Olsson19baf832005-06-21 12:43:18 -0700238}
239
240static inline int tkey_sub_equals(t_key a, int offset, int bits, t_key b)
241{
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700242 if (bits == 0 || offset >= KEYLENGTH)
243 return 1;
Olof Johansson91b9a272005-08-09 20:24:39 -0700244 bits = bits > KEYLENGTH ? KEYLENGTH : bits;
245 return ((a ^ b) << offset) >> (KEYLENGTH - bits) == 0;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700246}
Robert Olsson19baf832005-06-21 12:43:18 -0700247
248static inline int tkey_mismatch(t_key a, int offset, t_key b)
249{
250 t_key diff = a ^ b;
251 int i = offset;
252
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700253 if (!diff)
254 return 0;
255 while ((diff << i) >> (KEYLENGTH-1) == 0)
Robert Olsson19baf832005-06-21 12:43:18 -0700256 i++;
257 return i;
258}
259
Robert Olsson19baf832005-06-21 12:43:18 -0700260/*
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900261 To understand this stuff, an understanding of keys and all their bits is
262 necessary. Every node in the trie has a key associated with it, but not
Robert Olsson19baf832005-06-21 12:43:18 -0700263 all of the bits in that key are significant.
264
265 Consider a node 'n' and its parent 'tp'.
266
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900267 If n is a leaf, every bit in its key is significant. Its presence is
268 necessitated by path compression, since during a tree traversal (when
269 searching for a leaf - unless we are doing an insertion) we will completely
270 ignore all skipped bits we encounter. Thus we need to verify, at the end of
271 a potentially successful search, that we have indeed been walking the
Robert Olsson19baf832005-06-21 12:43:18 -0700272 correct key path.
273
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900274 Note that we can never "miss" the correct key in the tree if present by
275 following the wrong path. Path compression ensures that segments of the key
276 that are the same for all keys with a given prefix are skipped, but the
277 skipped part *is* identical for each node in the subtrie below the skipped
278 bit! trie_insert() in this implementation takes care of that - note the
Robert Olsson19baf832005-06-21 12:43:18 -0700279 call to tkey_sub_equals() in trie_insert().
280
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900281 if n is an internal node - a 'tnode' here, the various parts of its key
Robert Olsson19baf832005-06-21 12:43:18 -0700282 have many different meanings.
283
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900284 Example:
Robert Olsson19baf832005-06-21 12:43:18 -0700285 _________________________________________________________________
286 | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C |
287 -----------------------------------------------------------------
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900288 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Robert Olsson19baf832005-06-21 12:43:18 -0700289
290 _________________________________________________________________
291 | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u |
292 -----------------------------------------------------------------
293 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
294
295 tp->pos = 7
296 tp->bits = 3
297 n->pos = 15
Olof Johansson91b9a272005-08-09 20:24:39 -0700298 n->bits = 4
Robert Olsson19baf832005-06-21 12:43:18 -0700299
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900300 First, let's just ignore the bits that come before the parent tp, that is
301 the bits from 0 to (tp->pos-1). They are *known* but at this point we do
Robert Olsson19baf832005-06-21 12:43:18 -0700302 not use them for anything.
303
304 The bits from (tp->pos) to (tp->pos + tp->bits - 1) - "N", above - are the
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900305 index into the parent's child array. That is, they will be used to find
Robert Olsson19baf832005-06-21 12:43:18 -0700306 'n' among tp's children.
307
308 The bits from (tp->pos + tp->bits) to (n->pos - 1) - "S" - are skipped bits
309 for the node n.
310
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900311 All the bits we have seen so far are significant to the node n. The rest
Robert Olsson19baf832005-06-21 12:43:18 -0700312 of the bits are really not needed or indeed known in n->key.
313
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900314 The bits from (n->pos) to (n->pos + n->bits - 1) - "C" - are the index into
Robert Olsson19baf832005-06-21 12:43:18 -0700315 n's child array, and will of course be different for each child.
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900316
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700317
Robert Olsson19baf832005-06-21 12:43:18 -0700318 The rest of the bits, from (n->pos + n->bits) onward, are completely unknown
319 at this point.
320
321*/
322
Denis V. Lunevf5026fa2007-12-13 09:47:57 -0800323static const int halve_threshold = 25;
324static const int inflate_threshold = 50;
Jarek Poplawski345aa032009-07-07 19:39:16 -0700325static const int halve_threshold_root = 15;
Jens Låås80b71b82009-08-28 23:57:15 -0700326static const int inflate_threshold_root = 30;
Robert Olsson2373ce12005-08-25 13:01:29 -0700327
328static void __alias_free_mem(struct rcu_head *head)
329{
330 struct fib_alias *fa = container_of(head, struct fib_alias, rcu);
331 kmem_cache_free(fn_alias_kmem, fa);
332}
333
334static inline void alias_free_mem_rcu(struct fib_alias *fa)
335{
336 call_rcu(&fa->rcu, __alias_free_mem);
337}
338
339static void __leaf_free_rcu(struct rcu_head *head)
340{
Stephen Hemmingerbc3c8c12008-01-22 21:51:50 -0800341 struct leaf *l = container_of(head, struct leaf, rcu);
342 kmem_cache_free(trie_leaf_kmem, l);
Robert Olsson2373ce12005-08-25 13:01:29 -0700343}
344
Stephen Hemminger387a5482008-04-10 03:47:34 -0700345static inline void free_leaf(struct leaf *l)
346{
Eric Dumazet0c03eca2012-08-07 00:47:11 +0000347 call_rcu(&l->rcu, __leaf_free_rcu);
Stephen Hemminger387a5482008-04-10 03:47:34 -0700348}
349
Robert Olsson2373ce12005-08-25 13:01:29 -0700350static inline void free_leaf_info(struct leaf_info *leaf)
351{
Lai Jiangshanbceb0f42011-03-18 11:42:34 +0800352 kfree_rcu(leaf, rcu);
Robert Olsson2373ce12005-08-25 13:01:29 -0700353}
354
Eric Dumazet8d965442008-01-13 22:31:44 -0800355static struct tnode *tnode_alloc(size_t size)
Robert Olsson2373ce12005-08-25 13:01:29 -0700356{
Robert Olsson2373ce12005-08-25 13:01:29 -0700357 if (size <= PAGE_SIZE)
Eric Dumazet8d965442008-01-13 22:31:44 -0800358 return kzalloc(size, GFP_KERNEL);
Stephen Hemminger15be75c2008-04-10 02:56:38 -0700359 else
Eric Dumazet7a1c8e52010-11-20 07:46:35 +0000360 return vzalloc(size);
Stephen Hemminger15be75c2008-04-10 02:56:38 -0700361}
Robert Olsson2373ce12005-08-25 13:01:29 -0700362
Robert Olsson2373ce12005-08-25 13:01:29 -0700363static void __tnode_free_rcu(struct rcu_head *head)
364{
365 struct tnode *tn = container_of(head, struct tnode, rcu);
Eric Dumazet8d965442008-01-13 22:31:44 -0800366 size_t size = sizeof(struct tnode) +
David S. Millerb299e4f2011-02-02 20:48:10 -0800367 (sizeof(struct rt_trie_node *) << tn->bits);
Robert Olsson2373ce12005-08-25 13:01:29 -0700368
369 if (size <= PAGE_SIZE)
370 kfree(tn);
Al Viro00203562013-05-05 16:03:46 +0000371 else
372 vfree(tn);
Robert Olsson2373ce12005-08-25 13:01:29 -0700373}
374
375static inline void tnode_free(struct tnode *tn)
376{
Stephen Hemminger387a5482008-04-10 03:47:34 -0700377 if (IS_LEAF(tn))
378 free_leaf((struct leaf *) tn);
379 else
Robert Olsson550e29b2006-04-04 12:53:35 -0700380 call_rcu(&tn->rcu, __tnode_free_rcu);
Robert Olsson2373ce12005-08-25 13:01:29 -0700381}
382
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700383static void tnode_free_safe(struct tnode *tn)
384{
385 BUG_ON(IS_LEAF(tn));
Jarek Poplawski7b855762009-06-18 00:28:51 -0700386 tn->tnode_free = tnode_free_head;
387 tnode_free_head = tn;
Jarek Poplawskic3059472009-07-14 08:33:08 +0000388 tnode_free_size += sizeof(struct tnode) +
David S. Millerb299e4f2011-02-02 20:48:10 -0800389 (sizeof(struct rt_trie_node *) << tn->bits);
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700390}
391
392static void tnode_free_flush(void)
393{
394 struct tnode *tn;
395
396 while ((tn = tnode_free_head)) {
397 tnode_free_head = tn->tnode_free;
398 tn->tnode_free = NULL;
399 tnode_free(tn);
400 }
Jarek Poplawskic3059472009-07-14 08:33:08 +0000401
402 if (tnode_free_size >= PAGE_SIZE * sync_pages) {
403 tnode_free_size = 0;
404 synchronize_rcu();
405 }
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700406}
407
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800408static struct leaf *leaf_new(t_key key)
Robert Olsson19baf832005-06-21 12:43:18 -0700409{
Stephen Hemmingerbc3c8c12008-01-22 21:51:50 -0800410 struct leaf *l = kmem_cache_alloc(trie_leaf_kmem, GFP_KERNEL);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700411 if (l) {
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800412 l->parent = NULL;
413 /* set key and pos to reflect full key value
414 * any trailing zeros in the key should be ignored
415 * as the nodes are searched
416 */
417 l->key = key;
418 l->pos = KEYLENGTH;
419 /* set bits to 0 indicating we are not a tnode */
420 l->bits = 0;
421
Robert Olsson19baf832005-06-21 12:43:18 -0700422 INIT_HLIST_HEAD(&l->list);
423 }
424 return l;
425}
426
427static struct leaf_info *leaf_info_new(int plen)
428{
429 struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL);
Robert Olsson2373ce12005-08-25 13:01:29 -0700430 if (li) {
431 li->plen = plen;
Eric Dumazet5c745012011-07-18 03:16:33 +0000432 li->mask_plen = ntohl(inet_make_mask(plen));
Robert Olsson2373ce12005-08-25 13:01:29 -0700433 INIT_LIST_HEAD(&li->falh);
Patrick McHardyf0e36f82005-07-05 14:44:55 -0700434 }
Robert Olsson2373ce12005-08-25 13:01:29 -0700435 return li;
Patrick McHardyf0e36f82005-07-05 14:44:55 -0700436}
437
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800438static struct tnode *tnode_new(t_key key, int pos, int bits)
Robert Olsson19baf832005-06-21 12:43:18 -0700439{
David S. Millerb299e4f2011-02-02 20:48:10 -0800440 size_t sz = sizeof(struct tnode) + (sizeof(struct rt_trie_node *) << bits);
Patrick McHardyf0e36f82005-07-05 14:44:55 -0700441 struct tnode *tn = tnode_alloc(sz);
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800442 unsigned int shift = pos + bits;
443
444 /* verify bits and pos their msb bits clear and values are valid */
445 BUG_ON(!bits || (shift > KEYLENGTH));
Robert Olsson19baf832005-06-21 12:43:18 -0700446
Olof Johansson91b9a272005-08-09 20:24:39 -0700447 if (tn) {
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800448 tn->parent = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -0700449 tn->pos = pos;
450 tn->bits = bits;
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800451 tn->key = mask_pfx(key, pos);
Robert Olsson19baf832005-06-21 12:43:18 -0700452 tn->full_children = 0;
453 tn->empty_children = 1<<bits;
454 }
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700455
Eric Dumazeta034ee32010-09-09 23:32:28 +0000456 pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode),
Lin Ming4ea4bf72012-07-29 01:19:55 +0000457 sizeof(struct rt_trie_node *) << bits);
Robert Olsson19baf832005-06-21 12:43:18 -0700458 return tn;
459}
460
Robert Olsson19baf832005-06-21 12:43:18 -0700461/*
462 * Check whether a tnode 'n' is "full", i.e. it is an internal node
463 * and no bits are skipped. See discussion in dyntree paper p. 6
464 */
465
David S. Millerb299e4f2011-02-02 20:48:10 -0800466static inline int tnode_full(const struct tnode *tn, const struct rt_trie_node *n)
Robert Olsson19baf832005-06-21 12:43:18 -0700467{
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800468 return n && IS_TNODE(n) && (n->pos == (tn->pos + tn->bits));
Robert Olsson19baf832005-06-21 12:43:18 -0700469}
470
Lin Ming61648d92012-07-29 02:00:03 +0000471static inline void put_child(struct tnode *tn, int i,
David S. Millerb299e4f2011-02-02 20:48:10 -0800472 struct rt_trie_node *n)
Robert Olsson19baf832005-06-21 12:43:18 -0700473{
474 tnode_put_child_reorg(tn, i, n, -1);
475}
476
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700477 /*
Robert Olsson19baf832005-06-21 12:43:18 -0700478 * Add a child at position i overwriting the old value.
479 * Update the value of full_children and empty_children.
480 */
481
David S. Millerb299e4f2011-02-02 20:48:10 -0800482static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800483 int wasfull)
Robert Olsson19baf832005-06-21 12:43:18 -0700484{
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700485 struct rt_trie_node *chi = rtnl_dereference(tn->child[i]);
Robert Olsson19baf832005-06-21 12:43:18 -0700486 int isfull;
487
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700488 BUG_ON(i >= 1<<tn->bits);
489
Robert Olsson19baf832005-06-21 12:43:18 -0700490 /* update emptyChildren */
491 if (n == NULL && chi != NULL)
492 tn->empty_children++;
493 else if (n != NULL && chi == NULL)
494 tn->empty_children--;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700495
Robert Olsson19baf832005-06-21 12:43:18 -0700496 /* update fullChildren */
Olof Johansson91b9a272005-08-09 20:24:39 -0700497 if (wasfull == -1)
Robert Olsson19baf832005-06-21 12:43:18 -0700498 wasfull = tnode_full(tn, chi);
499
500 isfull = tnode_full(tn, n);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700501 if (wasfull && !isfull)
Robert Olsson19baf832005-06-21 12:43:18 -0700502 tn->full_children--;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700503 else if (!wasfull && isfull)
Robert Olsson19baf832005-06-21 12:43:18 -0700504 tn->full_children++;
Olof Johansson91b9a272005-08-09 20:24:39 -0700505
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800506 node_set_parent(n, tn);
Robert Olsson19baf832005-06-21 12:43:18 -0700507
Eric Dumazetcf778b02012-01-12 04:41:32 +0000508 rcu_assign_pointer(tn->child[i], n);
Robert Olsson19baf832005-06-21 12:43:18 -0700509}
510
Jens Låås80b71b82009-08-28 23:57:15 -0700511#define MAX_WORK 10
David S. Millerb299e4f2011-02-02 20:48:10 -0800512static struct rt_trie_node *resize(struct trie *t, struct tnode *tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700513{
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800514 struct rt_trie_node *n = NULL;
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700515 struct tnode *old_tn;
Robert Olssone6308be2005-10-04 13:01:58 -0700516 int inflate_threshold_use;
517 int halve_threshold_use;
Jens Låås80b71b82009-08-28 23:57:15 -0700518 int max_work;
Robert Olsson19baf832005-06-21 12:43:18 -0700519
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900520 if (!tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700521 return NULL;
522
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700523 pr_debug("In tnode_resize %p inflate_threshold=%d threshold=%d\n",
524 tn, inflate_threshold, halve_threshold);
Robert Olsson19baf832005-06-21 12:43:18 -0700525
526 /* No children */
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800527 if (tn->empty_children > (tnode_child_length(tn) - 1))
528 goto no_children;
529
Robert Olsson19baf832005-06-21 12:43:18 -0700530 /* One child */
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800531 if (tn->empty_children == (tnode_child_length(tn) - 1))
Jens Låås80b71b82009-08-28 23:57:15 -0700532 goto one_child;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700533 /*
Robert Olsson19baf832005-06-21 12:43:18 -0700534 * Double as long as the resulting node has a number of
535 * nonempty nodes that are above the threshold.
536 */
537
538 /*
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700539 * From "Implementing a dynamic compressed trie" by Stefan Nilsson of
540 * the Helsinki University of Technology and Matti Tikkanen of Nokia
Robert Olsson19baf832005-06-21 12:43:18 -0700541 * Telecommunications, page 6:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700542 * "A node is doubled if the ratio of non-empty children to all
Robert Olsson19baf832005-06-21 12:43:18 -0700543 * children in the *doubled* node is at least 'high'."
544 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700545 * 'high' in this instance is the variable 'inflate_threshold'. It
546 * is expressed as a percentage, so we multiply it with
547 * tnode_child_length() and instead of multiplying by 2 (since the
548 * child array will be doubled by inflate()) and multiplying
549 * the left-hand side by 100 (to handle the percentage thing) we
Robert Olsson19baf832005-06-21 12:43:18 -0700550 * multiply the left-hand side by 50.
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700551 *
552 * The left-hand side may look a bit weird: tnode_child_length(tn)
553 * - tn->empty_children is of course the number of non-null children
554 * in the current node. tn->full_children is the number of "full"
Robert Olsson19baf832005-06-21 12:43:18 -0700555 * children, that is non-null tnodes with a skip value of 0.
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700556 * All of those will be doubled in the resulting inflated tnode, so
Robert Olsson19baf832005-06-21 12:43:18 -0700557 * we just count them one extra time here.
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700558 *
Robert Olsson19baf832005-06-21 12:43:18 -0700559 * A clearer way to write this would be:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700560 *
Robert Olsson19baf832005-06-21 12:43:18 -0700561 * to_be_doubled = tn->full_children;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700562 * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children -
Robert Olsson19baf832005-06-21 12:43:18 -0700563 * tn->full_children;
564 *
565 * new_child_length = tnode_child_length(tn) * 2;
566 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700567 * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) /
Robert Olsson19baf832005-06-21 12:43:18 -0700568 * new_child_length;
569 * if (new_fill_factor >= inflate_threshold)
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700570 *
571 * ...and so on, tho it would mess up the while () loop.
572 *
Robert Olsson19baf832005-06-21 12:43:18 -0700573 * anyway,
574 * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >=
575 * inflate_threshold
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700576 *
Robert Olsson19baf832005-06-21 12:43:18 -0700577 * avoid a division:
578 * 100 * (not_to_be_doubled + 2*to_be_doubled) >=
579 * inflate_threshold * new_child_length
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700580 *
Robert Olsson19baf832005-06-21 12:43:18 -0700581 * expand not_to_be_doubled and to_be_doubled, and shorten:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700582 * 100 * (tnode_child_length(tn) - tn->empty_children +
Olof Johansson91b9a272005-08-09 20:24:39 -0700583 * tn->full_children) >= inflate_threshold * new_child_length
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700584 *
Robert Olsson19baf832005-06-21 12:43:18 -0700585 * expand new_child_length:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700586 * 100 * (tnode_child_length(tn) - tn->empty_children +
Olof Johansson91b9a272005-08-09 20:24:39 -0700587 * tn->full_children) >=
Robert Olsson19baf832005-06-21 12:43:18 -0700588 * inflate_threshold * tnode_child_length(tn) * 2
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700589 *
Robert Olsson19baf832005-06-21 12:43:18 -0700590 * shorten again:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700591 * 50 * (tn->full_children + tnode_child_length(tn) -
Olof Johansson91b9a272005-08-09 20:24:39 -0700592 * tn->empty_children) >= inflate_threshold *
Robert Olsson19baf832005-06-21 12:43:18 -0700593 * tnode_child_length(tn)
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700594 *
Robert Olsson19baf832005-06-21 12:43:18 -0700595 */
596
Robert Olssone6308be2005-10-04 13:01:58 -0700597 /* Keep root node larger */
598
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800599 if (!node_parent(tn)) {
Jens Låås80b71b82009-08-28 23:57:15 -0700600 inflate_threshold_use = inflate_threshold_root;
601 halve_threshold_use = halve_threshold_root;
Eric Dumazeta034ee32010-09-09 23:32:28 +0000602 } else {
Robert Olssone6308be2005-10-04 13:01:58 -0700603 inflate_threshold_use = inflate_threshold;
Jens Låås80b71b82009-08-28 23:57:15 -0700604 halve_threshold_use = halve_threshold;
605 }
Robert Olssone6308be2005-10-04 13:01:58 -0700606
Jens Låås80b71b82009-08-28 23:57:15 -0700607 max_work = MAX_WORK;
608 while ((tn->full_children > 0 && max_work-- &&
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800609 50 * (tn->full_children + tnode_child_length(tn)
610 - tn->empty_children)
611 >= inflate_threshold_use * tnode_child_length(tn))) {
Robert Olsson19baf832005-06-21 12:43:18 -0700612
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700613 old_tn = tn;
614 tn = inflate(t, tn);
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800615
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700616 if (IS_ERR(tn)) {
617 tn = old_tn;
Robert Olsson2f368952005-07-05 15:02:40 -0700618#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -0800619 this_cpu_inc(t->stats->resize_node_skipped);
Robert Olsson2f368952005-07-05 15:02:40 -0700620#endif
621 break;
622 }
Robert Olsson19baf832005-06-21 12:43:18 -0700623 }
624
Jens Låås80b71b82009-08-28 23:57:15 -0700625 /* Return if at least one inflate is run */
Eric Dumazeta034ee32010-09-09 23:32:28 +0000626 if (max_work != MAX_WORK)
David S. Millerb299e4f2011-02-02 20:48:10 -0800627 return (struct rt_trie_node *) tn;
Jens Låås80b71b82009-08-28 23:57:15 -0700628
Robert Olsson19baf832005-06-21 12:43:18 -0700629 /*
630 * Halve as long as the number of empty children in this
631 * node is above threshold.
632 */
Robert Olsson2f368952005-07-05 15:02:40 -0700633
Jens Låås80b71b82009-08-28 23:57:15 -0700634 max_work = MAX_WORK;
635 while (tn->bits > 1 && max_work-- &&
Robert Olsson19baf832005-06-21 12:43:18 -0700636 100 * (tnode_child_length(tn) - tn->empty_children) <
Robert Olssone6308be2005-10-04 13:01:58 -0700637 halve_threshold_use * tnode_child_length(tn)) {
Robert Olsson19baf832005-06-21 12:43:18 -0700638
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700639 old_tn = tn;
640 tn = halve(t, tn);
641 if (IS_ERR(tn)) {
642 tn = old_tn;
Robert Olsson2f368952005-07-05 15:02:40 -0700643#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -0800644 this_cpu_inc(t->stats->resize_node_skipped);
Robert Olsson2f368952005-07-05 15:02:40 -0700645#endif
646 break;
647 }
648 }
649
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700650
Robert Olsson19baf832005-06-21 12:43:18 -0700651 /* Only one child remains */
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800652 if (tn->empty_children == (tnode_child_length(tn) - 1)) {
653 unsigned long i;
Jens Låås80b71b82009-08-28 23:57:15 -0700654one_child:
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800655 for (i = tnode_child_length(tn); !n && i;)
656 n = tnode_get_child(tn, --i);
657no_children:
658 /* compress one level */
659 node_set_parent(n, NULL);
660 tnode_free_safe(tn);
661 return n;
Jens Låås80b71b82009-08-28 23:57:15 -0700662 }
David S. Millerb299e4f2011-02-02 20:48:10 -0800663 return (struct rt_trie_node *) tn;
Robert Olsson19baf832005-06-21 12:43:18 -0700664}
665
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700666
667static void tnode_clean_free(struct tnode *tn)
668{
669 int i;
670 struct tnode *tofree;
671
672 for (i = 0; i < tnode_child_length(tn); i++) {
673 tofree = (struct tnode *)rtnl_dereference(tn->child[i]);
674 if (tofree)
675 tnode_free(tofree);
676 }
677 tnode_free(tn);
678}
679
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700680static struct tnode *inflate(struct trie *t, struct tnode *tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700681{
Robert Olsson19baf832005-06-21 12:43:18 -0700682 struct tnode *oldtnode = tn;
683 int olen = tnode_child_length(tn);
684 int i;
685
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700686 pr_debug("In inflate\n");
Robert Olsson19baf832005-06-21 12:43:18 -0700687
688 tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits + 1);
689
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700690 if (!tn)
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700691 return ERR_PTR(-ENOMEM);
Robert Olsson2f368952005-07-05 15:02:40 -0700692
693 /*
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700694 * Preallocate and store tnodes before the actual work so we
695 * don't get into an inconsistent state if memory allocation
696 * fails. In case of failure we return the oldnode and inflate
Robert Olsson2f368952005-07-05 15:02:40 -0700697 * of tnode is ignored.
698 */
Olof Johansson91b9a272005-08-09 20:24:39 -0700699
700 for (i = 0; i < olen; i++) {
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800701 struct tnode *inode;
Robert Olsson2f368952005-07-05 15:02:40 -0700702
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800703 inode = (struct tnode *) tnode_get_child(oldtnode, i);
Robert Olsson2f368952005-07-05 15:02:40 -0700704 if (inode &&
705 IS_TNODE(inode) &&
706 inode->pos == oldtnode->pos + oldtnode->bits &&
707 inode->bits > 1) {
708 struct tnode *left, *right;
Stephen Hemmingerab66b4a2007-08-10 15:22:58 -0700709 t_key m = ~0U << (KEYLENGTH - 1) >> inode->pos;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700710
Robert Olsson2f368952005-07-05 15:02:40 -0700711 left = tnode_new(inode->key&(~m), inode->pos + 1,
712 inode->bits - 1);
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700713 if (!left)
714 goto nomem;
Olof Johansson91b9a272005-08-09 20:24:39 -0700715
Robert Olsson2f368952005-07-05 15:02:40 -0700716 right = tnode_new(inode->key|m, inode->pos + 1,
717 inode->bits - 1);
718
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900719 if (!right) {
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700720 tnode_free(left);
721 goto nomem;
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900722 }
Robert Olsson2f368952005-07-05 15:02:40 -0700723
Lin Ming61648d92012-07-29 02:00:03 +0000724 put_child(tn, 2*i, (struct rt_trie_node *) left);
725 put_child(tn, 2*i+1, (struct rt_trie_node *) right);
Robert Olsson2f368952005-07-05 15:02:40 -0700726 }
727 }
728
Olof Johansson91b9a272005-08-09 20:24:39 -0700729 for (i = 0; i < olen; i++) {
Stephen Hemmingerc95aaf92008-01-12 21:25:02 -0800730 struct tnode *inode;
David S. Millerb299e4f2011-02-02 20:48:10 -0800731 struct rt_trie_node *node = tnode_get_child(oldtnode, i);
Olof Johansson91b9a272005-08-09 20:24:39 -0700732 struct tnode *left, *right;
733 int size, j;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700734
Robert Olsson19baf832005-06-21 12:43:18 -0700735 /* An empty child */
736 if (node == NULL)
737 continue;
738
739 /* A leaf or an internal node with skipped bits */
740
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800741 if (IS_LEAF(node) || (node->pos > (tn->pos + tn->bits - 1))) {
baker.zhangbbe34cf2013-10-01 07:45:09 +0800742 put_child(tn,
743 tkey_extract_bits(node->key, oldtnode->pos, oldtnode->bits + 1),
744 node);
Robert Olsson19baf832005-06-21 12:43:18 -0700745 continue;
746 }
747
748 /* An internal node with two children */
749 inode = (struct tnode *) node;
750
751 if (inode->bits == 1) {
Lin Ming61648d92012-07-29 02:00:03 +0000752 put_child(tn, 2*i, rtnl_dereference(inode->child[0]));
753 put_child(tn, 2*i+1, rtnl_dereference(inode->child[1]));
Robert Olsson19baf832005-06-21 12:43:18 -0700754
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700755 tnode_free_safe(inode);
Olof Johansson91b9a272005-08-09 20:24:39 -0700756 continue;
Robert Olsson19baf832005-06-21 12:43:18 -0700757 }
758
Olof Johansson91b9a272005-08-09 20:24:39 -0700759 /* An internal node with more than two children */
Robert Olsson19baf832005-06-21 12:43:18 -0700760
Olof Johansson91b9a272005-08-09 20:24:39 -0700761 /* We will replace this node 'inode' with two new
762 * ones, 'left' and 'right', each with half of the
763 * original children. The two new nodes will have
764 * a position one bit further down the key and this
765 * means that the "significant" part of their keys
766 * (see the discussion near the top of this file)
767 * will differ by one bit, which will be "0" in
768 * left's key and "1" in right's key. Since we are
769 * moving the key position by one step, the bit that
770 * we are moving away from - the bit at position
771 * (inode->pos) - is the one that will differ between
772 * left and right. So... we synthesize that bit in the
773 * two new keys.
774 * The mask 'm' below will be a single "one" bit at
775 * the position (inode->pos)
776 */
Robert Olsson19baf832005-06-21 12:43:18 -0700777
Olof Johansson91b9a272005-08-09 20:24:39 -0700778 /* Use the old key, but set the new significant
779 * bit to zero.
780 */
Robert Olsson19baf832005-06-21 12:43:18 -0700781
Olof Johansson91b9a272005-08-09 20:24:39 -0700782 left = (struct tnode *) tnode_get_child(tn, 2*i);
Lin Ming61648d92012-07-29 02:00:03 +0000783 put_child(tn, 2*i, NULL);
Robert Olsson19baf832005-06-21 12:43:18 -0700784
Olof Johansson91b9a272005-08-09 20:24:39 -0700785 BUG_ON(!left);
Robert Olsson2f368952005-07-05 15:02:40 -0700786
Olof Johansson91b9a272005-08-09 20:24:39 -0700787 right = (struct tnode *) tnode_get_child(tn, 2*i+1);
Lin Ming61648d92012-07-29 02:00:03 +0000788 put_child(tn, 2*i+1, NULL);
Robert Olsson2f368952005-07-05 15:02:40 -0700789
Olof Johansson91b9a272005-08-09 20:24:39 -0700790 BUG_ON(!right);
Robert Olsson2f368952005-07-05 15:02:40 -0700791
Olof Johansson91b9a272005-08-09 20:24:39 -0700792 size = tnode_child_length(left);
793 for (j = 0; j < size; j++) {
Lin Ming61648d92012-07-29 02:00:03 +0000794 put_child(left, j, rtnl_dereference(inode->child[j]));
795 put_child(right, j, rtnl_dereference(inode->child[j + size]));
Robert Olsson19baf832005-06-21 12:43:18 -0700796 }
Lin Ming61648d92012-07-29 02:00:03 +0000797 put_child(tn, 2*i, resize(t, left));
798 put_child(tn, 2*i+1, resize(t, right));
Olof Johansson91b9a272005-08-09 20:24:39 -0700799
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700800 tnode_free_safe(inode);
Robert Olsson19baf832005-06-21 12:43:18 -0700801 }
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700802 tnode_free_safe(oldtnode);
Robert Olsson19baf832005-06-21 12:43:18 -0700803 return tn;
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700804nomem:
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700805 tnode_clean_free(tn);
806 return ERR_PTR(-ENOMEM);
Robert Olsson19baf832005-06-21 12:43:18 -0700807}
808
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700809static struct tnode *halve(struct trie *t, struct tnode *tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700810{
811 struct tnode *oldtnode = tn;
David S. Millerb299e4f2011-02-02 20:48:10 -0800812 struct rt_trie_node *left, *right;
Robert Olsson19baf832005-06-21 12:43:18 -0700813 int i;
814 int olen = tnode_child_length(tn);
815
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700816 pr_debug("In halve\n");
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700817
818 tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits - 1);
Robert Olsson19baf832005-06-21 12:43:18 -0700819
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700820 if (!tn)
821 return ERR_PTR(-ENOMEM);
Robert Olsson2f368952005-07-05 15:02:40 -0700822
823 /*
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700824 * Preallocate and store tnodes before the actual work so we
825 * don't get into an inconsistent state if memory allocation
826 * fails. In case of failure we return the oldnode and halve
Robert Olsson2f368952005-07-05 15:02:40 -0700827 * of tnode is ignored.
828 */
829
Olof Johansson91b9a272005-08-09 20:24:39 -0700830 for (i = 0; i < olen; i += 2) {
Robert Olsson2f368952005-07-05 15:02:40 -0700831 left = tnode_get_child(oldtnode, i);
832 right = tnode_get_child(oldtnode, i+1);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700833
Robert Olsson2f368952005-07-05 15:02:40 -0700834 /* Two nonempty children */
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700835 if (left && right) {
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700836 struct tnode *newn;
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700837
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700838 newn = tnode_new(left->key, tn->pos + tn->bits, 1);
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700839
840 if (!newn)
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700841 goto nomem;
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700842
Lin Ming61648d92012-07-29 02:00:03 +0000843 put_child(tn, i/2, (struct rt_trie_node *)newn);
Robert Olsson2f368952005-07-05 15:02:40 -0700844 }
Robert Olsson2f368952005-07-05 15:02:40 -0700845
Robert Olsson2f368952005-07-05 15:02:40 -0700846 }
Robert Olsson19baf832005-06-21 12:43:18 -0700847
Olof Johansson91b9a272005-08-09 20:24:39 -0700848 for (i = 0; i < olen; i += 2) {
849 struct tnode *newBinNode;
850
Robert Olsson19baf832005-06-21 12:43:18 -0700851 left = tnode_get_child(oldtnode, i);
852 right = tnode_get_child(oldtnode, i+1);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700853
Robert Olsson19baf832005-06-21 12:43:18 -0700854 /* At least one of the children is empty */
855 if (left == NULL) {
856 if (right == NULL) /* Both are empty */
857 continue;
Lin Ming61648d92012-07-29 02:00:03 +0000858 put_child(tn, i/2, right);
Olof Johansson91b9a272005-08-09 20:24:39 -0700859 continue;
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700860 }
Olof Johansson91b9a272005-08-09 20:24:39 -0700861
862 if (right == NULL) {
Lin Ming61648d92012-07-29 02:00:03 +0000863 put_child(tn, i/2, left);
Olof Johansson91b9a272005-08-09 20:24:39 -0700864 continue;
865 }
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700866
Robert Olsson19baf832005-06-21 12:43:18 -0700867 /* Two nonempty children */
Olof Johansson91b9a272005-08-09 20:24:39 -0700868 newBinNode = (struct tnode *) tnode_get_child(tn, i/2);
Lin Ming61648d92012-07-29 02:00:03 +0000869 put_child(tn, i/2, NULL);
870 put_child(newBinNode, 0, left);
871 put_child(newBinNode, 1, right);
872 put_child(tn, i/2, resize(t, newBinNode));
Robert Olsson19baf832005-06-21 12:43:18 -0700873 }
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700874 tnode_free_safe(oldtnode);
Robert Olsson19baf832005-06-21 12:43:18 -0700875 return tn;
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700876nomem:
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700877 tnode_clean_free(tn);
878 return ERR_PTR(-ENOMEM);
Robert Olsson19baf832005-06-21 12:43:18 -0700879}
880
Robert Olsson772cb712005-09-19 15:31:18 -0700881/* readside must use rcu_read_lock currently dump routines
Robert Olsson2373ce12005-08-25 13:01:29 -0700882 via get_fa_head and dump */
883
Robert Olsson772cb712005-09-19 15:31:18 -0700884static struct leaf_info *find_leaf_info(struct leaf *l, int plen)
Robert Olsson19baf832005-06-21 12:43:18 -0700885{
Robert Olsson772cb712005-09-19 15:31:18 -0700886 struct hlist_head *head = &l->list;
Robert Olsson19baf832005-06-21 12:43:18 -0700887 struct leaf_info *li;
888
Sasha Levinb67bfe02013-02-27 17:06:00 -0800889 hlist_for_each_entry_rcu(li, head, hlist)
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700890 if (li->plen == plen)
Robert Olsson19baf832005-06-21 12:43:18 -0700891 return li;
Olof Johansson91b9a272005-08-09 20:24:39 -0700892
Robert Olsson19baf832005-06-21 12:43:18 -0700893 return NULL;
894}
895
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800896static inline struct list_head *get_fa_head(struct leaf *l, int plen)
Robert Olsson19baf832005-06-21 12:43:18 -0700897{
Robert Olsson772cb712005-09-19 15:31:18 -0700898 struct leaf_info *li = find_leaf_info(l, plen);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700899
Olof Johansson91b9a272005-08-09 20:24:39 -0700900 if (!li)
901 return NULL;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700902
Olof Johansson91b9a272005-08-09 20:24:39 -0700903 return &li->falh;
Robert Olsson19baf832005-06-21 12:43:18 -0700904}
905
906static void insert_leaf_info(struct hlist_head *head, struct leaf_info *new)
907{
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900908 struct leaf_info *li = NULL, *last = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -0700909
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900910 if (hlist_empty(head)) {
911 hlist_add_head_rcu(&new->hlist, head);
912 } else {
Sasha Levinb67bfe02013-02-27 17:06:00 -0800913 hlist_for_each_entry(li, head, hlist) {
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900914 if (new->plen > li->plen)
915 break;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700916
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900917 last = li;
918 }
919 if (last)
Ken Helias1d023282014-08-06 16:09:16 -0700920 hlist_add_behind_rcu(&new->hlist, &last->hlist);
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900921 else
922 hlist_add_before_rcu(&new->hlist, &li->hlist);
923 }
Robert Olsson19baf832005-06-21 12:43:18 -0700924}
925
Robert Olsson2373ce12005-08-25 13:01:29 -0700926/* rcu_read_lock needs to be hold by caller from readside */
927
Robert Olsson19baf832005-06-21 12:43:18 -0700928static struct leaf *
929fib_find_node(struct trie *t, u32 key)
930{
931 int pos;
932 struct tnode *tn;
David S. Millerb299e4f2011-02-02 20:48:10 -0800933 struct rt_trie_node *n;
Robert Olsson19baf832005-06-21 12:43:18 -0700934
935 pos = 0;
Eric Dumazeta034ee32010-09-09 23:32:28 +0000936 n = rcu_dereference_rtnl(t->trie);
Robert Olsson19baf832005-06-21 12:43:18 -0700937
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800938 while (n && IS_TNODE(n)) {
Robert Olsson19baf832005-06-21 12:43:18 -0700939 tn = (struct tnode *) n;
Olof Johansson91b9a272005-08-09 20:24:39 -0700940
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700941 if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
Olof Johansson91b9a272005-08-09 20:24:39 -0700942 pos = tn->pos + tn->bits;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800943 n = tnode_get_child_rcu(tn,
944 tkey_extract_bits(key,
945 tn->pos,
946 tn->bits));
Olof Johansson91b9a272005-08-09 20:24:39 -0700947 } else
Robert Olsson19baf832005-06-21 12:43:18 -0700948 break;
949 }
950 /* Case we have found a leaf. Compare prefixes */
951
Olof Johansson91b9a272005-08-09 20:24:39 -0700952 if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key))
953 return (struct leaf *)n;
954
Robert Olsson19baf832005-06-21 12:43:18 -0700955 return NULL;
956}
957
Jarek Poplawski7b855762009-06-18 00:28:51 -0700958static void trie_rebalance(struct trie *t, struct tnode *tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700959{
Robert Olsson19baf832005-06-21 12:43:18 -0700960 int wasfull;
Robert Olsson3ed18d72009-05-21 15:20:59 -0700961 t_key cindex, key;
Stephen Hemminger06801912007-08-10 15:22:13 -0700962 struct tnode *tp;
Robert Olsson19baf832005-06-21 12:43:18 -0700963
Robert Olsson3ed18d72009-05-21 15:20:59 -0700964 key = tn->key;
965
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800966 while (tn != NULL && (tp = node_parent(tn)) != NULL) {
Robert Olsson19baf832005-06-21 12:43:18 -0700967 cindex = tkey_extract_bits(key, tp->pos, tp->bits);
968 wasfull = tnode_full(tp, tnode_get_child(tp, cindex));
Joe Perchese3192692012-06-03 17:41:40 +0000969 tn = (struct tnode *)resize(t, tn);
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800970
Joe Perchese3192692012-06-03 17:41:40 +0000971 tnode_put_child_reorg(tp, cindex,
David S. Millerb299e4f2011-02-02 20:48:10 -0800972 (struct rt_trie_node *)tn, wasfull);
Olof Johansson91b9a272005-08-09 20:24:39 -0700973
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800974 tp = node_parent(tn);
Jarek Poplawski008440e2009-06-30 12:47:19 -0700975 if (!tp)
Eric Dumazetcf778b02012-01-12 04:41:32 +0000976 rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
Jarek Poplawski008440e2009-06-30 12:47:19 -0700977
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700978 tnode_free_flush();
Stephen Hemminger06801912007-08-10 15:22:13 -0700979 if (!tp)
Robert Olsson19baf832005-06-21 12:43:18 -0700980 break;
Stephen Hemminger06801912007-08-10 15:22:13 -0700981 tn = tp;
Robert Olsson19baf832005-06-21 12:43:18 -0700982 }
Stephen Hemminger06801912007-08-10 15:22:13 -0700983
Robert Olsson19baf832005-06-21 12:43:18 -0700984 /* Handle last (top) tnode */
Jarek Poplawski7b855762009-06-18 00:28:51 -0700985 if (IS_TNODE(tn))
Joe Perchese3192692012-06-03 17:41:40 +0000986 tn = (struct tnode *)resize(t, tn);
Robert Olsson19baf832005-06-21 12:43:18 -0700987
Eric Dumazetcf778b02012-01-12 04:41:32 +0000988 rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
Jarek Poplawski7b855762009-06-18 00:28:51 -0700989 tnode_free_flush();
Robert Olsson19baf832005-06-21 12:43:18 -0700990}
991
Robert Olsson2373ce12005-08-25 13:01:29 -0700992/* only used from updater-side */
993
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -0800994static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
Robert Olsson19baf832005-06-21 12:43:18 -0700995{
996 int pos, newpos;
997 struct tnode *tp = NULL, *tn = NULL;
David S. Millerb299e4f2011-02-02 20:48:10 -0800998 struct rt_trie_node *n;
Robert Olsson19baf832005-06-21 12:43:18 -0700999 struct leaf *l;
1000 int missbit;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001001 struct list_head *fa_head = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001002 struct leaf_info *li;
1003 t_key cindex;
1004
1005 pos = 0;
Eric Dumazet0a5c0472011-03-31 01:51:35 -07001006 n = rtnl_dereference(t->trie);
Robert Olsson19baf832005-06-21 12:43:18 -07001007
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001008 /* If we point to NULL, stop. Either the tree is empty and we should
1009 * just put a new leaf in if, or we have reached an empty child slot,
Robert Olsson19baf832005-06-21 12:43:18 -07001010 * and we should just put our new leaf in that.
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001011 * If we point to a T_TNODE, check if it matches our key. Note that
1012 * a T_TNODE might be skipping any number of bits - its 'pos' need
Robert Olsson19baf832005-06-21 12:43:18 -07001013 * not be the parent's 'pos'+'bits'!
1014 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001015 * If it does match the current key, get pos/bits from it, extract
Robert Olsson19baf832005-06-21 12:43:18 -07001016 * the index from our key, push the T_TNODE and walk the tree.
1017 *
1018 * If it doesn't, we have to replace it with a new T_TNODE.
1019 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001020 * If we point to a T_LEAF, it might or might not have the same key
1021 * as we do. If it does, just change the value, update the T_LEAF's
1022 * value, and return it.
Robert Olsson19baf832005-06-21 12:43:18 -07001023 * If it doesn't, we need to replace it with a T_TNODE.
1024 */
1025
Alexander Duyck64c9b6f2014-12-31 10:55:35 -08001026 while (n && IS_TNODE(n)) {
Robert Olsson19baf832005-06-21 12:43:18 -07001027 tn = (struct tnode *) n;
Olof Johansson91b9a272005-08-09 20:24:39 -07001028
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001029 if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
Robert Olsson19baf832005-06-21 12:43:18 -07001030 tp = tn;
Olof Johansson91b9a272005-08-09 20:24:39 -07001031 pos = tn->pos + tn->bits;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001032 n = tnode_get_child(tn,
1033 tkey_extract_bits(key,
1034 tn->pos,
1035 tn->bits));
Robert Olsson19baf832005-06-21 12:43:18 -07001036
Stephen Hemminger06801912007-08-10 15:22:13 -07001037 BUG_ON(n && node_parent(n) != tn);
Olof Johansson91b9a272005-08-09 20:24:39 -07001038 } else
Robert Olsson19baf832005-06-21 12:43:18 -07001039 break;
1040 }
1041
1042 /*
1043 * n ----> NULL, LEAF or TNODE
1044 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001045 * tp is n's (parent) ----> NULL or TNODE
Robert Olsson19baf832005-06-21 12:43:18 -07001046 */
1047
Olof Johansson91b9a272005-08-09 20:24:39 -07001048 BUG_ON(tp && IS_LEAF(tp));
Robert Olsson19baf832005-06-21 12:43:18 -07001049
1050 /* Case 1: n is a leaf. Compare prefixes */
1051
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001052 if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) {
Stephen Hemmingerc95aaf92008-01-12 21:25:02 -08001053 l = (struct leaf *) n;
Robert Olsson19baf832005-06-21 12:43:18 -07001054 li = leaf_info_new(plen);
Olof Johansson91b9a272005-08-09 20:24:39 -07001055
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001056 if (!li)
1057 return NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001058
1059 fa_head = &li->falh;
1060 insert_leaf_info(&l->list, li);
1061 goto done;
1062 }
Alexander Duyck64c9b6f2014-12-31 10:55:35 -08001063 l = leaf_new(key);
Robert Olsson19baf832005-06-21 12:43:18 -07001064
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001065 if (!l)
1066 return NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001067
Robert Olsson19baf832005-06-21 12:43:18 -07001068 li = leaf_info_new(plen);
1069
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001070 if (!li) {
Stephen Hemminger387a5482008-04-10 03:47:34 -07001071 free_leaf(l);
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001072 return NULL;
Robert Olssonf835e472005-06-28 15:00:39 -07001073 }
Robert Olsson19baf832005-06-21 12:43:18 -07001074
1075 fa_head = &li->falh;
1076 insert_leaf_info(&l->list, li);
1077
Robert Olsson19baf832005-06-21 12:43:18 -07001078 if (t->trie && n == NULL) {
Olof Johansson91b9a272005-08-09 20:24:39 -07001079 /* Case 2: n is NULL, and will just insert a new leaf */
Robert Olsson19baf832005-06-21 12:43:18 -07001080
David S. Millerb299e4f2011-02-02 20:48:10 -08001081 node_set_parent((struct rt_trie_node *)l, tp);
Robert Olsson19baf832005-06-21 12:43:18 -07001082
Olof Johansson91b9a272005-08-09 20:24:39 -07001083 cindex = tkey_extract_bits(key, tp->pos, tp->bits);
Lin Ming61648d92012-07-29 02:00:03 +00001084 put_child(tp, cindex, (struct rt_trie_node *)l);
Olof Johansson91b9a272005-08-09 20:24:39 -07001085 } else {
1086 /* Case 3: n is a LEAF or a TNODE and the key doesn't match. */
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001087 /*
1088 * Add a new tnode here
Robert Olsson19baf832005-06-21 12:43:18 -07001089 * first tnode need some special handling
1090 */
1091
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001092 if (n) {
baker.zhang4c60f1d2013-10-08 11:36:51 +08001093 pos = tp ? tp->pos+tp->bits : 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001094 newpos = tkey_mismatch(key, pos, n->key);
1095 tn = tnode_new(n->key, newpos, 1);
Olof Johansson91b9a272005-08-09 20:24:39 -07001096 } else {
Robert Olsson19baf832005-06-21 12:43:18 -07001097 newpos = 0;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001098 tn = tnode_new(key, newpos, 1); /* First tnode */
Robert Olsson19baf832005-06-21 12:43:18 -07001099 }
Robert Olsson19baf832005-06-21 12:43:18 -07001100
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001101 if (!tn) {
Robert Olssonf835e472005-06-28 15:00:39 -07001102 free_leaf_info(li);
Stephen Hemminger387a5482008-04-10 03:47:34 -07001103 free_leaf(l);
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001104 return NULL;
Olof Johansson91b9a272005-08-09 20:24:39 -07001105 }
1106
David S. Millerb299e4f2011-02-02 20:48:10 -08001107 node_set_parent((struct rt_trie_node *)tn, tp);
Robert Olsson19baf832005-06-21 12:43:18 -07001108
Olof Johansson91b9a272005-08-09 20:24:39 -07001109 missbit = tkey_extract_bits(key, newpos, 1);
Lin Ming61648d92012-07-29 02:00:03 +00001110 put_child(tn, missbit, (struct rt_trie_node *)l);
1111 put_child(tn, 1-missbit, n);
Robert Olsson19baf832005-06-21 12:43:18 -07001112
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001113 if (tp) {
Robert Olsson19baf832005-06-21 12:43:18 -07001114 cindex = tkey_extract_bits(key, tp->pos, tp->bits);
Lin Ming61648d92012-07-29 02:00:03 +00001115 put_child(tp, cindex, (struct rt_trie_node *)tn);
Olof Johansson91b9a272005-08-09 20:24:39 -07001116 } else {
Eric Dumazetcf778b02012-01-12 04:41:32 +00001117 rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
Robert Olsson19baf832005-06-21 12:43:18 -07001118 }
Alexander Duycke962f302014-12-10 21:49:22 -08001119
1120 tp = tn;
Robert Olsson19baf832005-06-21 12:43:18 -07001121 }
Olof Johansson91b9a272005-08-09 20:24:39 -07001122
1123 if (tp && tp->pos + tp->bits > 32)
Joe Perches058bd4d2012-03-11 18:36:11 +00001124 pr_warn("fib_trie tp=%p pos=%d, bits=%d, key=%0x plen=%d\n",
1125 tp, tp->pos, tp->bits, key, plen);
Olof Johansson91b9a272005-08-09 20:24:39 -07001126
Robert Olsson19baf832005-06-21 12:43:18 -07001127 /* Rebalance the trie */
Robert Olsson2373ce12005-08-25 13:01:29 -07001128
Jarek Poplawski7b855762009-06-18 00:28:51 -07001129 trie_rebalance(t, tp);
Robert Olssonf835e472005-06-28 15:00:39 -07001130done:
Robert Olsson19baf832005-06-21 12:43:18 -07001131 return fa_head;
1132}
1133
Robert Olssond562f1f2007-03-26 14:22:22 -07001134/*
1135 * Caller must hold RTNL.
1136 */
Stephen Hemminger16c6cf82009-09-20 10:35:36 +00001137int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
Robert Olsson19baf832005-06-21 12:43:18 -07001138{
1139 struct trie *t = (struct trie *) tb->tb_data;
1140 struct fib_alias *fa, *new_fa;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001141 struct list_head *fa_head = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001142 struct fib_info *fi;
Thomas Graf4e902c52006-08-17 18:14:52 -07001143 int plen = cfg->fc_dst_len;
1144 u8 tos = cfg->fc_tos;
Robert Olsson19baf832005-06-21 12:43:18 -07001145 u32 key, mask;
1146 int err;
1147 struct leaf *l;
1148
1149 if (plen > 32)
1150 return -EINVAL;
1151
Thomas Graf4e902c52006-08-17 18:14:52 -07001152 key = ntohl(cfg->fc_dst);
Robert Olsson19baf832005-06-21 12:43:18 -07001153
Patrick McHardy2dfe55b2006-08-10 23:08:33 -07001154 pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen);
Robert Olsson19baf832005-06-21 12:43:18 -07001155
Olof Johansson91b9a272005-08-09 20:24:39 -07001156 mask = ntohl(inet_make_mask(plen));
Robert Olsson19baf832005-06-21 12:43:18 -07001157
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001158 if (key & ~mask)
Robert Olsson19baf832005-06-21 12:43:18 -07001159 return -EINVAL;
1160
1161 key = key & mask;
1162
Thomas Graf4e902c52006-08-17 18:14:52 -07001163 fi = fib_create_info(cfg);
1164 if (IS_ERR(fi)) {
1165 err = PTR_ERR(fi);
Robert Olsson19baf832005-06-21 12:43:18 -07001166 goto err;
Thomas Graf4e902c52006-08-17 18:14:52 -07001167 }
Robert Olsson19baf832005-06-21 12:43:18 -07001168
1169 l = fib_find_node(t, key);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001170 fa = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001171
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001172 if (l) {
Robert Olsson19baf832005-06-21 12:43:18 -07001173 fa_head = get_fa_head(l, plen);
1174 fa = fib_find_alias(fa_head, tos, fi->fib_priority);
1175 }
1176
1177 /* Now fa, if non-NULL, points to the first fib alias
1178 * with the same keys [prefix,tos,priority], if such key already
1179 * exists or to the node before which we will insert new one.
1180 *
1181 * If fa is NULL, we will need to allocate a new one and
1182 * insert to the head of f.
1183 *
1184 * If f is NULL, no fib node matched the destination key
1185 * and we need to allocate a new one of those as well.
1186 */
1187
Julian Anastasov936f6f82008-01-28 21:18:06 -08001188 if (fa && fa->fa_tos == tos &&
1189 fa->fa_info->fib_priority == fi->fib_priority) {
1190 struct fib_alias *fa_first, *fa_match;
Robert Olsson19baf832005-06-21 12:43:18 -07001191
1192 err = -EEXIST;
Thomas Graf4e902c52006-08-17 18:14:52 -07001193 if (cfg->fc_nlflags & NLM_F_EXCL)
Robert Olsson19baf832005-06-21 12:43:18 -07001194 goto out;
1195
Julian Anastasov936f6f82008-01-28 21:18:06 -08001196 /* We have 2 goals:
1197 * 1. Find exact match for type, scope, fib_info to avoid
1198 * duplicate routes
1199 * 2. Find next 'fa' (or head), NLM_F_APPEND inserts before it
1200 */
1201 fa_match = NULL;
1202 fa_first = fa;
1203 fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
1204 list_for_each_entry_continue(fa, fa_head, fa_list) {
1205 if (fa->fa_tos != tos)
1206 break;
1207 if (fa->fa_info->fib_priority != fi->fib_priority)
1208 break;
1209 if (fa->fa_type == cfg->fc_type &&
Julian Anastasov936f6f82008-01-28 21:18:06 -08001210 fa->fa_info == fi) {
1211 fa_match = fa;
1212 break;
1213 }
1214 }
1215
Thomas Graf4e902c52006-08-17 18:14:52 -07001216 if (cfg->fc_nlflags & NLM_F_REPLACE) {
Robert Olsson19baf832005-06-21 12:43:18 -07001217 struct fib_info *fi_drop;
1218 u8 state;
1219
Julian Anastasov936f6f82008-01-28 21:18:06 -08001220 fa = fa_first;
1221 if (fa_match) {
1222 if (fa == fa_match)
1223 err = 0;
Joonwoo Park67250332008-01-18 03:45:18 -08001224 goto out;
Julian Anastasov936f6f82008-01-28 21:18:06 -08001225 }
Robert Olsson2373ce12005-08-25 13:01:29 -07001226 err = -ENOBUFS;
Christoph Lametere94b1762006-12-06 20:33:17 -08001227 new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
Robert Olsson2373ce12005-08-25 13:01:29 -07001228 if (new_fa == NULL)
1229 goto out;
Robert Olsson19baf832005-06-21 12:43:18 -07001230
1231 fi_drop = fa->fa_info;
Robert Olsson2373ce12005-08-25 13:01:29 -07001232 new_fa->fa_tos = fa->fa_tos;
1233 new_fa->fa_info = fi;
Thomas Graf4e902c52006-08-17 18:14:52 -07001234 new_fa->fa_type = cfg->fc_type;
Robert Olsson19baf832005-06-21 12:43:18 -07001235 state = fa->fa_state;
Julian Anastasov936f6f82008-01-28 21:18:06 -08001236 new_fa->fa_state = state & ~FA_S_ACCESSED;
Robert Olsson19baf832005-06-21 12:43:18 -07001237
Robert Olsson2373ce12005-08-25 13:01:29 -07001238 list_replace_rcu(&fa->fa_list, &new_fa->fa_list);
1239 alias_free_mem_rcu(fa);
Robert Olsson19baf832005-06-21 12:43:18 -07001240
1241 fib_release_info(fi_drop);
1242 if (state & FA_S_ACCESSED)
Nicolas Dichtel4ccfe6d2012-09-07 00:45:29 +00001243 rt_cache_flush(cfg->fc_nlinfo.nl_net);
Milan Kocianb8f55832007-05-23 14:55:06 -07001244 rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
1245 tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
Robert Olsson19baf832005-06-21 12:43:18 -07001246
Olof Johansson91b9a272005-08-09 20:24:39 -07001247 goto succeeded;
Robert Olsson19baf832005-06-21 12:43:18 -07001248 }
1249 /* Error if we find a perfect match which
1250 * uses the same scope, type, and nexthop
1251 * information.
1252 */
Julian Anastasov936f6f82008-01-28 21:18:06 -08001253 if (fa_match)
1254 goto out;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001255
Thomas Graf4e902c52006-08-17 18:14:52 -07001256 if (!(cfg->fc_nlflags & NLM_F_APPEND))
Julian Anastasov936f6f82008-01-28 21:18:06 -08001257 fa = fa_first;
Robert Olsson19baf832005-06-21 12:43:18 -07001258 }
1259 err = -ENOENT;
Thomas Graf4e902c52006-08-17 18:14:52 -07001260 if (!(cfg->fc_nlflags & NLM_F_CREATE))
Robert Olsson19baf832005-06-21 12:43:18 -07001261 goto out;
1262
1263 err = -ENOBUFS;
Christoph Lametere94b1762006-12-06 20:33:17 -08001264 new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
Robert Olsson19baf832005-06-21 12:43:18 -07001265 if (new_fa == NULL)
1266 goto out;
1267
1268 new_fa->fa_info = fi;
1269 new_fa->fa_tos = tos;
Thomas Graf4e902c52006-08-17 18:14:52 -07001270 new_fa->fa_type = cfg->fc_type;
Robert Olsson19baf832005-06-21 12:43:18 -07001271 new_fa->fa_state = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001272 /*
1273 * Insert new entry to the list.
1274 */
1275
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001276 if (!fa_head) {
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001277 fa_head = fib_insert_node(t, key, plen);
1278 if (unlikely(!fa_head)) {
1279 err = -ENOMEM;
Robert Olssonf835e472005-06-28 15:00:39 -07001280 goto out_free_new_fa;
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001281 }
Robert Olssonf835e472005-06-28 15:00:39 -07001282 }
Robert Olsson19baf832005-06-21 12:43:18 -07001283
David S. Miller21d8c492011-04-14 14:49:37 -07001284 if (!plen)
1285 tb->tb_num_default++;
1286
Robert Olsson2373ce12005-08-25 13:01:29 -07001287 list_add_tail_rcu(&new_fa->fa_list,
1288 (fa ? &fa->fa_list : fa_head));
Robert Olsson19baf832005-06-21 12:43:18 -07001289
Nicolas Dichtel4ccfe6d2012-09-07 00:45:29 +00001290 rt_cache_flush(cfg->fc_nlinfo.nl_net);
Thomas Graf4e902c52006-08-17 18:14:52 -07001291 rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id,
Milan Kocianb8f55832007-05-23 14:55:06 -07001292 &cfg->fc_nlinfo, 0);
Robert Olsson19baf832005-06-21 12:43:18 -07001293succeeded:
1294 return 0;
Robert Olssonf835e472005-06-28 15:00:39 -07001295
1296out_free_new_fa:
1297 kmem_cache_free(fn_alias_kmem, new_fa);
Robert Olsson19baf832005-06-21 12:43:18 -07001298out:
1299 fib_release_info(fi);
Olof Johansson91b9a272005-08-09 20:24:39 -07001300err:
Robert Olsson19baf832005-06-21 12:43:18 -07001301 return err;
1302}
1303
Robert Olsson772cb712005-09-19 15:31:18 -07001304/* should be called with rcu_read_lock */
David S. Miller5b470442011-01-31 16:10:03 -08001305static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
David S. Miller22bd5b92011-03-11 19:54:08 -05001306 t_key key, const struct flowi4 *flp,
Eric Dumazetebc0ffa2010-10-05 10:41:36 +00001307 struct fib_result *res, int fib_flags)
Robert Olsson19baf832005-06-21 12:43:18 -07001308{
Robert Olsson19baf832005-06-21 12:43:18 -07001309 struct leaf_info *li;
1310 struct hlist_head *hhead = &l->list;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001311
Sasha Levinb67bfe02013-02-27 17:06:00 -08001312 hlist_for_each_entry_rcu(li, hhead, hlist) {
David S. Miller3be06862011-03-07 15:01:10 -08001313 struct fib_alias *fa;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001314
Eric Dumazet5c745012011-07-18 03:16:33 +00001315 if (l->key != (key & li->mask_plen))
Robert Olsson19baf832005-06-21 12:43:18 -07001316 continue;
1317
David S. Miller3be06862011-03-07 15:01:10 -08001318 list_for_each_entry_rcu(fa, &li->falh, fa_list) {
1319 struct fib_info *fi = fa->fa_info;
1320 int nhsel, err;
1321
David S. Miller22bd5b92011-03-11 19:54:08 -05001322 if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
David S. Miller3be06862011-03-07 15:01:10 -08001323 continue;
David S. Millerdccd9ecc2012-05-10 22:16:32 -04001324 if (fi->fib_dead)
1325 continue;
David S. Miller37e826c2011-03-24 18:06:47 -07001326 if (fa->fa_info->fib_scope < flp->flowi4_scope)
David S. Miller3be06862011-03-07 15:01:10 -08001327 continue;
1328 fib_alias_accessed(fa);
1329 err = fib_props[fa->fa_type].error;
1330 if (err) {
1331#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08001332 this_cpu_inc(t->stats->semantic_match_passed);
David S. Miller3be06862011-03-07 15:01:10 -08001333#endif
Julian Anastasov1fbc7842011-03-25 20:33:23 -07001334 return err;
David S. Miller3be06862011-03-07 15:01:10 -08001335 }
1336 if (fi->fib_flags & RTNH_F_DEAD)
1337 continue;
1338 for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
1339 const struct fib_nh *nh = &fi->fib_nh[nhsel];
1340
1341 if (nh->nh_flags & RTNH_F_DEAD)
1342 continue;
David S. Miller22bd5b92011-03-11 19:54:08 -05001343 if (flp->flowi4_oif && flp->flowi4_oif != nh->nh_oif)
David S. Miller3be06862011-03-07 15:01:10 -08001344 continue;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001345
Robert Olsson19baf832005-06-21 12:43:18 -07001346#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08001347 this_cpu_inc(t->stats->semantic_match_passed);
Robert Olsson19baf832005-06-21 12:43:18 -07001348#endif
Eric Dumazet5c745012011-07-18 03:16:33 +00001349 res->prefixlen = li->plen;
David S. Miller3be06862011-03-07 15:01:10 -08001350 res->nh_sel = nhsel;
1351 res->type = fa->fa_type;
David S. Miller37e826c2011-03-24 18:06:47 -07001352 res->scope = fa->fa_info->fib_scope;
David S. Miller3be06862011-03-07 15:01:10 -08001353 res->fi = fi;
1354 res->table = tb;
1355 res->fa_head = &li->falh;
1356 if (!(fib_flags & FIB_LOOKUP_NOREF))
Eric Dumazet5c745012011-07-18 03:16:33 +00001357 atomic_inc(&fi->fib_clntref);
David S. Miller3be06862011-03-07 15:01:10 -08001358 return 0;
1359 }
1360 }
1361
1362#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08001363 this_cpu_inc(t->stats->semantic_match_miss);
David S. Miller3be06862011-03-07 15:01:10 -08001364#endif
Robert Olsson19baf832005-06-21 12:43:18 -07001365 }
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001366
Ben Hutchings2e655572008-07-10 16:52:52 -07001367 return 1;
Robert Olsson19baf832005-06-21 12:43:18 -07001368}
1369
David S. Miller22bd5b92011-03-11 19:54:08 -05001370int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
Eric Dumazetebc0ffa2010-10-05 10:41:36 +00001371 struct fib_result *res, int fib_flags)
Robert Olsson19baf832005-06-21 12:43:18 -07001372{
1373 struct trie *t = (struct trie *) tb->tb_data;
Alexander Duyck8274a972014-12-31 10:55:29 -08001374#ifdef CONFIG_IP_FIB_TRIE_STATS
1375 struct trie_use_stats __percpu *stats = t->stats;
1376#endif
Ben Hutchings2e655572008-07-10 16:52:52 -07001377 int ret;
David S. Millerb299e4f2011-02-02 20:48:10 -08001378 struct rt_trie_node *n;
Robert Olsson19baf832005-06-21 12:43:18 -07001379 struct tnode *pn;
David S. Miller3b004562011-02-16 14:56:22 -08001380 unsigned int pos, bits;
David S. Miller22bd5b92011-03-11 19:54:08 -05001381 t_key key = ntohl(flp->daddr);
David S. Miller3b004562011-02-16 14:56:22 -08001382 unsigned int chopped_off;
Robert Olsson19baf832005-06-21 12:43:18 -07001383 t_key cindex = 0;
David S. Miller3b004562011-02-16 14:56:22 -08001384 unsigned int current_prefix_length = KEYLENGTH;
Olof Johansson91b9a272005-08-09 20:24:39 -07001385 struct tnode *cn;
Eric Dumazet874ffa82010-10-13 06:56:11 +00001386 t_key pref_mismatch;
Olof Johansson91b9a272005-08-09 20:24:39 -07001387
Robert Olsson2373ce12005-08-25 13:01:29 -07001388 rcu_read_lock();
Robert Olsson19baf832005-06-21 12:43:18 -07001389
Robert Olsson2373ce12005-08-25 13:01:29 -07001390 n = rcu_dereference(t->trie);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001391 if (!n)
Robert Olsson19baf832005-06-21 12:43:18 -07001392 goto failed;
1393
1394#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08001395 this_cpu_inc(stats->gets);
Robert Olsson19baf832005-06-21 12:43:18 -07001396#endif
1397
1398 /* Just a leaf? */
1399 if (IS_LEAF(n)) {
David S. Miller5b470442011-01-31 16:10:03 -08001400 ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags);
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001401 goto found;
Robert Olsson19baf832005-06-21 12:43:18 -07001402 }
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001403
Robert Olsson19baf832005-06-21 12:43:18 -07001404 pn = (struct tnode *) n;
1405 chopped_off = 0;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001406
Olof Johansson91b9a272005-08-09 20:24:39 -07001407 while (pn) {
Robert Olsson19baf832005-06-21 12:43:18 -07001408 pos = pn->pos;
1409 bits = pn->bits;
1410
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001411 if (!chopped_off)
Stephen Hemmingerab66b4a2007-08-10 15:22:58 -07001412 cindex = tkey_extract_bits(mask_pfx(key, current_prefix_length),
1413 pos, bits);
Robert Olsson19baf832005-06-21 12:43:18 -07001414
Jarek Poplawskib902e572009-07-14 11:20:32 +00001415 n = tnode_get_child_rcu(pn, cindex);
Robert Olsson19baf832005-06-21 12:43:18 -07001416
1417 if (n == NULL) {
1418#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08001419 this_cpu_inc(stats->null_node_hit);
Robert Olsson19baf832005-06-21 12:43:18 -07001420#endif
1421 goto backtrace;
1422 }
1423
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001424 if (IS_LEAF(n)) {
David S. Miller5b470442011-01-31 16:10:03 -08001425 ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags);
Ben Hutchings2e655572008-07-10 16:52:52 -07001426 if (ret > 0)
Olof Johansson91b9a272005-08-09 20:24:39 -07001427 goto backtrace;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001428 goto found;
Olof Johansson91b9a272005-08-09 20:24:39 -07001429 }
1430
Olof Johansson91b9a272005-08-09 20:24:39 -07001431 cn = (struct tnode *)n;
1432
1433 /*
1434 * It's a tnode, and we can do some extra checks here if we
1435 * like, to avoid descending into a dead-end branch.
1436 * This tnode is in the parent's child array at index
1437 * key[p_pos..p_pos+p_bits] but potentially with some bits
1438 * chopped off, so in reality the index may be just a
1439 * subprefix, padded with zero at the end.
1440 * We can also take a look at any skipped bits in this
1441 * tnode - everything up to p_pos is supposed to be ok,
1442 * and the non-chopped bits of the index (se previous
1443 * paragraph) are also guaranteed ok, but the rest is
1444 * considered unknown.
1445 *
1446 * The skipped bits are key[pos+bits..cn->pos].
1447 */
1448
1449 /* If current_prefix_length < pos+bits, we are already doing
1450 * actual prefix matching, which means everything from
1451 * pos+(bits-chopped_off) onward must be zero along some
1452 * branch of this subtree - otherwise there is *no* valid
1453 * prefix present. Here we can only check the skipped
1454 * bits. Remember, since we have already indexed into the
1455 * parent's child array, we know that the bits we chopped of
1456 * *are* zero.
1457 */
1458
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001459 /* NOTA BENE: Checking only skipped bits
1460 for the new node here */
Olof Johansson91b9a272005-08-09 20:24:39 -07001461
1462 if (current_prefix_length < pos+bits) {
1463 if (tkey_extract_bits(cn->key, current_prefix_length,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001464 cn->pos - current_prefix_length)
1465 || !(cn->child[0]))
Olof Johansson91b9a272005-08-09 20:24:39 -07001466 goto backtrace;
1467 }
1468
1469 /*
1470 * If chopped_off=0, the index is fully validated and we
1471 * only need to look at the skipped bits for this, the new,
1472 * tnode. What we actually want to do is to find out if
1473 * these skipped bits match our key perfectly, or if we will
1474 * have to count on finding a matching prefix further down,
1475 * because if we do, we would like to have some way of
1476 * verifying the existence of such a prefix at this point.
1477 */
1478
1479 /* The only thing we can do at this point is to verify that
1480 * any such matching prefix can indeed be a prefix to our
1481 * key, and if the bits in the node we are inspecting that
1482 * do not match our key are not ZERO, this cannot be true.
1483 * Thus, find out where there is a mismatch (before cn->pos)
1484 * and verify that all the mismatching bits are zero in the
1485 * new tnode's key.
1486 */
1487
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001488 /*
1489 * Note: We aren't very concerned about the piece of
1490 * the key that precede pn->pos+pn->bits, since these
1491 * have already been checked. The bits after cn->pos
1492 * aren't checked since these are by definition
1493 * "unknown" at this point. Thus, what we want to see
1494 * is if we are about to enter the "prefix matching"
1495 * state, and in that case verify that the skipped
1496 * bits that will prevail throughout this subtree are
1497 * zero, as they have to be if we are to find a
1498 * matching prefix.
Olof Johansson91b9a272005-08-09 20:24:39 -07001499 */
1500
Eric Dumazet874ffa82010-10-13 06:56:11 +00001501 pref_mismatch = mask_pfx(cn->key ^ key, cn->pos);
Olof Johansson91b9a272005-08-09 20:24:39 -07001502
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001503 /*
1504 * In short: If skipped bits in this node do not match
1505 * the search key, enter the "prefix matching"
1506 * state.directly.
Olof Johansson91b9a272005-08-09 20:24:39 -07001507 */
1508 if (pref_mismatch) {
Eric Dumazet79cda752012-08-07 10:45:47 +00001509 /* fls(x) = __fls(x) + 1 */
1510 int mp = KEYLENGTH - __fls(pref_mismatch) - 1;
Olof Johansson91b9a272005-08-09 20:24:39 -07001511
Eric Dumazet874ffa82010-10-13 06:56:11 +00001512 if (tkey_extract_bits(cn->key, mp, cn->pos - mp) != 0)
Olof Johansson91b9a272005-08-09 20:24:39 -07001513 goto backtrace;
1514
1515 if (current_prefix_length >= cn->pos)
1516 current_prefix_length = mp;
1517 }
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001518
Olof Johansson91b9a272005-08-09 20:24:39 -07001519 pn = (struct tnode *)n; /* Descend */
1520 chopped_off = 0;
1521 continue;
1522
Robert Olsson19baf832005-06-21 12:43:18 -07001523backtrace:
1524 chopped_off++;
1525
1526 /* As zero don't change the child key (cindex) */
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001527 while ((chopped_off <= pn->bits)
1528 && !(cindex & (1<<(chopped_off-1))))
Robert Olsson19baf832005-06-21 12:43:18 -07001529 chopped_off++;
Robert Olsson19baf832005-06-21 12:43:18 -07001530
1531 /* Decrease current_... with bits chopped off */
1532 if (current_prefix_length > pn->pos + pn->bits - chopped_off)
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001533 current_prefix_length = pn->pos + pn->bits
1534 - chopped_off;
Olof Johansson91b9a272005-08-09 20:24:39 -07001535
Robert Olsson19baf832005-06-21 12:43:18 -07001536 /*
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001537 * Either we do the actual chop off according or if we have
Robert Olsson19baf832005-06-21 12:43:18 -07001538 * chopped off all bits in this tnode walk up to our parent.
1539 */
1540
Olof Johansson91b9a272005-08-09 20:24:39 -07001541 if (chopped_off <= pn->bits) {
Robert Olsson19baf832005-06-21 12:43:18 -07001542 cindex &= ~(1 << (chopped_off-1));
Olof Johansson91b9a272005-08-09 20:24:39 -07001543 } else {
Alexander Duyck64c9b6f2014-12-31 10:55:35 -08001544 struct tnode *parent = node_parent_rcu(pn);
Stephen Hemminger06801912007-08-10 15:22:13 -07001545 if (!parent)
Robert Olsson19baf832005-06-21 12:43:18 -07001546 goto failed;
Olof Johansson91b9a272005-08-09 20:24:39 -07001547
Robert Olsson19baf832005-06-21 12:43:18 -07001548 /* Get Child's index */
Stephen Hemminger06801912007-08-10 15:22:13 -07001549 cindex = tkey_extract_bits(pn->key, parent->pos, parent->bits);
1550 pn = parent;
Robert Olsson19baf832005-06-21 12:43:18 -07001551 chopped_off = 0;
1552
1553#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08001554 this_cpu_inc(stats->backtrack);
Robert Olsson19baf832005-06-21 12:43:18 -07001555#endif
1556 goto backtrace;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001557 }
Robert Olsson19baf832005-06-21 12:43:18 -07001558 }
1559failed:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001560 ret = 1;
Robert Olsson19baf832005-06-21 12:43:18 -07001561found:
Robert Olsson2373ce12005-08-25 13:01:29 -07001562 rcu_read_unlock();
Robert Olsson19baf832005-06-21 12:43:18 -07001563 return ret;
1564}
Florian Westphal6fc01432011-08-25 13:46:12 +02001565EXPORT_SYMBOL_GPL(fib_table_lookup);
Robert Olsson19baf832005-06-21 12:43:18 -07001566
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001567/*
1568 * Remove the leaf and return parent.
1569 */
1570static void trie_leaf_remove(struct trie *t, struct leaf *l)
Robert Olsson19baf832005-06-21 12:43:18 -07001571{
Alexander Duyck64c9b6f2014-12-31 10:55:35 -08001572 struct tnode *tp = node_parent(l);
Robert Olsson19baf832005-06-21 12:43:18 -07001573
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001574 pr_debug("entering trie_leaf_remove(%p)\n", l);
Robert Olsson19baf832005-06-21 12:43:18 -07001575
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001576 if (tp) {
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001577 t_key cindex = tkey_extract_bits(l->key, tp->pos, tp->bits);
Lin Ming61648d92012-07-29 02:00:03 +00001578 put_child(tp, cindex, NULL);
Jarek Poplawski7b855762009-06-18 00:28:51 -07001579 trie_rebalance(t, tp);
Olof Johansson91b9a272005-08-09 20:24:39 -07001580 } else
Stephen Hemmingera9b3cd72011-08-01 16:19:00 +00001581 RCU_INIT_POINTER(t->trie, NULL);
Robert Olsson19baf832005-06-21 12:43:18 -07001582
Stephen Hemminger387a5482008-04-10 03:47:34 -07001583 free_leaf(l);
Robert Olsson19baf832005-06-21 12:43:18 -07001584}
1585
Robert Olssond562f1f2007-03-26 14:22:22 -07001586/*
1587 * Caller must hold RTNL.
1588 */
Stephen Hemminger16c6cf82009-09-20 10:35:36 +00001589int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
Robert Olsson19baf832005-06-21 12:43:18 -07001590{
1591 struct trie *t = (struct trie *) tb->tb_data;
1592 u32 key, mask;
Thomas Graf4e902c52006-08-17 18:14:52 -07001593 int plen = cfg->fc_dst_len;
1594 u8 tos = cfg->fc_tos;
Robert Olsson19baf832005-06-21 12:43:18 -07001595 struct fib_alias *fa, *fa_to_delete;
1596 struct list_head *fa_head;
1597 struct leaf *l;
Olof Johansson91b9a272005-08-09 20:24:39 -07001598 struct leaf_info *li;
1599
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001600 if (plen > 32)
Robert Olsson19baf832005-06-21 12:43:18 -07001601 return -EINVAL;
1602
Thomas Graf4e902c52006-08-17 18:14:52 -07001603 key = ntohl(cfg->fc_dst);
Olof Johansson91b9a272005-08-09 20:24:39 -07001604 mask = ntohl(inet_make_mask(plen));
Robert Olsson19baf832005-06-21 12:43:18 -07001605
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001606 if (key & ~mask)
Robert Olsson19baf832005-06-21 12:43:18 -07001607 return -EINVAL;
1608
1609 key = key & mask;
1610 l = fib_find_node(t, key);
1611
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001612 if (!l)
Robert Olsson19baf832005-06-21 12:43:18 -07001613 return -ESRCH;
1614
Igor Maravicad5b3102012-08-13 10:26:08 +02001615 li = find_leaf_info(l, plen);
1616
1617 if (!li)
1618 return -ESRCH;
1619
1620 fa_head = &li->falh;
Robert Olsson19baf832005-06-21 12:43:18 -07001621 fa = fib_find_alias(fa_head, tos, 0);
1622
1623 if (!fa)
1624 return -ESRCH;
1625
Stephen Hemminger0c7770c2005-08-23 21:59:41 -07001626 pr_debug("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t);
Robert Olsson19baf832005-06-21 12:43:18 -07001627
1628 fa_to_delete = NULL;
Julian Anastasov936f6f82008-01-28 21:18:06 -08001629 fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
1630 list_for_each_entry_continue(fa, fa_head, fa_list) {
Robert Olsson19baf832005-06-21 12:43:18 -07001631 struct fib_info *fi = fa->fa_info;
1632
1633 if (fa->fa_tos != tos)
1634 break;
1635
Thomas Graf4e902c52006-08-17 18:14:52 -07001636 if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) &&
1637 (cfg->fc_scope == RT_SCOPE_NOWHERE ||
David S. Miller37e826c2011-03-24 18:06:47 -07001638 fa->fa_info->fib_scope == cfg->fc_scope) &&
Julian Anastasov74cb3c12011-03-19 12:13:46 +00001639 (!cfg->fc_prefsrc ||
1640 fi->fib_prefsrc == cfg->fc_prefsrc) &&
Thomas Graf4e902c52006-08-17 18:14:52 -07001641 (!cfg->fc_protocol ||
1642 fi->fib_protocol == cfg->fc_protocol) &&
1643 fib_nh_match(cfg, fi) == 0) {
Robert Olsson19baf832005-06-21 12:43:18 -07001644 fa_to_delete = fa;
1645 break;
1646 }
1647 }
1648
Olof Johansson91b9a272005-08-09 20:24:39 -07001649 if (!fa_to_delete)
1650 return -ESRCH;
Robert Olsson19baf832005-06-21 12:43:18 -07001651
Olof Johansson91b9a272005-08-09 20:24:39 -07001652 fa = fa_to_delete;
Thomas Graf4e902c52006-08-17 18:14:52 -07001653 rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id,
Milan Kocianb8f55832007-05-23 14:55:06 -07001654 &cfg->fc_nlinfo, 0);
Robert Olsson19baf832005-06-21 12:43:18 -07001655
Robert Olsson2373ce12005-08-25 13:01:29 -07001656 list_del_rcu(&fa->fa_list);
Robert Olsson19baf832005-06-21 12:43:18 -07001657
David S. Miller21d8c492011-04-14 14:49:37 -07001658 if (!plen)
1659 tb->tb_num_default--;
1660
Olof Johansson91b9a272005-08-09 20:24:39 -07001661 if (list_empty(fa_head)) {
Robert Olsson2373ce12005-08-25 13:01:29 -07001662 hlist_del_rcu(&li->hlist);
Olof Johansson91b9a272005-08-09 20:24:39 -07001663 free_leaf_info(li);
Robert Olsson2373ce12005-08-25 13:01:29 -07001664 }
Olof Johansson91b9a272005-08-09 20:24:39 -07001665
1666 if (hlist_empty(&l->list))
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001667 trie_leaf_remove(t, l);
Olof Johansson91b9a272005-08-09 20:24:39 -07001668
1669 if (fa->fa_state & FA_S_ACCESSED)
Nicolas Dichtel4ccfe6d2012-09-07 00:45:29 +00001670 rt_cache_flush(cfg->fc_nlinfo.nl_net);
Olof Johansson91b9a272005-08-09 20:24:39 -07001671
Robert Olsson2373ce12005-08-25 13:01:29 -07001672 fib_release_info(fa->fa_info);
1673 alias_free_mem_rcu(fa);
Olof Johansson91b9a272005-08-09 20:24:39 -07001674 return 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001675}
1676
Stephen Hemmingeref3660c2008-04-10 03:46:12 -07001677static int trie_flush_list(struct list_head *head)
Robert Olsson19baf832005-06-21 12:43:18 -07001678{
1679 struct fib_alias *fa, *fa_node;
1680 int found = 0;
1681
1682 list_for_each_entry_safe(fa, fa_node, head, fa_list) {
1683 struct fib_info *fi = fa->fa_info;
Robert Olsson19baf832005-06-21 12:43:18 -07001684
Robert Olsson2373ce12005-08-25 13:01:29 -07001685 if (fi && (fi->fib_flags & RTNH_F_DEAD)) {
1686 list_del_rcu(&fa->fa_list);
1687 fib_release_info(fa->fa_info);
1688 alias_free_mem_rcu(fa);
Robert Olsson19baf832005-06-21 12:43:18 -07001689 found++;
1690 }
1691 }
1692 return found;
1693}
1694
Stephen Hemmingeref3660c2008-04-10 03:46:12 -07001695static int trie_flush_leaf(struct leaf *l)
Robert Olsson19baf832005-06-21 12:43:18 -07001696{
1697 int found = 0;
1698 struct hlist_head *lih = &l->list;
Sasha Levinb67bfe02013-02-27 17:06:00 -08001699 struct hlist_node *tmp;
Robert Olsson19baf832005-06-21 12:43:18 -07001700 struct leaf_info *li = NULL;
1701
Sasha Levinb67bfe02013-02-27 17:06:00 -08001702 hlist_for_each_entry_safe(li, tmp, lih, hlist) {
Stephen Hemmingeref3660c2008-04-10 03:46:12 -07001703 found += trie_flush_list(&li->falh);
Robert Olsson19baf832005-06-21 12:43:18 -07001704
1705 if (list_empty(&li->falh)) {
Robert Olsson2373ce12005-08-25 13:01:29 -07001706 hlist_del_rcu(&li->hlist);
Robert Olsson19baf832005-06-21 12:43:18 -07001707 free_leaf_info(li);
1708 }
1709 }
1710 return found;
1711}
1712
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001713/*
1714 * Scan for the next right leaf starting at node p->child[idx]
1715 * Since we have back pointer, no recursion necessary.
1716 */
David S. Millerb299e4f2011-02-02 20:48:10 -08001717static struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c)
Robert Olsson19baf832005-06-21 12:43:18 -07001718{
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001719 do {
1720 t_key idx;
Robert Olsson19baf832005-06-21 12:43:18 -07001721
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001722 if (c)
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001723 idx = tkey_extract_bits(c->key, p->pos, p->bits) + 1;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001724 else
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001725 idx = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001726
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001727 while (idx < 1u << p->bits) {
1728 c = tnode_get_child_rcu(p, idx++);
Robert Olsson2373ce12005-08-25 13:01:29 -07001729 if (!c)
Olof Johansson91b9a272005-08-09 20:24:39 -07001730 continue;
Robert Olsson19baf832005-06-21 12:43:18 -07001731
Eric Dumazetaab515d2013-08-05 11:18:49 -07001732 if (IS_LEAF(c))
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001733 return (struct leaf *) c;
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001734
1735 /* Rescan start scanning in new node */
1736 p = (struct tnode *) c;
1737 idx = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001738 }
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001739
1740 /* Node empty, walk back up to parent */
David S. Millerb299e4f2011-02-02 20:48:10 -08001741 c = (struct rt_trie_node *) p;
Eric Dumazeta034ee32010-09-09 23:32:28 +00001742 } while ((p = node_parent_rcu(c)) != NULL);
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001743
1744 return NULL; /* Root of trie */
1745}
1746
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001747static struct leaf *trie_firstleaf(struct trie *t)
1748{
Eric Dumazeta034ee32010-09-09 23:32:28 +00001749 struct tnode *n = (struct tnode *)rcu_dereference_rtnl(t->trie);
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001750
1751 if (!n)
1752 return NULL;
1753
1754 if (IS_LEAF(n)) /* trie is just a leaf */
1755 return (struct leaf *) n;
1756
1757 return leaf_walk_rcu(n, NULL);
1758}
1759
1760static struct leaf *trie_nextleaf(struct leaf *l)
1761{
David S. Millerb299e4f2011-02-02 20:48:10 -08001762 struct rt_trie_node *c = (struct rt_trie_node *) l;
Jarek Poplawskib902e572009-07-14 11:20:32 +00001763 struct tnode *p = node_parent_rcu(c);
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001764
1765 if (!p)
1766 return NULL; /* trie with just one leaf */
1767
1768 return leaf_walk_rcu(p, c);
Robert Olsson19baf832005-06-21 12:43:18 -07001769}
1770
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001771static struct leaf *trie_leafindex(struct trie *t, int index)
1772{
1773 struct leaf *l = trie_firstleaf(t);
1774
Stephen Hemmingerec28cf72008-02-11 21:12:49 -08001775 while (l && index-- > 0)
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001776 l = trie_nextleaf(l);
Stephen Hemmingerec28cf72008-02-11 21:12:49 -08001777
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001778 return l;
1779}
1780
1781
Robert Olssond562f1f2007-03-26 14:22:22 -07001782/*
1783 * Caller must hold RTNL.
1784 */
Stephen Hemminger16c6cf82009-09-20 10:35:36 +00001785int fib_table_flush(struct fib_table *tb)
Robert Olsson19baf832005-06-21 12:43:18 -07001786{
1787 struct trie *t = (struct trie *) tb->tb_data;
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001788 struct leaf *l, *ll = NULL;
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001789 int found = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001790
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001791 for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) {
Stephen Hemmingeref3660c2008-04-10 03:46:12 -07001792 found += trie_flush_leaf(l);
Robert Olsson19baf832005-06-21 12:43:18 -07001793
1794 if (ll && hlist_empty(&ll->list))
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001795 trie_leaf_remove(t, ll);
Robert Olsson19baf832005-06-21 12:43:18 -07001796 ll = l;
1797 }
1798
1799 if (ll && hlist_empty(&ll->list))
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001800 trie_leaf_remove(t, ll);
Robert Olsson19baf832005-06-21 12:43:18 -07001801
Stephen Hemminger0c7770c2005-08-23 21:59:41 -07001802 pr_debug("trie_flush found=%d\n", found);
Robert Olsson19baf832005-06-21 12:43:18 -07001803 return found;
1804}
1805
Pavel Emelyanov4aa2c462010-10-28 02:00:43 +00001806void fib_free_table(struct fib_table *tb)
1807{
Alexander Duyck8274a972014-12-31 10:55:29 -08001808#ifdef CONFIG_IP_FIB_TRIE_STATS
1809 struct trie *t = (struct trie *)tb->tb_data;
1810
1811 free_percpu(t->stats);
1812#endif /* CONFIG_IP_FIB_TRIE_STATS */
Pavel Emelyanov4aa2c462010-10-28 02:00:43 +00001813 kfree(tb);
1814}
1815
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001816static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
1817 struct fib_table *tb,
Robert Olsson19baf832005-06-21 12:43:18 -07001818 struct sk_buff *skb, struct netlink_callback *cb)
1819{
1820 int i, s_i;
1821 struct fib_alias *fa;
Al Viro32ab5f82006-09-26 22:21:45 -07001822 __be32 xkey = htonl(key);
Robert Olsson19baf832005-06-21 12:43:18 -07001823
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001824 s_i = cb->args[5];
Robert Olsson19baf832005-06-21 12:43:18 -07001825 i = 0;
1826
Robert Olsson2373ce12005-08-25 13:01:29 -07001827 /* rcu_read_lock is hold by caller */
1828
1829 list_for_each_entry_rcu(fa, fah, fa_list) {
Robert Olsson19baf832005-06-21 12:43:18 -07001830 if (i < s_i) {
1831 i++;
1832 continue;
1833 }
Robert Olsson19baf832005-06-21 12:43:18 -07001834
Eric W. Biederman15e47302012-09-07 20:12:54 +00001835 if (fib_dump_info(skb, NETLINK_CB(cb->skb).portid,
Robert Olsson19baf832005-06-21 12:43:18 -07001836 cb->nlh->nlmsg_seq,
1837 RTM_NEWROUTE,
1838 tb->tb_id,
1839 fa->fa_type,
Thomas Grafbe403ea2006-08-17 18:15:17 -07001840 xkey,
Robert Olsson19baf832005-06-21 12:43:18 -07001841 plen,
1842 fa->fa_tos,
Stephen Hemminger64347f72008-01-22 21:55:01 -08001843 fa->fa_info, NLM_F_MULTI) < 0) {
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001844 cb->args[5] = i;
Robert Olsson19baf832005-06-21 12:43:18 -07001845 return -1;
Olof Johansson91b9a272005-08-09 20:24:39 -07001846 }
Robert Olsson19baf832005-06-21 12:43:18 -07001847 i++;
1848 }
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001849 cb->args[5] = i;
Robert Olsson19baf832005-06-21 12:43:18 -07001850 return skb->len;
1851}
1852
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001853static int fn_trie_dump_leaf(struct leaf *l, struct fib_table *tb,
1854 struct sk_buff *skb, struct netlink_callback *cb)
Robert Olsson19baf832005-06-21 12:43:18 -07001855{
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001856 struct leaf_info *li;
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001857 int i, s_i;
Robert Olsson19baf832005-06-21 12:43:18 -07001858
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001859 s_i = cb->args[4];
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001860 i = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001861
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001862 /* rcu_read_lock is hold by caller */
Sasha Levinb67bfe02013-02-27 17:06:00 -08001863 hlist_for_each_entry_rcu(li, &l->list, hlist) {
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001864 if (i < s_i) {
1865 i++;
Robert Olsson19baf832005-06-21 12:43:18 -07001866 continue;
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001867 }
Robert Olsson19baf832005-06-21 12:43:18 -07001868
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001869 if (i > s_i)
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001870 cb->args[5] = 0;
Olof Johansson91b9a272005-08-09 20:24:39 -07001871
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001872 if (list_empty(&li->falh))
Robert Olsson19baf832005-06-21 12:43:18 -07001873 continue;
1874
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001875 if (fn_trie_dump_fa(l->key, li->plen, &li->falh, tb, skb, cb) < 0) {
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001876 cb->args[4] = i;
Robert Olsson19baf832005-06-21 12:43:18 -07001877 return -1;
1878 }
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001879 i++;
Robert Olsson19baf832005-06-21 12:43:18 -07001880 }
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001881
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001882 cb->args[4] = i;
Robert Olsson19baf832005-06-21 12:43:18 -07001883 return skb->len;
1884}
1885
Stephen Hemminger16c6cf82009-09-20 10:35:36 +00001886int fib_table_dump(struct fib_table *tb, struct sk_buff *skb,
1887 struct netlink_callback *cb)
Robert Olsson19baf832005-06-21 12:43:18 -07001888{
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001889 struct leaf *l;
Robert Olsson19baf832005-06-21 12:43:18 -07001890 struct trie *t = (struct trie *) tb->tb_data;
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001891 t_key key = cb->args[2];
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001892 int count = cb->args[3];
Robert Olsson19baf832005-06-21 12:43:18 -07001893
Robert Olsson2373ce12005-08-25 13:01:29 -07001894 rcu_read_lock();
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001895 /* Dump starting at last key.
1896 * Note: 0.0.0.0/0 (ie default) is first key.
1897 */
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001898 if (count == 0)
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001899 l = trie_firstleaf(t);
1900 else {
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001901 /* Normally, continue from last key, but if that is missing
1902 * fallback to using slow rescan
1903 */
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001904 l = fib_find_node(t, key);
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001905 if (!l)
1906 l = trie_leafindex(t, count);
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001907 }
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001908
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001909 while (l) {
1910 cb->args[2] = l->key;
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001911 if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) {
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001912 cb->args[3] = count;
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001913 rcu_read_unlock();
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001914 return -1;
Robert Olsson19baf832005-06-21 12:43:18 -07001915 }
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001916
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001917 ++count;
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001918 l = trie_nextleaf(l);
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001919 memset(&cb->args[4], 0,
1920 sizeof(cb->args) - 4*sizeof(cb->args[0]));
Robert Olsson19baf832005-06-21 12:43:18 -07001921 }
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001922 cb->args[3] = count;
Robert Olsson2373ce12005-08-25 13:01:29 -07001923 rcu_read_unlock();
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001924
Robert Olsson19baf832005-06-21 12:43:18 -07001925 return skb->len;
Robert Olsson19baf832005-06-21 12:43:18 -07001926}
1927
David S. Miller5348ba82011-02-01 15:30:56 -08001928void __init fib_trie_init(void)
Stephen Hemminger7f9b8052008-01-14 23:14:20 -08001929{
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001930 fn_alias_kmem = kmem_cache_create("ip_fib_alias",
1931 sizeof(struct fib_alias),
Stephen Hemmingerbc3c8c12008-01-22 21:51:50 -08001932 0, SLAB_PANIC, NULL);
1933
1934 trie_leaf_kmem = kmem_cache_create("ip_fib_trie",
1935 max(sizeof(struct leaf),
1936 sizeof(struct leaf_info)),
1937 0, SLAB_PANIC, NULL);
Stephen Hemminger7f9b8052008-01-14 23:14:20 -08001938}
Robert Olsson19baf832005-06-21 12:43:18 -07001939
Stephen Hemminger7f9b8052008-01-14 23:14:20 -08001940
David S. Miller5348ba82011-02-01 15:30:56 -08001941struct fib_table *fib_trie_table(u32 id)
Robert Olsson19baf832005-06-21 12:43:18 -07001942{
1943 struct fib_table *tb;
1944 struct trie *t;
1945
Robert Olsson19baf832005-06-21 12:43:18 -07001946 tb = kmalloc(sizeof(struct fib_table) + sizeof(struct trie),
1947 GFP_KERNEL);
1948 if (tb == NULL)
1949 return NULL;
1950
1951 tb->tb_id = id;
Denis V. Lunev971b8932007-12-08 00:32:23 -08001952 tb->tb_default = -1;
David S. Miller21d8c492011-04-14 14:49:37 -07001953 tb->tb_num_default = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001954
1955 t = (struct trie *) tb->tb_data;
Alexander Duyck8274a972014-12-31 10:55:29 -08001956 RCU_INIT_POINTER(t->trie, NULL);
1957#ifdef CONFIG_IP_FIB_TRIE_STATS
1958 t->stats = alloc_percpu(struct trie_use_stats);
1959 if (!t->stats) {
1960 kfree(tb);
1961 tb = NULL;
1962 }
1963#endif
Robert Olsson19baf832005-06-21 12:43:18 -07001964
Robert Olsson19baf832005-06-21 12:43:18 -07001965 return tb;
1966}
1967
Robert Olsson19baf832005-06-21 12:43:18 -07001968#ifdef CONFIG_PROC_FS
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001969/* Depth first Trie walk iterator */
1970struct fib_trie_iter {
Denis V. Lunev1c340b22008-01-10 03:27:17 -08001971 struct seq_net_private p;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07001972 struct fib_table *tb;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001973 struct tnode *tnode;
Eric Dumazeta034ee32010-09-09 23:32:28 +00001974 unsigned int index;
1975 unsigned int depth;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001976};
Robert Olsson19baf832005-06-21 12:43:18 -07001977
David S. Millerb299e4f2011-02-02 20:48:10 -08001978static struct rt_trie_node *fib_trie_get_next(struct fib_trie_iter *iter)
Robert Olsson19baf832005-06-21 12:43:18 -07001979{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001980 struct tnode *tn = iter->tnode;
Eric Dumazeta034ee32010-09-09 23:32:28 +00001981 unsigned int cindex = iter->index;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001982 struct tnode *p;
1983
Eric W. Biederman6640e692007-01-24 14:42:04 -08001984 /* A single entry routing table */
1985 if (!tn)
1986 return NULL;
1987
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001988 pr_debug("get_next iter={node=%p index=%d depth=%d}\n",
1989 iter->tnode, iter->index, iter->depth);
1990rescan:
1991 while (cindex < (1<<tn->bits)) {
David S. Millerb299e4f2011-02-02 20:48:10 -08001992 struct rt_trie_node *n = tnode_get_child_rcu(tn, cindex);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001993
1994 if (n) {
1995 if (IS_LEAF(n)) {
1996 iter->tnode = tn;
1997 iter->index = cindex + 1;
1998 } else {
1999 /* push down one level */
2000 iter->tnode = (struct tnode *) n;
2001 iter->index = 0;
2002 ++iter->depth;
2003 }
2004 return n;
2005 }
2006
2007 ++cindex;
2008 }
2009
2010 /* Current node exhausted, pop back up */
David S. Millerb299e4f2011-02-02 20:48:10 -08002011 p = node_parent_rcu((struct rt_trie_node *)tn);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002012 if (p) {
2013 cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1;
2014 tn = p;
2015 --iter->depth;
2016 goto rescan;
2017 }
2018
2019 /* got root? */
Robert Olsson19baf832005-06-21 12:43:18 -07002020 return NULL;
2021}
2022
David S. Millerb299e4f2011-02-02 20:48:10 -08002023static struct rt_trie_node *fib_trie_get_first(struct fib_trie_iter *iter,
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002024 struct trie *t)
Robert Olsson19baf832005-06-21 12:43:18 -07002025{
David S. Millerb299e4f2011-02-02 20:48:10 -08002026 struct rt_trie_node *n;
Robert Olsson5ddf0eb2006-03-20 21:34:12 -08002027
Stephen Hemminger132adf52007-03-08 20:44:43 -08002028 if (!t)
Robert Olsson5ddf0eb2006-03-20 21:34:12 -08002029 return NULL;
2030
2031 n = rcu_dereference(t->trie);
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002032 if (!n)
Robert Olsson5ddf0eb2006-03-20 21:34:12 -08002033 return NULL;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002034
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002035 if (IS_TNODE(n)) {
2036 iter->tnode = (struct tnode *) n;
2037 iter->index = 0;
2038 iter->depth = 1;
2039 } else {
2040 iter->tnode = NULL;
2041 iter->index = 0;
2042 iter->depth = 0;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002043 }
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002044
2045 return n;
Robert Olsson19baf832005-06-21 12:43:18 -07002046}
2047
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002048static void trie_collect_stats(struct trie *t, struct trie_stat *s)
Robert Olsson19baf832005-06-21 12:43:18 -07002049{
David S. Millerb299e4f2011-02-02 20:48:10 -08002050 struct rt_trie_node *n;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002051 struct fib_trie_iter iter;
Robert Olsson19baf832005-06-21 12:43:18 -07002052
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002053 memset(s, 0, sizeof(*s));
Robert Olsson19baf832005-06-21 12:43:18 -07002054
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002055 rcu_read_lock();
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002056 for (n = fib_trie_get_first(&iter, t); n; n = fib_trie_get_next(&iter)) {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002057 if (IS_LEAF(n)) {
Stephen Hemminger93672292008-01-22 21:54:05 -08002058 struct leaf *l = (struct leaf *)n;
2059 struct leaf_info *li;
Stephen Hemminger93672292008-01-22 21:54:05 -08002060
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002061 s->leaves++;
2062 s->totdepth += iter.depth;
2063 if (iter.depth > s->maxdepth)
2064 s->maxdepth = iter.depth;
Stephen Hemminger93672292008-01-22 21:54:05 -08002065
Sasha Levinb67bfe02013-02-27 17:06:00 -08002066 hlist_for_each_entry_rcu(li, &l->list, hlist)
Stephen Hemminger93672292008-01-22 21:54:05 -08002067 ++s->prefixes;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002068 } else {
2069 const struct tnode *tn = (const struct tnode *) n;
2070 int i;
Robert Olsson19baf832005-06-21 12:43:18 -07002071
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002072 s->tnodes++;
Stephen Hemminger132adf52007-03-08 20:44:43 -08002073 if (tn->bits < MAX_STAT_DEPTH)
Robert Olsson06ef9212006-03-20 21:35:01 -08002074 s->nodesizes[tn->bits]++;
2075
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002076 for (i = 0; i < (1<<tn->bits); i++)
2077 if (!tn->child[i])
2078 s->nullpointers++;
2079 }
2080 }
2081 rcu_read_unlock();
Robert Olsson19baf832005-06-21 12:43:18 -07002082}
2083
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07002084/*
Robert Olsson19baf832005-06-21 12:43:18 -07002085 * This outputs /proc/net/fib_triestats
Robert Olsson19baf832005-06-21 12:43:18 -07002086 */
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002087static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
Robert Olsson19baf832005-06-21 12:43:18 -07002088{
Eric Dumazeta034ee32010-09-09 23:32:28 +00002089 unsigned int i, max, pointers, bytes, avdepth;
Robert Olsson19baf832005-06-21 12:43:18 -07002090
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002091 if (stat->leaves)
2092 avdepth = stat->totdepth*100 / stat->leaves;
2093 else
2094 avdepth = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07002095
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08002096 seq_printf(seq, "\tAver depth: %u.%02d\n",
2097 avdepth / 100, avdepth % 100);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002098 seq_printf(seq, "\tMax depth: %u\n", stat->maxdepth);
Robert Olsson19baf832005-06-21 12:43:18 -07002099
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002100 seq_printf(seq, "\tLeaves: %u\n", stat->leaves);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002101 bytes = sizeof(struct leaf) * stat->leaves;
Stephen Hemminger93672292008-01-22 21:54:05 -08002102
2103 seq_printf(seq, "\tPrefixes: %u\n", stat->prefixes);
2104 bytes += sizeof(struct leaf_info) * stat->prefixes;
2105
Stephen Hemminger187b5182008-01-12 20:55:55 -08002106 seq_printf(seq, "\tInternal nodes: %u\n\t", stat->tnodes);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002107 bytes += sizeof(struct tnode) * stat->tnodes;
Robert Olsson19baf832005-06-21 12:43:18 -07002108
Robert Olsson06ef9212006-03-20 21:35:01 -08002109 max = MAX_STAT_DEPTH;
2110 while (max > 0 && stat->nodesizes[max-1] == 0)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002111 max--;
Robert Olsson19baf832005-06-21 12:43:18 -07002112
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002113 pointers = 0;
Jerry Snitselaarf585a992013-07-22 12:01:58 -07002114 for (i = 1; i < max; i++)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002115 if (stat->nodesizes[i] != 0) {
Stephen Hemminger187b5182008-01-12 20:55:55 -08002116 seq_printf(seq, " %u: %u", i, stat->nodesizes[i]);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002117 pointers += (1<<i) * stat->nodesizes[i];
2118 }
2119 seq_putc(seq, '\n');
Stephen Hemminger187b5182008-01-12 20:55:55 -08002120 seq_printf(seq, "\tPointers: %u\n", pointers);
Robert Olsson19baf832005-06-21 12:43:18 -07002121
David S. Millerb299e4f2011-02-02 20:48:10 -08002122 bytes += sizeof(struct rt_trie_node *) * pointers;
Stephen Hemminger187b5182008-01-12 20:55:55 -08002123 seq_printf(seq, "Null ptrs: %u\n", stat->nullpointers);
2124 seq_printf(seq, "Total size: %u kB\n", (bytes + 1023) / 1024);
Stephen Hemminger66a2f7f2008-01-12 21:23:17 -08002125}
Robert Olsson19baf832005-06-21 12:43:18 -07002126
2127#ifdef CONFIG_IP_FIB_TRIE_STATS
Stephen Hemminger66a2f7f2008-01-12 21:23:17 -08002128static void trie_show_usage(struct seq_file *seq,
Alexander Duyck8274a972014-12-31 10:55:29 -08002129 const struct trie_use_stats __percpu *stats)
Stephen Hemminger66a2f7f2008-01-12 21:23:17 -08002130{
Alexander Duyck8274a972014-12-31 10:55:29 -08002131 struct trie_use_stats s = { 0 };
2132 int cpu;
2133
2134 /* loop through all of the CPUs and gather up the stats */
2135 for_each_possible_cpu(cpu) {
2136 const struct trie_use_stats *pcpu = per_cpu_ptr(stats, cpu);
2137
2138 s.gets += pcpu->gets;
2139 s.backtrack += pcpu->backtrack;
2140 s.semantic_match_passed += pcpu->semantic_match_passed;
2141 s.semantic_match_miss += pcpu->semantic_match_miss;
2142 s.null_node_hit += pcpu->null_node_hit;
2143 s.resize_node_skipped += pcpu->resize_node_skipped;
2144 }
2145
Stephen Hemminger66a2f7f2008-01-12 21:23:17 -08002146 seq_printf(seq, "\nCounters:\n---------\n");
Alexander Duyck8274a972014-12-31 10:55:29 -08002147 seq_printf(seq, "gets = %u\n", s.gets);
2148 seq_printf(seq, "backtracks = %u\n", s.backtrack);
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08002149 seq_printf(seq, "semantic match passed = %u\n",
Alexander Duyck8274a972014-12-31 10:55:29 -08002150 s.semantic_match_passed);
2151 seq_printf(seq, "semantic match miss = %u\n", s.semantic_match_miss);
2152 seq_printf(seq, "null node hit= %u\n", s.null_node_hit);
2153 seq_printf(seq, "skipped node resize = %u\n\n", s.resize_node_skipped);
Robert Olsson19baf832005-06-21 12:43:18 -07002154}
Stephen Hemminger66a2f7f2008-01-12 21:23:17 -08002155#endif /* CONFIG_IP_FIB_TRIE_STATS */
2156
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002157static void fib_table_print(struct seq_file *seq, struct fib_table *tb)
Stephen Hemmingerd717a9a2008-01-14 23:11:54 -08002158{
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002159 if (tb->tb_id == RT_TABLE_LOCAL)
2160 seq_puts(seq, "Local:\n");
2161 else if (tb->tb_id == RT_TABLE_MAIN)
2162 seq_puts(seq, "Main:\n");
2163 else
2164 seq_printf(seq, "Id %d:\n", tb->tb_id);
Stephen Hemmingerd717a9a2008-01-14 23:11:54 -08002165}
Robert Olsson19baf832005-06-21 12:43:18 -07002166
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002167
Robert Olsson19baf832005-06-21 12:43:18 -07002168static int fib_triestat_seq_show(struct seq_file *seq, void *v)
2169{
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002170 struct net *net = (struct net *)seq->private;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002171 unsigned int h;
Eric W. Biederman877a9bf2007-12-07 00:47:47 -08002172
Stephen Hemmingerd717a9a2008-01-14 23:11:54 -08002173 seq_printf(seq,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08002174 "Basic info: size of leaf:"
2175 " %Zd bytes, size of tnode: %Zd bytes.\n",
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002176 sizeof(struct leaf), sizeof(struct tnode));
Olof Johansson91b9a272005-08-09 20:24:39 -07002177
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002178 for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
2179 struct hlist_head *head = &net->ipv4.fib_table_hash[h];
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002180 struct fib_table *tb;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002181
Sasha Levinb67bfe02013-02-27 17:06:00 -08002182 hlist_for_each_entry_rcu(tb, head, tb_hlist) {
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002183 struct trie *t = (struct trie *) tb->tb_data;
2184 struct trie_stat stat;
2185
2186 if (!t)
2187 continue;
2188
2189 fib_table_print(seq, tb);
2190
2191 trie_collect_stats(t, &stat);
2192 trie_show_stats(seq, &stat);
2193#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08002194 trie_show_usage(seq, t->stats);
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002195#endif
2196 }
2197 }
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002198
Robert Olsson19baf832005-06-21 12:43:18 -07002199 return 0;
2200}
2201
Robert Olsson19baf832005-06-21 12:43:18 -07002202static int fib_triestat_seq_open(struct inode *inode, struct file *file)
2203{
Pavel Emelyanovde05c552008-07-18 04:07:21 -07002204 return single_open_net(inode, file, fib_triestat_seq_show);
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002205}
2206
Arjan van de Ven9a321442007-02-12 00:55:35 -08002207static const struct file_operations fib_triestat_fops = {
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07002208 .owner = THIS_MODULE,
2209 .open = fib_triestat_seq_open,
2210 .read = seq_read,
2211 .llseek = seq_lseek,
Pavel Emelyanovb6fcbdb2008-07-18 04:07:44 -07002212 .release = single_release_net,
Robert Olsson19baf832005-06-21 12:43:18 -07002213};
2214
David S. Millerb299e4f2011-02-02 20:48:10 -08002215static struct rt_trie_node *fib_trie_get_idx(struct seq_file *seq, loff_t pos)
Robert Olsson19baf832005-06-21 12:43:18 -07002216{
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002217 struct fib_trie_iter *iter = seq->private;
2218 struct net *net = seq_file_net(seq);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002219 loff_t idx = 0;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002220 unsigned int h;
Robert Olsson19baf832005-06-21 12:43:18 -07002221
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002222 for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
2223 struct hlist_head *head = &net->ipv4.fib_table_hash[h];
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002224 struct fib_table *tb;
2225
Sasha Levinb67bfe02013-02-27 17:06:00 -08002226 hlist_for_each_entry_rcu(tb, head, tb_hlist) {
David S. Millerb299e4f2011-02-02 20:48:10 -08002227 struct rt_trie_node *n;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002228
2229 for (n = fib_trie_get_first(iter,
2230 (struct trie *) tb->tb_data);
2231 n; n = fib_trie_get_next(iter))
2232 if (pos == idx++) {
2233 iter->tb = tb;
2234 return n;
2235 }
2236 }
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002237 }
Robert Olsson19baf832005-06-21 12:43:18 -07002238
Robert Olsson19baf832005-06-21 12:43:18 -07002239 return NULL;
2240}
2241
2242static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
Stephen Hemmingerc95aaf92008-01-12 21:25:02 -08002243 __acquires(RCU)
Robert Olsson19baf832005-06-21 12:43:18 -07002244{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002245 rcu_read_lock();
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002246 return fib_trie_get_idx(seq, *pos);
Robert Olsson19baf832005-06-21 12:43:18 -07002247}
2248
2249static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2250{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002251 struct fib_trie_iter *iter = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002252 struct net *net = seq_file_net(seq);
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002253 struct fib_table *tb = iter->tb;
2254 struct hlist_node *tb_node;
2255 unsigned int h;
David S. Millerb299e4f2011-02-02 20:48:10 -08002256 struct rt_trie_node *n;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002257
Robert Olsson19baf832005-06-21 12:43:18 -07002258 ++*pos;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002259 /* next node in same table */
2260 n = fib_trie_get_next(iter);
2261 if (n)
2262 return n;
Olof Johansson91b9a272005-08-09 20:24:39 -07002263
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002264 /* walk rest of this hash chain */
2265 h = tb->tb_id & (FIB_TABLE_HASHSZ - 1);
Eric Dumazet0a5c0472011-03-31 01:51:35 -07002266 while ((tb_node = rcu_dereference(hlist_next_rcu(&tb->tb_hlist)))) {
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002267 tb = hlist_entry(tb_node, struct fib_table, tb_hlist);
2268 n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
2269 if (n)
2270 goto found;
2271 }
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002272
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002273 /* new hash chain */
2274 while (++h < FIB_TABLE_HASHSZ) {
2275 struct hlist_head *head = &net->ipv4.fib_table_hash[h];
Sasha Levinb67bfe02013-02-27 17:06:00 -08002276 hlist_for_each_entry_rcu(tb, head, tb_hlist) {
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002277 n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
2278 if (n)
2279 goto found;
2280 }
2281 }
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002282 return NULL;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002283
2284found:
2285 iter->tb = tb;
2286 return n;
Robert Olsson19baf832005-06-21 12:43:18 -07002287}
2288
2289static void fib_trie_seq_stop(struct seq_file *seq, void *v)
Stephen Hemmingerc95aaf92008-01-12 21:25:02 -08002290 __releases(RCU)
Robert Olsson19baf832005-06-21 12:43:18 -07002291{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002292 rcu_read_unlock();
Robert Olsson19baf832005-06-21 12:43:18 -07002293}
2294
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002295static void seq_indent(struct seq_file *seq, int n)
2296{
Eric Dumazeta034ee32010-09-09 23:32:28 +00002297 while (n-- > 0)
2298 seq_puts(seq, " ");
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002299}
Robert Olsson19baf832005-06-21 12:43:18 -07002300
Eric Dumazet28d36e32008-01-14 23:09:56 -08002301static inline const char *rtn_scope(char *buf, size_t len, enum rt_scope_t s)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002302{
Stephen Hemminger132adf52007-03-08 20:44:43 -08002303 switch (s) {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002304 case RT_SCOPE_UNIVERSE: return "universe";
2305 case RT_SCOPE_SITE: return "site";
2306 case RT_SCOPE_LINK: return "link";
2307 case RT_SCOPE_HOST: return "host";
2308 case RT_SCOPE_NOWHERE: return "nowhere";
2309 default:
Eric Dumazet28d36e32008-01-14 23:09:56 -08002310 snprintf(buf, len, "scope=%d", s);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002311 return buf;
2312 }
2313}
2314
Jan Engelhardt36cbd3d2009-08-05 10:42:58 -07002315static const char *const rtn_type_names[__RTN_MAX] = {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002316 [RTN_UNSPEC] = "UNSPEC",
2317 [RTN_UNICAST] = "UNICAST",
2318 [RTN_LOCAL] = "LOCAL",
2319 [RTN_BROADCAST] = "BROADCAST",
2320 [RTN_ANYCAST] = "ANYCAST",
2321 [RTN_MULTICAST] = "MULTICAST",
2322 [RTN_BLACKHOLE] = "BLACKHOLE",
2323 [RTN_UNREACHABLE] = "UNREACHABLE",
2324 [RTN_PROHIBIT] = "PROHIBIT",
2325 [RTN_THROW] = "THROW",
2326 [RTN_NAT] = "NAT",
2327 [RTN_XRESOLVE] = "XRESOLVE",
2328};
2329
Eric Dumazeta034ee32010-09-09 23:32:28 +00002330static inline const char *rtn_type(char *buf, size_t len, unsigned int t)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002331{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002332 if (t < __RTN_MAX && rtn_type_names[t])
2333 return rtn_type_names[t];
Eric Dumazet28d36e32008-01-14 23:09:56 -08002334 snprintf(buf, len, "type %u", t);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002335 return buf;
2336}
2337
2338/* Pretty print the trie */
Robert Olsson19baf832005-06-21 12:43:18 -07002339static int fib_trie_seq_show(struct seq_file *seq, void *v)
2340{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002341 const struct fib_trie_iter *iter = seq->private;
David S. Millerb299e4f2011-02-02 20:48:10 -08002342 struct rt_trie_node *n = v;
Robert Olsson19baf832005-06-21 12:43:18 -07002343
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002344 if (!node_parent_rcu(n))
2345 fib_table_print(seq, iter->tb);
Robert Olsson095b8502007-01-26 19:06:01 -08002346
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002347 if (IS_TNODE(n)) {
2348 struct tnode *tn = (struct tnode *) n;
Alexander Duyck64c9b6f2014-12-31 10:55:35 -08002349 __be32 prf = htonl(tn->key);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002350
Robert Olsson1d25cd62005-09-19 15:29:52 -07002351 seq_indent(seq, iter->depth-1);
Harvey Harrison673d57e2008-10-31 00:53:57 -07002352 seq_printf(seq, " +-- %pI4/%d %d %d %d\n",
2353 &prf, tn->pos, tn->bits, tn->full_children,
Robert Olsson1d25cd62005-09-19 15:29:52 -07002354 tn->empty_children);
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09002355
Olof Johansson91b9a272005-08-09 20:24:39 -07002356 } else {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002357 struct leaf *l = (struct leaf *) n;
Stephen Hemminger13280422008-01-22 21:54:37 -08002358 struct leaf_info *li;
Al Viro32ab5f82006-09-26 22:21:45 -07002359 __be32 val = htonl(l->key);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002360
2361 seq_indent(seq, iter->depth);
Harvey Harrison673d57e2008-10-31 00:53:57 -07002362 seq_printf(seq, " |-- %pI4\n", &val);
Eric Dumazet28d36e32008-01-14 23:09:56 -08002363
Sasha Levinb67bfe02013-02-27 17:06:00 -08002364 hlist_for_each_entry_rcu(li, &l->list, hlist) {
Stephen Hemminger13280422008-01-22 21:54:37 -08002365 struct fib_alias *fa;
Eric Dumazet28d36e32008-01-14 23:09:56 -08002366
Stephen Hemminger13280422008-01-22 21:54:37 -08002367 list_for_each_entry_rcu(fa, &li->falh, fa_list) {
2368 char buf1[32], buf2[32];
Eric Dumazet28d36e32008-01-14 23:09:56 -08002369
Stephen Hemminger13280422008-01-22 21:54:37 -08002370 seq_indent(seq, iter->depth+1);
2371 seq_printf(seq, " /%d %s %s", li->plen,
2372 rtn_scope(buf1, sizeof(buf1),
David S. Miller37e826c2011-03-24 18:06:47 -07002373 fa->fa_info->fib_scope),
Stephen Hemminger13280422008-01-22 21:54:37 -08002374 rtn_type(buf2, sizeof(buf2),
2375 fa->fa_type));
2376 if (fa->fa_tos)
Denis V. Lunevb9c4d822008-02-05 02:58:45 -08002377 seq_printf(seq, " tos=%d", fa->fa_tos);
Stephen Hemminger13280422008-01-22 21:54:37 -08002378 seq_putc(seq, '\n');
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002379 }
2380 }
Robert Olsson19baf832005-06-21 12:43:18 -07002381 }
2382
2383 return 0;
2384}
2385
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002386static const struct seq_operations fib_trie_seq_ops = {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002387 .start = fib_trie_seq_start,
2388 .next = fib_trie_seq_next,
2389 .stop = fib_trie_seq_stop,
2390 .show = fib_trie_seq_show,
Robert Olsson19baf832005-06-21 12:43:18 -07002391};
2392
2393static int fib_trie_seq_open(struct inode *inode, struct file *file)
2394{
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002395 return seq_open_net(inode, file, &fib_trie_seq_ops,
2396 sizeof(struct fib_trie_iter));
Robert Olsson19baf832005-06-21 12:43:18 -07002397}
2398
Arjan van de Ven9a321442007-02-12 00:55:35 -08002399static const struct file_operations fib_trie_fops = {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002400 .owner = THIS_MODULE,
2401 .open = fib_trie_seq_open,
2402 .read = seq_read,
2403 .llseek = seq_lseek,
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002404 .release = seq_release_net,
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002405};
2406
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002407struct fib_route_iter {
2408 struct seq_net_private p;
2409 struct trie *main_trie;
2410 loff_t pos;
2411 t_key key;
2412};
2413
2414static struct leaf *fib_route_get_idx(struct fib_route_iter *iter, loff_t pos)
2415{
2416 struct leaf *l = NULL;
2417 struct trie *t = iter->main_trie;
2418
2419 /* use cache location of last found key */
2420 if (iter->pos > 0 && pos >= iter->pos && (l = fib_find_node(t, iter->key)))
2421 pos -= iter->pos;
2422 else {
2423 iter->pos = 0;
2424 l = trie_firstleaf(t);
2425 }
2426
2427 while (l && pos-- > 0) {
2428 iter->pos++;
2429 l = trie_nextleaf(l);
2430 }
2431
2432 if (l)
2433 iter->key = pos; /* remember it */
2434 else
2435 iter->pos = 0; /* forget it */
2436
2437 return l;
2438}
2439
2440static void *fib_route_seq_start(struct seq_file *seq, loff_t *pos)
2441 __acquires(RCU)
2442{
2443 struct fib_route_iter *iter = seq->private;
2444 struct fib_table *tb;
2445
2446 rcu_read_lock();
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002447 tb = fib_get_table(seq_file_net(seq), RT_TABLE_MAIN);
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002448 if (!tb)
2449 return NULL;
2450
2451 iter->main_trie = (struct trie *) tb->tb_data;
2452 if (*pos == 0)
2453 return SEQ_START_TOKEN;
2454 else
2455 return fib_route_get_idx(iter, *pos - 1);
2456}
2457
2458static void *fib_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2459{
2460 struct fib_route_iter *iter = seq->private;
2461 struct leaf *l = v;
2462
2463 ++*pos;
2464 if (v == SEQ_START_TOKEN) {
2465 iter->pos = 0;
2466 l = trie_firstleaf(iter->main_trie);
2467 } else {
2468 iter->pos++;
2469 l = trie_nextleaf(l);
2470 }
2471
2472 if (l)
2473 iter->key = l->key;
2474 else
2475 iter->pos = 0;
2476 return l;
2477}
2478
2479static void fib_route_seq_stop(struct seq_file *seq, void *v)
2480 __releases(RCU)
2481{
2482 rcu_read_unlock();
2483}
2484
Eric Dumazeta034ee32010-09-09 23:32:28 +00002485static unsigned int fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002486{
Eric Dumazeta034ee32010-09-09 23:32:28 +00002487 unsigned int flags = 0;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002488
Eric Dumazeta034ee32010-09-09 23:32:28 +00002489 if (type == RTN_UNREACHABLE || type == RTN_PROHIBIT)
2490 flags = RTF_REJECT;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002491 if (fi && fi->fib_nh->nh_gw)
2492 flags |= RTF_GATEWAY;
Al Viro32ab5f82006-09-26 22:21:45 -07002493 if (mask == htonl(0xFFFFFFFF))
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002494 flags |= RTF_HOST;
2495 flags |= RTF_UP;
2496 return flags;
2497}
2498
2499/*
2500 * This outputs /proc/net/route.
2501 * The format of the file is not supposed to be changed
Eric Dumazeta034ee32010-09-09 23:32:28 +00002502 * and needs to be same as fib_hash output to avoid breaking
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002503 * legacy utilities
2504 */
2505static int fib_route_seq_show(struct seq_file *seq, void *v)
2506{
2507 struct leaf *l = v;
Stephen Hemminger13280422008-01-22 21:54:37 -08002508 struct leaf_info *li;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002509
2510 if (v == SEQ_START_TOKEN) {
2511 seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
2512 "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
2513 "\tWindow\tIRTT");
2514 return 0;
2515 }
2516
Sasha Levinb67bfe02013-02-27 17:06:00 -08002517 hlist_for_each_entry_rcu(li, &l->list, hlist) {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002518 struct fib_alias *fa;
Al Viro32ab5f82006-09-26 22:21:45 -07002519 __be32 mask, prefix;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002520
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002521 mask = inet_make_mask(li->plen);
2522 prefix = htonl(l->key);
2523
2524 list_for_each_entry_rcu(fa, &li->falh, fa_list) {
Herbert Xu1371e372005-10-15 09:42:39 +10002525 const struct fib_info *fi = fa->fa_info;
Eric Dumazeta034ee32010-09-09 23:32:28 +00002526 unsigned int flags = fib_flag_trans(fa->fa_type, mask, fi);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002527
2528 if (fa->fa_type == RTN_BROADCAST
2529 || fa->fa_type == RTN_MULTICAST)
2530 continue;
2531
Tetsuo Handa652586d2013-11-14 14:31:57 -08002532 seq_setwidth(seq, 127);
2533
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002534 if (fi)
Pavel Emelyanov5e659e42008-04-24 01:02:16 -07002535 seq_printf(seq,
2536 "%s\t%08X\t%08X\t%04X\t%d\t%u\t"
Tetsuo Handa652586d2013-11-14 14:31:57 -08002537 "%d\t%08X\t%d\t%u\t%u",
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002538 fi->fib_dev ? fi->fib_dev->name : "*",
2539 prefix,
2540 fi->fib_nh->nh_gw, flags, 0, 0,
2541 fi->fib_priority,
2542 mask,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08002543 (fi->fib_advmss ?
2544 fi->fib_advmss + 40 : 0),
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002545 fi->fib_window,
Tetsuo Handa652586d2013-11-14 14:31:57 -08002546 fi->fib_rtt >> 3);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002547 else
Pavel Emelyanov5e659e42008-04-24 01:02:16 -07002548 seq_printf(seq,
2549 "*\t%08X\t%08X\t%04X\t%d\t%u\t"
Tetsuo Handa652586d2013-11-14 14:31:57 -08002550 "%d\t%08X\t%d\t%u\t%u",
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002551 prefix, 0, flags, 0, 0, 0,
Tetsuo Handa652586d2013-11-14 14:31:57 -08002552 mask, 0, 0, 0);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002553
Tetsuo Handa652586d2013-11-14 14:31:57 -08002554 seq_pad(seq, '\n');
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002555 }
2556 }
2557
2558 return 0;
2559}
2560
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002561static const struct seq_operations fib_route_seq_ops = {
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002562 .start = fib_route_seq_start,
2563 .next = fib_route_seq_next,
2564 .stop = fib_route_seq_stop,
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002565 .show = fib_route_seq_show,
2566};
2567
2568static int fib_route_seq_open(struct inode *inode, struct file *file)
2569{
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002570 return seq_open_net(inode, file, &fib_route_seq_ops,
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002571 sizeof(struct fib_route_iter));
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002572}
2573
Arjan van de Ven9a321442007-02-12 00:55:35 -08002574static const struct file_operations fib_route_fops = {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002575 .owner = THIS_MODULE,
2576 .open = fib_route_seq_open,
2577 .read = seq_read,
2578 .llseek = seq_lseek,
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002579 .release = seq_release_net,
Robert Olsson19baf832005-06-21 12:43:18 -07002580};
2581
Denis V. Lunev61a02652008-01-10 03:21:09 -08002582int __net_init fib_proc_init(struct net *net)
Robert Olsson19baf832005-06-21 12:43:18 -07002583{
Gao fengd4beaa62013-02-18 01:34:54 +00002584 if (!proc_create("fib_trie", S_IRUGO, net->proc_net, &fib_trie_fops))
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002585 goto out1;
2586
Gao fengd4beaa62013-02-18 01:34:54 +00002587 if (!proc_create("fib_triestat", S_IRUGO, net->proc_net,
2588 &fib_triestat_fops))
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002589 goto out2;
2590
Gao fengd4beaa62013-02-18 01:34:54 +00002591 if (!proc_create("route", S_IRUGO, net->proc_net, &fib_route_fops))
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002592 goto out3;
2593
Robert Olsson19baf832005-06-21 12:43:18 -07002594 return 0;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002595
2596out3:
Gao fengece31ff2013-02-18 01:34:56 +00002597 remove_proc_entry("fib_triestat", net->proc_net);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002598out2:
Gao fengece31ff2013-02-18 01:34:56 +00002599 remove_proc_entry("fib_trie", net->proc_net);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002600out1:
2601 return -ENOMEM;
Robert Olsson19baf832005-06-21 12:43:18 -07002602}
2603
Denis V. Lunev61a02652008-01-10 03:21:09 -08002604void __net_exit fib_proc_exit(struct net *net)
Robert Olsson19baf832005-06-21 12:43:18 -07002605{
Gao fengece31ff2013-02-18 01:34:56 +00002606 remove_proc_entry("fib_trie", net->proc_net);
2607 remove_proc_entry("fib_triestat", net->proc_net);
2608 remove_proc_entry("route", net->proc_net);
Robert Olsson19baf832005-06-21 12:43:18 -07002609}
2610
2611#endif /* CONFIG_PROC_FS */