blob: 94c929f6c7529218116540eb67278779df1495f9 [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;
Alexander Duyck37fd30f2014-12-31 10:55:41 -080098 struct rcu_head rcu;
Alexander Duyckadaf9812014-12-31 10:55:47 -080099 union {
100 /* The fields in this struct are valid if bits > 0 (TNODE) */
101 struct {
102 unsigned int full_children; /* KEYLENGTH bits needed */
103 unsigned int empty_children; /* KEYLENGTH bits needed */
104 struct tnode __rcu *child[0];
105 };
106 /* This list pointer if valid if bits == 0 (LEAF) */
107 struct hlist_head list;
108 };
Robert Olsson19baf832005-06-21 12:43:18 -0700109};
110
111struct leaf_info {
112 struct hlist_node hlist;
113 int plen;
Eric Dumazet5c745012011-07-18 03:16:33 +0000114 u32 mask_plen; /* ntohl(inet_make_mask(plen)) */
Robert Olsson19baf832005-06-21 12:43:18 -0700115 struct list_head falh;
Eric Dumazet5c745012011-07-18 03:16:33 +0000116 struct rcu_head rcu;
Robert Olsson19baf832005-06-21 12:43:18 -0700117};
118
Robert Olsson19baf832005-06-21 12:43:18 -0700119#ifdef CONFIG_IP_FIB_TRIE_STATS
120struct trie_use_stats {
121 unsigned int gets;
122 unsigned int backtrack;
123 unsigned int semantic_match_passed;
124 unsigned int semantic_match_miss;
125 unsigned int null_node_hit;
Robert Olsson2f368952005-07-05 15:02:40 -0700126 unsigned int resize_node_skipped;
Robert Olsson19baf832005-06-21 12:43:18 -0700127};
128#endif
129
130struct trie_stat {
131 unsigned int totdepth;
132 unsigned int maxdepth;
133 unsigned int tnodes;
134 unsigned int leaves;
135 unsigned int nullpointers;
Stephen Hemminger93672292008-01-22 21:54:05 -0800136 unsigned int prefixes;
Robert Olsson06ef9212006-03-20 21:35:01 -0800137 unsigned int nodesizes[MAX_STAT_DEPTH];
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700138};
Robert Olsson19baf832005-06-21 12:43:18 -0700139
140struct trie {
Alexander Duyckadaf9812014-12-31 10:55:47 -0800141 struct tnode __rcu *trie;
Robert Olsson19baf832005-06-21 12:43:18 -0700142#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -0800143 struct trie_use_stats __percpu *stats;
Robert Olsson19baf832005-06-21 12:43:18 -0700144#endif
Robert Olsson19baf832005-06-21 12:43:18 -0700145};
146
Alexander Duyckadaf9812014-12-31 10:55:47 -0800147static void tnode_put_child_reorg(struct tnode *tn, int i, struct tnode *n,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800148 int wasfull);
Alexander Duyckadaf9812014-12-31 10:55:47 -0800149static struct tnode *resize(struct trie *t, struct tnode *tn);
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700150static struct tnode *inflate(struct trie *t, struct tnode *tn);
151static struct tnode *halve(struct trie *t, struct tnode *tn);
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700152/* tnodes to free after resize(); protected by RTNL */
Alexander Duyck37fd30f2014-12-31 10:55:41 -0800153static struct callback_head *tnode_free_head;
Jarek Poplawskic3059472009-07-14 08:33:08 +0000154static size_t tnode_free_size;
155
156/*
157 * synchronize_rcu after call_rcu for that many pages; it should be especially
158 * useful before resizing the root node with PREEMPT_NONE configs; the value was
159 * obtained experimentally, aiming to avoid visible slowdown.
160 */
161static const int sync_pages = 128;
Robert Olsson19baf832005-06-21 12:43:18 -0700162
Christoph Lametere18b8902006-12-06 20:33:20 -0800163static struct kmem_cache *fn_alias_kmem __read_mostly;
Stephen Hemmingerbc3c8c12008-01-22 21:51:50 -0800164static struct kmem_cache *trie_leaf_kmem __read_mostly;
Robert Olsson19baf832005-06-21 12:43:18 -0700165
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800166/* caller must hold RTNL */
167#define node_parent(n) rtnl_dereference((n)->parent)
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700168
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800169/* caller must hold RCU read lock or RTNL */
170#define node_parent_rcu(n) rcu_dereference_rtnl((n)->parent)
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700171
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800172/* wrapper for rcu_assign_pointer */
Alexander Duyckadaf9812014-12-31 10:55:47 -0800173static inline void node_set_parent(struct tnode *n, struct tnode *tp)
Stephen Hemminger06801912007-08-10 15:22:13 -0700174{
Alexander Duyckadaf9812014-12-31 10:55:47 -0800175 if (n)
176 rcu_assign_pointer(n->parent, tp);
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800177}
178
179#define NODE_INIT_PARENT(n, p) RCU_INIT_POINTER((n)->parent, p)
180
181/* This provides us with the number of children in this node, in the case of a
182 * leaf this will return 0 meaning none of the children are accessible.
183 */
184static inline int tnode_child_length(const struct tnode *tn)
185{
186 return (1ul << tn->bits) & ~(1ul);
Stephen Hemminger06801912007-08-10 15:22:13 -0700187}
Robert Olsson2373ce12005-08-25 13:01:29 -0700188
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700189/*
190 * caller must hold RTNL
191 */
Alexander Duyckadaf9812014-12-31 10:55:47 -0800192static inline struct tnode *tnode_get_child(const struct tnode *tn, unsigned int i)
Robert Olsson19baf832005-06-21 12:43:18 -0700193{
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800194 BUG_ON(i >= tnode_child_length(tn));
Robert Olsson19baf832005-06-21 12:43:18 -0700195
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700196 return rtnl_dereference(tn->child[i]);
Eric Dumazetb59cfbf2008-01-18 03:31:36 -0800197}
198
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700199/*
200 * caller must hold RCU read lock or RTNL
201 */
Alexander Duyckadaf9812014-12-31 10:55:47 -0800202static inline struct tnode *tnode_get_child_rcu(const struct tnode *tn, unsigned int i)
Eric Dumazetb59cfbf2008-01-18 03:31:36 -0800203{
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800204 BUG_ON(i >= tnode_child_length(tn));
Eric Dumazetb59cfbf2008-01-18 03:31:36 -0800205
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700206 return rcu_dereference_rtnl(tn->child[i]);
Robert Olsson19baf832005-06-21 12:43:18 -0700207}
208
David S. Miller3b004562011-02-16 14:56:22 -0800209static inline t_key mask_pfx(t_key k, unsigned int l)
Stephen Hemmingerab66b4a2007-08-10 15:22:58 -0700210{
211 return (l == 0) ? 0 : k >> (KEYLENGTH-l) << (KEYLENGTH-l);
212}
213
David S. Miller3b004562011-02-16 14:56:22 -0800214static inline t_key tkey_extract_bits(t_key a, unsigned int offset, unsigned int bits)
Robert Olsson19baf832005-06-21 12:43:18 -0700215{
Olof Johansson91b9a272005-08-09 20:24:39 -0700216 if (offset < KEYLENGTH)
Robert Olsson19baf832005-06-21 12:43:18 -0700217 return ((t_key)(a << offset)) >> (KEYLENGTH - bits);
Olof Johansson91b9a272005-08-09 20:24:39 -0700218 else
Robert Olsson19baf832005-06-21 12:43:18 -0700219 return 0;
220}
221
222static inline int tkey_equals(t_key a, t_key b)
223{
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700224 return a == b;
Robert Olsson19baf832005-06-21 12:43:18 -0700225}
226
227static inline int tkey_sub_equals(t_key a, int offset, int bits, t_key b)
228{
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700229 if (bits == 0 || offset >= KEYLENGTH)
230 return 1;
Olof Johansson91b9a272005-08-09 20:24:39 -0700231 bits = bits > KEYLENGTH ? KEYLENGTH : bits;
232 return ((a ^ b) << offset) >> (KEYLENGTH - bits) == 0;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700233}
Robert Olsson19baf832005-06-21 12:43:18 -0700234
235static inline int tkey_mismatch(t_key a, int offset, t_key b)
236{
237 t_key diff = a ^ b;
238 int i = offset;
239
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700240 if (!diff)
241 return 0;
242 while ((diff << i) >> (KEYLENGTH-1) == 0)
Robert Olsson19baf832005-06-21 12:43:18 -0700243 i++;
244 return i;
245}
246
Robert Olsson19baf832005-06-21 12:43:18 -0700247/*
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900248 To understand this stuff, an understanding of keys and all their bits is
249 necessary. Every node in the trie has a key associated with it, but not
Robert Olsson19baf832005-06-21 12:43:18 -0700250 all of the bits in that key are significant.
251
252 Consider a node 'n' and its parent 'tp'.
253
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900254 If n is a leaf, every bit in its key is significant. Its presence is
255 necessitated by path compression, since during a tree traversal (when
256 searching for a leaf - unless we are doing an insertion) we will completely
257 ignore all skipped bits we encounter. Thus we need to verify, at the end of
258 a potentially successful search, that we have indeed been walking the
Robert Olsson19baf832005-06-21 12:43:18 -0700259 correct key path.
260
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900261 Note that we can never "miss" the correct key in the tree if present by
262 following the wrong path. Path compression ensures that segments of the key
263 that are the same for all keys with a given prefix are skipped, but the
264 skipped part *is* identical for each node in the subtrie below the skipped
265 bit! trie_insert() in this implementation takes care of that - note the
Robert Olsson19baf832005-06-21 12:43:18 -0700266 call to tkey_sub_equals() in trie_insert().
267
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900268 if n is an internal node - a 'tnode' here, the various parts of its key
Robert Olsson19baf832005-06-21 12:43:18 -0700269 have many different meanings.
270
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900271 Example:
Robert Olsson19baf832005-06-21 12:43:18 -0700272 _________________________________________________________________
273 | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C |
274 -----------------------------------------------------------------
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900275 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Robert Olsson19baf832005-06-21 12:43:18 -0700276
277 _________________________________________________________________
278 | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u |
279 -----------------------------------------------------------------
280 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
281
282 tp->pos = 7
283 tp->bits = 3
284 n->pos = 15
Olof Johansson91b9a272005-08-09 20:24:39 -0700285 n->bits = 4
Robert Olsson19baf832005-06-21 12:43:18 -0700286
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900287 First, let's just ignore the bits that come before the parent tp, that is
288 the bits from 0 to (tp->pos-1). They are *known* but at this point we do
Robert Olsson19baf832005-06-21 12:43:18 -0700289 not use them for anything.
290
291 The bits from (tp->pos) to (tp->pos + tp->bits - 1) - "N", above - are the
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900292 index into the parent's child array. That is, they will be used to find
Robert Olsson19baf832005-06-21 12:43:18 -0700293 'n' among tp's children.
294
295 The bits from (tp->pos + tp->bits) to (n->pos - 1) - "S" - are skipped bits
296 for the node n.
297
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900298 All the bits we have seen so far are significant to the node n. The rest
Robert Olsson19baf832005-06-21 12:43:18 -0700299 of the bits are really not needed or indeed known in n->key.
300
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900301 The bits from (n->pos) to (n->pos + n->bits - 1) - "C" - are the index into
Robert Olsson19baf832005-06-21 12:43:18 -0700302 n's child array, and will of course be different for each child.
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900303
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700304
Robert Olsson19baf832005-06-21 12:43:18 -0700305 The rest of the bits, from (n->pos + n->bits) onward, are completely unknown
306 at this point.
307
308*/
309
Denis V. Lunevf5026fa2007-12-13 09:47:57 -0800310static const int halve_threshold = 25;
311static const int inflate_threshold = 50;
Jarek Poplawski345aa032009-07-07 19:39:16 -0700312static const int halve_threshold_root = 15;
Jens Låås80b71b82009-08-28 23:57:15 -0700313static const int inflate_threshold_root = 30;
Robert Olsson2373ce12005-08-25 13:01:29 -0700314
315static void __alias_free_mem(struct rcu_head *head)
316{
317 struct fib_alias *fa = container_of(head, struct fib_alias, rcu);
318 kmem_cache_free(fn_alias_kmem, fa);
319}
320
321static inline void alias_free_mem_rcu(struct fib_alias *fa)
322{
323 call_rcu(&fa->rcu, __alias_free_mem);
324}
325
Alexander Duyck37fd30f2014-12-31 10:55:41 -0800326#define TNODE_KMALLOC_MAX \
Alexander Duyckadaf9812014-12-31 10:55:47 -0800327 ilog2((PAGE_SIZE - sizeof(struct tnode)) / sizeof(struct tnode *))
Alexander Duyck37fd30f2014-12-31 10:55:41 -0800328
329static void __node_free_rcu(struct rcu_head *head)
Robert Olsson2373ce12005-08-25 13:01:29 -0700330{
Alexander Duyckadaf9812014-12-31 10:55:47 -0800331 struct tnode *n = container_of(head, struct tnode, rcu);
Alexander Duyck37fd30f2014-12-31 10:55:41 -0800332
333 if (IS_LEAF(n))
334 kmem_cache_free(trie_leaf_kmem, n);
335 else if (n->bits <= TNODE_KMALLOC_MAX)
336 kfree(n);
337 else
338 vfree(n);
Robert Olsson2373ce12005-08-25 13:01:29 -0700339}
340
Alexander Duyck37fd30f2014-12-31 10:55:41 -0800341#define node_free(n) call_rcu(&n->rcu, __node_free_rcu)
Stephen Hemminger387a5482008-04-10 03:47:34 -0700342
Robert Olsson2373ce12005-08-25 13:01:29 -0700343static inline void free_leaf_info(struct leaf_info *leaf)
344{
Lai Jiangshanbceb0f42011-03-18 11:42:34 +0800345 kfree_rcu(leaf, rcu);
Robert Olsson2373ce12005-08-25 13:01:29 -0700346}
347
Eric Dumazet8d965442008-01-13 22:31:44 -0800348static struct tnode *tnode_alloc(size_t size)
Robert Olsson2373ce12005-08-25 13:01:29 -0700349{
Robert Olsson2373ce12005-08-25 13:01:29 -0700350 if (size <= PAGE_SIZE)
Eric Dumazet8d965442008-01-13 22:31:44 -0800351 return kzalloc(size, GFP_KERNEL);
Stephen Hemminger15be75c2008-04-10 02:56:38 -0700352 else
Eric Dumazet7a1c8e52010-11-20 07:46:35 +0000353 return vzalloc(size);
Stephen Hemminger15be75c2008-04-10 02:56:38 -0700354}
Robert Olsson2373ce12005-08-25 13:01:29 -0700355
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700356static void tnode_free_safe(struct tnode *tn)
357{
358 BUG_ON(IS_LEAF(tn));
Alexander Duyck37fd30f2014-12-31 10:55:41 -0800359 tn->rcu.next = tnode_free_head;
360 tnode_free_head = &tn->rcu;
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700361}
362
363static void tnode_free_flush(void)
364{
Alexander Duyck37fd30f2014-12-31 10:55:41 -0800365 struct callback_head *head;
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700366
Alexander Duyck37fd30f2014-12-31 10:55:41 -0800367 while ((head = tnode_free_head)) {
368 struct tnode *tn = container_of(head, struct tnode, rcu);
369
370 tnode_free_head = head->next;
371 tnode_free_size += offsetof(struct tnode, child[1 << tn->bits]);
372
373 node_free(tn);
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700374 }
Jarek Poplawskic3059472009-07-14 08:33:08 +0000375
376 if (tnode_free_size >= PAGE_SIZE * sync_pages) {
377 tnode_free_size = 0;
378 synchronize_rcu();
379 }
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700380}
381
Alexander Duyckadaf9812014-12-31 10:55:47 -0800382static struct tnode *leaf_new(t_key key)
Robert Olsson19baf832005-06-21 12:43:18 -0700383{
Alexander Duyckadaf9812014-12-31 10:55:47 -0800384 struct tnode *l = kmem_cache_alloc(trie_leaf_kmem, GFP_KERNEL);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700385 if (l) {
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800386 l->parent = NULL;
387 /* set key and pos to reflect full key value
388 * any trailing zeros in the key should be ignored
389 * as the nodes are searched
390 */
391 l->key = key;
392 l->pos = KEYLENGTH;
393 /* set bits to 0 indicating we are not a tnode */
394 l->bits = 0;
395
Robert Olsson19baf832005-06-21 12:43:18 -0700396 INIT_HLIST_HEAD(&l->list);
397 }
398 return l;
399}
400
401static struct leaf_info *leaf_info_new(int plen)
402{
403 struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL);
Robert Olsson2373ce12005-08-25 13:01:29 -0700404 if (li) {
405 li->plen = plen;
Eric Dumazet5c745012011-07-18 03:16:33 +0000406 li->mask_plen = ntohl(inet_make_mask(plen));
Robert Olsson2373ce12005-08-25 13:01:29 -0700407 INIT_LIST_HEAD(&li->falh);
Patrick McHardyf0e36f82005-07-05 14:44:55 -0700408 }
Robert Olsson2373ce12005-08-25 13:01:29 -0700409 return li;
Patrick McHardyf0e36f82005-07-05 14:44:55 -0700410}
411
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800412static struct tnode *tnode_new(t_key key, int pos, int bits)
Robert Olsson19baf832005-06-21 12:43:18 -0700413{
Alexander Duyck37fd30f2014-12-31 10:55:41 -0800414 size_t sz = offsetof(struct tnode, child[1 << bits]);
Patrick McHardyf0e36f82005-07-05 14:44:55 -0700415 struct tnode *tn = tnode_alloc(sz);
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800416 unsigned int shift = pos + bits;
417
418 /* verify bits and pos their msb bits clear and values are valid */
419 BUG_ON(!bits || (shift > KEYLENGTH));
Robert Olsson19baf832005-06-21 12:43:18 -0700420
Olof Johansson91b9a272005-08-09 20:24:39 -0700421 if (tn) {
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800422 tn->parent = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -0700423 tn->pos = pos;
424 tn->bits = bits;
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800425 tn->key = mask_pfx(key, pos);
Robert Olsson19baf832005-06-21 12:43:18 -0700426 tn->full_children = 0;
427 tn->empty_children = 1<<bits;
428 }
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700429
Eric Dumazeta034ee32010-09-09 23:32:28 +0000430 pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode),
Alexander Duyckadaf9812014-12-31 10:55:47 -0800431 sizeof(struct tnode *) << bits);
Robert Olsson19baf832005-06-21 12:43:18 -0700432 return tn;
433}
434
Robert Olsson19baf832005-06-21 12:43:18 -0700435/*
436 * Check whether a tnode 'n' is "full", i.e. it is an internal node
437 * and no bits are skipped. See discussion in dyntree paper p. 6
438 */
439
Alexander Duyckadaf9812014-12-31 10:55:47 -0800440static inline int tnode_full(const struct tnode *tn, const struct tnode *n)
Robert Olsson19baf832005-06-21 12:43:18 -0700441{
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800442 return n && IS_TNODE(n) && (n->pos == (tn->pos + tn->bits));
Robert Olsson19baf832005-06-21 12:43:18 -0700443}
444
Lin Ming61648d92012-07-29 02:00:03 +0000445static inline void put_child(struct tnode *tn, int i,
Alexander Duyckadaf9812014-12-31 10:55:47 -0800446 struct tnode *n)
Robert Olsson19baf832005-06-21 12:43:18 -0700447{
448 tnode_put_child_reorg(tn, i, n, -1);
449}
450
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700451 /*
Robert Olsson19baf832005-06-21 12:43:18 -0700452 * Add a child at position i overwriting the old value.
453 * Update the value of full_children and empty_children.
454 */
455
Alexander Duyckadaf9812014-12-31 10:55:47 -0800456static void tnode_put_child_reorg(struct tnode *tn, int i, struct tnode *n,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800457 int wasfull)
Robert Olsson19baf832005-06-21 12:43:18 -0700458{
Alexander Duyckadaf9812014-12-31 10:55:47 -0800459 struct tnode *chi = rtnl_dereference(tn->child[i]);
Robert Olsson19baf832005-06-21 12:43:18 -0700460 int isfull;
461
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700462 BUG_ON(i >= 1<<tn->bits);
463
Robert Olsson19baf832005-06-21 12:43:18 -0700464 /* update emptyChildren */
465 if (n == NULL && chi != NULL)
466 tn->empty_children++;
467 else if (n != NULL && chi == NULL)
468 tn->empty_children--;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700469
Robert Olsson19baf832005-06-21 12:43:18 -0700470 /* update fullChildren */
Olof Johansson91b9a272005-08-09 20:24:39 -0700471 if (wasfull == -1)
Robert Olsson19baf832005-06-21 12:43:18 -0700472 wasfull = tnode_full(tn, chi);
473
474 isfull = tnode_full(tn, n);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700475 if (wasfull && !isfull)
Robert Olsson19baf832005-06-21 12:43:18 -0700476 tn->full_children--;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700477 else if (!wasfull && isfull)
Robert Olsson19baf832005-06-21 12:43:18 -0700478 tn->full_children++;
Olof Johansson91b9a272005-08-09 20:24:39 -0700479
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800480 node_set_parent(n, tn);
Robert Olsson19baf832005-06-21 12:43:18 -0700481
Eric Dumazetcf778b02012-01-12 04:41:32 +0000482 rcu_assign_pointer(tn->child[i], n);
Robert Olsson19baf832005-06-21 12:43:18 -0700483}
484
Jens Låås80b71b82009-08-28 23:57:15 -0700485#define MAX_WORK 10
Alexander Duyckadaf9812014-12-31 10:55:47 -0800486static struct tnode *resize(struct trie *t, struct tnode *tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700487{
Alexander Duyckadaf9812014-12-31 10:55:47 -0800488 struct tnode *old_tn, *n = NULL;
Robert Olssone6308be2005-10-04 13:01:58 -0700489 int inflate_threshold_use;
490 int halve_threshold_use;
Jens Låås80b71b82009-08-28 23:57:15 -0700491 int max_work;
Robert Olsson19baf832005-06-21 12:43:18 -0700492
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900493 if (!tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700494 return NULL;
495
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700496 pr_debug("In tnode_resize %p inflate_threshold=%d threshold=%d\n",
497 tn, inflate_threshold, halve_threshold);
Robert Olsson19baf832005-06-21 12:43:18 -0700498
499 /* No children */
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800500 if (tn->empty_children > (tnode_child_length(tn) - 1))
501 goto no_children;
502
Robert Olsson19baf832005-06-21 12:43:18 -0700503 /* One child */
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800504 if (tn->empty_children == (tnode_child_length(tn) - 1))
Jens Låås80b71b82009-08-28 23:57:15 -0700505 goto one_child;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700506 /*
Robert Olsson19baf832005-06-21 12:43:18 -0700507 * Double as long as the resulting node has a number of
508 * nonempty nodes that are above the threshold.
509 */
510
511 /*
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700512 * From "Implementing a dynamic compressed trie" by Stefan Nilsson of
513 * the Helsinki University of Technology and Matti Tikkanen of Nokia
Robert Olsson19baf832005-06-21 12:43:18 -0700514 * Telecommunications, page 6:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700515 * "A node is doubled if the ratio of non-empty children to all
Robert Olsson19baf832005-06-21 12:43:18 -0700516 * children in the *doubled* node is at least 'high'."
517 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700518 * 'high' in this instance is the variable 'inflate_threshold'. It
519 * is expressed as a percentage, so we multiply it with
520 * tnode_child_length() and instead of multiplying by 2 (since the
521 * child array will be doubled by inflate()) and multiplying
522 * the left-hand side by 100 (to handle the percentage thing) we
Robert Olsson19baf832005-06-21 12:43:18 -0700523 * multiply the left-hand side by 50.
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700524 *
525 * The left-hand side may look a bit weird: tnode_child_length(tn)
526 * - tn->empty_children is of course the number of non-null children
527 * in the current node. tn->full_children is the number of "full"
Robert Olsson19baf832005-06-21 12:43:18 -0700528 * children, that is non-null tnodes with a skip value of 0.
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700529 * All of those will be doubled in the resulting inflated tnode, so
Robert Olsson19baf832005-06-21 12:43:18 -0700530 * we just count them one extra time here.
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700531 *
Robert Olsson19baf832005-06-21 12:43:18 -0700532 * A clearer way to write this would be:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700533 *
Robert Olsson19baf832005-06-21 12:43:18 -0700534 * to_be_doubled = tn->full_children;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700535 * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children -
Robert Olsson19baf832005-06-21 12:43:18 -0700536 * tn->full_children;
537 *
538 * new_child_length = tnode_child_length(tn) * 2;
539 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700540 * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) /
Robert Olsson19baf832005-06-21 12:43:18 -0700541 * new_child_length;
542 * if (new_fill_factor >= inflate_threshold)
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700543 *
544 * ...and so on, tho it would mess up the while () loop.
545 *
Robert Olsson19baf832005-06-21 12:43:18 -0700546 * anyway,
547 * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >=
548 * inflate_threshold
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700549 *
Robert Olsson19baf832005-06-21 12:43:18 -0700550 * avoid a division:
551 * 100 * (not_to_be_doubled + 2*to_be_doubled) >=
552 * inflate_threshold * new_child_length
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700553 *
Robert Olsson19baf832005-06-21 12:43:18 -0700554 * expand not_to_be_doubled and to_be_doubled, and shorten:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700555 * 100 * (tnode_child_length(tn) - tn->empty_children +
Olof Johansson91b9a272005-08-09 20:24:39 -0700556 * tn->full_children) >= inflate_threshold * new_child_length
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700557 *
Robert Olsson19baf832005-06-21 12:43:18 -0700558 * expand new_child_length:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700559 * 100 * (tnode_child_length(tn) - tn->empty_children +
Olof Johansson91b9a272005-08-09 20:24:39 -0700560 * tn->full_children) >=
Robert Olsson19baf832005-06-21 12:43:18 -0700561 * inflate_threshold * tnode_child_length(tn) * 2
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700562 *
Robert Olsson19baf832005-06-21 12:43:18 -0700563 * shorten again:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700564 * 50 * (tn->full_children + tnode_child_length(tn) -
Olof Johansson91b9a272005-08-09 20:24:39 -0700565 * tn->empty_children) >= inflate_threshold *
Robert Olsson19baf832005-06-21 12:43:18 -0700566 * tnode_child_length(tn)
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700567 *
Robert Olsson19baf832005-06-21 12:43:18 -0700568 */
569
Robert Olssone6308be2005-10-04 13:01:58 -0700570 /* Keep root node larger */
571
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800572 if (!node_parent(tn)) {
Jens Låås80b71b82009-08-28 23:57:15 -0700573 inflate_threshold_use = inflate_threshold_root;
574 halve_threshold_use = halve_threshold_root;
Eric Dumazeta034ee32010-09-09 23:32:28 +0000575 } else {
Robert Olssone6308be2005-10-04 13:01:58 -0700576 inflate_threshold_use = inflate_threshold;
Jens Låås80b71b82009-08-28 23:57:15 -0700577 halve_threshold_use = halve_threshold;
578 }
Robert Olssone6308be2005-10-04 13:01:58 -0700579
Jens Låås80b71b82009-08-28 23:57:15 -0700580 max_work = MAX_WORK;
581 while ((tn->full_children > 0 && max_work-- &&
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800582 50 * (tn->full_children + tnode_child_length(tn)
583 - tn->empty_children)
584 >= inflate_threshold_use * tnode_child_length(tn))) {
Robert Olsson19baf832005-06-21 12:43:18 -0700585
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700586 old_tn = tn;
587 tn = inflate(t, tn);
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800588
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700589 if (IS_ERR(tn)) {
590 tn = old_tn;
Robert Olsson2f368952005-07-05 15:02:40 -0700591#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -0800592 this_cpu_inc(t->stats->resize_node_skipped);
Robert Olsson2f368952005-07-05 15:02:40 -0700593#endif
594 break;
595 }
Robert Olsson19baf832005-06-21 12:43:18 -0700596 }
597
Jens Låås80b71b82009-08-28 23:57:15 -0700598 /* Return if at least one inflate is run */
Eric Dumazeta034ee32010-09-09 23:32:28 +0000599 if (max_work != MAX_WORK)
Alexander Duyckadaf9812014-12-31 10:55:47 -0800600 return tn;
Jens Låås80b71b82009-08-28 23:57:15 -0700601
Robert Olsson19baf832005-06-21 12:43:18 -0700602 /*
603 * Halve as long as the number of empty children in this
604 * node is above threshold.
605 */
Robert Olsson2f368952005-07-05 15:02:40 -0700606
Jens Låås80b71b82009-08-28 23:57:15 -0700607 max_work = MAX_WORK;
608 while (tn->bits > 1 && max_work-- &&
Robert Olsson19baf832005-06-21 12:43:18 -0700609 100 * (tnode_child_length(tn) - tn->empty_children) <
Robert Olssone6308be2005-10-04 13:01:58 -0700610 halve_threshold_use * tnode_child_length(tn)) {
Robert Olsson19baf832005-06-21 12:43:18 -0700611
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700612 old_tn = tn;
613 tn = halve(t, tn);
614 if (IS_ERR(tn)) {
615 tn = old_tn;
Robert Olsson2f368952005-07-05 15:02:40 -0700616#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -0800617 this_cpu_inc(t->stats->resize_node_skipped);
Robert Olsson2f368952005-07-05 15:02:40 -0700618#endif
619 break;
620 }
621 }
622
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700623
Robert Olsson19baf832005-06-21 12:43:18 -0700624 /* Only one child remains */
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800625 if (tn->empty_children == (tnode_child_length(tn) - 1)) {
626 unsigned long i;
Jens Låås80b71b82009-08-28 23:57:15 -0700627one_child:
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800628 for (i = tnode_child_length(tn); !n && i;)
629 n = tnode_get_child(tn, --i);
630no_children:
631 /* compress one level */
632 node_set_parent(n, NULL);
633 tnode_free_safe(tn);
634 return n;
Jens Låås80b71b82009-08-28 23:57:15 -0700635 }
Alexander Duyckadaf9812014-12-31 10:55:47 -0800636 return tn;
Robert Olsson19baf832005-06-21 12:43:18 -0700637}
638
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700639
640static void tnode_clean_free(struct tnode *tn)
641{
Alexander Duyckadaf9812014-12-31 10:55:47 -0800642 struct tnode *tofree;
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700643 int i;
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700644
645 for (i = 0; i < tnode_child_length(tn); i++) {
Alexander Duyck37fd30f2014-12-31 10:55:41 -0800646 tofree = rtnl_dereference(tn->child[i]);
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700647 if (tofree)
Alexander Duyck37fd30f2014-12-31 10:55:41 -0800648 node_free(tofree);
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700649 }
Alexander Duyck37fd30f2014-12-31 10:55:41 -0800650 node_free(tn);
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700651}
652
Alexander Duyckadaf9812014-12-31 10:55:47 -0800653static struct tnode *inflate(struct trie *t, struct tnode *oldtnode)
Robert Olsson19baf832005-06-21 12:43:18 -0700654{
Alexander Duyckadaf9812014-12-31 10:55:47 -0800655 int olen = tnode_child_length(oldtnode);
656 struct tnode *tn;
Robert Olsson19baf832005-06-21 12:43:18 -0700657 int i;
658
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700659 pr_debug("In inflate\n");
Robert Olsson19baf832005-06-21 12:43:18 -0700660
661 tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits + 1);
662
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700663 if (!tn)
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700664 return ERR_PTR(-ENOMEM);
Robert Olsson2f368952005-07-05 15:02:40 -0700665
666 /*
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700667 * Preallocate and store tnodes before the actual work so we
668 * don't get into an inconsistent state if memory allocation
669 * fails. In case of failure we return the oldnode and inflate
Robert Olsson2f368952005-07-05 15:02:40 -0700670 * of tnode is ignored.
671 */
Olof Johansson91b9a272005-08-09 20:24:39 -0700672
673 for (i = 0; i < olen; i++) {
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800674 struct tnode *inode;
Robert Olsson2f368952005-07-05 15:02:40 -0700675
Alexander Duyckadaf9812014-12-31 10:55:47 -0800676 inode = tnode_get_child(oldtnode, i);
677 if (tnode_full(oldtnode, inode) && inode->bits > 1) {
Robert Olsson2f368952005-07-05 15:02:40 -0700678 struct tnode *left, *right;
Stephen Hemmingerab66b4a2007-08-10 15:22:58 -0700679 t_key m = ~0U << (KEYLENGTH - 1) >> inode->pos;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700680
Robert Olsson2f368952005-07-05 15:02:40 -0700681 left = tnode_new(inode->key&(~m), inode->pos + 1,
682 inode->bits - 1);
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700683 if (!left)
684 goto nomem;
Olof Johansson91b9a272005-08-09 20:24:39 -0700685
Robert Olsson2f368952005-07-05 15:02:40 -0700686 right = tnode_new(inode->key|m, inode->pos + 1,
687 inode->bits - 1);
688
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900689 if (!right) {
Alexander Duyck37fd30f2014-12-31 10:55:41 -0800690 node_free(left);
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700691 goto nomem;
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900692 }
Robert Olsson2f368952005-07-05 15:02:40 -0700693
Alexander Duyckadaf9812014-12-31 10:55:47 -0800694 put_child(tn, 2*i, left);
695 put_child(tn, 2*i+1, right);
Robert Olsson2f368952005-07-05 15:02:40 -0700696 }
697 }
698
Olof Johansson91b9a272005-08-09 20:24:39 -0700699 for (i = 0; i < olen; i++) {
Alexander Duyckadaf9812014-12-31 10:55:47 -0800700 struct tnode *inode = tnode_get_child(oldtnode, i);
Olof Johansson91b9a272005-08-09 20:24:39 -0700701 struct tnode *left, *right;
702 int size, j;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700703
Robert Olsson19baf832005-06-21 12:43:18 -0700704 /* An empty child */
Alexander Duyckadaf9812014-12-31 10:55:47 -0800705 if (inode == NULL)
Robert Olsson19baf832005-06-21 12:43:18 -0700706 continue;
707
708 /* A leaf or an internal node with skipped bits */
Alexander Duyckadaf9812014-12-31 10:55:47 -0800709 if (!tnode_full(oldtnode, inode)) {
baker.zhangbbe34cf2013-10-01 07:45:09 +0800710 put_child(tn,
Alexander Duyckadaf9812014-12-31 10:55:47 -0800711 tkey_extract_bits(inode->key, tn->pos, tn->bits),
712 inode);
Robert Olsson19baf832005-06-21 12:43:18 -0700713 continue;
714 }
715
716 /* An internal node with two children */
Robert Olsson19baf832005-06-21 12:43:18 -0700717 if (inode->bits == 1) {
Lin Ming61648d92012-07-29 02:00:03 +0000718 put_child(tn, 2*i, rtnl_dereference(inode->child[0]));
719 put_child(tn, 2*i+1, rtnl_dereference(inode->child[1]));
Robert Olsson19baf832005-06-21 12:43:18 -0700720
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700721 tnode_free_safe(inode);
Olof Johansson91b9a272005-08-09 20:24:39 -0700722 continue;
Robert Olsson19baf832005-06-21 12:43:18 -0700723 }
724
Olof Johansson91b9a272005-08-09 20:24:39 -0700725 /* An internal node with more than two children */
Robert Olsson19baf832005-06-21 12:43:18 -0700726
Olof Johansson91b9a272005-08-09 20:24:39 -0700727 /* We will replace this node 'inode' with two new
728 * ones, 'left' and 'right', each with half of the
729 * original children. The two new nodes will have
730 * a position one bit further down the key and this
731 * means that the "significant" part of their keys
732 * (see the discussion near the top of this file)
733 * will differ by one bit, which will be "0" in
734 * left's key and "1" in right's key. Since we are
735 * moving the key position by one step, the bit that
736 * we are moving away from - the bit at position
737 * (inode->pos) - is the one that will differ between
738 * left and right. So... we synthesize that bit in the
739 * two new keys.
740 * The mask 'm' below will be a single "one" bit at
741 * the position (inode->pos)
742 */
Robert Olsson19baf832005-06-21 12:43:18 -0700743
Olof Johansson91b9a272005-08-09 20:24:39 -0700744 /* Use the old key, but set the new significant
745 * bit to zero.
746 */
Robert Olsson19baf832005-06-21 12:43:18 -0700747
Alexander Duyckadaf9812014-12-31 10:55:47 -0800748 left = tnode_get_child(tn, 2*i);
Lin Ming61648d92012-07-29 02:00:03 +0000749 put_child(tn, 2*i, NULL);
Robert Olsson19baf832005-06-21 12:43:18 -0700750
Olof Johansson91b9a272005-08-09 20:24:39 -0700751 BUG_ON(!left);
Robert Olsson2f368952005-07-05 15:02:40 -0700752
Alexander Duyckadaf9812014-12-31 10:55:47 -0800753 right = tnode_get_child(tn, 2*i+1);
Lin Ming61648d92012-07-29 02:00:03 +0000754 put_child(tn, 2*i+1, NULL);
Robert Olsson2f368952005-07-05 15:02:40 -0700755
Olof Johansson91b9a272005-08-09 20:24:39 -0700756 BUG_ON(!right);
Robert Olsson2f368952005-07-05 15:02:40 -0700757
Olof Johansson91b9a272005-08-09 20:24:39 -0700758 size = tnode_child_length(left);
759 for (j = 0; j < size; j++) {
Lin Ming61648d92012-07-29 02:00:03 +0000760 put_child(left, j, rtnl_dereference(inode->child[j]));
761 put_child(right, j, rtnl_dereference(inode->child[j + size]));
Robert Olsson19baf832005-06-21 12:43:18 -0700762 }
Lin Ming61648d92012-07-29 02:00:03 +0000763 put_child(tn, 2*i, resize(t, left));
764 put_child(tn, 2*i+1, resize(t, right));
Olof Johansson91b9a272005-08-09 20:24:39 -0700765
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700766 tnode_free_safe(inode);
Robert Olsson19baf832005-06-21 12:43:18 -0700767 }
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700768 tnode_free_safe(oldtnode);
Robert Olsson19baf832005-06-21 12:43:18 -0700769 return tn;
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700770nomem:
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700771 tnode_clean_free(tn);
772 return ERR_PTR(-ENOMEM);
Robert Olsson19baf832005-06-21 12:43:18 -0700773}
774
Alexander Duyckadaf9812014-12-31 10:55:47 -0800775static struct tnode *halve(struct trie *t, struct tnode *oldtnode)
Robert Olsson19baf832005-06-21 12:43:18 -0700776{
Alexander Duyckadaf9812014-12-31 10:55:47 -0800777 int olen = tnode_child_length(oldtnode);
778 struct tnode *tn, *left, *right;
Robert Olsson19baf832005-06-21 12:43:18 -0700779 int i;
Robert Olsson19baf832005-06-21 12:43:18 -0700780
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700781 pr_debug("In halve\n");
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700782
783 tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits - 1);
Robert Olsson19baf832005-06-21 12:43:18 -0700784
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700785 if (!tn)
786 return ERR_PTR(-ENOMEM);
Robert Olsson2f368952005-07-05 15:02:40 -0700787
788 /*
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700789 * Preallocate and store tnodes before the actual work so we
790 * don't get into an inconsistent state if memory allocation
791 * fails. In case of failure we return the oldnode and halve
Robert Olsson2f368952005-07-05 15:02:40 -0700792 * of tnode is ignored.
793 */
794
Olof Johansson91b9a272005-08-09 20:24:39 -0700795 for (i = 0; i < olen; i += 2) {
Robert Olsson2f368952005-07-05 15:02:40 -0700796 left = tnode_get_child(oldtnode, i);
797 right = tnode_get_child(oldtnode, i+1);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700798
Robert Olsson2f368952005-07-05 15:02:40 -0700799 /* Two nonempty children */
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700800 if (left && right) {
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700801 struct tnode *newn;
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700802
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700803 newn = tnode_new(left->key, tn->pos + tn->bits, 1);
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700804
805 if (!newn)
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700806 goto nomem;
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700807
Alexander Duyckadaf9812014-12-31 10:55:47 -0800808 put_child(tn, i/2, newn);
Robert Olsson2f368952005-07-05 15:02:40 -0700809 }
Robert Olsson2f368952005-07-05 15:02:40 -0700810
Robert Olsson2f368952005-07-05 15:02:40 -0700811 }
Robert Olsson19baf832005-06-21 12:43:18 -0700812
Olof Johansson91b9a272005-08-09 20:24:39 -0700813 for (i = 0; i < olen; i += 2) {
814 struct tnode *newBinNode;
815
Robert Olsson19baf832005-06-21 12:43:18 -0700816 left = tnode_get_child(oldtnode, i);
817 right = tnode_get_child(oldtnode, i+1);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700818
Robert Olsson19baf832005-06-21 12:43:18 -0700819 /* At least one of the children is empty */
820 if (left == NULL) {
821 if (right == NULL) /* Both are empty */
822 continue;
Lin Ming61648d92012-07-29 02:00:03 +0000823 put_child(tn, i/2, right);
Olof Johansson91b9a272005-08-09 20:24:39 -0700824 continue;
Stephen Hemminger0c7770c2005-08-23 21:59:41 -0700825 }
Olof Johansson91b9a272005-08-09 20:24:39 -0700826
827 if (right == NULL) {
Lin Ming61648d92012-07-29 02:00:03 +0000828 put_child(tn, i/2, left);
Olof Johansson91b9a272005-08-09 20:24:39 -0700829 continue;
830 }
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700831
Robert Olsson19baf832005-06-21 12:43:18 -0700832 /* Two nonempty children */
Alexander Duyckadaf9812014-12-31 10:55:47 -0800833 newBinNode = tnode_get_child(tn, i/2);
Lin Ming61648d92012-07-29 02:00:03 +0000834 put_child(tn, i/2, NULL);
835 put_child(newBinNode, 0, left);
836 put_child(newBinNode, 1, right);
837 put_child(tn, i/2, resize(t, newBinNode));
Robert Olsson19baf832005-06-21 12:43:18 -0700838 }
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700839 tnode_free_safe(oldtnode);
Robert Olsson19baf832005-06-21 12:43:18 -0700840 return tn;
Robert Olsson2f80b3c2005-08-09 20:25:06 -0700841nomem:
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700842 tnode_clean_free(tn);
843 return ERR_PTR(-ENOMEM);
Robert Olsson19baf832005-06-21 12:43:18 -0700844}
845
Robert Olsson772cb712005-09-19 15:31:18 -0700846/* readside must use rcu_read_lock currently dump routines
Robert Olsson2373ce12005-08-25 13:01:29 -0700847 via get_fa_head and dump */
848
Alexander Duyckadaf9812014-12-31 10:55:47 -0800849static struct leaf_info *find_leaf_info(struct tnode *l, int plen)
Robert Olsson19baf832005-06-21 12:43:18 -0700850{
Robert Olsson772cb712005-09-19 15:31:18 -0700851 struct hlist_head *head = &l->list;
Robert Olsson19baf832005-06-21 12:43:18 -0700852 struct leaf_info *li;
853
Sasha Levinb67bfe02013-02-27 17:06:00 -0800854 hlist_for_each_entry_rcu(li, head, hlist)
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700855 if (li->plen == plen)
Robert Olsson19baf832005-06-21 12:43:18 -0700856 return li;
Olof Johansson91b9a272005-08-09 20:24:39 -0700857
Robert Olsson19baf832005-06-21 12:43:18 -0700858 return NULL;
859}
860
Alexander Duyckadaf9812014-12-31 10:55:47 -0800861static inline struct list_head *get_fa_head(struct tnode *l, int plen)
Robert Olsson19baf832005-06-21 12:43:18 -0700862{
Robert Olsson772cb712005-09-19 15:31:18 -0700863 struct leaf_info *li = find_leaf_info(l, plen);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700864
Olof Johansson91b9a272005-08-09 20:24:39 -0700865 if (!li)
866 return NULL;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700867
Olof Johansson91b9a272005-08-09 20:24:39 -0700868 return &li->falh;
Robert Olsson19baf832005-06-21 12:43:18 -0700869}
870
871static void insert_leaf_info(struct hlist_head *head, struct leaf_info *new)
872{
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900873 struct leaf_info *li = NULL, *last = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -0700874
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900875 if (hlist_empty(head)) {
876 hlist_add_head_rcu(&new->hlist, head);
877 } else {
Sasha Levinb67bfe02013-02-27 17:06:00 -0800878 hlist_for_each_entry(li, head, hlist) {
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900879 if (new->plen > li->plen)
880 break;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700881
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900882 last = li;
883 }
884 if (last)
Ken Helias1d023282014-08-06 16:09:16 -0700885 hlist_add_behind_rcu(&new->hlist, &last->hlist);
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900886 else
887 hlist_add_before_rcu(&new->hlist, &li->hlist);
888 }
Robert Olsson19baf832005-06-21 12:43:18 -0700889}
890
Robert Olsson2373ce12005-08-25 13:01:29 -0700891/* rcu_read_lock needs to be hold by caller from readside */
892
Alexander Duyckadaf9812014-12-31 10:55:47 -0800893static struct tnode *fib_find_node(struct trie *t, u32 key)
Robert Olsson19baf832005-06-21 12:43:18 -0700894{
Alexander Duyckadaf9812014-12-31 10:55:47 -0800895 struct tnode *n = rcu_dereference_rtnl(t->trie);
896 int pos = 0;
Robert Olsson19baf832005-06-21 12:43:18 -0700897
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800898 while (n && IS_TNODE(n)) {
Alexander Duyckadaf9812014-12-31 10:55:47 -0800899 if (tkey_sub_equals(n->key, pos, n->pos-pos, key)) {
900 pos = n->pos + n->bits;
901 n = tnode_get_child_rcu(n,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800902 tkey_extract_bits(key,
Alexander Duyckadaf9812014-12-31 10:55:47 -0800903 n->pos,
904 n->bits));
Olof Johansson91b9a272005-08-09 20:24:39 -0700905 } else
Robert Olsson19baf832005-06-21 12:43:18 -0700906 break;
907 }
908 /* Case we have found a leaf. Compare prefixes */
909
Olof Johansson91b9a272005-08-09 20:24:39 -0700910 if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key))
Alexander Duyckadaf9812014-12-31 10:55:47 -0800911 return n;
Olof Johansson91b9a272005-08-09 20:24:39 -0700912
Robert Olsson19baf832005-06-21 12:43:18 -0700913 return NULL;
914}
915
Jarek Poplawski7b855762009-06-18 00:28:51 -0700916static void trie_rebalance(struct trie *t, struct tnode *tn)
Robert Olsson19baf832005-06-21 12:43:18 -0700917{
Robert Olsson19baf832005-06-21 12:43:18 -0700918 int wasfull;
Robert Olsson3ed18d72009-05-21 15:20:59 -0700919 t_key cindex, key;
Stephen Hemminger06801912007-08-10 15:22:13 -0700920 struct tnode *tp;
Robert Olsson19baf832005-06-21 12:43:18 -0700921
Robert Olsson3ed18d72009-05-21 15:20:59 -0700922 key = tn->key;
923
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800924 while (tn != NULL && (tp = node_parent(tn)) != NULL) {
Robert Olsson19baf832005-06-21 12:43:18 -0700925 cindex = tkey_extract_bits(key, tp->pos, tp->bits);
926 wasfull = tnode_full(tp, tnode_get_child(tp, cindex));
Alexander Duyckadaf9812014-12-31 10:55:47 -0800927 tn = resize(t, tn);
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800928
Alexander Duyckadaf9812014-12-31 10:55:47 -0800929 tnode_put_child_reorg(tp, cindex, tn, wasfull);
Olof Johansson91b9a272005-08-09 20:24:39 -0700930
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800931 tp = node_parent(tn);
Jarek Poplawski008440e2009-06-30 12:47:19 -0700932 if (!tp)
Alexander Duyckadaf9812014-12-31 10:55:47 -0800933 rcu_assign_pointer(t->trie, tn);
Jarek Poplawski008440e2009-06-30 12:47:19 -0700934
Jarek Poplawskie0f7cb82009-06-15 02:31:29 -0700935 tnode_free_flush();
Stephen Hemminger06801912007-08-10 15:22:13 -0700936 if (!tp)
Robert Olsson19baf832005-06-21 12:43:18 -0700937 break;
Stephen Hemminger06801912007-08-10 15:22:13 -0700938 tn = tp;
Robert Olsson19baf832005-06-21 12:43:18 -0700939 }
Stephen Hemminger06801912007-08-10 15:22:13 -0700940
Robert Olsson19baf832005-06-21 12:43:18 -0700941 /* Handle last (top) tnode */
Jarek Poplawski7b855762009-06-18 00:28:51 -0700942 if (IS_TNODE(tn))
Alexander Duyckadaf9812014-12-31 10:55:47 -0800943 tn = resize(t, tn);
Robert Olsson19baf832005-06-21 12:43:18 -0700944
Alexander Duyckadaf9812014-12-31 10:55:47 -0800945 rcu_assign_pointer(t->trie, tn);
Jarek Poplawski7b855762009-06-18 00:28:51 -0700946 tnode_free_flush();
Robert Olsson19baf832005-06-21 12:43:18 -0700947}
948
Robert Olsson2373ce12005-08-25 13:01:29 -0700949/* only used from updater-side */
950
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -0800951static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
Robert Olsson19baf832005-06-21 12:43:18 -0700952{
953 int pos, newpos;
954 struct tnode *tp = NULL, *tn = NULL;
Alexander Duyckadaf9812014-12-31 10:55:47 -0800955 struct tnode *n;
956 struct tnode *l;
Robert Olsson19baf832005-06-21 12:43:18 -0700957 int missbit;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700958 struct list_head *fa_head = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -0700959 struct leaf_info *li;
960 t_key cindex;
961
962 pos = 0;
Eric Dumazet0a5c0472011-03-31 01:51:35 -0700963 n = rtnl_dereference(t->trie);
Robert Olsson19baf832005-06-21 12:43:18 -0700964
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700965 /* If we point to NULL, stop. Either the tree is empty and we should
966 * just put a new leaf in if, or we have reached an empty child slot,
Robert Olsson19baf832005-06-21 12:43:18 -0700967 * and we should just put our new leaf in that.
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700968 * If we point to a T_TNODE, check if it matches our key. Note that
969 * a T_TNODE might be skipping any number of bits - its 'pos' need
Robert Olsson19baf832005-06-21 12:43:18 -0700970 * not be the parent's 'pos'+'bits'!
971 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700972 * If it does match the current key, get pos/bits from it, extract
Robert Olsson19baf832005-06-21 12:43:18 -0700973 * the index from our key, push the T_TNODE and walk the tree.
974 *
975 * If it doesn't, we have to replace it with a new T_TNODE.
976 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -0700977 * If we point to a T_LEAF, it might or might not have the same key
978 * as we do. If it does, just change the value, update the T_LEAF's
979 * value, and return it.
Robert Olsson19baf832005-06-21 12:43:18 -0700980 * If it doesn't, we need to replace it with a T_TNODE.
981 */
982
Alexander Duyck64c9b6f2014-12-31 10:55:35 -0800983 while (n && IS_TNODE(n)) {
Alexander Duyckadaf9812014-12-31 10:55:47 -0800984 if (tkey_sub_equals(n->key, pos, n->pos-pos, key)) {
985 tp = n;
986 pos = n->pos + n->bits;
987 n = tnode_get_child(n,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -0800988 tkey_extract_bits(key,
Alexander Duyckadaf9812014-12-31 10:55:47 -0800989 n->pos,
990 n->bits));
Robert Olsson19baf832005-06-21 12:43:18 -0700991
Alexander Duyckadaf9812014-12-31 10:55:47 -0800992 BUG_ON(n && node_parent(n) != tp);
Olof Johansson91b9a272005-08-09 20:24:39 -0700993 } else
Robert Olsson19baf832005-06-21 12:43:18 -0700994 break;
995 }
996
997 /*
998 * n ----> NULL, LEAF or TNODE
999 *
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001000 * tp is n's (parent) ----> NULL or TNODE
Robert Olsson19baf832005-06-21 12:43:18 -07001001 */
1002
Olof Johansson91b9a272005-08-09 20:24:39 -07001003 BUG_ON(tp && IS_LEAF(tp));
Robert Olsson19baf832005-06-21 12:43:18 -07001004
1005 /* Case 1: n is a leaf. Compare prefixes */
1006
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001007 if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) {
Robert Olsson19baf832005-06-21 12:43:18 -07001008 li = leaf_info_new(plen);
Olof Johansson91b9a272005-08-09 20:24:39 -07001009
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001010 if (!li)
1011 return NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001012
1013 fa_head = &li->falh;
Alexander Duyckadaf9812014-12-31 10:55:47 -08001014 insert_leaf_info(&n->list, li);
Robert Olsson19baf832005-06-21 12:43:18 -07001015 goto done;
1016 }
Alexander Duyck64c9b6f2014-12-31 10:55:35 -08001017 l = leaf_new(key);
Robert Olsson19baf832005-06-21 12:43:18 -07001018
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001019 if (!l)
1020 return NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001021
Robert Olsson19baf832005-06-21 12:43:18 -07001022 li = leaf_info_new(plen);
1023
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001024 if (!li) {
Alexander Duyck37fd30f2014-12-31 10:55:41 -08001025 node_free(l);
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001026 return NULL;
Robert Olssonf835e472005-06-28 15:00:39 -07001027 }
Robert Olsson19baf832005-06-21 12:43:18 -07001028
1029 fa_head = &li->falh;
1030 insert_leaf_info(&l->list, li);
1031
Robert Olsson19baf832005-06-21 12:43:18 -07001032 if (t->trie && n == NULL) {
Olof Johansson91b9a272005-08-09 20:24:39 -07001033 /* Case 2: n is NULL, and will just insert a new leaf */
Robert Olsson19baf832005-06-21 12:43:18 -07001034
Alexander Duyckadaf9812014-12-31 10:55:47 -08001035 node_set_parent(l, tp);
Robert Olsson19baf832005-06-21 12:43:18 -07001036
Olof Johansson91b9a272005-08-09 20:24:39 -07001037 cindex = tkey_extract_bits(key, tp->pos, tp->bits);
Alexander Duyckadaf9812014-12-31 10:55:47 -08001038 put_child(tp, cindex, l);
Olof Johansson91b9a272005-08-09 20:24:39 -07001039 } else {
1040 /* Case 3: n is a LEAF or a TNODE and the key doesn't match. */
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001041 /*
1042 * Add a new tnode here
Robert Olsson19baf832005-06-21 12:43:18 -07001043 * first tnode need some special handling
1044 */
1045
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001046 if (n) {
baker.zhang4c60f1d2013-10-08 11:36:51 +08001047 pos = tp ? tp->pos+tp->bits : 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001048 newpos = tkey_mismatch(key, pos, n->key);
1049 tn = tnode_new(n->key, newpos, 1);
Olof Johansson91b9a272005-08-09 20:24:39 -07001050 } else {
Robert Olsson19baf832005-06-21 12:43:18 -07001051 newpos = 0;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001052 tn = tnode_new(key, newpos, 1); /* First tnode */
Robert Olsson19baf832005-06-21 12:43:18 -07001053 }
Robert Olsson19baf832005-06-21 12:43:18 -07001054
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001055 if (!tn) {
Robert Olssonf835e472005-06-28 15:00:39 -07001056 free_leaf_info(li);
Alexander Duyck37fd30f2014-12-31 10:55:41 -08001057 node_free(l);
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001058 return NULL;
Olof Johansson91b9a272005-08-09 20:24:39 -07001059 }
1060
Alexander Duyckadaf9812014-12-31 10:55:47 -08001061 node_set_parent(tn, tp);
Robert Olsson19baf832005-06-21 12:43:18 -07001062
Olof Johansson91b9a272005-08-09 20:24:39 -07001063 missbit = tkey_extract_bits(key, newpos, 1);
Alexander Duyckadaf9812014-12-31 10:55:47 -08001064 put_child(tn, missbit, l);
Lin Ming61648d92012-07-29 02:00:03 +00001065 put_child(tn, 1-missbit, n);
Robert Olsson19baf832005-06-21 12:43:18 -07001066
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001067 if (tp) {
Robert Olsson19baf832005-06-21 12:43:18 -07001068 cindex = tkey_extract_bits(key, tp->pos, tp->bits);
Alexander Duyckadaf9812014-12-31 10:55:47 -08001069 put_child(tp, cindex, tn);
Olof Johansson91b9a272005-08-09 20:24:39 -07001070 } else {
Alexander Duyckadaf9812014-12-31 10:55:47 -08001071 rcu_assign_pointer(t->trie, tn);
Robert Olsson19baf832005-06-21 12:43:18 -07001072 }
Alexander Duycke962f302014-12-10 21:49:22 -08001073
1074 tp = tn;
Robert Olsson19baf832005-06-21 12:43:18 -07001075 }
Olof Johansson91b9a272005-08-09 20:24:39 -07001076
1077 if (tp && tp->pos + tp->bits > 32)
Joe Perches058bd4d2012-03-11 18:36:11 +00001078 pr_warn("fib_trie tp=%p pos=%d, bits=%d, key=%0x plen=%d\n",
1079 tp, tp->pos, tp->bits, key, plen);
Olof Johansson91b9a272005-08-09 20:24:39 -07001080
Robert Olsson19baf832005-06-21 12:43:18 -07001081 /* Rebalance the trie */
Robert Olsson2373ce12005-08-25 13:01:29 -07001082
Jarek Poplawski7b855762009-06-18 00:28:51 -07001083 trie_rebalance(t, tp);
Robert Olssonf835e472005-06-28 15:00:39 -07001084done:
Robert Olsson19baf832005-06-21 12:43:18 -07001085 return fa_head;
1086}
1087
Robert Olssond562f1f2007-03-26 14:22:22 -07001088/*
1089 * Caller must hold RTNL.
1090 */
Stephen Hemminger16c6cf82009-09-20 10:35:36 +00001091int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
Robert Olsson19baf832005-06-21 12:43:18 -07001092{
1093 struct trie *t = (struct trie *) tb->tb_data;
1094 struct fib_alias *fa, *new_fa;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001095 struct list_head *fa_head = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001096 struct fib_info *fi;
Thomas Graf4e902c52006-08-17 18:14:52 -07001097 int plen = cfg->fc_dst_len;
1098 u8 tos = cfg->fc_tos;
Robert Olsson19baf832005-06-21 12:43:18 -07001099 u32 key, mask;
1100 int err;
Alexander Duyckadaf9812014-12-31 10:55:47 -08001101 struct tnode *l;
Robert Olsson19baf832005-06-21 12:43:18 -07001102
1103 if (plen > 32)
1104 return -EINVAL;
1105
Thomas Graf4e902c52006-08-17 18:14:52 -07001106 key = ntohl(cfg->fc_dst);
Robert Olsson19baf832005-06-21 12:43:18 -07001107
Patrick McHardy2dfe55b2006-08-10 23:08:33 -07001108 pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen);
Robert Olsson19baf832005-06-21 12:43:18 -07001109
Olof Johansson91b9a272005-08-09 20:24:39 -07001110 mask = ntohl(inet_make_mask(plen));
Robert Olsson19baf832005-06-21 12:43:18 -07001111
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001112 if (key & ~mask)
Robert Olsson19baf832005-06-21 12:43:18 -07001113 return -EINVAL;
1114
1115 key = key & mask;
1116
Thomas Graf4e902c52006-08-17 18:14:52 -07001117 fi = fib_create_info(cfg);
1118 if (IS_ERR(fi)) {
1119 err = PTR_ERR(fi);
Robert Olsson19baf832005-06-21 12:43:18 -07001120 goto err;
Thomas Graf4e902c52006-08-17 18:14:52 -07001121 }
Robert Olsson19baf832005-06-21 12:43:18 -07001122
1123 l = fib_find_node(t, key);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001124 fa = NULL;
Robert Olsson19baf832005-06-21 12:43:18 -07001125
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001126 if (l) {
Robert Olsson19baf832005-06-21 12:43:18 -07001127 fa_head = get_fa_head(l, plen);
1128 fa = fib_find_alias(fa_head, tos, fi->fib_priority);
1129 }
1130
1131 /* Now fa, if non-NULL, points to the first fib alias
1132 * with the same keys [prefix,tos,priority], if such key already
1133 * exists or to the node before which we will insert new one.
1134 *
1135 * If fa is NULL, we will need to allocate a new one and
1136 * insert to the head of f.
1137 *
1138 * If f is NULL, no fib node matched the destination key
1139 * and we need to allocate a new one of those as well.
1140 */
1141
Julian Anastasov936f6f82008-01-28 21:18:06 -08001142 if (fa && fa->fa_tos == tos &&
1143 fa->fa_info->fib_priority == fi->fib_priority) {
1144 struct fib_alias *fa_first, *fa_match;
Robert Olsson19baf832005-06-21 12:43:18 -07001145
1146 err = -EEXIST;
Thomas Graf4e902c52006-08-17 18:14:52 -07001147 if (cfg->fc_nlflags & NLM_F_EXCL)
Robert Olsson19baf832005-06-21 12:43:18 -07001148 goto out;
1149
Julian Anastasov936f6f82008-01-28 21:18:06 -08001150 /* We have 2 goals:
1151 * 1. Find exact match for type, scope, fib_info to avoid
1152 * duplicate routes
1153 * 2. Find next 'fa' (or head), NLM_F_APPEND inserts before it
1154 */
1155 fa_match = NULL;
1156 fa_first = fa;
1157 fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
1158 list_for_each_entry_continue(fa, fa_head, fa_list) {
1159 if (fa->fa_tos != tos)
1160 break;
1161 if (fa->fa_info->fib_priority != fi->fib_priority)
1162 break;
1163 if (fa->fa_type == cfg->fc_type &&
Julian Anastasov936f6f82008-01-28 21:18:06 -08001164 fa->fa_info == fi) {
1165 fa_match = fa;
1166 break;
1167 }
1168 }
1169
Thomas Graf4e902c52006-08-17 18:14:52 -07001170 if (cfg->fc_nlflags & NLM_F_REPLACE) {
Robert Olsson19baf832005-06-21 12:43:18 -07001171 struct fib_info *fi_drop;
1172 u8 state;
1173
Julian Anastasov936f6f82008-01-28 21:18:06 -08001174 fa = fa_first;
1175 if (fa_match) {
1176 if (fa == fa_match)
1177 err = 0;
Joonwoo Park67250332008-01-18 03:45:18 -08001178 goto out;
Julian Anastasov936f6f82008-01-28 21:18:06 -08001179 }
Robert Olsson2373ce12005-08-25 13:01:29 -07001180 err = -ENOBUFS;
Christoph Lametere94b1762006-12-06 20:33:17 -08001181 new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
Robert Olsson2373ce12005-08-25 13:01:29 -07001182 if (new_fa == NULL)
1183 goto out;
Robert Olsson19baf832005-06-21 12:43:18 -07001184
1185 fi_drop = fa->fa_info;
Robert Olsson2373ce12005-08-25 13:01:29 -07001186 new_fa->fa_tos = fa->fa_tos;
1187 new_fa->fa_info = fi;
Thomas Graf4e902c52006-08-17 18:14:52 -07001188 new_fa->fa_type = cfg->fc_type;
Robert Olsson19baf832005-06-21 12:43:18 -07001189 state = fa->fa_state;
Julian Anastasov936f6f82008-01-28 21:18:06 -08001190 new_fa->fa_state = state & ~FA_S_ACCESSED;
Robert Olsson19baf832005-06-21 12:43:18 -07001191
Robert Olsson2373ce12005-08-25 13:01:29 -07001192 list_replace_rcu(&fa->fa_list, &new_fa->fa_list);
1193 alias_free_mem_rcu(fa);
Robert Olsson19baf832005-06-21 12:43:18 -07001194
1195 fib_release_info(fi_drop);
1196 if (state & FA_S_ACCESSED)
Nicolas Dichtel4ccfe6d2012-09-07 00:45:29 +00001197 rt_cache_flush(cfg->fc_nlinfo.nl_net);
Milan Kocianb8f55832007-05-23 14:55:06 -07001198 rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
1199 tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
Robert Olsson19baf832005-06-21 12:43:18 -07001200
Olof Johansson91b9a272005-08-09 20:24:39 -07001201 goto succeeded;
Robert Olsson19baf832005-06-21 12:43:18 -07001202 }
1203 /* Error if we find a perfect match which
1204 * uses the same scope, type, and nexthop
1205 * information.
1206 */
Julian Anastasov936f6f82008-01-28 21:18:06 -08001207 if (fa_match)
1208 goto out;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001209
Thomas Graf4e902c52006-08-17 18:14:52 -07001210 if (!(cfg->fc_nlflags & NLM_F_APPEND))
Julian Anastasov936f6f82008-01-28 21:18:06 -08001211 fa = fa_first;
Robert Olsson19baf832005-06-21 12:43:18 -07001212 }
1213 err = -ENOENT;
Thomas Graf4e902c52006-08-17 18:14:52 -07001214 if (!(cfg->fc_nlflags & NLM_F_CREATE))
Robert Olsson19baf832005-06-21 12:43:18 -07001215 goto out;
1216
1217 err = -ENOBUFS;
Christoph Lametere94b1762006-12-06 20:33:17 -08001218 new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
Robert Olsson19baf832005-06-21 12:43:18 -07001219 if (new_fa == NULL)
1220 goto out;
1221
1222 new_fa->fa_info = fi;
1223 new_fa->fa_tos = tos;
Thomas Graf4e902c52006-08-17 18:14:52 -07001224 new_fa->fa_type = cfg->fc_type;
Robert Olsson19baf832005-06-21 12:43:18 -07001225 new_fa->fa_state = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001226 /*
1227 * Insert new entry to the list.
1228 */
1229
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001230 if (!fa_head) {
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001231 fa_head = fib_insert_node(t, key, plen);
1232 if (unlikely(!fa_head)) {
1233 err = -ENOMEM;
Robert Olssonf835e472005-06-28 15:00:39 -07001234 goto out_free_new_fa;
Stephen Hemmingerfea86ad2008-01-12 20:57:07 -08001235 }
Robert Olssonf835e472005-06-28 15:00:39 -07001236 }
Robert Olsson19baf832005-06-21 12:43:18 -07001237
David S. Miller21d8c492011-04-14 14:49:37 -07001238 if (!plen)
1239 tb->tb_num_default++;
1240
Robert Olsson2373ce12005-08-25 13:01:29 -07001241 list_add_tail_rcu(&new_fa->fa_list,
1242 (fa ? &fa->fa_list : fa_head));
Robert Olsson19baf832005-06-21 12:43:18 -07001243
Nicolas Dichtel4ccfe6d2012-09-07 00:45:29 +00001244 rt_cache_flush(cfg->fc_nlinfo.nl_net);
Thomas Graf4e902c52006-08-17 18:14:52 -07001245 rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id,
Milan Kocianb8f55832007-05-23 14:55:06 -07001246 &cfg->fc_nlinfo, 0);
Robert Olsson19baf832005-06-21 12:43:18 -07001247succeeded:
1248 return 0;
Robert Olssonf835e472005-06-28 15:00:39 -07001249
1250out_free_new_fa:
1251 kmem_cache_free(fn_alias_kmem, new_fa);
Robert Olsson19baf832005-06-21 12:43:18 -07001252out:
1253 fib_release_info(fi);
Olof Johansson91b9a272005-08-09 20:24:39 -07001254err:
Robert Olsson19baf832005-06-21 12:43:18 -07001255 return err;
1256}
1257
Robert Olsson772cb712005-09-19 15:31:18 -07001258/* should be called with rcu_read_lock */
Alexander Duyckadaf9812014-12-31 10:55:47 -08001259static int check_leaf(struct fib_table *tb, struct trie *t, struct tnode *l,
David S. Miller22bd5b92011-03-11 19:54:08 -05001260 t_key key, const struct flowi4 *flp,
Eric Dumazetebc0ffa2010-10-05 10:41:36 +00001261 struct fib_result *res, int fib_flags)
Robert Olsson19baf832005-06-21 12:43:18 -07001262{
Robert Olsson19baf832005-06-21 12:43:18 -07001263 struct leaf_info *li;
1264 struct hlist_head *hhead = &l->list;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001265
Sasha Levinb67bfe02013-02-27 17:06:00 -08001266 hlist_for_each_entry_rcu(li, hhead, hlist) {
David S. Miller3be06862011-03-07 15:01:10 -08001267 struct fib_alias *fa;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001268
Eric Dumazet5c745012011-07-18 03:16:33 +00001269 if (l->key != (key & li->mask_plen))
Robert Olsson19baf832005-06-21 12:43:18 -07001270 continue;
1271
David S. Miller3be06862011-03-07 15:01:10 -08001272 list_for_each_entry_rcu(fa, &li->falh, fa_list) {
1273 struct fib_info *fi = fa->fa_info;
1274 int nhsel, err;
1275
David S. Miller22bd5b92011-03-11 19:54:08 -05001276 if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
David S. Miller3be06862011-03-07 15:01:10 -08001277 continue;
David S. Millerdccd9ecc2012-05-10 22:16:32 -04001278 if (fi->fib_dead)
1279 continue;
David S. Miller37e826c2011-03-24 18:06:47 -07001280 if (fa->fa_info->fib_scope < flp->flowi4_scope)
David S. Miller3be06862011-03-07 15:01:10 -08001281 continue;
1282 fib_alias_accessed(fa);
1283 err = fib_props[fa->fa_type].error;
1284 if (err) {
1285#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08001286 this_cpu_inc(t->stats->semantic_match_passed);
David S. Miller3be06862011-03-07 15:01:10 -08001287#endif
Julian Anastasov1fbc7842011-03-25 20:33:23 -07001288 return err;
David S. Miller3be06862011-03-07 15:01:10 -08001289 }
1290 if (fi->fib_flags & RTNH_F_DEAD)
1291 continue;
1292 for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
1293 const struct fib_nh *nh = &fi->fib_nh[nhsel];
1294
1295 if (nh->nh_flags & RTNH_F_DEAD)
1296 continue;
David S. Miller22bd5b92011-03-11 19:54:08 -05001297 if (flp->flowi4_oif && flp->flowi4_oif != nh->nh_oif)
David S. Miller3be06862011-03-07 15:01:10 -08001298 continue;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001299
Robert Olsson19baf832005-06-21 12:43:18 -07001300#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08001301 this_cpu_inc(t->stats->semantic_match_passed);
Robert Olsson19baf832005-06-21 12:43:18 -07001302#endif
Eric Dumazet5c745012011-07-18 03:16:33 +00001303 res->prefixlen = li->plen;
David S. Miller3be06862011-03-07 15:01:10 -08001304 res->nh_sel = nhsel;
1305 res->type = fa->fa_type;
David S. Miller37e826c2011-03-24 18:06:47 -07001306 res->scope = fa->fa_info->fib_scope;
David S. Miller3be06862011-03-07 15:01:10 -08001307 res->fi = fi;
1308 res->table = tb;
1309 res->fa_head = &li->falh;
1310 if (!(fib_flags & FIB_LOOKUP_NOREF))
Eric Dumazet5c745012011-07-18 03:16:33 +00001311 atomic_inc(&fi->fib_clntref);
David S. Miller3be06862011-03-07 15:01:10 -08001312 return 0;
1313 }
1314 }
1315
1316#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08001317 this_cpu_inc(t->stats->semantic_match_miss);
David S. Miller3be06862011-03-07 15:01:10 -08001318#endif
Robert Olsson19baf832005-06-21 12:43:18 -07001319 }
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001320
Ben Hutchings2e655572008-07-10 16:52:52 -07001321 return 1;
Robert Olsson19baf832005-06-21 12:43:18 -07001322}
1323
David S. Miller22bd5b92011-03-11 19:54:08 -05001324int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
Eric Dumazetebc0ffa2010-10-05 10:41:36 +00001325 struct fib_result *res, int fib_flags)
Robert Olsson19baf832005-06-21 12:43:18 -07001326{
1327 struct trie *t = (struct trie *) tb->tb_data;
Alexander Duyck8274a972014-12-31 10:55:29 -08001328#ifdef CONFIG_IP_FIB_TRIE_STATS
1329 struct trie_use_stats __percpu *stats = t->stats;
1330#endif
Ben Hutchings2e655572008-07-10 16:52:52 -07001331 int ret;
Alexander Duyckadaf9812014-12-31 10:55:47 -08001332 struct tnode *n;
Robert Olsson19baf832005-06-21 12:43:18 -07001333 struct tnode *pn;
David S. Miller3b004562011-02-16 14:56:22 -08001334 unsigned int pos, bits;
David S. Miller22bd5b92011-03-11 19:54:08 -05001335 t_key key = ntohl(flp->daddr);
David S. Miller3b004562011-02-16 14:56:22 -08001336 unsigned int chopped_off;
Robert Olsson19baf832005-06-21 12:43:18 -07001337 t_key cindex = 0;
David S. Miller3b004562011-02-16 14:56:22 -08001338 unsigned int current_prefix_length = KEYLENGTH;
Olof Johansson91b9a272005-08-09 20:24:39 -07001339 struct tnode *cn;
Eric Dumazet874ffa82010-10-13 06:56:11 +00001340 t_key pref_mismatch;
Olof Johansson91b9a272005-08-09 20:24:39 -07001341
Robert Olsson2373ce12005-08-25 13:01:29 -07001342 rcu_read_lock();
Robert Olsson19baf832005-06-21 12:43:18 -07001343
Robert Olsson2373ce12005-08-25 13:01:29 -07001344 n = rcu_dereference(t->trie);
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001345 if (!n)
Robert Olsson19baf832005-06-21 12:43:18 -07001346 goto failed;
1347
1348#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08001349 this_cpu_inc(stats->gets);
Robert Olsson19baf832005-06-21 12:43:18 -07001350#endif
1351
1352 /* Just a leaf? */
1353 if (IS_LEAF(n)) {
Alexander Duyckadaf9812014-12-31 10:55:47 -08001354 ret = check_leaf(tb, t, n, key, flp, res, fib_flags);
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001355 goto found;
Robert Olsson19baf832005-06-21 12:43:18 -07001356 }
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001357
Alexander Duyckadaf9812014-12-31 10:55:47 -08001358 pn = n;
Robert Olsson19baf832005-06-21 12:43:18 -07001359 chopped_off = 0;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001360
Olof Johansson91b9a272005-08-09 20:24:39 -07001361 while (pn) {
Robert Olsson19baf832005-06-21 12:43:18 -07001362 pos = pn->pos;
1363 bits = pn->bits;
1364
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001365 if (!chopped_off)
Stephen Hemmingerab66b4a2007-08-10 15:22:58 -07001366 cindex = tkey_extract_bits(mask_pfx(key, current_prefix_length),
1367 pos, bits);
Robert Olsson19baf832005-06-21 12:43:18 -07001368
Jarek Poplawskib902e572009-07-14 11:20:32 +00001369 n = tnode_get_child_rcu(pn, cindex);
Robert Olsson19baf832005-06-21 12:43:18 -07001370
1371 if (n == NULL) {
1372#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08001373 this_cpu_inc(stats->null_node_hit);
Robert Olsson19baf832005-06-21 12:43:18 -07001374#endif
1375 goto backtrace;
1376 }
1377
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001378 if (IS_LEAF(n)) {
Alexander Duyckadaf9812014-12-31 10:55:47 -08001379 ret = check_leaf(tb, t, n, key, flp, res, fib_flags);
Ben Hutchings2e655572008-07-10 16:52:52 -07001380 if (ret > 0)
Olof Johansson91b9a272005-08-09 20:24:39 -07001381 goto backtrace;
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001382 goto found;
Olof Johansson91b9a272005-08-09 20:24:39 -07001383 }
1384
Alexander Duyckadaf9812014-12-31 10:55:47 -08001385 cn = n;
Olof Johansson91b9a272005-08-09 20:24:39 -07001386
1387 /*
1388 * It's a tnode, and we can do some extra checks here if we
1389 * like, to avoid descending into a dead-end branch.
1390 * This tnode is in the parent's child array at index
1391 * key[p_pos..p_pos+p_bits] but potentially with some bits
1392 * chopped off, so in reality the index may be just a
1393 * subprefix, padded with zero at the end.
1394 * We can also take a look at any skipped bits in this
1395 * tnode - everything up to p_pos is supposed to be ok,
1396 * and the non-chopped bits of the index (se previous
1397 * paragraph) are also guaranteed ok, but the rest is
1398 * considered unknown.
1399 *
1400 * The skipped bits are key[pos+bits..cn->pos].
1401 */
1402
1403 /* If current_prefix_length < pos+bits, we are already doing
1404 * actual prefix matching, which means everything from
1405 * pos+(bits-chopped_off) onward must be zero along some
1406 * branch of this subtree - otherwise there is *no* valid
1407 * prefix present. Here we can only check the skipped
1408 * bits. Remember, since we have already indexed into the
1409 * parent's child array, we know that the bits we chopped of
1410 * *are* zero.
1411 */
1412
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001413 /* NOTA BENE: Checking only skipped bits
1414 for the new node here */
Olof Johansson91b9a272005-08-09 20:24:39 -07001415
1416 if (current_prefix_length < pos+bits) {
1417 if (tkey_extract_bits(cn->key, current_prefix_length,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001418 cn->pos - current_prefix_length)
1419 || !(cn->child[0]))
Olof Johansson91b9a272005-08-09 20:24:39 -07001420 goto backtrace;
1421 }
1422
1423 /*
1424 * If chopped_off=0, the index is fully validated and we
1425 * only need to look at the skipped bits for this, the new,
1426 * tnode. What we actually want to do is to find out if
1427 * these skipped bits match our key perfectly, or if we will
1428 * have to count on finding a matching prefix further down,
1429 * because if we do, we would like to have some way of
1430 * verifying the existence of such a prefix at this point.
1431 */
1432
1433 /* The only thing we can do at this point is to verify that
1434 * any such matching prefix can indeed be a prefix to our
1435 * key, and if the bits in the node we are inspecting that
1436 * do not match our key are not ZERO, this cannot be true.
1437 * Thus, find out where there is a mismatch (before cn->pos)
1438 * and verify that all the mismatching bits are zero in the
1439 * new tnode's key.
1440 */
1441
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001442 /*
1443 * Note: We aren't very concerned about the piece of
1444 * the key that precede pn->pos+pn->bits, since these
1445 * have already been checked. The bits after cn->pos
1446 * aren't checked since these are by definition
1447 * "unknown" at this point. Thus, what we want to see
1448 * is if we are about to enter the "prefix matching"
1449 * state, and in that case verify that the skipped
1450 * bits that will prevail throughout this subtree are
1451 * zero, as they have to be if we are to find a
1452 * matching prefix.
Olof Johansson91b9a272005-08-09 20:24:39 -07001453 */
1454
Eric Dumazet874ffa82010-10-13 06:56:11 +00001455 pref_mismatch = mask_pfx(cn->key ^ key, cn->pos);
Olof Johansson91b9a272005-08-09 20:24:39 -07001456
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001457 /*
1458 * In short: If skipped bits in this node do not match
1459 * the search key, enter the "prefix matching"
1460 * state.directly.
Olof Johansson91b9a272005-08-09 20:24:39 -07001461 */
1462 if (pref_mismatch) {
Eric Dumazet79cda752012-08-07 10:45:47 +00001463 /* fls(x) = __fls(x) + 1 */
1464 int mp = KEYLENGTH - __fls(pref_mismatch) - 1;
Olof Johansson91b9a272005-08-09 20:24:39 -07001465
Eric Dumazet874ffa82010-10-13 06:56:11 +00001466 if (tkey_extract_bits(cn->key, mp, cn->pos - mp) != 0)
Olof Johansson91b9a272005-08-09 20:24:39 -07001467 goto backtrace;
1468
1469 if (current_prefix_length >= cn->pos)
1470 current_prefix_length = mp;
1471 }
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001472
Alexander Duyckadaf9812014-12-31 10:55:47 -08001473 pn = n; /* Descend */
Olof Johansson91b9a272005-08-09 20:24:39 -07001474 chopped_off = 0;
1475 continue;
1476
Robert Olsson19baf832005-06-21 12:43:18 -07001477backtrace:
1478 chopped_off++;
1479
1480 /* As zero don't change the child key (cindex) */
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001481 while ((chopped_off <= pn->bits)
1482 && !(cindex & (1<<(chopped_off-1))))
Robert Olsson19baf832005-06-21 12:43:18 -07001483 chopped_off++;
Robert Olsson19baf832005-06-21 12:43:18 -07001484
1485 /* Decrease current_... with bits chopped off */
1486 if (current_prefix_length > pn->pos + pn->bits - chopped_off)
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001487 current_prefix_length = pn->pos + pn->bits
1488 - chopped_off;
Olof Johansson91b9a272005-08-09 20:24:39 -07001489
Robert Olsson19baf832005-06-21 12:43:18 -07001490 /*
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001491 * Either we do the actual chop off according or if we have
Robert Olsson19baf832005-06-21 12:43:18 -07001492 * chopped off all bits in this tnode walk up to our parent.
1493 */
1494
Olof Johansson91b9a272005-08-09 20:24:39 -07001495 if (chopped_off <= pn->bits) {
Robert Olsson19baf832005-06-21 12:43:18 -07001496 cindex &= ~(1 << (chopped_off-1));
Olof Johansson91b9a272005-08-09 20:24:39 -07001497 } else {
Alexander Duyck64c9b6f2014-12-31 10:55:35 -08001498 struct tnode *parent = node_parent_rcu(pn);
Stephen Hemminger06801912007-08-10 15:22:13 -07001499 if (!parent)
Robert Olsson19baf832005-06-21 12:43:18 -07001500 goto failed;
Olof Johansson91b9a272005-08-09 20:24:39 -07001501
Robert Olsson19baf832005-06-21 12:43:18 -07001502 /* Get Child's index */
Stephen Hemminger06801912007-08-10 15:22:13 -07001503 cindex = tkey_extract_bits(pn->key, parent->pos, parent->bits);
1504 pn = parent;
Robert Olsson19baf832005-06-21 12:43:18 -07001505 chopped_off = 0;
1506
1507#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08001508 this_cpu_inc(stats->backtrack);
Robert Olsson19baf832005-06-21 12:43:18 -07001509#endif
1510 goto backtrace;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001511 }
Robert Olsson19baf832005-06-21 12:43:18 -07001512 }
1513failed:
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001514 ret = 1;
Robert Olsson19baf832005-06-21 12:43:18 -07001515found:
Robert Olsson2373ce12005-08-25 13:01:29 -07001516 rcu_read_unlock();
Robert Olsson19baf832005-06-21 12:43:18 -07001517 return ret;
1518}
Florian Westphal6fc01432011-08-25 13:46:12 +02001519EXPORT_SYMBOL_GPL(fib_table_lookup);
Robert Olsson19baf832005-06-21 12:43:18 -07001520
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001521/*
1522 * Remove the leaf and return parent.
1523 */
Alexander Duyckadaf9812014-12-31 10:55:47 -08001524static void trie_leaf_remove(struct trie *t, struct tnode *l)
Robert Olsson19baf832005-06-21 12:43:18 -07001525{
Alexander Duyck64c9b6f2014-12-31 10:55:35 -08001526 struct tnode *tp = node_parent(l);
Robert Olsson19baf832005-06-21 12:43:18 -07001527
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001528 pr_debug("entering trie_leaf_remove(%p)\n", l);
Robert Olsson19baf832005-06-21 12:43:18 -07001529
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001530 if (tp) {
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001531 t_key cindex = tkey_extract_bits(l->key, tp->pos, tp->bits);
Lin Ming61648d92012-07-29 02:00:03 +00001532 put_child(tp, cindex, NULL);
Jarek Poplawski7b855762009-06-18 00:28:51 -07001533 trie_rebalance(t, tp);
Olof Johansson91b9a272005-08-09 20:24:39 -07001534 } else
Stephen Hemmingera9b3cd72011-08-01 16:19:00 +00001535 RCU_INIT_POINTER(t->trie, NULL);
Robert Olsson19baf832005-06-21 12:43:18 -07001536
Alexander Duyck37fd30f2014-12-31 10:55:41 -08001537 node_free(l);
Robert Olsson19baf832005-06-21 12:43:18 -07001538}
1539
Robert Olssond562f1f2007-03-26 14:22:22 -07001540/*
1541 * Caller must hold RTNL.
1542 */
Stephen Hemminger16c6cf82009-09-20 10:35:36 +00001543int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
Robert Olsson19baf832005-06-21 12:43:18 -07001544{
1545 struct trie *t = (struct trie *) tb->tb_data;
1546 u32 key, mask;
Thomas Graf4e902c52006-08-17 18:14:52 -07001547 int plen = cfg->fc_dst_len;
1548 u8 tos = cfg->fc_tos;
Robert Olsson19baf832005-06-21 12:43:18 -07001549 struct fib_alias *fa, *fa_to_delete;
1550 struct list_head *fa_head;
Alexander Duyckadaf9812014-12-31 10:55:47 -08001551 struct tnode *l;
Olof Johansson91b9a272005-08-09 20:24:39 -07001552 struct leaf_info *li;
1553
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001554 if (plen > 32)
Robert Olsson19baf832005-06-21 12:43:18 -07001555 return -EINVAL;
1556
Thomas Graf4e902c52006-08-17 18:14:52 -07001557 key = ntohl(cfg->fc_dst);
Olof Johansson91b9a272005-08-09 20:24:39 -07001558 mask = ntohl(inet_make_mask(plen));
Robert Olsson19baf832005-06-21 12:43:18 -07001559
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001560 if (key & ~mask)
Robert Olsson19baf832005-06-21 12:43:18 -07001561 return -EINVAL;
1562
1563 key = key & mask;
1564 l = fib_find_node(t, key);
1565
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001566 if (!l)
Robert Olsson19baf832005-06-21 12:43:18 -07001567 return -ESRCH;
1568
Igor Maravicad5b3102012-08-13 10:26:08 +02001569 li = find_leaf_info(l, plen);
1570
1571 if (!li)
1572 return -ESRCH;
1573
1574 fa_head = &li->falh;
Robert Olsson19baf832005-06-21 12:43:18 -07001575 fa = fib_find_alias(fa_head, tos, 0);
1576
1577 if (!fa)
1578 return -ESRCH;
1579
Stephen Hemminger0c7770c2005-08-23 21:59:41 -07001580 pr_debug("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t);
Robert Olsson19baf832005-06-21 12:43:18 -07001581
1582 fa_to_delete = NULL;
Julian Anastasov936f6f82008-01-28 21:18:06 -08001583 fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
1584 list_for_each_entry_continue(fa, fa_head, fa_list) {
Robert Olsson19baf832005-06-21 12:43:18 -07001585 struct fib_info *fi = fa->fa_info;
1586
1587 if (fa->fa_tos != tos)
1588 break;
1589
Thomas Graf4e902c52006-08-17 18:14:52 -07001590 if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) &&
1591 (cfg->fc_scope == RT_SCOPE_NOWHERE ||
David S. Miller37e826c2011-03-24 18:06:47 -07001592 fa->fa_info->fib_scope == cfg->fc_scope) &&
Julian Anastasov74cb3c12011-03-19 12:13:46 +00001593 (!cfg->fc_prefsrc ||
1594 fi->fib_prefsrc == cfg->fc_prefsrc) &&
Thomas Graf4e902c52006-08-17 18:14:52 -07001595 (!cfg->fc_protocol ||
1596 fi->fib_protocol == cfg->fc_protocol) &&
1597 fib_nh_match(cfg, fi) == 0) {
Robert Olsson19baf832005-06-21 12:43:18 -07001598 fa_to_delete = fa;
1599 break;
1600 }
1601 }
1602
Olof Johansson91b9a272005-08-09 20:24:39 -07001603 if (!fa_to_delete)
1604 return -ESRCH;
Robert Olsson19baf832005-06-21 12:43:18 -07001605
Olof Johansson91b9a272005-08-09 20:24:39 -07001606 fa = fa_to_delete;
Thomas Graf4e902c52006-08-17 18:14:52 -07001607 rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id,
Milan Kocianb8f55832007-05-23 14:55:06 -07001608 &cfg->fc_nlinfo, 0);
Robert Olsson19baf832005-06-21 12:43:18 -07001609
Robert Olsson2373ce12005-08-25 13:01:29 -07001610 list_del_rcu(&fa->fa_list);
Robert Olsson19baf832005-06-21 12:43:18 -07001611
David S. Miller21d8c492011-04-14 14:49:37 -07001612 if (!plen)
1613 tb->tb_num_default--;
1614
Olof Johansson91b9a272005-08-09 20:24:39 -07001615 if (list_empty(fa_head)) {
Robert Olsson2373ce12005-08-25 13:01:29 -07001616 hlist_del_rcu(&li->hlist);
Olof Johansson91b9a272005-08-09 20:24:39 -07001617 free_leaf_info(li);
Robert Olsson2373ce12005-08-25 13:01:29 -07001618 }
Olof Johansson91b9a272005-08-09 20:24:39 -07001619
1620 if (hlist_empty(&l->list))
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001621 trie_leaf_remove(t, l);
Olof Johansson91b9a272005-08-09 20:24:39 -07001622
1623 if (fa->fa_state & FA_S_ACCESSED)
Nicolas Dichtel4ccfe6d2012-09-07 00:45:29 +00001624 rt_cache_flush(cfg->fc_nlinfo.nl_net);
Olof Johansson91b9a272005-08-09 20:24:39 -07001625
Robert Olsson2373ce12005-08-25 13:01:29 -07001626 fib_release_info(fa->fa_info);
1627 alias_free_mem_rcu(fa);
Olof Johansson91b9a272005-08-09 20:24:39 -07001628 return 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001629}
1630
Stephen Hemmingeref3660c2008-04-10 03:46:12 -07001631static int trie_flush_list(struct list_head *head)
Robert Olsson19baf832005-06-21 12:43:18 -07001632{
1633 struct fib_alias *fa, *fa_node;
1634 int found = 0;
1635
1636 list_for_each_entry_safe(fa, fa_node, head, fa_list) {
1637 struct fib_info *fi = fa->fa_info;
Robert Olsson19baf832005-06-21 12:43:18 -07001638
Robert Olsson2373ce12005-08-25 13:01:29 -07001639 if (fi && (fi->fib_flags & RTNH_F_DEAD)) {
1640 list_del_rcu(&fa->fa_list);
1641 fib_release_info(fa->fa_info);
1642 alias_free_mem_rcu(fa);
Robert Olsson19baf832005-06-21 12:43:18 -07001643 found++;
1644 }
1645 }
1646 return found;
1647}
1648
Alexander Duyckadaf9812014-12-31 10:55:47 -08001649static int trie_flush_leaf(struct tnode *l)
Robert Olsson19baf832005-06-21 12:43:18 -07001650{
1651 int found = 0;
1652 struct hlist_head *lih = &l->list;
Sasha Levinb67bfe02013-02-27 17:06:00 -08001653 struct hlist_node *tmp;
Robert Olsson19baf832005-06-21 12:43:18 -07001654 struct leaf_info *li = NULL;
1655
Sasha Levinb67bfe02013-02-27 17:06:00 -08001656 hlist_for_each_entry_safe(li, tmp, lih, hlist) {
Stephen Hemmingeref3660c2008-04-10 03:46:12 -07001657 found += trie_flush_list(&li->falh);
Robert Olsson19baf832005-06-21 12:43:18 -07001658
1659 if (list_empty(&li->falh)) {
Robert Olsson2373ce12005-08-25 13:01:29 -07001660 hlist_del_rcu(&li->hlist);
Robert Olsson19baf832005-06-21 12:43:18 -07001661 free_leaf_info(li);
1662 }
1663 }
1664 return found;
1665}
1666
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001667/*
1668 * Scan for the next right leaf starting at node p->child[idx]
1669 * Since we have back pointer, no recursion necessary.
1670 */
Alexander Duyckadaf9812014-12-31 10:55:47 -08001671static struct tnode *leaf_walk_rcu(struct tnode *p, struct tnode *c)
Robert Olsson19baf832005-06-21 12:43:18 -07001672{
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001673 do {
1674 t_key idx;
Robert Olsson19baf832005-06-21 12:43:18 -07001675
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001676 if (c)
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001677 idx = tkey_extract_bits(c->key, p->pos, p->bits) + 1;
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07001678 else
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001679 idx = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001680
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001681 while (idx < 1u << p->bits) {
1682 c = tnode_get_child_rcu(p, idx++);
Robert Olsson2373ce12005-08-25 13:01:29 -07001683 if (!c)
Olof Johansson91b9a272005-08-09 20:24:39 -07001684 continue;
Robert Olsson19baf832005-06-21 12:43:18 -07001685
Eric Dumazetaab515d2013-08-05 11:18:49 -07001686 if (IS_LEAF(c))
Alexander Duyckadaf9812014-12-31 10:55:47 -08001687 return c;
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001688
1689 /* Rescan start scanning in new node */
Alexander Duyckadaf9812014-12-31 10:55:47 -08001690 p = c;
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001691 idx = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001692 }
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001693
1694 /* Node empty, walk back up to parent */
Alexander Duyckadaf9812014-12-31 10:55:47 -08001695 c = p;
Eric Dumazeta034ee32010-09-09 23:32:28 +00001696 } while ((p = node_parent_rcu(c)) != NULL);
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001697
1698 return NULL; /* Root of trie */
1699}
1700
Alexander Duyckadaf9812014-12-31 10:55:47 -08001701static struct tnode *trie_firstleaf(struct trie *t)
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001702{
Alexander Duyckadaf9812014-12-31 10:55:47 -08001703 struct tnode *n = rcu_dereference_rtnl(t->trie);
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001704
1705 if (!n)
1706 return NULL;
1707
1708 if (IS_LEAF(n)) /* trie is just a leaf */
Alexander Duyckadaf9812014-12-31 10:55:47 -08001709 return n;
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001710
1711 return leaf_walk_rcu(n, NULL);
1712}
1713
Alexander Duyckadaf9812014-12-31 10:55:47 -08001714static struct tnode *trie_nextleaf(struct tnode *l)
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001715{
Alexander Duyckadaf9812014-12-31 10:55:47 -08001716 struct tnode *p = node_parent_rcu(l);
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001717
1718 if (!p)
1719 return NULL; /* trie with just one leaf */
1720
Alexander Duyckadaf9812014-12-31 10:55:47 -08001721 return leaf_walk_rcu(p, l);
Robert Olsson19baf832005-06-21 12:43:18 -07001722}
1723
Alexander Duyckadaf9812014-12-31 10:55:47 -08001724static struct tnode *trie_leafindex(struct trie *t, int index)
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001725{
Alexander Duyckadaf9812014-12-31 10:55:47 -08001726 struct tnode *l = trie_firstleaf(t);
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001727
Stephen Hemmingerec28cf72008-02-11 21:12:49 -08001728 while (l && index-- > 0)
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001729 l = trie_nextleaf(l);
Stephen Hemmingerec28cf72008-02-11 21:12:49 -08001730
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001731 return l;
1732}
1733
1734
Robert Olssond562f1f2007-03-26 14:22:22 -07001735/*
1736 * Caller must hold RTNL.
1737 */
Stephen Hemminger16c6cf82009-09-20 10:35:36 +00001738int fib_table_flush(struct fib_table *tb)
Robert Olsson19baf832005-06-21 12:43:18 -07001739{
1740 struct trie *t = (struct trie *) tb->tb_data;
Alexander Duyckadaf9812014-12-31 10:55:47 -08001741 struct tnode *l, *ll = NULL;
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001742 int found = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001743
Stephen Hemminger82cfbb02008-01-22 21:55:32 -08001744 for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) {
Stephen Hemmingeref3660c2008-04-10 03:46:12 -07001745 found += trie_flush_leaf(l);
Robert Olsson19baf832005-06-21 12:43:18 -07001746
1747 if (ll && hlist_empty(&ll->list))
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001748 trie_leaf_remove(t, ll);
Robert Olsson19baf832005-06-21 12:43:18 -07001749 ll = l;
1750 }
1751
1752 if (ll && hlist_empty(&ll->list))
Stephen Hemminger9195bef2008-01-22 21:56:34 -08001753 trie_leaf_remove(t, ll);
Robert Olsson19baf832005-06-21 12:43:18 -07001754
Stephen Hemminger0c7770c2005-08-23 21:59:41 -07001755 pr_debug("trie_flush found=%d\n", found);
Robert Olsson19baf832005-06-21 12:43:18 -07001756 return found;
1757}
1758
Pavel Emelyanov4aa2c462010-10-28 02:00:43 +00001759void fib_free_table(struct fib_table *tb)
1760{
Alexander Duyck8274a972014-12-31 10:55:29 -08001761#ifdef CONFIG_IP_FIB_TRIE_STATS
1762 struct trie *t = (struct trie *)tb->tb_data;
1763
1764 free_percpu(t->stats);
1765#endif /* CONFIG_IP_FIB_TRIE_STATS */
Pavel Emelyanov4aa2c462010-10-28 02:00:43 +00001766 kfree(tb);
1767}
1768
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001769static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
1770 struct fib_table *tb,
Robert Olsson19baf832005-06-21 12:43:18 -07001771 struct sk_buff *skb, struct netlink_callback *cb)
1772{
1773 int i, s_i;
1774 struct fib_alias *fa;
Al Viro32ab5f82006-09-26 22:21:45 -07001775 __be32 xkey = htonl(key);
Robert Olsson19baf832005-06-21 12:43:18 -07001776
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001777 s_i = cb->args[5];
Robert Olsson19baf832005-06-21 12:43:18 -07001778 i = 0;
1779
Robert Olsson2373ce12005-08-25 13:01:29 -07001780 /* rcu_read_lock is hold by caller */
1781
1782 list_for_each_entry_rcu(fa, fah, fa_list) {
Robert Olsson19baf832005-06-21 12:43:18 -07001783 if (i < s_i) {
1784 i++;
1785 continue;
1786 }
Robert Olsson19baf832005-06-21 12:43:18 -07001787
Eric W. Biederman15e47302012-09-07 20:12:54 +00001788 if (fib_dump_info(skb, NETLINK_CB(cb->skb).portid,
Robert Olsson19baf832005-06-21 12:43:18 -07001789 cb->nlh->nlmsg_seq,
1790 RTM_NEWROUTE,
1791 tb->tb_id,
1792 fa->fa_type,
Thomas Grafbe403ea2006-08-17 18:15:17 -07001793 xkey,
Robert Olsson19baf832005-06-21 12:43:18 -07001794 plen,
1795 fa->fa_tos,
Stephen Hemminger64347f72008-01-22 21:55:01 -08001796 fa->fa_info, NLM_F_MULTI) < 0) {
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001797 cb->args[5] = i;
Robert Olsson19baf832005-06-21 12:43:18 -07001798 return -1;
Olof Johansson91b9a272005-08-09 20:24:39 -07001799 }
Robert Olsson19baf832005-06-21 12:43:18 -07001800 i++;
1801 }
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001802 cb->args[5] = i;
Robert Olsson19baf832005-06-21 12:43:18 -07001803 return skb->len;
1804}
1805
Alexander Duyckadaf9812014-12-31 10:55:47 -08001806static int fn_trie_dump_leaf(struct tnode *l, struct fib_table *tb,
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001807 struct sk_buff *skb, struct netlink_callback *cb)
Robert Olsson19baf832005-06-21 12:43:18 -07001808{
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001809 struct leaf_info *li;
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001810 int i, s_i;
Robert Olsson19baf832005-06-21 12:43:18 -07001811
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001812 s_i = cb->args[4];
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001813 i = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001814
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001815 /* rcu_read_lock is hold by caller */
Sasha Levinb67bfe02013-02-27 17:06:00 -08001816 hlist_for_each_entry_rcu(li, &l->list, hlist) {
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001817 if (i < s_i) {
1818 i++;
Robert Olsson19baf832005-06-21 12:43:18 -07001819 continue;
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001820 }
Robert Olsson19baf832005-06-21 12:43:18 -07001821
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001822 if (i > s_i)
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001823 cb->args[5] = 0;
Olof Johansson91b9a272005-08-09 20:24:39 -07001824
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001825 if (list_empty(&li->falh))
Robert Olsson19baf832005-06-21 12:43:18 -07001826 continue;
1827
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001828 if (fn_trie_dump_fa(l->key, li->plen, &li->falh, tb, skb, cb) < 0) {
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001829 cb->args[4] = i;
Robert Olsson19baf832005-06-21 12:43:18 -07001830 return -1;
1831 }
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001832 i++;
Robert Olsson19baf832005-06-21 12:43:18 -07001833 }
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001834
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001835 cb->args[4] = i;
Robert Olsson19baf832005-06-21 12:43:18 -07001836 return skb->len;
1837}
1838
Stephen Hemminger16c6cf82009-09-20 10:35:36 +00001839int fib_table_dump(struct fib_table *tb, struct sk_buff *skb,
1840 struct netlink_callback *cb)
Robert Olsson19baf832005-06-21 12:43:18 -07001841{
Alexander Duyckadaf9812014-12-31 10:55:47 -08001842 struct tnode *l;
Robert Olsson19baf832005-06-21 12:43:18 -07001843 struct trie *t = (struct trie *) tb->tb_data;
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001844 t_key key = cb->args[2];
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001845 int count = cb->args[3];
Robert Olsson19baf832005-06-21 12:43:18 -07001846
Robert Olsson2373ce12005-08-25 13:01:29 -07001847 rcu_read_lock();
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001848 /* Dump starting at last key.
1849 * Note: 0.0.0.0/0 (ie default) is first key.
1850 */
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001851 if (count == 0)
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001852 l = trie_firstleaf(t);
1853 else {
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001854 /* Normally, continue from last key, but if that is missing
1855 * fallback to using slow rescan
1856 */
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001857 l = fib_find_node(t, key);
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001858 if (!l)
1859 l = trie_leafindex(t, count);
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001860 }
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001861
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001862 while (l) {
1863 cb->args[2] = l->key;
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001864 if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) {
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001865 cb->args[3] = count;
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001866 rcu_read_unlock();
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001867 return -1;
Robert Olsson19baf832005-06-21 12:43:18 -07001868 }
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001869
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001870 ++count;
Stephen Hemmingerd5ce8a02008-01-22 21:57:22 -08001871 l = trie_nextleaf(l);
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001872 memset(&cb->args[4], 0,
1873 sizeof(cb->args) - 4*sizeof(cb->args[0]));
Robert Olsson19baf832005-06-21 12:43:18 -07001874 }
Stephen Hemminger71d67e62008-01-31 16:45:47 -08001875 cb->args[3] = count;
Robert Olsson2373ce12005-08-25 13:01:29 -07001876 rcu_read_unlock();
Stephen Hemmingera88ee222008-01-22 21:56:11 -08001877
Robert Olsson19baf832005-06-21 12:43:18 -07001878 return skb->len;
Robert Olsson19baf832005-06-21 12:43:18 -07001879}
1880
David S. Miller5348ba82011-02-01 15:30:56 -08001881void __init fib_trie_init(void)
Stephen Hemminger7f9b8052008-01-14 23:14:20 -08001882{
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08001883 fn_alias_kmem = kmem_cache_create("ip_fib_alias",
1884 sizeof(struct fib_alias),
Stephen Hemmingerbc3c8c12008-01-22 21:51:50 -08001885 0, SLAB_PANIC, NULL);
1886
1887 trie_leaf_kmem = kmem_cache_create("ip_fib_trie",
Alexander Duyckadaf9812014-12-31 10:55:47 -08001888 max(sizeof(struct tnode),
Stephen Hemmingerbc3c8c12008-01-22 21:51:50 -08001889 sizeof(struct leaf_info)),
1890 0, SLAB_PANIC, NULL);
Stephen Hemminger7f9b8052008-01-14 23:14:20 -08001891}
Robert Olsson19baf832005-06-21 12:43:18 -07001892
Stephen Hemminger7f9b8052008-01-14 23:14:20 -08001893
David S. Miller5348ba82011-02-01 15:30:56 -08001894struct fib_table *fib_trie_table(u32 id)
Robert Olsson19baf832005-06-21 12:43:18 -07001895{
1896 struct fib_table *tb;
1897 struct trie *t;
1898
Robert Olsson19baf832005-06-21 12:43:18 -07001899 tb = kmalloc(sizeof(struct fib_table) + sizeof(struct trie),
1900 GFP_KERNEL);
1901 if (tb == NULL)
1902 return NULL;
1903
1904 tb->tb_id = id;
Denis V. Lunev971b8932007-12-08 00:32:23 -08001905 tb->tb_default = -1;
David S. Miller21d8c492011-04-14 14:49:37 -07001906 tb->tb_num_default = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07001907
1908 t = (struct trie *) tb->tb_data;
Alexander Duyck8274a972014-12-31 10:55:29 -08001909 RCU_INIT_POINTER(t->trie, NULL);
1910#ifdef CONFIG_IP_FIB_TRIE_STATS
1911 t->stats = alloc_percpu(struct trie_use_stats);
1912 if (!t->stats) {
1913 kfree(tb);
1914 tb = NULL;
1915 }
1916#endif
Robert Olsson19baf832005-06-21 12:43:18 -07001917
Robert Olsson19baf832005-06-21 12:43:18 -07001918 return tb;
1919}
1920
Robert Olsson19baf832005-06-21 12:43:18 -07001921#ifdef CONFIG_PROC_FS
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001922/* Depth first Trie walk iterator */
1923struct fib_trie_iter {
Denis V. Lunev1c340b22008-01-10 03:27:17 -08001924 struct seq_net_private p;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07001925 struct fib_table *tb;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001926 struct tnode *tnode;
Eric Dumazeta034ee32010-09-09 23:32:28 +00001927 unsigned int index;
1928 unsigned int depth;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001929};
Robert Olsson19baf832005-06-21 12:43:18 -07001930
Alexander Duyckadaf9812014-12-31 10:55:47 -08001931static struct tnode *fib_trie_get_next(struct fib_trie_iter *iter)
Robert Olsson19baf832005-06-21 12:43:18 -07001932{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001933 struct tnode *tn = iter->tnode;
Eric Dumazeta034ee32010-09-09 23:32:28 +00001934 unsigned int cindex = iter->index;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001935 struct tnode *p;
1936
Eric W. Biederman6640e692007-01-24 14:42:04 -08001937 /* A single entry routing table */
1938 if (!tn)
1939 return NULL;
1940
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001941 pr_debug("get_next iter={node=%p index=%d depth=%d}\n",
1942 iter->tnode, iter->index, iter->depth);
1943rescan:
1944 while (cindex < (1<<tn->bits)) {
Alexander Duyckadaf9812014-12-31 10:55:47 -08001945 struct tnode *n = tnode_get_child_rcu(tn, cindex);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001946
1947 if (n) {
1948 if (IS_LEAF(n)) {
1949 iter->tnode = tn;
1950 iter->index = cindex + 1;
1951 } else {
1952 /* push down one level */
Alexander Duyckadaf9812014-12-31 10:55:47 -08001953 iter->tnode = n;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001954 iter->index = 0;
1955 ++iter->depth;
1956 }
1957 return n;
1958 }
1959
1960 ++cindex;
1961 }
1962
1963 /* Current node exhausted, pop back up */
Alexander Duyckadaf9812014-12-31 10:55:47 -08001964 p = node_parent_rcu(tn);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001965 if (p) {
1966 cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1;
1967 tn = p;
1968 --iter->depth;
1969 goto rescan;
1970 }
1971
1972 /* got root? */
Robert Olsson19baf832005-06-21 12:43:18 -07001973 return NULL;
1974}
1975
Alexander Duyckadaf9812014-12-31 10:55:47 -08001976static struct tnode *fib_trie_get_first(struct fib_trie_iter *iter,
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001977 struct trie *t)
Robert Olsson19baf832005-06-21 12:43:18 -07001978{
Alexander Duyckadaf9812014-12-31 10:55:47 -08001979 struct tnode *n;
Robert Olsson5ddf0eb2006-03-20 21:34:12 -08001980
Stephen Hemminger132adf52007-03-08 20:44:43 -08001981 if (!t)
Robert Olsson5ddf0eb2006-03-20 21:34:12 -08001982 return NULL;
1983
1984 n = rcu_dereference(t->trie);
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07001985 if (!n)
Robert Olsson5ddf0eb2006-03-20 21:34:12 -08001986 return NULL;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001987
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07001988 if (IS_TNODE(n)) {
Alexander Duyckadaf9812014-12-31 10:55:47 -08001989 iter->tnode = n;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07001990 iter->index = 0;
1991 iter->depth = 1;
1992 } else {
1993 iter->tnode = NULL;
1994 iter->index = 0;
1995 iter->depth = 0;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07001996 }
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07001997
1998 return n;
Robert Olsson19baf832005-06-21 12:43:18 -07001999}
2000
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002001static void trie_collect_stats(struct trie *t, struct trie_stat *s)
Robert Olsson19baf832005-06-21 12:43:18 -07002002{
Alexander Duyckadaf9812014-12-31 10:55:47 -08002003 struct tnode *n;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002004 struct fib_trie_iter iter;
Robert Olsson19baf832005-06-21 12:43:18 -07002005
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002006 memset(s, 0, sizeof(*s));
Robert Olsson19baf832005-06-21 12:43:18 -07002007
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002008 rcu_read_lock();
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002009 for (n = fib_trie_get_first(&iter, t); n; n = fib_trie_get_next(&iter)) {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002010 if (IS_LEAF(n)) {
Stephen Hemminger93672292008-01-22 21:54:05 -08002011 struct leaf_info *li;
Stephen Hemminger93672292008-01-22 21:54:05 -08002012
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002013 s->leaves++;
2014 s->totdepth += iter.depth;
2015 if (iter.depth > s->maxdepth)
2016 s->maxdepth = iter.depth;
Stephen Hemminger93672292008-01-22 21:54:05 -08002017
Alexander Duyckadaf9812014-12-31 10:55:47 -08002018 hlist_for_each_entry_rcu(li, &n->list, hlist)
Stephen Hemminger93672292008-01-22 21:54:05 -08002019 ++s->prefixes;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002020 } else {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002021 int i;
Robert Olsson19baf832005-06-21 12:43:18 -07002022
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002023 s->tnodes++;
Alexander Duyckadaf9812014-12-31 10:55:47 -08002024 if (n->bits < MAX_STAT_DEPTH)
2025 s->nodesizes[n->bits]++;
Robert Olsson06ef9212006-03-20 21:35:01 -08002026
Alexander Duyckadaf9812014-12-31 10:55:47 -08002027 for (i = 0; i < tnode_child_length(n); i++)
2028 if (!rcu_access_pointer(n->child[i]))
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002029 s->nullpointers++;
2030 }
2031 }
2032 rcu_read_unlock();
Robert Olsson19baf832005-06-21 12:43:18 -07002033}
2034
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07002035/*
Robert Olsson19baf832005-06-21 12:43:18 -07002036 * This outputs /proc/net/fib_triestats
Robert Olsson19baf832005-06-21 12:43:18 -07002037 */
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002038static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
Robert Olsson19baf832005-06-21 12:43:18 -07002039{
Eric Dumazeta034ee32010-09-09 23:32:28 +00002040 unsigned int i, max, pointers, bytes, avdepth;
Robert Olsson19baf832005-06-21 12:43:18 -07002041
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002042 if (stat->leaves)
2043 avdepth = stat->totdepth*100 / stat->leaves;
2044 else
2045 avdepth = 0;
Robert Olsson19baf832005-06-21 12:43:18 -07002046
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08002047 seq_printf(seq, "\tAver depth: %u.%02d\n",
2048 avdepth / 100, avdepth % 100);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002049 seq_printf(seq, "\tMax depth: %u\n", stat->maxdepth);
Robert Olsson19baf832005-06-21 12:43:18 -07002050
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002051 seq_printf(seq, "\tLeaves: %u\n", stat->leaves);
Alexander Duyckadaf9812014-12-31 10:55:47 -08002052 bytes = sizeof(struct tnode) * stat->leaves;
Stephen Hemminger93672292008-01-22 21:54:05 -08002053
2054 seq_printf(seq, "\tPrefixes: %u\n", stat->prefixes);
2055 bytes += sizeof(struct leaf_info) * stat->prefixes;
2056
Stephen Hemminger187b5182008-01-12 20:55:55 -08002057 seq_printf(seq, "\tInternal nodes: %u\n\t", stat->tnodes);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002058 bytes += sizeof(struct tnode) * stat->tnodes;
Robert Olsson19baf832005-06-21 12:43:18 -07002059
Robert Olsson06ef9212006-03-20 21:35:01 -08002060 max = MAX_STAT_DEPTH;
2061 while (max > 0 && stat->nodesizes[max-1] == 0)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002062 max--;
Robert Olsson19baf832005-06-21 12:43:18 -07002063
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002064 pointers = 0;
Jerry Snitselaarf585a992013-07-22 12:01:58 -07002065 for (i = 1; i < max; i++)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002066 if (stat->nodesizes[i] != 0) {
Stephen Hemminger187b5182008-01-12 20:55:55 -08002067 seq_printf(seq, " %u: %u", i, stat->nodesizes[i]);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002068 pointers += (1<<i) * stat->nodesizes[i];
2069 }
2070 seq_putc(seq, '\n');
Stephen Hemminger187b5182008-01-12 20:55:55 -08002071 seq_printf(seq, "\tPointers: %u\n", pointers);
Robert Olsson19baf832005-06-21 12:43:18 -07002072
Alexander Duyckadaf9812014-12-31 10:55:47 -08002073 bytes += sizeof(struct tnode *) * pointers;
Stephen Hemminger187b5182008-01-12 20:55:55 -08002074 seq_printf(seq, "Null ptrs: %u\n", stat->nullpointers);
2075 seq_printf(seq, "Total size: %u kB\n", (bytes + 1023) / 1024);
Stephen Hemminger66a2f7f2008-01-12 21:23:17 -08002076}
Robert Olsson19baf832005-06-21 12:43:18 -07002077
2078#ifdef CONFIG_IP_FIB_TRIE_STATS
Stephen Hemminger66a2f7f2008-01-12 21:23:17 -08002079static void trie_show_usage(struct seq_file *seq,
Alexander Duyck8274a972014-12-31 10:55:29 -08002080 const struct trie_use_stats __percpu *stats)
Stephen Hemminger66a2f7f2008-01-12 21:23:17 -08002081{
Alexander Duyck8274a972014-12-31 10:55:29 -08002082 struct trie_use_stats s = { 0 };
2083 int cpu;
2084
2085 /* loop through all of the CPUs and gather up the stats */
2086 for_each_possible_cpu(cpu) {
2087 const struct trie_use_stats *pcpu = per_cpu_ptr(stats, cpu);
2088
2089 s.gets += pcpu->gets;
2090 s.backtrack += pcpu->backtrack;
2091 s.semantic_match_passed += pcpu->semantic_match_passed;
2092 s.semantic_match_miss += pcpu->semantic_match_miss;
2093 s.null_node_hit += pcpu->null_node_hit;
2094 s.resize_node_skipped += pcpu->resize_node_skipped;
2095 }
2096
Stephen Hemminger66a2f7f2008-01-12 21:23:17 -08002097 seq_printf(seq, "\nCounters:\n---------\n");
Alexander Duyck8274a972014-12-31 10:55:29 -08002098 seq_printf(seq, "gets = %u\n", s.gets);
2099 seq_printf(seq, "backtracks = %u\n", s.backtrack);
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08002100 seq_printf(seq, "semantic match passed = %u\n",
Alexander Duyck8274a972014-12-31 10:55:29 -08002101 s.semantic_match_passed);
2102 seq_printf(seq, "semantic match miss = %u\n", s.semantic_match_miss);
2103 seq_printf(seq, "null node hit= %u\n", s.null_node_hit);
2104 seq_printf(seq, "skipped node resize = %u\n\n", s.resize_node_skipped);
Robert Olsson19baf832005-06-21 12:43:18 -07002105}
Stephen Hemminger66a2f7f2008-01-12 21:23:17 -08002106#endif /* CONFIG_IP_FIB_TRIE_STATS */
2107
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002108static void fib_table_print(struct seq_file *seq, struct fib_table *tb)
Stephen Hemmingerd717a9a2008-01-14 23:11:54 -08002109{
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002110 if (tb->tb_id == RT_TABLE_LOCAL)
2111 seq_puts(seq, "Local:\n");
2112 else if (tb->tb_id == RT_TABLE_MAIN)
2113 seq_puts(seq, "Main:\n");
2114 else
2115 seq_printf(seq, "Id %d:\n", tb->tb_id);
Stephen Hemmingerd717a9a2008-01-14 23:11:54 -08002116}
Robert Olsson19baf832005-06-21 12:43:18 -07002117
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002118
Robert Olsson19baf832005-06-21 12:43:18 -07002119static int fib_triestat_seq_show(struct seq_file *seq, void *v)
2120{
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002121 struct net *net = (struct net *)seq->private;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002122 unsigned int h;
Eric W. Biederman877a9bf2007-12-07 00:47:47 -08002123
Stephen Hemmingerd717a9a2008-01-14 23:11:54 -08002124 seq_printf(seq,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08002125 "Basic info: size of leaf:"
2126 " %Zd bytes, size of tnode: %Zd bytes.\n",
Alexander Duyckadaf9812014-12-31 10:55:47 -08002127 sizeof(struct tnode), sizeof(struct tnode));
Olof Johansson91b9a272005-08-09 20:24:39 -07002128
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002129 for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
2130 struct hlist_head *head = &net->ipv4.fib_table_hash[h];
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002131 struct fib_table *tb;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002132
Sasha Levinb67bfe02013-02-27 17:06:00 -08002133 hlist_for_each_entry_rcu(tb, head, tb_hlist) {
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002134 struct trie *t = (struct trie *) tb->tb_data;
2135 struct trie_stat stat;
2136
2137 if (!t)
2138 continue;
2139
2140 fib_table_print(seq, tb);
2141
2142 trie_collect_stats(t, &stat);
2143 trie_show_stats(seq, &stat);
2144#ifdef CONFIG_IP_FIB_TRIE_STATS
Alexander Duyck8274a972014-12-31 10:55:29 -08002145 trie_show_usage(seq, t->stats);
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002146#endif
2147 }
2148 }
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002149
Robert Olsson19baf832005-06-21 12:43:18 -07002150 return 0;
2151}
2152
Robert Olsson19baf832005-06-21 12:43:18 -07002153static int fib_triestat_seq_open(struct inode *inode, struct file *file)
2154{
Pavel Emelyanovde05c552008-07-18 04:07:21 -07002155 return single_open_net(inode, file, fib_triestat_seq_show);
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002156}
2157
Arjan van de Ven9a321442007-02-12 00:55:35 -08002158static const struct file_operations fib_triestat_fops = {
Stephen Hemmingerc877efb2005-07-19 14:01:51 -07002159 .owner = THIS_MODULE,
2160 .open = fib_triestat_seq_open,
2161 .read = seq_read,
2162 .llseek = seq_lseek,
Pavel Emelyanovb6fcbdb2008-07-18 04:07:44 -07002163 .release = single_release_net,
Robert Olsson19baf832005-06-21 12:43:18 -07002164};
2165
Alexander Duyckadaf9812014-12-31 10:55:47 -08002166static struct tnode *fib_trie_get_idx(struct seq_file *seq, loff_t pos)
Robert Olsson19baf832005-06-21 12:43:18 -07002167{
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002168 struct fib_trie_iter *iter = seq->private;
2169 struct net *net = seq_file_net(seq);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002170 loff_t idx = 0;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002171 unsigned int h;
Robert Olsson19baf832005-06-21 12:43:18 -07002172
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002173 for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
2174 struct hlist_head *head = &net->ipv4.fib_table_hash[h];
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002175 struct fib_table *tb;
2176
Sasha Levinb67bfe02013-02-27 17:06:00 -08002177 hlist_for_each_entry_rcu(tb, head, tb_hlist) {
Alexander Duyckadaf9812014-12-31 10:55:47 -08002178 struct tnode *n;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002179
2180 for (n = fib_trie_get_first(iter,
2181 (struct trie *) tb->tb_data);
2182 n; n = fib_trie_get_next(iter))
2183 if (pos == idx++) {
2184 iter->tb = tb;
2185 return n;
2186 }
2187 }
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002188 }
Robert Olsson19baf832005-06-21 12:43:18 -07002189
Robert Olsson19baf832005-06-21 12:43:18 -07002190 return NULL;
2191}
2192
2193static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
Stephen Hemmingerc95aaf92008-01-12 21:25:02 -08002194 __acquires(RCU)
Robert Olsson19baf832005-06-21 12:43:18 -07002195{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002196 rcu_read_lock();
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002197 return fib_trie_get_idx(seq, *pos);
Robert Olsson19baf832005-06-21 12:43:18 -07002198}
2199
2200static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2201{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002202 struct fib_trie_iter *iter = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002203 struct net *net = seq_file_net(seq);
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002204 struct fib_table *tb = iter->tb;
2205 struct hlist_node *tb_node;
2206 unsigned int h;
Alexander Duyckadaf9812014-12-31 10:55:47 -08002207 struct tnode *n;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002208
Robert Olsson19baf832005-06-21 12:43:18 -07002209 ++*pos;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002210 /* next node in same table */
2211 n = fib_trie_get_next(iter);
2212 if (n)
2213 return n;
Olof Johansson91b9a272005-08-09 20:24:39 -07002214
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002215 /* walk rest of this hash chain */
2216 h = tb->tb_id & (FIB_TABLE_HASHSZ - 1);
Eric Dumazet0a5c0472011-03-31 01:51:35 -07002217 while ((tb_node = rcu_dereference(hlist_next_rcu(&tb->tb_hlist)))) {
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002218 tb = hlist_entry(tb_node, struct fib_table, tb_hlist);
2219 n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
2220 if (n)
2221 goto found;
2222 }
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002223
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002224 /* new hash chain */
2225 while (++h < FIB_TABLE_HASHSZ) {
2226 struct hlist_head *head = &net->ipv4.fib_table_hash[h];
Sasha Levinb67bfe02013-02-27 17:06:00 -08002227 hlist_for_each_entry_rcu(tb, head, tb_hlist) {
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002228 n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
2229 if (n)
2230 goto found;
2231 }
2232 }
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002233 return NULL;
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002234
2235found:
2236 iter->tb = tb;
2237 return n;
Robert Olsson19baf832005-06-21 12:43:18 -07002238}
2239
2240static void fib_trie_seq_stop(struct seq_file *seq, void *v)
Stephen Hemmingerc95aaf92008-01-12 21:25:02 -08002241 __releases(RCU)
Robert Olsson19baf832005-06-21 12:43:18 -07002242{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002243 rcu_read_unlock();
Robert Olsson19baf832005-06-21 12:43:18 -07002244}
2245
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002246static void seq_indent(struct seq_file *seq, int n)
2247{
Eric Dumazeta034ee32010-09-09 23:32:28 +00002248 while (n-- > 0)
2249 seq_puts(seq, " ");
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002250}
Robert Olsson19baf832005-06-21 12:43:18 -07002251
Eric Dumazet28d36e32008-01-14 23:09:56 -08002252static inline const char *rtn_scope(char *buf, size_t len, enum rt_scope_t s)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002253{
Stephen Hemminger132adf52007-03-08 20:44:43 -08002254 switch (s) {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002255 case RT_SCOPE_UNIVERSE: return "universe";
2256 case RT_SCOPE_SITE: return "site";
2257 case RT_SCOPE_LINK: return "link";
2258 case RT_SCOPE_HOST: return "host";
2259 case RT_SCOPE_NOWHERE: return "nowhere";
2260 default:
Eric Dumazet28d36e32008-01-14 23:09:56 -08002261 snprintf(buf, len, "scope=%d", s);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002262 return buf;
2263 }
2264}
2265
Jan Engelhardt36cbd3d2009-08-05 10:42:58 -07002266static const char *const rtn_type_names[__RTN_MAX] = {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002267 [RTN_UNSPEC] = "UNSPEC",
2268 [RTN_UNICAST] = "UNICAST",
2269 [RTN_LOCAL] = "LOCAL",
2270 [RTN_BROADCAST] = "BROADCAST",
2271 [RTN_ANYCAST] = "ANYCAST",
2272 [RTN_MULTICAST] = "MULTICAST",
2273 [RTN_BLACKHOLE] = "BLACKHOLE",
2274 [RTN_UNREACHABLE] = "UNREACHABLE",
2275 [RTN_PROHIBIT] = "PROHIBIT",
2276 [RTN_THROW] = "THROW",
2277 [RTN_NAT] = "NAT",
2278 [RTN_XRESOLVE] = "XRESOLVE",
2279};
2280
Eric Dumazeta034ee32010-09-09 23:32:28 +00002281static inline const char *rtn_type(char *buf, size_t len, unsigned int t)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002282{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002283 if (t < __RTN_MAX && rtn_type_names[t])
2284 return rtn_type_names[t];
Eric Dumazet28d36e32008-01-14 23:09:56 -08002285 snprintf(buf, len, "type %u", t);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002286 return buf;
2287}
2288
2289/* Pretty print the trie */
Robert Olsson19baf832005-06-21 12:43:18 -07002290static int fib_trie_seq_show(struct seq_file *seq, void *v)
2291{
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002292 const struct fib_trie_iter *iter = seq->private;
Alexander Duyckadaf9812014-12-31 10:55:47 -08002293 struct tnode *n = v;
Robert Olsson19baf832005-06-21 12:43:18 -07002294
Stephen Hemminger3d3b2d22008-03-23 22:43:56 -07002295 if (!node_parent_rcu(n))
2296 fib_table_print(seq, iter->tb);
Robert Olsson095b8502007-01-26 19:06:01 -08002297
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002298 if (IS_TNODE(n)) {
Alexander Duyckadaf9812014-12-31 10:55:47 -08002299 __be32 prf = htonl(n->key);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002300
Alexander Duyckadaf9812014-12-31 10:55:47 -08002301 seq_indent(seq, iter->depth - 1);
Harvey Harrison673d57e2008-10-31 00:53:57 -07002302 seq_printf(seq, " +-- %pI4/%d %d %d %d\n",
Alexander Duyckadaf9812014-12-31 10:55:47 -08002303 &prf, n->pos, n->bits, n->full_children,
2304 n->empty_children);
Olof Johansson91b9a272005-08-09 20:24:39 -07002305 } else {
Stephen Hemminger13280422008-01-22 21:54:37 -08002306 struct leaf_info *li;
Alexander Duyckadaf9812014-12-31 10:55:47 -08002307 __be32 val = htonl(n->key);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002308
2309 seq_indent(seq, iter->depth);
Harvey Harrison673d57e2008-10-31 00:53:57 -07002310 seq_printf(seq, " |-- %pI4\n", &val);
Eric Dumazet28d36e32008-01-14 23:09:56 -08002311
Alexander Duyckadaf9812014-12-31 10:55:47 -08002312 hlist_for_each_entry_rcu(li, &n->list, hlist) {
Stephen Hemminger13280422008-01-22 21:54:37 -08002313 struct fib_alias *fa;
Eric Dumazet28d36e32008-01-14 23:09:56 -08002314
Stephen Hemminger13280422008-01-22 21:54:37 -08002315 list_for_each_entry_rcu(fa, &li->falh, fa_list) {
2316 char buf1[32], buf2[32];
Eric Dumazet28d36e32008-01-14 23:09:56 -08002317
Stephen Hemminger13280422008-01-22 21:54:37 -08002318 seq_indent(seq, iter->depth+1);
2319 seq_printf(seq, " /%d %s %s", li->plen,
2320 rtn_scope(buf1, sizeof(buf1),
David S. Miller37e826c2011-03-24 18:06:47 -07002321 fa->fa_info->fib_scope),
Stephen Hemminger13280422008-01-22 21:54:37 -08002322 rtn_type(buf2, sizeof(buf2),
2323 fa->fa_type));
2324 if (fa->fa_tos)
Denis V. Lunevb9c4d822008-02-05 02:58:45 -08002325 seq_printf(seq, " tos=%d", fa->fa_tos);
Stephen Hemminger13280422008-01-22 21:54:37 -08002326 seq_putc(seq, '\n');
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002327 }
2328 }
Robert Olsson19baf832005-06-21 12:43:18 -07002329 }
2330
2331 return 0;
2332}
2333
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002334static const struct seq_operations fib_trie_seq_ops = {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002335 .start = fib_trie_seq_start,
2336 .next = fib_trie_seq_next,
2337 .stop = fib_trie_seq_stop,
2338 .show = fib_trie_seq_show,
Robert Olsson19baf832005-06-21 12:43:18 -07002339};
2340
2341static int fib_trie_seq_open(struct inode *inode, struct file *file)
2342{
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002343 return seq_open_net(inode, file, &fib_trie_seq_ops,
2344 sizeof(struct fib_trie_iter));
Robert Olsson19baf832005-06-21 12:43:18 -07002345}
2346
Arjan van de Ven9a321442007-02-12 00:55:35 -08002347static const struct file_operations fib_trie_fops = {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002348 .owner = THIS_MODULE,
2349 .open = fib_trie_seq_open,
2350 .read = seq_read,
2351 .llseek = seq_lseek,
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002352 .release = seq_release_net,
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002353};
2354
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002355struct fib_route_iter {
2356 struct seq_net_private p;
2357 struct trie *main_trie;
2358 loff_t pos;
2359 t_key key;
2360};
2361
Alexander Duyckadaf9812014-12-31 10:55:47 -08002362static struct tnode *fib_route_get_idx(struct fib_route_iter *iter, loff_t pos)
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002363{
Alexander Duyckadaf9812014-12-31 10:55:47 -08002364 struct tnode *l = NULL;
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002365 struct trie *t = iter->main_trie;
2366
2367 /* use cache location of last found key */
2368 if (iter->pos > 0 && pos >= iter->pos && (l = fib_find_node(t, iter->key)))
2369 pos -= iter->pos;
2370 else {
2371 iter->pos = 0;
2372 l = trie_firstleaf(t);
2373 }
2374
2375 while (l && pos-- > 0) {
2376 iter->pos++;
2377 l = trie_nextleaf(l);
2378 }
2379
2380 if (l)
2381 iter->key = pos; /* remember it */
2382 else
2383 iter->pos = 0; /* forget it */
2384
2385 return l;
2386}
2387
2388static void *fib_route_seq_start(struct seq_file *seq, loff_t *pos)
2389 __acquires(RCU)
2390{
2391 struct fib_route_iter *iter = seq->private;
2392 struct fib_table *tb;
2393
2394 rcu_read_lock();
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002395 tb = fib_get_table(seq_file_net(seq), RT_TABLE_MAIN);
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002396 if (!tb)
2397 return NULL;
2398
2399 iter->main_trie = (struct trie *) tb->tb_data;
2400 if (*pos == 0)
2401 return SEQ_START_TOKEN;
2402 else
2403 return fib_route_get_idx(iter, *pos - 1);
2404}
2405
2406static void *fib_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2407{
2408 struct fib_route_iter *iter = seq->private;
Alexander Duyckadaf9812014-12-31 10:55:47 -08002409 struct tnode *l = v;
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002410
2411 ++*pos;
2412 if (v == SEQ_START_TOKEN) {
2413 iter->pos = 0;
2414 l = trie_firstleaf(iter->main_trie);
2415 } else {
2416 iter->pos++;
2417 l = trie_nextleaf(l);
2418 }
2419
2420 if (l)
2421 iter->key = l->key;
2422 else
2423 iter->pos = 0;
2424 return l;
2425}
2426
2427static void fib_route_seq_stop(struct seq_file *seq, void *v)
2428 __releases(RCU)
2429{
2430 rcu_read_unlock();
2431}
2432
Eric Dumazeta034ee32010-09-09 23:32:28 +00002433static unsigned int fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002434{
Eric Dumazeta034ee32010-09-09 23:32:28 +00002435 unsigned int flags = 0;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002436
Eric Dumazeta034ee32010-09-09 23:32:28 +00002437 if (type == RTN_UNREACHABLE || type == RTN_PROHIBIT)
2438 flags = RTF_REJECT;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002439 if (fi && fi->fib_nh->nh_gw)
2440 flags |= RTF_GATEWAY;
Al Viro32ab5f82006-09-26 22:21:45 -07002441 if (mask == htonl(0xFFFFFFFF))
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002442 flags |= RTF_HOST;
2443 flags |= RTF_UP;
2444 return flags;
2445}
2446
2447/*
2448 * This outputs /proc/net/route.
2449 * The format of the file is not supposed to be changed
Eric Dumazeta034ee32010-09-09 23:32:28 +00002450 * and needs to be same as fib_hash output to avoid breaking
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002451 * legacy utilities
2452 */
2453static int fib_route_seq_show(struct seq_file *seq, void *v)
2454{
Alexander Duyckadaf9812014-12-31 10:55:47 -08002455 struct tnode *l = v;
Stephen Hemminger13280422008-01-22 21:54:37 -08002456 struct leaf_info *li;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002457
2458 if (v == SEQ_START_TOKEN) {
2459 seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
2460 "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
2461 "\tWindow\tIRTT");
2462 return 0;
2463 }
2464
Sasha Levinb67bfe02013-02-27 17:06:00 -08002465 hlist_for_each_entry_rcu(li, &l->list, hlist) {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002466 struct fib_alias *fa;
Al Viro32ab5f82006-09-26 22:21:45 -07002467 __be32 mask, prefix;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002468
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002469 mask = inet_make_mask(li->plen);
2470 prefix = htonl(l->key);
2471
2472 list_for_each_entry_rcu(fa, &li->falh, fa_list) {
Herbert Xu1371e372005-10-15 09:42:39 +10002473 const struct fib_info *fi = fa->fa_info;
Eric Dumazeta034ee32010-09-09 23:32:28 +00002474 unsigned int flags = fib_flag_trans(fa->fa_type, mask, fi);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002475
2476 if (fa->fa_type == RTN_BROADCAST
2477 || fa->fa_type == RTN_MULTICAST)
2478 continue;
2479
Tetsuo Handa652586d2013-11-14 14:31:57 -08002480 seq_setwidth(seq, 127);
2481
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002482 if (fi)
Pavel Emelyanov5e659e42008-04-24 01:02:16 -07002483 seq_printf(seq,
2484 "%s\t%08X\t%08X\t%04X\t%d\t%u\t"
Tetsuo Handa652586d2013-11-14 14:31:57 -08002485 "%d\t%08X\t%d\t%u\t%u",
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002486 fi->fib_dev ? fi->fib_dev->name : "*",
2487 prefix,
2488 fi->fib_nh->nh_gw, flags, 0, 0,
2489 fi->fib_priority,
2490 mask,
Stephen Hemmingera07f5f52008-01-22 21:53:36 -08002491 (fi->fib_advmss ?
2492 fi->fib_advmss + 40 : 0),
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002493 fi->fib_window,
Tetsuo Handa652586d2013-11-14 14:31:57 -08002494 fi->fib_rtt >> 3);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002495 else
Pavel Emelyanov5e659e42008-04-24 01:02:16 -07002496 seq_printf(seq,
2497 "*\t%08X\t%08X\t%04X\t%d\t%u\t"
Tetsuo Handa652586d2013-11-14 14:31:57 -08002498 "%d\t%08X\t%d\t%u\t%u",
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002499 prefix, 0, flags, 0, 0, 0,
Tetsuo Handa652586d2013-11-14 14:31:57 -08002500 mask, 0, 0, 0);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002501
Tetsuo Handa652586d2013-11-14 14:31:57 -08002502 seq_pad(seq, '\n');
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002503 }
2504 }
2505
2506 return 0;
2507}
2508
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002509static const struct seq_operations fib_route_seq_ops = {
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002510 .start = fib_route_seq_start,
2511 .next = fib_route_seq_next,
2512 .stop = fib_route_seq_stop,
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002513 .show = fib_route_seq_show,
2514};
2515
2516static int fib_route_seq_open(struct inode *inode, struct file *file)
2517{
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002518 return seq_open_net(inode, file, &fib_route_seq_ops,
Stephen Hemminger8315f5d2008-02-11 21:14:39 -08002519 sizeof(struct fib_route_iter));
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002520}
2521
Arjan van de Ven9a321442007-02-12 00:55:35 -08002522static const struct file_operations fib_route_fops = {
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002523 .owner = THIS_MODULE,
2524 .open = fib_route_seq_open,
2525 .read = seq_read,
2526 .llseek = seq_lseek,
Denis V. Lunev1c340b22008-01-10 03:27:17 -08002527 .release = seq_release_net,
Robert Olsson19baf832005-06-21 12:43:18 -07002528};
2529
Denis V. Lunev61a02652008-01-10 03:21:09 -08002530int __net_init fib_proc_init(struct net *net)
Robert Olsson19baf832005-06-21 12:43:18 -07002531{
Gao fengd4beaa62013-02-18 01:34:54 +00002532 if (!proc_create("fib_trie", S_IRUGO, net->proc_net, &fib_trie_fops))
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002533 goto out1;
2534
Gao fengd4beaa62013-02-18 01:34:54 +00002535 if (!proc_create("fib_triestat", S_IRUGO, net->proc_net,
2536 &fib_triestat_fops))
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002537 goto out2;
2538
Gao fengd4beaa62013-02-18 01:34:54 +00002539 if (!proc_create("route", S_IRUGO, net->proc_net, &fib_route_fops))
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002540 goto out3;
2541
Robert Olsson19baf832005-06-21 12:43:18 -07002542 return 0;
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002543
2544out3:
Gao fengece31ff2013-02-18 01:34:56 +00002545 remove_proc_entry("fib_triestat", net->proc_net);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002546out2:
Gao fengece31ff2013-02-18 01:34:56 +00002547 remove_proc_entry("fib_trie", net->proc_net);
Stephen Hemmingercb7b5932005-09-09 13:35:42 -07002548out1:
2549 return -ENOMEM;
Robert Olsson19baf832005-06-21 12:43:18 -07002550}
2551
Denis V. Lunev61a02652008-01-10 03:21:09 -08002552void __net_exit fib_proc_exit(struct net *net)
Robert Olsson19baf832005-06-21 12:43:18 -07002553{
Gao fengece31ff2013-02-18 01:34:56 +00002554 remove_proc_entry("fib_trie", net->proc_net);
2555 remove_proc_entry("fib_triestat", net->proc_net);
2556 remove_proc_entry("route", net->proc_net);
Robert Olsson19baf832005-06-21 12:43:18 -07002557}
2558
2559#endif /* CONFIG_PROC_FS */