fib_trie.c revision 058bd4d2a4ff0aaa4a5381c67e776729d840c785
119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson/*
219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *   This program is free software; you can redistribute it and/or
319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *   modify it under the terms of the GNU General Public License
419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *   as published by the Free Software Foundation; either version
519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *   2 of the License, or (at your option) any later version.
619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *   Robert Olsson <robert.olsson@its.uu.se> Uppsala Universitet
819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *     & Swedish University of Agricultural Sciences.
919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
10e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki *   Jens Laas <jens.laas@data.slu.se> Swedish University of
1119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *     Agricultural Sciences.
12e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki *
1319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *   Hans Liss <hans.liss@its.uu.se>  Uppsala Universitet
1419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
1525985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * This work is based on the LPC-trie which is originally described in:
16e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki *
1719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * An experimental study of compression methods for dynamic tries
1819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002.
19631dd1a885b6d7e9f6f51b4e5b311c2bb04c323cJustin P. Mattock * http://www.csc.kth.se/~snilsson/software/dyntrie2/
2019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
2119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
2219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson
2319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, June 1999
2419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
2519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
2619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Code from fib_hash has been reused which includes the following header:
2719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
2819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
2919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * INET		An implementation of the TCP/IP protocol suite for the LINUX
3019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		operating system.  INET is implemented using the  BSD Socket
3119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		interface as the means of communication with the user level.
3219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
3319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		IPv4 FIB: lookup engine and maintenance routines.
3419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
3519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
3619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
3719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
3819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		This program is free software; you can redistribute it and/or
3919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		modify it under the terms of the GNU General Public License
4019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		as published by the Free Software Foundation; either version
4119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		2 of the License, or (at your option) any later version.
42fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson *
43fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson * Substantial contributions to this work comes from:
44fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson *
45fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson *		David S. Miller, <davem@davemloft.net>
46fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson *		Stephen Hemminger <shemminger@osdl.org>
47fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson *		Paul E. McKenney <paulmck@us.ibm.com>
48fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson *		Patrick McHardy <kaber@trash.net>
4919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */
5019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
5180b71b80df14d885f7e50e115c1348398f418759Jens Låås#define VERSION "0.409"
5219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
5319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <asm/uaccess.h>
5419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <asm/system.h>
551977f032722c27ee3730284582fd3991ad9ac81bJiri Slaby#include <linux/bitops.h>
5619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/types.h>
5719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/kernel.h>
5819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/mm.h>
5919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/string.h>
6019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/socket.h>
6119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/sockios.h>
6219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/errno.h>
6319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/in.h>
6419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/inet.h>
65cd8787ab04d23f925f440b712b43a6fd5cb31eceStephen Hemminger#include <linux/inetdevice.h>
6619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/netdevice.h>
6719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/if_arp.h>
6819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/proc_fs.h>
692373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson#include <linux/rcupdate.h>
7019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/skbuff.h>
7119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/netlink.h>
7219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/init.h>
7319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/list.h>
745a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
7570c71606190e9115e5f8363bfcd164c582eb314aPaul Gortmaker#include <linux/prefetch.h>
76bc3b2d7fb9b014d75ebb79ba371a763dbab5e8cfPaul Gortmaker#include <linux/export.h>
77457c4cbc5a3dde259d2a1f15d5f9785290397267Eric W. Biederman#include <net/net_namespace.h>
7819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/ip.h>
7919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/protocol.h>
8019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/route.h>
8119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/tcp.h>
8219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/sock.h>
8319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/ip_fib.h>
8419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include "fib_lookup.h"
8519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8606ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson#define MAX_STAT_DEPTH 32
8719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define KEYLENGTH (8*sizeof(t_key))
8919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
9019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssontypedef unsigned int t_key;
9119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
9219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define T_TNODE 0
9319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define T_LEAF  1
9419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define NODE_TYPE_MASK	0x1UL
952373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson#define NODE_TYPE(node) ((node)->parent & NODE_TYPE_MASK)
962373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
9791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson#define IS_TNODE(n) (!(n->parent & T_LEAF))
9891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson#define IS_LEAF(n) (n->parent & T_LEAF)
9919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
100b299e4f001cfa16205f9121f4630970049652268David S. Millerstruct rt_trie_node {
10191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	unsigned long parent;
1028d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	t_key key;
10319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
10419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
10519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct leaf {
10691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	unsigned long parent;
1078d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	t_key key;
10819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_head list;
1092373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct rcu_head rcu;
11019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
11119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
11219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct leaf_info {
11319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_node hlist;
11419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int plen;
1155c74501f76360ce6f410730b9b5e5976f38e8504Eric Dumazet	u32 mask_plen; /* ntohl(inet_make_mask(plen)) */
11619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct list_head falh;
1175c74501f76360ce6f410730b9b5e5976f38e8504Eric Dumazet	struct rcu_head rcu;
11819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
11919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
12019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct tnode {
12191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	unsigned long parent;
1228d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	t_key key;
123112d8cfcbf4f5ef0cf669cb5864f1206972076d6Eric Dumazet	unsigned char pos;		/* 2log(KEYLENGTH) bits needed */
124112d8cfcbf4f5ef0cf669cb5864f1206972076d6Eric Dumazet	unsigned char bits;		/* 2log(KEYLENGTH) bits needed */
1258d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	unsigned int full_children;	/* KEYLENGTH bits needed */
1268d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	unsigned int empty_children;	/* KEYLENGTH bits needed */
12715be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	union {
12815be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger		struct rcu_head rcu;
12915be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger		struct work_struct work;
130e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski		struct tnode *tnode_free;
13115be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	};
1320a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	struct rt_trie_node __rcu *child[0];
13319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
13419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
13519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
13619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct trie_use_stats {
13719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int gets;
13819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int backtrack;
13919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int semantic_match_passed;
14019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int semantic_match_miss;
14119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int null_node_hit;
1422f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	unsigned int resize_node_skipped;
14319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
14419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
14519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
14619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct trie_stat {
14719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int totdepth;
14819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int maxdepth;
14919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int tnodes;
15019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int leaves;
15119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int nullpointers;
152936722922f6d2366378de606a40c14f96915474dStephen Hemminger	unsigned int prefixes;
15306ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson	unsigned int nodesizes[MAX_STAT_DEPTH];
154c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger};
15519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
15619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct trie {
1570a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	struct rt_trie_node __rcu *trie;
15819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
15919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie_use_stats stats;
16019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
16119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
16219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
163b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic void put_child(struct trie *t, struct tnode *tn, int i, struct rt_trie_node *n);
164b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n,
165a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				  int wasfull);
166b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic struct rt_trie_node *resize(struct trie *t, struct tnode *tn);
1672f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *inflate(struct trie *t, struct tnode *tn);
1682f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *halve(struct trie *t, struct tnode *tn);
169e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski/* tnodes to free after resize(); protected by RTNL */
170e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawskistatic struct tnode *tnode_free_head;
171c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawskistatic size_t tnode_free_size;
172c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski
173c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski/*
174c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski * synchronize_rcu after call_rcu for that many pages; it should be especially
175c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski * useful before resizing the root node with PREEMPT_NONE configs; the value was
176c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski * obtained experimentally, aiming to avoid visible slowdown.
177c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski */
178c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawskistatic const int sync_pages = 128;
17919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
180e18b890bb0881bbab6f4f1a6cd20d9c60d66b003Christoph Lameterstatic struct kmem_cache *fn_alias_kmem __read_mostly;
181bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemmingerstatic struct kmem_cache *trie_leaf_kmem __read_mostly;
18219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1830a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet/*
1840a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet * caller must hold RTNL
1850a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet */
1860a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazetstatic inline struct tnode *node_parent(const struct rt_trie_node *node)
1870680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger{
1880a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	unsigned long parent;
1890a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet
1900a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	parent = rcu_dereference_index_check(node->parent, lockdep_rtnl_is_held());
1910a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet
1920a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	return (struct tnode *)(parent & ~NODE_TYPE_MASK);
193b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet}
194b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet
1950a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet/*
1960a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet * caller must hold RCU read lock or RTNL
1970a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet */
1980a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazetstatic inline struct tnode *node_parent_rcu(const struct rt_trie_node *node)
199b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet{
2000a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	unsigned long parent;
2010a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet
2020a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	parent = rcu_dereference_index_check(node->parent, rcu_read_lock_held() ||
2030a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet							   lockdep_rtnl_is_held());
2040680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger
2050a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	return (struct tnode *)(parent & ~NODE_TYPE_MASK);
2060680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger}
2070680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger
208cf778b00e96df6d64f8e21b8395d1f8a859ecdc7Eric Dumazet/* Same as rcu_assign_pointer
2096440cc9e0f48ade57af7be28008cbfa6a991f287Stephen Hemminger * but that macro() assumes that value is a pointer.
2106440cc9e0f48ade57af7be28008cbfa6a991f287Stephen Hemminger */
211b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic inline void node_set_parent(struct rt_trie_node *node, struct tnode *ptr)
2120680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger{
2136440cc9e0f48ade57af7be28008cbfa6a991f287Stephen Hemminger	smp_wmb();
2146440cc9e0f48ade57af7be28008cbfa6a991f287Stephen Hemminger	node->parent = (unsigned long)ptr | NODE_TYPE(node);
2150680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger}
2162373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
2170a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet/*
2180a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet * caller must hold RTNL
2190a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet */
2200a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazetstatic inline struct rt_trie_node *tnode_get_child(const struct tnode *tn, unsigned int i)
221b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet{
222b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet	BUG_ON(i >= 1U << tn->bits);
2232373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
2240a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	return rtnl_dereference(tn->child[i]);
225b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet}
226b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet
2270a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet/*
2280a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet * caller must hold RCU read lock or RTNL
2290a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet */
2300a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazetstatic inline struct rt_trie_node *tnode_get_child_rcu(const struct tnode *tn, unsigned int i)
23119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2320a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	BUG_ON(i >= 1U << tn->bits);
23319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2340a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	return rcu_dereference_rtnl(tn->child[i]);
23519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
23619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
237bb435b8d816582064ee0ddb1e2a6fbca67f34108Stephen Hemmingerstatic inline int tnode_child_length(const struct tnode *tn)
23819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
23991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	return 1 << tn->bits;
24019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
24119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2423b004569d86d02786ebae496e75dc0b625be3e9aDavid S. Millerstatic inline t_key mask_pfx(t_key k, unsigned int l)
243ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger{
244ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger	return (l == 0) ? 0 : k >> (KEYLENGTH-l) << (KEYLENGTH-l);
245ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger}
246ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger
2473b004569d86d02786ebae496e75dc0b625be3e9aDavid S. Millerstatic inline t_key tkey_extract_bits(t_key a, unsigned int offset, unsigned int bits)
24819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
24991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (offset < KEYLENGTH)
25019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return ((t_key)(a << offset)) >> (KEYLENGTH - bits);
25191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	else
25219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return 0;
25319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
25419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
25519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline int tkey_equals(t_key a, t_key b)
25619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
257c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	return a == b;
25819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
25919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
26019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline int tkey_sub_equals(t_key a, int offset, int bits, t_key b)
26119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
262c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (bits == 0 || offset >= KEYLENGTH)
263c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		return 1;
26491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	bits = bits > KEYLENGTH ? KEYLENGTH : bits;
26591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	return ((a ^ b) << offset) >> (KEYLENGTH - bits) == 0;
266c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger}
26719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
26819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline int tkey_mismatch(t_key a, int offset, t_key b)
26919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
27019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t_key diff = a ^ b;
27119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i = offset;
27219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
273c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!diff)
274c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		return 0;
275c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	while ((diff << i) >> (KEYLENGTH-1) == 0)
27619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		i++;
27719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return i;
27819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
27919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
28019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson/*
281e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  To understand this stuff, an understanding of keys and all their bits is
282e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  necessary. Every node in the trie has a key associated with it, but not
28319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  all of the bits in that key are significant.
28419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
28519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  Consider a node 'n' and its parent 'tp'.
28619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
287e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  If n is a leaf, every bit in its key is significant. Its presence is
288e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  necessitated by path compression, since during a tree traversal (when
289e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  searching for a leaf - unless we are doing an insertion) we will completely
290e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  ignore all skipped bits we encounter. Thus we need to verify, at the end of
291e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  a potentially successful search, that we have indeed been walking the
29219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  correct key path.
29319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
294e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  Note that we can never "miss" the correct key in the tree if present by
295e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  following the wrong path. Path compression ensures that segments of the key
296e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  that are the same for all keys with a given prefix are skipped, but the
297e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  skipped part *is* identical for each node in the subtrie below the skipped
298e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  bit! trie_insert() in this implementation takes care of that - note the
29919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  call to tkey_sub_equals() in trie_insert().
30019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
301e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  if n is an internal node - a 'tnode' here, the various parts of its key
30219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  have many different meanings.
30319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
304e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  Example:
30519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  _________________________________________________________________
30619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C |
30719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  -----------------------------------------------------------------
308e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki    0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
30919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
31019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  _________________________________________________________________
31119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u |
31219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  -----------------------------------------------------------------
31319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson   16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31
31419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
31519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  tp->pos = 7
31619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  tp->bits = 3
31719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  n->pos = 15
31891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson  n->bits = 4
31919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
320e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  First, let's just ignore the bits that come before the parent tp, that is
321e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  the bits from 0 to (tp->pos-1). They are *known* but at this point we do
32219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  not use them for anything.
32319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
32419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  The bits from (tp->pos) to (tp->pos + tp->bits - 1) - "N", above - are the
325e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  index into the parent's child array. That is, they will be used to find
32619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  'n' among tp's children.
32719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
32819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  The bits from (tp->pos + tp->bits) to (n->pos - 1) - "S" - are skipped bits
32919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  for the node n.
33019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
331e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  All the bits we have seen so far are significant to the node n. The rest
33219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  of the bits are really not needed or indeed known in n->key.
33319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
334e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  The bits from (n->pos) to (n->pos + n->bits - 1) - "C" - are the index into
33519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  n's child array, and will of course be different for each child.
336e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki
337c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
33819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  The rest of the bits, from (n->pos + n->bits) onward, are completely unknown
33919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  at this point.
34019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
34119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson*/
34219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
3430c7770c740156c8802c23d24fc094d06967d997dStephen Hemmingerstatic inline void check_tnode(const struct tnode *tn)
34419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
3450c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	WARN_ON(tn && tn->pos+tn->bits > 32);
34619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
34719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
348f5026fabda54e5ab5d469d8cfac5f46b4d321ce9Denis V. Lunevstatic const int halve_threshold = 25;
349f5026fabda54e5ab5d469d8cfac5f46b4d321ce9Denis V. Lunevstatic const int inflate_threshold = 50;
350345aa031207d02d7438c1aa96ed9315911ecd745Jarek Poplawskistatic const int halve_threshold_root = 15;
35180b71b80df14d885f7e50e115c1348398f418759Jens Lååsstatic const int inflate_threshold_root = 30;
3522373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
3532373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __alias_free_mem(struct rcu_head *head)
35419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
3552373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct fib_alias *fa = container_of(head, struct fib_alias, rcu);
3562373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	kmem_cache_free(fn_alias_kmem, fa);
35719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
35819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
3592373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic inline void alias_free_mem_rcu(struct fib_alias *fa)
36019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
3612373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	call_rcu(&fa->rcu, __alias_free_mem);
3622373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
36391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
3642373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __leaf_free_rcu(struct rcu_head *head)
3652373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{
366bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger	struct leaf *l = container_of(head, struct leaf, rcu);
367bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger	kmem_cache_free(trie_leaf_kmem, l);
3682373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
36991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
370387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemmingerstatic inline void free_leaf(struct leaf *l)
371387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger{
372387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger	call_rcu_bh(&l->rcu, __leaf_free_rcu);
373387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger}
374387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger
3752373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic inline void free_leaf_info(struct leaf_info *leaf)
37619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
377bceb0f4512d448763fe98c9f37504c98bbebbed6Lai Jiangshan	kfree_rcu(leaf, rcu);
37819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
37919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
3808d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazetstatic struct tnode *tnode_alloc(size_t size)
381f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy{
3822373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	if (size <= PAGE_SIZE)
3838d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet		return kzalloc(size, GFP_KERNEL);
38415be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	else
3857a1c8e5ab120a5f352e78bbc1fa5bb64e6f23639Eric Dumazet		return vzalloc(size);
38615be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger}
3872373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
38815be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemmingerstatic void __tnode_vfree(struct work_struct *arg)
38915be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger{
39015be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	struct tnode *tn = container_of(arg, struct tnode, work);
39115be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	vfree(tn);
392f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy}
393f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy
3942373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __tnode_free_rcu(struct rcu_head *head)
395f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy{
3962373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct tnode *tn = container_of(head, struct tnode, rcu);
3978d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	size_t size = sizeof(struct tnode) +
398b299e4f001cfa16205f9121f4630970049652268David S. Miller		      (sizeof(struct rt_trie_node *) << tn->bits);
399f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy
400f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy	if (size <= PAGE_SIZE)
401f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy		kfree(tn);
40215be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	else {
40315be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger		INIT_WORK(&tn->work, __tnode_vfree);
40415be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger		schedule_work(&tn->work);
40515be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	}
406f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy}
407f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy
4082373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic inline void tnode_free(struct tnode *tn)
4092373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{
410387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger	if (IS_LEAF(tn))
411387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger		free_leaf((struct leaf *) tn);
412387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger	else
413550e29bc96e6f1ced2bca82dace197b009434367Robert Olsson		call_rcu(&tn->rcu, __tnode_free_rcu);
4142373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
4152373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
416e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawskistatic void tnode_free_safe(struct tnode *tn)
417e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski{
418e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski	BUG_ON(IS_LEAF(tn));
4197b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawski	tn->tnode_free = tnode_free_head;
4207b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawski	tnode_free_head = tn;
421c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski	tnode_free_size += sizeof(struct tnode) +
422b299e4f001cfa16205f9121f4630970049652268David S. Miller			   (sizeof(struct rt_trie_node *) << tn->bits);
423e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski}
424e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski
425e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawskistatic void tnode_free_flush(void)
426e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski{
427e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski	struct tnode *tn;
428e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski
429e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski	while ((tn = tnode_free_head)) {
430e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski		tnode_free_head = tn->tnode_free;
431e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski		tn->tnode_free = NULL;
432e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski		tnode_free(tn);
433e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski	}
434c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski
435c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski	if (tnode_free_size >= PAGE_SIZE * sync_pages) {
436c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski		tnode_free_size = 0;
437c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski		synchronize_rcu();
438c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski	}
439e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski}
440e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski
4412373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic struct leaf *leaf_new(void)
4422373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{
443bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger	struct leaf *l = kmem_cache_alloc(trie_leaf_kmem, GFP_KERNEL);
4442373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	if (l) {
4452373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		l->parent = T_LEAF;
4462373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		INIT_HLIST_HEAD(&l->list);
4472373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	}
4482373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	return l;
4492373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
4502373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
4512373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic struct leaf_info *leaf_info_new(int plen)
4522373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{
4532373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct leaf_info *li = kmalloc(sizeof(struct leaf_info),  GFP_KERNEL);
4542373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	if (li) {
4552373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		li->plen = plen;
4565c74501f76360ce6f410730b9b5e5976f38e8504Eric Dumazet		li->mask_plen = ntohl(inet_make_mask(plen));
4572373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		INIT_LIST_HEAD(&li->falh);
4582373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	}
4592373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	return li;
4602373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
4612373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
462a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic struct tnode *tnode_new(t_key key, int pos, int bits)
46319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
464b299e4f001cfa16205f9121f4630970049652268David S. Miller	size_t sz = sizeof(struct tnode) + (sizeof(struct rt_trie_node *) << bits);
465f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy	struct tnode *tn = tnode_alloc(sz);
46619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
46791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (tn) {
4682373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		tn->parent = T_TNODE;
46919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->pos = pos;
47019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->bits = bits;
47119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->key = key;
47219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->full_children = 0;
47319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->empty_children = 1<<bits;
47419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
475c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
476a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet	pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode),
477b299e4f001cfa16205f9121f4630970049652268David S. Miller		 sizeof(struct rt_trie_node) << bits);
47819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return tn;
47919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
48019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
48119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson/*
48219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Check whether a tnode 'n' is "full", i.e. it is an internal node
48319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * and no bits are skipped. See discussion in dyntree paper p. 6
48419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */
48519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
486b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic inline int tnode_full(const struct tnode *tn, const struct rt_trie_node *n)
48719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
488c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (n == NULL || IS_LEAF(n))
48919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return 0;
49019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
49119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return ((struct tnode *) n)->pos == tn->pos + tn->bits;
49219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
49319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
494a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic inline void put_child(struct trie *t, struct tnode *tn, int i,
495b299e4f001cfa16205f9121f4630970049652268David S. Miller			     struct rt_trie_node *n)
49619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
49719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tnode_put_child_reorg(tn, i, n, -1);
49819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
49919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
500c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger /*
50119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  * Add a child at position i overwriting the old value.
50219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  * Update the value of full_children and empty_children.
50319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  */
50419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
505b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n,
506a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				  int wasfull)
50719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
5080a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	struct rt_trie_node *chi = rtnl_dereference(tn->child[i]);
50919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int isfull;
51019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
5110c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	BUG_ON(i >= 1<<tn->bits);
5120c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
51319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* update emptyChildren */
51419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (n == NULL && chi != NULL)
51519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->empty_children++;
51619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	else if (n != NULL && chi == NULL)
51719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->empty_children--;
518c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
51919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* update fullChildren */
52091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (wasfull == -1)
52119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		wasfull = tnode_full(tn, chi);
52219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
52319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	isfull = tnode_full(tn, n);
524c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (wasfull && !isfull)
52519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->full_children--;
526c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	else if (!wasfull && isfull)
52719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->full_children++;
52891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
529c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (n)
5300680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger		node_set_parent(n, tn);
53119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
532cf778b00e96df6d64f8e21b8395d1f8a859ecdc7Eric Dumazet	rcu_assign_pointer(tn->child[i], n);
53319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
53419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
53580b71b80df14d885f7e50e115c1348398f418759Jens Låås#define MAX_WORK 10
536b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic struct rt_trie_node *resize(struct trie *t, struct tnode *tn)
53719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
53819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i;
5392f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	struct tnode *old_tn;
540e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson	int inflate_threshold_use;
541e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson	int halve_threshold_use;
54280b71b80df14d885f7e50e115c1348398f418759Jens Låås	int max_work;
54319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
544e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	if (!tn)
54519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return NULL;
54619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
5470c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("In tnode_resize %p inflate_threshold=%d threshold=%d\n",
5480c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		 tn, inflate_threshold, halve_threshold);
54919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
55019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* No children */
55119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (tn->empty_children == tnode_child_length(tn)) {
552e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski		tnode_free_safe(tn);
55319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return NULL;
55419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
55519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* One child */
55619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (tn->empty_children == tnode_child_length(tn) - 1)
55780b71b80df14d885f7e50e115c1348398f418759Jens Låås		goto one_child;
558c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	/*
55919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * Double as long as the resulting node has a number of
56019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * nonempty nodes that are above the threshold.
56119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
56219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
56319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/*
564c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * From "Implementing a dynamic compressed trie" by Stefan Nilsson of
565c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * the Helsinki University of Technology and Matti Tikkanen of Nokia
56619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * Telecommunications, page 6:
567c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * "A node is doubled if the ratio of non-empty children to all
56819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * children in the *doubled* node is at least 'high'."
56919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
570c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * 'high' in this instance is the variable 'inflate_threshold'. It
571c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * is expressed as a percentage, so we multiply it with
572c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * tnode_child_length() and instead of multiplying by 2 (since the
573c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * child array will be doubled by inflate()) and multiplying
574c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * the left-hand side by 100 (to handle the percentage thing) we
57519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * multiply the left-hand side by 50.
576c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
577c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * The left-hand side may look a bit weird: tnode_child_length(tn)
578c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * - tn->empty_children is of course the number of non-null children
579c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * in the current node. tn->full_children is the number of "full"
58019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * children, that is non-null tnodes with a skip value of 0.
581c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * All of those will be doubled in the resulting inflated tnode, so
58219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * we just count them one extra time here.
583c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
58419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * A clearer way to write this would be:
585c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
58619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * to_be_doubled = tn->full_children;
587c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children -
58819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *     tn->full_children;
58919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
59019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * new_child_length = tnode_child_length(tn) * 2;
59119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
592c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) /
59319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *      new_child_length;
59419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * if (new_fill_factor >= inflate_threshold)
595c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
596c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * ...and so on, tho it would mess up the while () loop.
597c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
59819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * anyway,
59919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >=
60019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *      inflate_threshold
601c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
60219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * avoid a division:
60319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * 100 * (not_to_be_doubled + 2*to_be_doubled) >=
60419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *      inflate_threshold * new_child_length
605c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
60619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * expand not_to_be_doubled and to_be_doubled, and shorten:
607c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * 100 * (tnode_child_length(tn) - tn->empty_children +
60891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	 *    tn->full_children) >= inflate_threshold * new_child_length
609c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
61019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * expand new_child_length:
611c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * 100 * (tnode_child_length(tn) - tn->empty_children +
61291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	 *    tn->full_children) >=
61319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *      inflate_threshold * tnode_child_length(tn) * 2
614c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
61519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * shorten again:
616c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * 50 * (tn->full_children + tnode_child_length(tn) -
61791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	 *    tn->empty_children) >= inflate_threshold *
61819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *    tnode_child_length(tn)
619c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
62019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
62119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
62219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	check_tnode(tn);
623c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
624e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson	/* Keep root node larger  */
625e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson
626b299e4f001cfa16205f9121f4630970049652268David S. Miller	if (!node_parent((struct rt_trie_node *)tn)) {
62780b71b80df14d885f7e50e115c1348398f418759Jens Låås		inflate_threshold_use = inflate_threshold_root;
62880b71b80df14d885f7e50e115c1348398f418759Jens Låås		halve_threshold_use = halve_threshold_root;
629a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet	} else {
630e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson		inflate_threshold_use = inflate_threshold;
63180b71b80df14d885f7e50e115c1348398f418759Jens Låås		halve_threshold_use = halve_threshold;
63280b71b80df14d885f7e50e115c1348398f418759Jens Låås	}
633e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson
63480b71b80df14d885f7e50e115c1348398f418759Jens Låås	max_work = MAX_WORK;
63580b71b80df14d885f7e50e115c1348398f418759Jens Låås	while ((tn->full_children > 0 &&  max_work-- &&
636a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		50 * (tn->full_children + tnode_child_length(tn)
637a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		      - tn->empty_children)
638a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		>= inflate_threshold_use * tnode_child_length(tn))) {
63919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
6402f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		old_tn = tn;
6412f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		tn = inflate(t, tn);
642a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
6432f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		if (IS_ERR(tn)) {
6442f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			tn = old_tn;
6452f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
6462f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			t->stats.resize_node_skipped++;
6472f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#endif
6482f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			break;
6492f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		}
65019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
65119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
65219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	check_tnode(tn);
65319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
65480b71b80df14d885f7e50e115c1348398f418759Jens Låås	/* Return if at least one inflate is run */
655a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet	if (max_work != MAX_WORK)
656b299e4f001cfa16205f9121f4630970049652268David S. Miller		return (struct rt_trie_node *) tn;
65780b71b80df14d885f7e50e115c1348398f418759Jens Låås
65819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/*
65919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * Halve as long as the number of empty children in this
66019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * node is above threshold.
66119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
6622f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
66380b71b80df14d885f7e50e115c1348398f418759Jens Låås	max_work = MAX_WORK;
66480b71b80df14d885f7e50e115c1348398f418759Jens Låås	while (tn->bits > 1 &&  max_work-- &&
66519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	       100 * (tnode_child_length(tn) - tn->empty_children) <
666e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson	       halve_threshold_use * tnode_child_length(tn)) {
6672f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
6682f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		old_tn = tn;
6692f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		tn = halve(t, tn);
6702f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		if (IS_ERR(tn)) {
6712f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			tn = old_tn;
6722f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
6732f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			t->stats.resize_node_skipped++;
6742f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#endif
6752f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			break;
6762f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		}
6772f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	}
67819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
679c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
68019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Only one child remains */
68180b71b80df14d885f7e50e115c1348398f418759Jens Låås	if (tn->empty_children == tnode_child_length(tn) - 1) {
68280b71b80df14d885f7e50e115c1348398f418759Jens Lååsone_child:
68319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		for (i = 0; i < tnode_child_length(tn); i++) {
684b299e4f001cfa16205f9121f4630970049652268David S. Miller			struct rt_trie_node *n;
68519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
6860a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet			n = rtnl_dereference(tn->child[i]);
6872373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			if (!n)
68891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				continue;
68991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
69091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			/* compress one level */
69191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
6920680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger			node_set_parent(n, NULL);
693e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski			tnode_free_safe(tn);
69491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			return n;
69519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
69680b71b80df14d885f7e50e115c1348398f418759Jens Låås	}
697b299e4f001cfa16205f9121f4630970049652268David S. Miller	return (struct rt_trie_node *) tn;
69819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
69919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
7000a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet
7010a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazetstatic void tnode_clean_free(struct tnode *tn)
7020a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet{
7030a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	int i;
7040a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	struct tnode *tofree;
7050a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet
7060a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	for (i = 0; i < tnode_child_length(tn); i++) {
7070a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet		tofree = (struct tnode *)rtnl_dereference(tn->child[i]);
7080a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet		if (tofree)
7090a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet			tnode_free(tofree);
7100a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	}
7110a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	tnode_free(tn);
7120a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet}
7130a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet
7142f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *inflate(struct trie *t, struct tnode *tn)
71519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
71619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *oldtnode = tn;
71719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int olen = tnode_child_length(tn);
71819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i;
71919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
7200c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("In inflate\n");
72119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
72219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits + 1);
72319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
7240c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	if (!tn)
7252f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		return ERR_PTR(-ENOMEM);
7262f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
7272f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	/*
728c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * Preallocate and store tnodes before the actual work so we
729c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * don't get into an inconsistent state if memory allocation
730c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * fails. In case of failure we return the oldnode and  inflate
7312f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	 * of tnode is ignored.
7322f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	 */
73391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
73491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (i = 0; i < olen; i++) {
735a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		struct tnode *inode;
7362f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
737a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		inode = (struct tnode *) tnode_get_child(oldtnode, i);
7382f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		if (inode &&
7392f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		    IS_TNODE(inode) &&
7402f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		    inode->pos == oldtnode->pos + oldtnode->bits &&
7412f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		    inode->bits > 1) {
7422f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			struct tnode *left, *right;
743ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger			t_key m = ~0U << (KEYLENGTH - 1) >> inode->pos;
744c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
7452f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			left = tnode_new(inode->key&(~m), inode->pos + 1,
7462f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson					 inode->bits - 1);
7472f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			if (!left)
7482f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				goto nomem;
74991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
7502f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			right = tnode_new(inode->key|m, inode->pos + 1,
7512f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson					  inode->bits - 1);
7522f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
753e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki			if (!right) {
7542f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				tnode_free(left);
7552f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				goto nomem;
756e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki			}
7572f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
758b299e4f001cfa16205f9121f4630970049652268David S. Miller			put_child(t, tn, 2*i, (struct rt_trie_node *) left);
759b299e4f001cfa16205f9121f4630970049652268David S. Miller			put_child(t, tn, 2*i+1, (struct rt_trie_node *) right);
7602f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		}
7612f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	}
7622f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
76391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (i = 0; i < olen; i++) {
764c95aaf9af5a1f6dee56d1f2ab4915cd722d608daStephen Hemminger		struct tnode *inode;
765b299e4f001cfa16205f9121f4630970049652268David S. Miller		struct rt_trie_node *node = tnode_get_child(oldtnode, i);
76691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		struct tnode *left, *right;
76791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		int size, j;
768c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
76919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* An empty child */
77019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (node == NULL)
77119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
77219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
77319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* A leaf or an internal node with skipped bits */
77419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
775c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (IS_LEAF(node) || ((struct tnode *) node)->pos >
77619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		   tn->pos + tn->bits - 1) {
777a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			if (tkey_extract_bits(node->key,
778a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger					      oldtnode->pos + oldtnode->bits,
779a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger					      1) == 0)
78019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				put_child(t, tn, 2*i, node);
78119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			else
78219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				put_child(t, tn, 2*i+1, node);
78319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
78419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
78519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
78619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* An internal node with two children */
78719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		inode = (struct tnode *) node;
78819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
78919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (inode->bits == 1) {
7900a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet			put_child(t, tn, 2*i, rtnl_dereference(inode->child[0]));
7910a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet			put_child(t, tn, 2*i+1, rtnl_dereference(inode->child[1]));
79219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
793e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski			tnode_free_safe(inode);
79491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			continue;
79519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
79619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
79791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* An internal node with more than two children */
79891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
79991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* We will replace this node 'inode' with two new
80091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * ones, 'left' and 'right', each with half of the
80191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * original children. The two new nodes will have
80291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * a position one bit further down the key and this
80391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * means that the "significant" part of their keys
80491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * (see the discussion near the top of this file)
80591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * will differ by one bit, which will be "0" in
80691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * left's key and "1" in right's key. Since we are
80791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * moving the key position by one step, the bit that
80891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * we are moving away from - the bit at position
80991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * (inode->pos) - is the one that will differ between
81091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * left and right. So... we synthesize that bit in the
81191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * two  new keys.
81291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * The mask 'm' below will be a single "one" bit at
81391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * the position (inode->pos)
81491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
81519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
81691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* Use the old key, but set the new significant
81791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 *   bit to zero.
81891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
8192f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
82091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		left = (struct tnode *) tnode_get_child(tn, 2*i);
82191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, 2*i, NULL);
8222f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
82391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		BUG_ON(!left);
8242f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
82591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		right = (struct tnode *) tnode_get_child(tn, 2*i+1);
82691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, 2*i+1, NULL);
82719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
82891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		BUG_ON(!right);
82919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
83091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		size = tnode_child_length(left);
83191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		for (j = 0; j < size; j++) {
8320a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet			put_child(t, left, j, rtnl_dereference(inode->child[j]));
8330a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet			put_child(t, right, j, rtnl_dereference(inode->child[j + size]));
83419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
83591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, 2*i, resize(t, left));
83691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, 2*i+1, resize(t, right));
83791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
838e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski		tnode_free_safe(inode);
83919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
840e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski	tnode_free_safe(oldtnode);
84119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return tn;
8422f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonnomem:
8430a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	tnode_clean_free(tn);
8440a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	return ERR_PTR(-ENOMEM);
84519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
84619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8472f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *halve(struct trie *t, struct tnode *tn)
84819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
84919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *oldtnode = tn;
850b299e4f001cfa16205f9121f4630970049652268David S. Miller	struct rt_trie_node *left, *right;
85119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i;
85219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int olen = tnode_child_length(tn);
85319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8540c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("In halve\n");
855c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
856c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits - 1);
85719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8582f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	if (!tn)
8592f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		return ERR_PTR(-ENOMEM);
8602f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
8612f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	/*
862c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * Preallocate and store tnodes before the actual work so we
863c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * don't get into an inconsistent state if memory allocation
864c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * fails. In case of failure we return the oldnode and halve
8652f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	 * of tnode is ignored.
8662f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	 */
8672f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
86891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (i = 0; i < olen; i += 2) {
8692f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		left = tnode_get_child(oldtnode, i);
8702f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		right = tnode_get_child(oldtnode, i+1);
871c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
8722f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		/* Two nonempty children */
8730c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		if (left && right) {
8742f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			struct tnode *newn;
8750c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
8762f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			newn = tnode_new(left->key, tn->pos + tn->bits, 1);
8770c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
8780c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger			if (!newn)
8792f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				goto nomem;
8800c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
881b299e4f001cfa16205f9121f4630970049652268David S. Miller			put_child(t, tn, i/2, (struct rt_trie_node *)newn);
8822f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		}
8832f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
8842f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	}
88519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
88691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (i = 0; i < olen; i += 2) {
88791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		struct tnode *newBinNode;
88891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
88919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		left = tnode_get_child(oldtnode, i);
89019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		right = tnode_get_child(oldtnode, i+1);
891c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
89219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* At least one of the children is empty */
89319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (left == NULL) {
89419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			if (right == NULL)    /* Both are empty */
89519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				continue;
89619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			put_child(t, tn, i/2, right);
89791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			continue;
8980c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		}
89991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
90091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (right == NULL) {
90119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			put_child(t, tn, i/2, left);
90291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			continue;
90391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
904c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
90519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* Two nonempty children */
90691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		newBinNode = (struct tnode *) tnode_get_child(tn, i/2);
90791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, i/2, NULL);
90891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, newBinNode, 0, left);
90991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, newBinNode, 1, right);
91091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, i/2, resize(t, newBinNode));
91119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
912e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski	tnode_free_safe(oldtnode);
91319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return tn;
9142f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonnomem:
9150a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	tnode_clean_free(tn);
9160a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	return ERR_PTR(-ENOMEM);
91719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
91819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
919772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson/* readside must use rcu_read_lock currently dump routines
9202373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson via get_fa_head and dump */
9212373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
922772cb712b1373d335ef2874ea357ec681edc754bRobert Olssonstatic struct leaf_info *find_leaf_info(struct leaf *l, int plen)
92319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
924772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson	struct hlist_head *head = &l->list;
92519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_node *node;
92619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf_info *li;
92719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
9282373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	hlist_for_each_entry_rcu(li, node, head, hlist)
929c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (li->plen == plen)
93019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			return li;
93191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
93219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return NULL;
93319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
93419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
935a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic inline struct list_head *get_fa_head(struct leaf *l, int plen)
93619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
937772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson	struct leaf_info *li = find_leaf_info(l, plen);
938c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
93991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (!li)
94091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		return NULL;
941c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
94291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	return &li->falh;
94319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
94419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
94519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic void insert_leaf_info(struct hlist_head *head, struct leaf_info *new)
94619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
947e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	struct leaf_info *li = NULL, *last = NULL;
948e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	struct hlist_node *node;
949e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki
950e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	if (hlist_empty(head)) {
951e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki		hlist_add_head_rcu(&new->hlist, head);
952e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	} else {
953e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki		hlist_for_each_entry(li, node, head, hlist) {
954e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki			if (new->plen > li->plen)
955e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki				break;
956e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki
957e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki			last = li;
958e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki		}
959e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki		if (last)
960e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki			hlist_add_after_rcu(&last->hlist, &new->hlist);
961e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki		else
962e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki			hlist_add_before_rcu(&new->hlist, &li->hlist);
963e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	}
96419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
96519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
9662373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson/* rcu_read_lock needs to be hold by caller from readside */
9672373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
96819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic struct leaf *
96919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfib_find_node(struct trie *t, u32 key)
97019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
97119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int pos;
97219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *tn;
973b299e4f001cfa16205f9121f4630970049652268David S. Miller	struct rt_trie_node *n;
97419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
97519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	pos = 0;
976a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet	n = rcu_dereference_rtnl(t->trie);
97719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
97819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	while (n != NULL &&  NODE_TYPE(n) == T_TNODE) {
97919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn = (struct tnode *) n;
98091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
98119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		check_tnode(tn);
98291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
983c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
98491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			pos = tn->pos + tn->bits;
985a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			n = tnode_get_child_rcu(tn,
986a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger						tkey_extract_bits(key,
987a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger								  tn->pos,
988a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger								  tn->bits));
98991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else
99019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
99119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
99219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Case we have found a leaf. Compare prefixes */
99319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
99491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key))
99591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		return (struct leaf *)n;
99691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
99719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return NULL;
99819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
99919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
10007b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawskistatic void trie_rebalance(struct trie *t, struct tnode *tn)
100119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
100219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int wasfull;
10033ed18d76d959e5cbfa5d70c8f7ba95476582a556Robert Olsson	t_key cindex, key;
10040680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger	struct tnode *tp;
100519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
10063ed18d76d959e5cbfa5d70c8f7ba95476582a556Robert Olsson	key = tn->key;
10073ed18d76d959e5cbfa5d70c8f7ba95476582a556Robert Olsson
1008b299e4f001cfa16205f9121f4630970049652268David S. Miller	while (tn != NULL && (tp = node_parent((struct rt_trie_node *)tn)) != NULL) {
100919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		cindex = tkey_extract_bits(key, tp->pos, tp->bits);
101019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		wasfull = tnode_full(tp, tnode_get_child(tp, cindex));
1011a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		tn = (struct tnode *) resize(t, (struct tnode *)tn);
1012a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
1013a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		tnode_put_child_reorg((struct tnode *)tp, cindex,
1014b299e4f001cfa16205f9121f4630970049652268David S. Miller				      (struct rt_trie_node *)tn, wasfull);
101591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1016b299e4f001cfa16205f9121f4630970049652268David S. Miller		tp = node_parent((struct rt_trie_node *) tn);
1017008440e3ad4b72f5048d1b1f6f5ed894fdc5ad08Jarek Poplawski		if (!tp)
1018cf778b00e96df6d64f8e21b8395d1f8a859ecdc7Eric Dumazet			rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
1019008440e3ad4b72f5048d1b1f6f5ed894fdc5ad08Jarek Poplawski
1020e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski		tnode_free_flush();
10210680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger		if (!tp)
102219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
10230680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger		tn = tp;
102419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
10250680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger
102619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Handle last (top) tnode */
10277b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawski	if (IS_TNODE(tn))
1028a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		tn = (struct tnode *)resize(t, (struct tnode *)tn);
102919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1030cf778b00e96df6d64f8e21b8395d1f8a859ecdc7Eric Dumazet	rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
10317b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawski	tnode_free_flush();
103219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
103319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
10342373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson/* only used from updater-side */
10352373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
1036fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemmingerstatic struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
103719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
103819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int pos, newpos;
103919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *tp = NULL, *tn = NULL;
1040b299e4f001cfa16205f9121f4630970049652268David S. Miller	struct rt_trie_node *n;
104119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *l;
104219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int missbit;
1043c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	struct list_head *fa_head = NULL;
104419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf_info *li;
104519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t_key cindex;
104619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
104719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	pos = 0;
10480a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	n = rtnl_dereference(t->trie);
104919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1050c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	/* If we point to NULL, stop. Either the tree is empty and we should
1051c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * just put a new leaf in if, or we have reached an empty child slot,
105219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * and we should just put our new leaf in that.
1053c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * If we point to a T_TNODE, check if it matches our key. Note that
1054c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * a T_TNODE might be skipping any number of bits - its 'pos' need
105519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * not be the parent's 'pos'+'bits'!
105619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
1057c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * If it does match the current key, get pos/bits from it, extract
105819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * the index from our key, push the T_TNODE and walk the tree.
105919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
106019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * If it doesn't, we have to replace it with a new T_TNODE.
106119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
1062c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * If we point to a T_LEAF, it might or might not have the same key
1063c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * as we do. If it does, just change the value, update the T_LEAF's
1064c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * value, and return it.
106519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * If it doesn't, we need to replace it with a T_TNODE.
106619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
106719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
106819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	while (n != NULL &&  NODE_TYPE(n) == T_TNODE) {
106919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn = (struct tnode *) n;
107091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1071c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		check_tnode(tn);
107291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1073c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
107419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			tp = tn;
107591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			pos = tn->pos + tn->bits;
1076a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			n = tnode_get_child(tn,
1077a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger					    tkey_extract_bits(key,
1078a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger							      tn->pos,
1079a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger							      tn->bits));
108019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
10810680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger			BUG_ON(n && node_parent(n) != tn);
108291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else
108319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
108419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
108519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
108619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/*
108719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * n  ----> NULL, LEAF or TNODE
108819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
1089c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * tp is n's (parent) ----> NULL or TNODE
109019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
109119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
109291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	BUG_ON(tp && IS_LEAF(tp));
109319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
109419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Case 1: n is a leaf. Compare prefixes */
109519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1096c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) {
1097c95aaf9af5a1f6dee56d1f2ab4915cd722d608daStephen Hemminger		l = (struct leaf *) n;
109819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		li = leaf_info_new(plen);
109991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1100fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger		if (!li)
1101fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger			return NULL;
110219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
110319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fa_head = &li->falh;
110419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		insert_leaf_info(&l->list, li);
110519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto done;
110619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
110719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l = leaf_new();
110819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1109fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger	if (!l)
1110fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger		return NULL;
111119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
111219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l->key = key;
111319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	li = leaf_info_new(plen);
111419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1115c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!li) {
1116387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger		free_leaf(l);
1117fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger		return NULL;
1118f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson	}
111919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
112019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa_head = &li->falh;
112119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	insert_leaf_info(&l->list, li);
112219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
112319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (t->trie && n == NULL) {
112491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* Case 2: n is NULL, and will just insert a new leaf */
112519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1126b299e4f001cfa16205f9121f4630970049652268David S. Miller		node_set_parent((struct rt_trie_node *)l, tp);
112719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
112891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		cindex = tkey_extract_bits(key, tp->pos, tp->bits);
1129b299e4f001cfa16205f9121f4630970049652268David S. Miller		put_child(t, (struct tnode *)tp, cindex, (struct rt_trie_node *)l);
113091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	} else {
113191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* Case 3: n is a LEAF or a TNODE and the key doesn't match. */
1132c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		/*
1133c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		 *  Add a new tnode here
113419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 *  first tnode need some special handling
113519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 */
113619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
113719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (tp)
113891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			pos = tp->pos+tp->bits;
113919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		else
114091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			pos = 0;
114191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1142c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (n) {
114319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			newpos = tkey_mismatch(key, pos, n->key);
114419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			tn = tnode_new(n->key, newpos, 1);
114591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else {
114619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			newpos = 0;
1147c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger			tn = tnode_new(key, newpos, 1); /* First tnode */
114819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
114919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1150c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (!tn) {
1151f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson			free_leaf_info(li);
1152387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger			free_leaf(l);
1153fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger			return NULL;
115491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
115591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1156b299e4f001cfa16205f9121f4630970049652268David S. Miller		node_set_parent((struct rt_trie_node *)tn, tp);
115719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
115891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		missbit = tkey_extract_bits(key, newpos, 1);
1159b299e4f001cfa16205f9121f4630970049652268David S. Miller		put_child(t, tn, missbit, (struct rt_trie_node *)l);
116019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		put_child(t, tn, 1-missbit, n);
116119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1162c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (tp) {
116319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			cindex = tkey_extract_bits(key, tp->pos, tp->bits);
1164a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			put_child(t, (struct tnode *)tp, cindex,
1165b299e4f001cfa16205f9121f4630970049652268David S. Miller				  (struct rt_trie_node *)tn);
116691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else {
1167cf778b00e96df6d64f8e21b8395d1f8a859ecdc7Eric Dumazet			rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
116819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			tp = tn;
116919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
117019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
117191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
117291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (tp && tp->pos + tp->bits > 32)
1173058bd4d2a4ff0aaa4a5381c67e776729d840c785Joe Perches		pr_warn("fib_trie tp=%p pos=%d, bits=%d, key=%0x plen=%d\n",
1174058bd4d2a4ff0aaa4a5381c67e776729d840c785Joe Perches			tp, tp->pos, tp->bits, key, plen);
117591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
117619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Rebalance the trie */
11772373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
11787b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawski	trie_rebalance(t, tp);
1179f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olssondone:
118019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return fa_head;
118119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
118219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1183d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson/*
1184d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson * Caller must hold RTNL.
1185d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson */
118616c6cf8bb471392fd09b48b7c27e7d83a446b4bcStephen Hemmingerint fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
118719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
118819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
118919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa, *new_fa;
1190c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	struct list_head *fa_head = NULL;
119119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_info *fi;
11924e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	int plen = cfg->fc_dst_len;
11934e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	u8 tos = cfg->fc_tos;
119419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	u32 key, mask;
119519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int err;
119619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *l;
119719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
119819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (plen > 32)
119919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -EINVAL;
120019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
12014e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	key = ntohl(cfg->fc_dst);
120219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
12032dfe55b47e3d66ded5a84caf71e0da5710edf48bPatrick McHardy	pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen);
120419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
120591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	mask = ntohl(inet_make_mask(plen));
120619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1207c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (key & ~mask)
120819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -EINVAL;
120919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
121019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	key = key & mask;
121119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
12124e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	fi = fib_create_info(cfg);
12134e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	if (IS_ERR(fi)) {
12144e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		err = PTR_ERR(fi);
121519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto err;
12164e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	}
121719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
121819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l = fib_find_node(t, key);
1219c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	fa = NULL;
122019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1221c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (l) {
122219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fa_head = get_fa_head(l, plen);
122319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fa = fib_find_alias(fa_head, tos, fi->fib_priority);
122419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
122519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
122619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Now fa, if non-NULL, points to the first fib alias
122719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * with the same keys [prefix,tos,priority], if such key already
122819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * exists or to the node before which we will insert new one.
122919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
123019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * If fa is NULL, we will need to allocate a new one and
123119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * insert to the head of f.
123219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
123319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * If f is NULL, no fib node matched the destination key
123419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * and we need to allocate a new one of those as well.
123519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
123619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1237936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov	if (fa && fa->fa_tos == tos &&
1238936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov	    fa->fa_info->fib_priority == fi->fib_priority) {
1239936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		struct fib_alias *fa_first, *fa_match;
124019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
124119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		err = -EEXIST;
12424e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		if (cfg->fc_nlflags & NLM_F_EXCL)
124319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			goto out;
124419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1245936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		/* We have 2 goals:
1246936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		 * 1. Find exact match for type, scope, fib_info to avoid
1247936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		 * duplicate routes
1248936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		 * 2. Find next 'fa' (or head), NLM_F_APPEND inserts before it
1249936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		 */
1250936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		fa_match = NULL;
1251936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		fa_first = fa;
1252936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
1253936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		list_for_each_entry_continue(fa, fa_head, fa_list) {
1254936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			if (fa->fa_tos != tos)
1255936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov				break;
1256936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			if (fa->fa_info->fib_priority != fi->fib_priority)
1257936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov				break;
1258936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			if (fa->fa_type == cfg->fc_type &&
1259936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			    fa->fa_info == fi) {
1260936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov				fa_match = fa;
1261936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov				break;
1262936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			}
1263936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		}
1264936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov
12654e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		if (cfg->fc_nlflags & NLM_F_REPLACE) {
126619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			struct fib_info *fi_drop;
126719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			u8 state;
126819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1269936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			fa = fa_first;
1270936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			if (fa_match) {
1271936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov				if (fa == fa_match)
1272936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov					err = 0;
12736725033fa27c8f49e1221d2badbaaaf1ef459519Joonwoo Park				goto out;
1274936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			}
12752373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			err = -ENOBUFS;
1276e94b1766097d53e6f3ccfb36c8baa562ffeda3fcChristoph Lameter			new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
12772373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			if (new_fa == NULL)
12782373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson				goto out;
127919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
128019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			fi_drop = fa->fa_info;
12812373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			new_fa->fa_tos = fa->fa_tos;
12822373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			new_fa->fa_info = fi;
12834e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf			new_fa->fa_type = cfg->fc_type;
128419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			state = fa->fa_state;
1285936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			new_fa->fa_state = state & ~FA_S_ACCESSED;
128619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
12872373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			list_replace_rcu(&fa->fa_list, &new_fa->fa_list);
12882373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			alias_free_mem_rcu(fa);
128919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
129019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			fib_release_info(fi_drop);
129119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			if (state & FA_S_ACCESSED)
129276e6ebfb40a2455c18234dcb0f9df37533215461Denis V. Lunev				rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
1293b8f558313506b5bc435f2e031f3bec4b1725098eMilan Kocian			rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
1294b8f558313506b5bc435f2e031f3bec4b1725098eMilan Kocian				tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
129519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
129691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			goto succeeded;
129719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
129819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* Error if we find a perfect match which
129919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 * uses the same scope, type, and nexthop
130019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 * information.
130119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 */
1302936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		if (fa_match)
1303936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			goto out;
1304a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
13054e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		if (!(cfg->fc_nlflags & NLM_F_APPEND))
1306936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			fa = fa_first;
130719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
130819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	err = -ENOENT;
13094e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	if (!(cfg->fc_nlflags & NLM_F_CREATE))
131019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
131119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
131219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	err = -ENOBUFS;
1313e94b1766097d53e6f3ccfb36c8baa562ffeda3fcChristoph Lameter	new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
131419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (new_fa == NULL)
131519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
131619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
131719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	new_fa->fa_info = fi;
131819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	new_fa->fa_tos = tos;
13194e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	new_fa->fa_type = cfg->fc_type;
132019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	new_fa->fa_state = 0;
132119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/*
132219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * Insert new entry to the list.
132319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
132419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1325c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!fa_head) {
1326fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger		fa_head = fib_insert_node(t, key, plen);
1327fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger		if (unlikely(!fa_head)) {
1328fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger			err = -ENOMEM;
1329f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson			goto out_free_new_fa;
1330fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger		}
1331f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson	}
133219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
133321d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller	if (!plen)
133421d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller		tb->tb_num_default++;
133521d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller
13362373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	list_add_tail_rcu(&new_fa->fa_list,
13372373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			  (fa ? &fa->fa_list : fa_head));
133819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
133976e6ebfb40a2455c18234dcb0f9df37533215461Denis V. Lunev	rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
13404e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id,
1341b8f558313506b5bc435f2e031f3bec4b1725098eMilan Kocian		  &cfg->fc_nlinfo, 0);
134219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonsucceeded:
134319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return 0;
1344f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson
1345f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olssonout_free_new_fa:
1346f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson	kmem_cache_free(fn_alias_kmem, new_fa);
134719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonout:
134819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fib_release_info(fi);
134991b9a277fc4d207249e459a455abf804ebb5499dOlof Johanssonerr:
135019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return err;
135119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
135219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1353772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson/* should be called with rcu_read_lock */
13545b4704419cbd0b7597a91c19f9e8e8b17c1af071David S. Millerstatic int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
135522bd5b9b13f2931ac80949f8bfbc40e8cab05be7David S. Miller		      t_key key,  const struct flowi4 *flp,
1356ebc0ffae5dfb4447e0a431ffe7fe1d467c48bbb9Eric Dumazet		      struct fib_result *res, int fib_flags)
135719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
135819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf_info *li;
135919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_head *hhead = &l->list;
136019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_node *node;
1361c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
13622373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	hlist_for_each_entry_rcu(li, node, hhead, hlist) {
13633be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller		struct fib_alias *fa;
1364a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
13655c74501f76360ce6f410730b9b5e5976f38e8504Eric Dumazet		if (l->key != (key & li->mask_plen))
136619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
136719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
13683be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller		list_for_each_entry_rcu(fa, &li->falh, fa_list) {
13693be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller			struct fib_info *fi = fa->fa_info;
13703be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller			int nhsel, err;
1371a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
137222bd5b9b13f2931ac80949f8bfbc40e8cab05be7David S. Miller			if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
13733be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller				continue;
137437e826c513883099c298317bad1b3b677b2905fbDavid S. Miller			if (fa->fa_info->fib_scope < flp->flowi4_scope)
13753be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller				continue;
13763be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller			fib_alias_accessed(fa);
13773be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller			err = fib_props[fa->fa_type].error;
13783be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller			if (err) {
137919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
13801fbc78439291627642517f15b9b91f3125588143Julian Anastasov				t->stats.semantic_match_passed++;
13813be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller#endif
13821fbc78439291627642517f15b9b91f3125588143Julian Anastasov				return err;
13833be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller			}
13843be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller			if (fi->fib_flags & RTNH_F_DEAD)
13853be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller				continue;
13863be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller			for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
13873be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller				const struct fib_nh *nh = &fi->fib_nh[nhsel];
13883be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller
13893be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller				if (nh->nh_flags & RTNH_F_DEAD)
13903be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller					continue;
139122bd5b9b13f2931ac80949f8bfbc40e8cab05be7David S. Miller				if (flp->flowi4_oif && flp->flowi4_oif != nh->nh_oif)
13923be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller					continue;
13933be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller
13943be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller#ifdef CONFIG_IP_FIB_TRIE_STATS
13953be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller				t->stats.semantic_match_passed++;
13963be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller#endif
13975c74501f76360ce6f410730b9b5e5976f38e8504Eric Dumazet				res->prefixlen = li->plen;
13983be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller				res->nh_sel = nhsel;
13993be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller				res->type = fa->fa_type;
140037e826c513883099c298317bad1b3b677b2905fbDavid S. Miller				res->scope = fa->fa_info->fib_scope;
14013be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller				res->fi = fi;
14023be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller				res->table = tb;
14033be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller				res->fa_head = &li->falh;
14043be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller				if (!(fib_flags & FIB_LOOKUP_NOREF))
14055c74501f76360ce6f410730b9b5e5976f38e8504Eric Dumazet					atomic_inc(&fi->fib_clntref);
14063be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller				return 0;
14073be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller			}
14083be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller		}
14093be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller
14103be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller#ifdef CONFIG_IP_FIB_TRIE_STATS
14113be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller		t->stats.semantic_match_miss++;
141219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
141319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
1414a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
14152e655571c618434c24ac2ca989374fdd84470d6dBen Hutchings	return 1;
141619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
141719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
141822bd5b9b13f2931ac80949f8bfbc40e8cab05be7David S. Millerint fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
1419ebc0ffae5dfb4447e0a431ffe7fe1d467c48bbb9Eric Dumazet		     struct fib_result *res, int fib_flags)
142019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
142119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
14222e655571c618434c24ac2ca989374fdd84470d6dBen Hutchings	int ret;
1423b299e4f001cfa16205f9121f4630970049652268David S. Miller	struct rt_trie_node *n;
142419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *pn;
14253b004569d86d02786ebae496e75dc0b625be3e9aDavid S. Miller	unsigned int pos, bits;
142622bd5b9b13f2931ac80949f8bfbc40e8cab05be7David S. Miller	t_key key = ntohl(flp->daddr);
14273b004569d86d02786ebae496e75dc0b625be3e9aDavid S. Miller	unsigned int chopped_off;
142819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t_key cindex = 0;
14293b004569d86d02786ebae496e75dc0b625be3e9aDavid S. Miller	unsigned int current_prefix_length = KEYLENGTH;
143091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	struct tnode *cn;
1431874ffa8f72444d6253d2669fed304875c128f86bEric Dumazet	t_key pref_mismatch;
143291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
14332373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_lock();
143491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
14352373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	n = rcu_dereference(t->trie);
1436c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!n)
143719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto failed;
143819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
143919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
144019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t->stats.gets++;
144119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
144219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
144319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Just a leaf? */
144419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (IS_LEAF(n)) {
14455b4704419cbd0b7597a91c19f9e8e8b17c1af071David S. Miller		ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags);
1446a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		goto found;
144719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
1448a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
144919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	pn = (struct tnode *) n;
145019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	chopped_off = 0;
1451c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
145291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	while (pn) {
145319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		pos = pn->pos;
145419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		bits = pn->bits;
145519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1456c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (!chopped_off)
1457ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger			cindex = tkey_extract_bits(mask_pfx(key, current_prefix_length),
1458ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger						   pos, bits);
145919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1460b902e5735272b6a79fe2853180b2ad6658aa9678Jarek Poplawski		n = tnode_get_child_rcu(pn, cindex);
146119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
146219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (n == NULL) {
146319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
146419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			t->stats.null_node_hit++;
146519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
146619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			goto backtrace;
146719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
146819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
146991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (IS_LEAF(n)) {
14705b4704419cbd0b7597a91c19f9e8e8b17c1af071David S. Miller			ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags);
14712e655571c618434c24ac2ca989374fdd84470d6dBen Hutchings			if (ret > 0)
147291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				goto backtrace;
1473a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			goto found;
147491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
147591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
147691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		cn = (struct tnode *)n;
147719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
147891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/*
147991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * It's a tnode, and we can do some extra checks here if we
148091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * like, to avoid descending into a dead-end branch.
148191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * This tnode is in the parent's child array at index
148291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * key[p_pos..p_pos+p_bits] but potentially with some bits
148391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * chopped off, so in reality the index may be just a
148491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * subprefix, padded with zero at the end.
148591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * We can also take a look at any skipped bits in this
148691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * tnode - everything up to p_pos is supposed to be ok,
148791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * and the non-chopped bits of the index (se previous
148891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * paragraph) are also guaranteed ok, but the rest is
148991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * considered unknown.
149091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 *
149191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * The skipped bits are key[pos+bits..cn->pos].
149291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
149319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
149491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* If current_prefix_length < pos+bits, we are already doing
149591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * actual prefix  matching, which means everything from
149691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * pos+(bits-chopped_off) onward must be zero along some
149791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * branch of this subtree - otherwise there is *no* valid
149891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * prefix present. Here we can only check the skipped
149991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * bits. Remember, since we have already indexed into the
150091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * parent's child array, we know that the bits we chopped of
150191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * *are* zero.
150291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
150319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1504a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		/* NOTA BENE: Checking only skipped bits
1505a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   for the new node here */
150619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
150791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (current_prefix_length < pos+bits) {
150891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			if (tkey_extract_bits(cn->key, current_prefix_length,
1509a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger						cn->pos - current_prefix_length)
1510a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			    || !(cn->child[0]))
151191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				goto backtrace;
151291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
151319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
151491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/*
151591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * If chopped_off=0, the index is fully validated and we
151691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * only need to look at the skipped bits for this, the new,
151791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * tnode. What we actually want to do is to find out if
151891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * these skipped bits match our key perfectly, or if we will
151991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * have to count on finding a matching prefix further down,
152091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * because if we do, we would like to have some way of
152191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * verifying the existence of such a prefix at this point.
152291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
152319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
152491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* The only thing we can do at this point is to verify that
152591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * any such matching prefix can indeed be a prefix to our
152691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * key, and if the bits in the node we are inspecting that
152791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * do not match our key are not ZERO, this cannot be true.
152891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * Thus, find out where there is a mismatch (before cn->pos)
152991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * and verify that all the mismatching bits are zero in the
153091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * new tnode's key.
153191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
153219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1533a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		/*
1534a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * Note: We aren't very concerned about the piece of
1535a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * the key that precede pn->pos+pn->bits, since these
1536a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * have already been checked. The bits after cn->pos
1537a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * aren't checked since these are by definition
1538a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * "unknown" at this point. Thus, what we want to see
1539a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * is if we are about to enter the "prefix matching"
1540a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * state, and in that case verify that the skipped
1541a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * bits that will prevail throughout this subtree are
1542a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * zero, as they have to be if we are to find a
1543a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * matching prefix.
154491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
154591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1546874ffa8f72444d6253d2669fed304875c128f86bEric Dumazet		pref_mismatch = mask_pfx(cn->key ^ key, cn->pos);
154791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1548a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		/*
1549a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * In short: If skipped bits in this node do not match
1550a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * the search key, enter the "prefix matching"
1551a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * state.directly.
155291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
155391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (pref_mismatch) {
1554874ffa8f72444d6253d2669fed304875c128f86bEric Dumazet			int mp = KEYLENGTH - fls(pref_mismatch);
155591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1556874ffa8f72444d6253d2669fed304875c128f86bEric Dumazet			if (tkey_extract_bits(cn->key, mp, cn->pos - mp) != 0)
155791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				goto backtrace;
155891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
155991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			if (current_prefix_length >= cn->pos)
156091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				current_prefix_length = mp;
1561c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		}
1562a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
156391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		pn = (struct tnode *)n; /* Descend */
156491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		chopped_off = 0;
156591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		continue;
156691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
156719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonbacktrace:
156819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		chopped_off++;
156919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
157019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* As zero don't change the child key (cindex) */
1571a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		while ((chopped_off <= pn->bits)
1572a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		       && !(cindex & (1<<(chopped_off-1))))
157319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			chopped_off++;
157419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
157519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* Decrease current_... with bits chopped off */
157619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (current_prefix_length > pn->pos + pn->bits - chopped_off)
1577a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			current_prefix_length = pn->pos + pn->bits
1578a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				- chopped_off;
157991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
158019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/*
1581c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		 * Either we do the actual chop off according or if we have
158219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 * chopped off all bits in this tnode walk up to our parent.
158319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 */
158419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
158591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (chopped_off <= pn->bits) {
158619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			cindex &= ~(1 << (chopped_off-1));
158791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else {
1588b299e4f001cfa16205f9121f4630970049652268David S. Miller			struct tnode *parent = node_parent_rcu((struct rt_trie_node *) pn);
15890680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger			if (!parent)
159019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				goto failed;
159191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
159219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			/* Get Child's index */
15930680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger			cindex = tkey_extract_bits(pn->key, parent->pos, parent->bits);
15940680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger			pn = parent;
159519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			chopped_off = 0;
159619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
159719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
159819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			t->stats.backtrack++;
159919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
160019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			goto backtrace;
1601c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		}
160219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
160319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfailed:
1604c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	ret = 1;
160519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfound:
16062373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_unlock();
160719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return ret;
160819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
16096fc01438a94702bd160cb1b89203d9b97ae68cedFlorian WestphalEXPORT_SYMBOL_GPL(fib_table_lookup);
161019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16119195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger/*
16129195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger * Remove the leaf and return parent.
16139195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger */
16149195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemmingerstatic void trie_leaf_remove(struct trie *t, struct leaf *l)
161519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
1616b299e4f001cfa16205f9121f4630970049652268David S. Miller	struct tnode *tp = node_parent((struct rt_trie_node *) l);
1617c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
16189195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger	pr_debug("entering trie_leaf_remove(%p)\n", l);
161919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1620c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (tp) {
16219195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger		t_key cindex = tkey_extract_bits(l->key, tp->pos, tp->bits);
162219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		put_child(t, (struct tnode *)tp, cindex, NULL);
16237b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawski		trie_rebalance(t, tp);
162491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	} else
1625a9b3cd7f323b2e57593e7215362a7b02fc933e3aStephen Hemminger		RCU_INIT_POINTER(t->trie, NULL);
162619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1627387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger	free_leaf(l);
162819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
162919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1630d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson/*
1631d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson * Caller must hold RTNL.
1632d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson */
163316c6cf8bb471392fd09b48b7c27e7d83a446b4bcStephen Hemmingerint fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
163419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
163519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
163619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	u32 key, mask;
16374e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	int plen = cfg->fc_dst_len;
16384e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	u8 tos = cfg->fc_tos;
163919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa, *fa_to_delete;
164019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct list_head *fa_head;
164119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *l;
164291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	struct leaf_info *li;
164391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1644c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (plen > 32)
164519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -EINVAL;
164619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16474e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	key = ntohl(cfg->fc_dst);
164891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	mask = ntohl(inet_make_mask(plen));
164919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1650c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (key & ~mask)
165119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -EINVAL;
165219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
165319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	key = key & mask;
165419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l = fib_find_node(t, key);
165519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1656c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!l)
165719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -ESRCH;
165819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
165919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa_head = get_fa_head(l, plen);
166019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa = fib_find_alias(fa_head, tos, 0);
166119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
166219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (!fa)
166319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -ESRCH;
166419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16650c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t);
166619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
166719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa_to_delete = NULL;
1668936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov	fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
1669936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov	list_for_each_entry_continue(fa, fa_head, fa_list) {
167019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		struct fib_info *fi = fa->fa_info;
167119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
167219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fa->fa_tos != tos)
167319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
167419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16754e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) &&
16764e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		    (cfg->fc_scope == RT_SCOPE_NOWHERE ||
167737e826c513883099c298317bad1b3b677b2905fbDavid S. Miller		     fa->fa_info->fib_scope == cfg->fc_scope) &&
167874cb3c108bc0f599a4eb40980db8580cfba725c9Julian Anastasov		    (!cfg->fc_prefsrc ||
167974cb3c108bc0f599a4eb40980db8580cfba725c9Julian Anastasov		     fi->fib_prefsrc == cfg->fc_prefsrc) &&
16804e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		    (!cfg->fc_protocol ||
16814e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		     fi->fib_protocol == cfg->fc_protocol) &&
16824e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		    fib_nh_match(cfg, fi) == 0) {
168319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			fa_to_delete = fa;
168419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
168519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
168619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
168719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
168891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (!fa_to_delete)
168991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		return -ESRCH;
169019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
169191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	fa = fa_to_delete;
16924e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id,
1693b8f558313506b5bc435f2e031f3bec4b1725098eMilan Kocian		  &cfg->fc_nlinfo, 0);
169491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
169591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	l = fib_find_node(t, key);
1696772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson	li = find_leaf_info(l, plen);
169719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16982373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	list_del_rcu(&fa->fa_list);
169919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
170021d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller	if (!plen)
170121d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller		tb->tb_num_default--;
170221d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller
170391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (list_empty(fa_head)) {
17042373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		hlist_del_rcu(&li->hlist);
170591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		free_leaf_info(li);
17062373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	}
170719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
170891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (hlist_empty(&l->list))
17099195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger		trie_leaf_remove(t, l);
171019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
171191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (fa->fa_state & FA_S_ACCESSED)
171276e6ebfb40a2455c18234dcb0f9df37533215461Denis V. Lunev		rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
171319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
17142373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	fib_release_info(fa->fa_info);
17152373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	alias_free_mem_rcu(fa);
171691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	return 0;
171719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
171819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1719ef3660ce0649fa10265455f539b72607cff53d02Stephen Hemmingerstatic int trie_flush_list(struct list_head *head)
172019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
172119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa, *fa_node;
172219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int found = 0;
172319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
172419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	list_for_each_entry_safe(fa, fa_node, head, fa_list) {
172519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		struct fib_info *fi = fa->fa_info;
172619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
17272373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		if (fi && (fi->fib_flags & RTNH_F_DEAD)) {
17282373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			list_del_rcu(&fa->fa_list);
17292373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			fib_release_info(fa->fa_info);
17302373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			alias_free_mem_rcu(fa);
173119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			found++;
173219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
173319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
173419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return found;
173519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
173619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1737ef3660ce0649fa10265455f539b72607cff53d02Stephen Hemmingerstatic int trie_flush_leaf(struct leaf *l)
173819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
173919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int found = 0;
174019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_head *lih = &l->list;
174119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_node *node, *tmp;
174219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf_info *li = NULL;
174319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
174419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	hlist_for_each_entry_safe(li, node, tmp, lih, hlist) {
1745ef3660ce0649fa10265455f539b72607cff53d02Stephen Hemminger		found += trie_flush_list(&li->falh);
174619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
174719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (list_empty(&li->falh)) {
17482373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			hlist_del_rcu(&li->hlist);
174919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			free_leaf_info(li);
175019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
175119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
175219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return found;
175319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
175419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
175582cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger/*
175682cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger * Scan for the next right leaf starting at node p->child[idx]
175782cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger * Since we have back pointer, no recursion necessary.
175882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger */
1759b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c)
176019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
176182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	do {
176282cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger		t_key idx;
1763c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
1764c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (c)
176582cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			idx = tkey_extract_bits(c->key, p->pos, p->bits) + 1;
1766c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		else
176782cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			idx = 0;
17682373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
176982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger		while (idx < 1u << p->bits) {
177082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			c = tnode_get_child_rcu(p, idx++);
17712373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			if (!c)
177291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				continue;
177391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
177482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			if (IS_LEAF(c)) {
17750a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet				prefetch(rcu_dereference_rtnl(p->child[idx]));
177682cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger				return (struct leaf *) c;
177719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			}
177882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
177982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			/* Rescan start scanning in new node */
178082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			p = (struct tnode *) c;
178182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			idx = 0;
178219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
178382cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
178482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger		/* Node empty, walk back up to parent */
1785b299e4f001cfa16205f9121f4630970049652268David S. Miller		c = (struct rt_trie_node *) p;
1786a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet	} while ((p = node_parent_rcu(c)) != NULL);
178782cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
178882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	return NULL; /* Root of trie */
178982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger}
179082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
179182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemmingerstatic struct leaf *trie_firstleaf(struct trie *t)
179282cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger{
1793a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet	struct tnode *n = (struct tnode *)rcu_dereference_rtnl(t->trie);
179482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
179582cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	if (!n)
179682cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger		return NULL;
179782cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
179882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	if (IS_LEAF(n))          /* trie is just a leaf */
179982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger		return (struct leaf *) n;
180082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
180182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	return leaf_walk_rcu(n, NULL);
180282cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger}
180382cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
180482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemmingerstatic struct leaf *trie_nextleaf(struct leaf *l)
180582cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger{
1806b299e4f001cfa16205f9121f4630970049652268David S. Miller	struct rt_trie_node *c = (struct rt_trie_node *) l;
1807b902e5735272b6a79fe2853180b2ad6658aa9678Jarek Poplawski	struct tnode *p = node_parent_rcu(c);
180882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
180982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	if (!p)
181082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger		return NULL;	/* trie with just one leaf */
181182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
181282cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	return leaf_walk_rcu(p, c);
181319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
181419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
181571d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemmingerstatic struct leaf *trie_leafindex(struct trie *t, int index)
181671d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger{
181771d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	struct leaf *l = trie_firstleaf(t);
181871d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger
1819ec28cf738d899e9d0652108e1986101771aacb2eStephen Hemminger	while (l && index-- > 0)
182071d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		l = trie_nextleaf(l);
1821ec28cf738d899e9d0652108e1986101771aacb2eStephen Hemminger
182271d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	return l;
182371d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger}
182471d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger
182571d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger
1826d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson/*
1827d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson * Caller must hold RTNL.
1828d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson */
182916c6cf8bb471392fd09b48b7c27e7d83a446b4bcStephen Hemmingerint fib_table_flush(struct fib_table *tb)
183019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
183119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
18329195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger	struct leaf *l, *ll = NULL;
183382cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	int found = 0;
183419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
183582cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) {
1836ef3660ce0649fa10265455f539b72607cff53d02Stephen Hemminger		found += trie_flush_leaf(l);
183719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
183819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (ll && hlist_empty(&ll->list))
18399195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger			trie_leaf_remove(t, ll);
184019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		ll = l;
184119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
184219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
184319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (ll && hlist_empty(&ll->list))
18449195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger		trie_leaf_remove(t, ll);
184519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
18460c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("trie_flush found=%d\n", found);
184719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return found;
184819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
184919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
18504aa2c466a7733af093a526e9d1cdd0b3b90d47e9Pavel Emelyanovvoid fib_free_table(struct fib_table *tb)
18514aa2c466a7733af093a526e9d1cdd0b3b90d47e9Pavel Emelyanov{
18524aa2c466a7733af093a526e9d1cdd0b3b90d47e9Pavel Emelyanov	kfree(tb);
18534aa2c466a7733af093a526e9d1cdd0b3b90d47e9Pavel Emelyanov}
18544aa2c466a7733af093a526e9d1cdd0b3b90d47e9Pavel Emelyanov
1855a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
1856a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			   struct fib_table *tb,
185719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			   struct sk_buff *skb, struct netlink_callback *cb)
185819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
185919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i, s_i;
186019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa;
186132ab5f80334fc067386c4c56c434010c01cff6b9Al Viro	__be32 xkey = htonl(key);
186219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
186371d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	s_i = cb->args[5];
186419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	i = 0;
186519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
18662373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	/* rcu_read_lock is hold by caller */
18672373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
18682373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	list_for_each_entry_rcu(fa, fah, fa_list) {
186919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (i < s_i) {
187019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			i++;
187119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
187219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
187319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
187419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid,
187519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  cb->nlh->nlmsg_seq,
187619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  RTM_NEWROUTE,
187719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  tb->tb_id,
187819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  fa->fa_type,
1879be403ea1856f1428b5912b42184acbba808c41d6Thomas Graf				  xkey,
188019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  plen,
188119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  fa->fa_tos,
188264347f786d13349d6a6f812f3a83c269e26c0136Stephen Hemminger				  fa->fa_info, NLM_F_MULTI) < 0) {
188371d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger			cb->args[5] = i;
188419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			return -1;
188591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
188619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		i++;
188719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
188871d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	cb->args[5] = i;
188919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return skb->len;
189019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
189119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1892a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemmingerstatic int fn_trie_dump_leaf(struct leaf *l, struct fib_table *tb,
1893a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger			struct sk_buff *skb, struct netlink_callback *cb)
189419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
1895a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	struct leaf_info *li;
1896a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	struct hlist_node *node;
1897a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	int i, s_i;
189819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
189971d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	s_i = cb->args[4];
1900a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	i = 0;
190119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1902a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	/* rcu_read_lock is hold by caller */
1903a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
1904a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		if (i < s_i) {
1905a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger			i++;
190619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
1907a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		}
190891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1909a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		if (i > s_i)
191071d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger			cb->args[5] = 0;
191119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1912a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		if (list_empty(&li->falh))
191319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
191419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1915a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		if (fn_trie_dump_fa(l->key, li->plen, &li->falh, tb, skb, cb) < 0) {
191671d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger			cb->args[4] = i;
191719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			return -1;
191819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
1919a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		i++;
192019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
1921a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger
192271d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	cb->args[4] = i;
192319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return skb->len;
192419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
192519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
192616c6cf8bb471392fd09b48b7c27e7d83a446b4bcStephen Hemmingerint fib_table_dump(struct fib_table *tb, struct sk_buff *skb,
192716c6cf8bb471392fd09b48b7c27e7d83a446b4bcStephen Hemminger		   struct netlink_callback *cb)
192819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
1929a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	struct leaf *l;
193019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
1931d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	t_key key = cb->args[2];
193271d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	int count = cb->args[3];
193319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
19342373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_lock();
1935d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	/* Dump starting at last key.
1936d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	 * Note: 0.0.0.0/0 (ie default) is first key.
1937d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	 */
193871d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	if (count == 0)
1939d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger		l = trie_firstleaf(t);
1940d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	else {
194171d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		/* Normally, continue from last key, but if that is missing
194271d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		 * fallback to using slow rescan
194371d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		 */
1944d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger		l = fib_find_node(t, key);
194571d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		if (!l)
194671d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger			l = trie_leafindex(t, count);
1947d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	}
1948a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger
1949d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	while (l) {
1950d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger		cb->args[2] = l->key;
1951a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) {
195271d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger			cb->args[3] = count;
1953a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger			rcu_read_unlock();
1954a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger			return -1;
195519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
1956d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger
195771d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		++count;
1958d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger		l = trie_nextleaf(l);
195971d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		memset(&cb->args[4], 0,
196071d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		       sizeof(cb->args) - 4*sizeof(cb->args[0]));
196119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
196271d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	cb->args[3] = count;
19632373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_unlock();
1964a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger
196519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return skb->len;
196619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
196719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
19685348ba85a02ffe80a8af33a524b6610966760d3dDavid S. Millervoid __init fib_trie_init(void)
19697f9b80529b8a2ad8b3273b15fb444a0e34b760a9Stephen Hemminger{
1970a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	fn_alias_kmem = kmem_cache_create("ip_fib_alias",
1971a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger					  sizeof(struct fib_alias),
1972bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger					  0, SLAB_PANIC, NULL);
1973bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger
1974bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger	trie_leaf_kmem = kmem_cache_create("ip_fib_trie",
1975bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger					   max(sizeof(struct leaf),
1976bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger					       sizeof(struct leaf_info)),
1977bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger					   0, SLAB_PANIC, NULL);
19787f9b80529b8a2ad8b3273b15fb444a0e34b760a9Stephen Hemminger}
197919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
19807f9b80529b8a2ad8b3273b15fb444a0e34b760a9Stephen Hemminger
19815348ba85a02ffe80a8af33a524b6610966760d3dDavid S. Millerstruct fib_table *fib_trie_table(u32 id)
198219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
198319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_table *tb;
198419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t;
198519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
198619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb = kmalloc(sizeof(struct fib_table) + sizeof(struct trie),
198719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		     GFP_KERNEL);
198819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (tb == NULL)
198919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return NULL;
199019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
199119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_id = id;
1992971b893e79db0f7dccfcea15dbdebca3ca64a84dDenis V. Lunev	tb->tb_default = -1;
199321d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller	tb->tb_num_default = 0;
199419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
199519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t = (struct trie *) tb->tb_data;
1996c28a1cf448e59019fa681741963c3acaeaeb6d27Stephen Hemminger	memset(t, 0, sizeof(*t));
199719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
199819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return tb;
199919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
200019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2001cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger#ifdef CONFIG_PROC_FS
2002cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/* Depth first Trie walk iterator */
2003cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstruct fib_trie_iter {
20041c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	struct seq_net_private p;
20053d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	struct fib_table *tb;
2006cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct tnode *tnode;
2007a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet	unsigned int index;
2008a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet	unsigned int depth;
2009cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger};
201019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2011b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic struct rt_trie_node *fib_trie_get_next(struct fib_trie_iter *iter)
201219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2013cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct tnode *tn = iter->tnode;
2014a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet	unsigned int cindex = iter->index;
2015cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct tnode *p;
201619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
20176640e69731b42fd5e3d2b26201c8b34fc897a0eeEric W. Biederman	/* A single entry routing table */
20186640e69731b42fd5e3d2b26201c8b34fc897a0eeEric W. Biederman	if (!tn)
20196640e69731b42fd5e3d2b26201c8b34fc897a0eeEric W. Biederman		return NULL;
20206640e69731b42fd5e3d2b26201c8b34fc897a0eeEric W. Biederman
2021cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	pr_debug("get_next iter={node=%p index=%d depth=%d}\n",
2022cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		 iter->tnode, iter->index, iter->depth);
2023cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerrescan:
2024cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	while (cindex < (1<<tn->bits)) {
2025b299e4f001cfa16205f9121f4630970049652268David S. Miller		struct rt_trie_node *n = tnode_get_child_rcu(tn, cindex);
202619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2027cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		if (n) {
2028cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (IS_LEAF(n)) {
2029cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				iter->tnode = tn;
2030cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				iter->index = cindex + 1;
2031cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			} else {
2032cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				/* push down one level */
2033cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				iter->tnode = (struct tnode *) n;
2034cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				iter->index = 0;
2035cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				++iter->depth;
2036cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			}
2037cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			return n;
2038cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		}
203919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2040cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		++cindex;
2041cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
204291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2043cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	/* Current node exhausted, pop back up */
2044b299e4f001cfa16205f9121f4630970049652268David S. Miller	p = node_parent_rcu((struct rt_trie_node *)tn);
2045cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (p) {
2046cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1;
2047cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		tn = p;
2048cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		--iter->depth;
2049cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto rescan;
205019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
2051cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2052cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	/* got root? */
2053cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return NULL;
205419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
205519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2056b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic struct rt_trie_node *fib_trie_get_first(struct fib_trie_iter *iter,
2057cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				       struct trie *t)
205819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2059b299e4f001cfa16205f9121f4630970049652268David S. Miller	struct rt_trie_node *n;
20605ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson
2061132adf54639cf7dd9315e8df89c2faa59f6e46d9Stephen Hemminger	if (!t)
20625ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson		return NULL;
20635ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson
20645ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson	n = rcu_dereference(t->trie);
20653d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	if (!n)
20665ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson		return NULL;
206719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
20683d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	if (IS_TNODE(n)) {
20693d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		iter->tnode = (struct tnode *) n;
20703d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		iter->index = 0;
20713d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		iter->depth = 1;
20723d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	} else {
20733d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		iter->tnode = NULL;
20743d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		iter->index = 0;
20753d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		iter->depth = 0;
207691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	}
20773d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
20783d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	return n;
2079cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
208091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2081cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void trie_collect_stats(struct trie *t, struct trie_stat *s)
2082cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
2083b299e4f001cfa16205f9121f4630970049652268David S. Miller	struct rt_trie_node *n;
2084cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct fib_trie_iter iter;
208591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2086cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	memset(s, 0, sizeof(*s));
208791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2088cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	rcu_read_lock();
20893d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	for (n = fib_trie_get_first(&iter, t); n; n = fib_trie_get_next(&iter)) {
2090cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		if (IS_LEAF(n)) {
2091936722922f6d2366378de606a40c14f96915474dStephen Hemminger			struct leaf *l = (struct leaf *)n;
2092936722922f6d2366378de606a40c14f96915474dStephen Hemminger			struct leaf_info *li;
2093936722922f6d2366378de606a40c14f96915474dStephen Hemminger			struct hlist_node *tmp;
2094936722922f6d2366378de606a40c14f96915474dStephen Hemminger
2095cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			s->leaves++;
2096cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			s->totdepth += iter.depth;
2097cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (iter.depth > s->maxdepth)
2098cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				s->maxdepth = iter.depth;
2099936722922f6d2366378de606a40c14f96915474dStephen Hemminger
2100936722922f6d2366378de606a40c14f96915474dStephen Hemminger			hlist_for_each_entry_rcu(li, tmp, &l->list, hlist)
2101936722922f6d2366378de606a40c14f96915474dStephen Hemminger				++s->prefixes;
2102cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		} else {
2103cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			const struct tnode *tn = (const struct tnode *) n;
2104cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			int i;
2105cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2106cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			s->tnodes++;
2107132adf54639cf7dd9315e8df89c2faa59f6e46d9Stephen Hemminger			if (tn->bits < MAX_STAT_DEPTH)
210806ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson				s->nodesizes[tn->bits]++;
210906ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson
2110cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			for (i = 0; i < (1<<tn->bits); i++)
2111cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				if (!tn->child[i])
2112cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					s->nullpointers++;
211319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
211419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
21152373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_unlock();
211619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
211719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2118cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/*
2119cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger *	This outputs /proc/net/fib_triestats
2120cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger */
2121cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
212219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2123a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet	unsigned int i, max, pointers, bytes, avdepth;
2124c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
2125cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (stat->leaves)
2126cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		avdepth = stat->totdepth*100 / stat->leaves;
2127cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	else
2128cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		avdepth = 0;
212991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2130a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "\tAver depth:     %u.%02d\n",
2131a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   avdepth / 100, avdepth % 100);
2132cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq, "\tMax depth:      %u\n", stat->maxdepth);
213391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2134cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq, "\tLeaves:         %u\n", stat->leaves);
2135cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	bytes = sizeof(struct leaf) * stat->leaves;
2136936722922f6d2366378de606a40c14f96915474dStephen Hemminger
2137936722922f6d2366378de606a40c14f96915474dStephen Hemminger	seq_printf(seq, "\tPrefixes:       %u\n", stat->prefixes);
2138936722922f6d2366378de606a40c14f96915474dStephen Hemminger	bytes += sizeof(struct leaf_info) * stat->prefixes;
2139936722922f6d2366378de606a40c14f96915474dStephen Hemminger
2140187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger	seq_printf(seq, "\tInternal nodes: %u\n\t", stat->tnodes);
2141cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	bytes += sizeof(struct tnode) * stat->tnodes;
214219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
214306ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson	max = MAX_STAT_DEPTH;
214406ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson	while (max > 0 && stat->nodesizes[max-1] == 0)
2145cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		max--;
214619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2147cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	pointers = 0;
2148cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	for (i = 1; i <= max; i++)
2149cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		if (stat->nodesizes[i] != 0) {
2150187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger			seq_printf(seq, "  %u: %u",  i, stat->nodesizes[i]);
2151cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			pointers += (1<<i) * stat->nodesizes[i];
2152cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		}
2153cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_putc(seq, '\n');
2154187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger	seq_printf(seq, "\tPointers: %u\n", pointers);
21552373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
2156b299e4f001cfa16205f9121f4630970049652268David S. Miller	bytes += sizeof(struct rt_trie_node *) * pointers;
2157187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger	seq_printf(seq, "Null ptrs: %u\n", stat->nullpointers);
2158187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger	seq_printf(seq, "Total size: %u  kB\n", (bytes + 1023) / 1024);
215966a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger}
21602373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
2161cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger#ifdef CONFIG_IP_FIB_TRIE_STATS
216266a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemmingerstatic void trie_show_usage(struct seq_file *seq,
216366a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger			    const struct trie_use_stats *stats)
216466a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger{
216566a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger	seq_printf(seq, "\nCounters:\n---------\n");
2166a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "gets = %u\n", stats->gets);
2167a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "backtracks = %u\n", stats->backtrack);
2168a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "semantic match passed = %u\n",
2169a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   stats->semantic_match_passed);
2170a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "semantic match miss = %u\n",
2171a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   stats->semantic_match_miss);
2172a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "null node hit= %u\n", stats->null_node_hit);
2173a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "skipped node resize = %u\n\n",
2174a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   stats->resize_node_skipped);
2175cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
217666a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger#endif /*  CONFIG_IP_FIB_TRIE_STATS */
217766a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger
21783d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemmingerstatic void fib_table_print(struct seq_file *seq, struct fib_table *tb)
2179d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger{
21803d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	if (tb->tb_id == RT_TABLE_LOCAL)
21813d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		seq_puts(seq, "Local:\n");
21823d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	else if (tb->tb_id == RT_TABLE_MAIN)
21833d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		seq_puts(seq, "Main:\n");
21843d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	else
21853d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		seq_printf(seq, "Id %d:\n", tb->tb_id);
2186d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger}
218719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
21883d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
2189cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_triestat_seq_show(struct seq_file *seq, void *v)
2190cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
21911c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	struct net *net = (struct net *)seq->private;
21923d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	unsigned int h;
2193877a9bff3889512d7326d6bf0ba6ed3ddda6d772Eric W. Biederman
2194d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger	seq_printf(seq,
2195a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   "Basic info: size of leaf:"
2196a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   " %Zd bytes, size of tnode: %Zd bytes.\n",
2197d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger		   sizeof(struct leaf), sizeof(struct tnode));
2198d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger
21993d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
22003d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
22013d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct hlist_node *node;
22023d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct fib_table *tb;
22033d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
22043d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
22053d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			struct trie *t = (struct trie *) tb->tb_data;
22063d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			struct trie_stat stat;
2207877a9bff3889512d7326d6bf0ba6ed3ddda6d772Eric W. Biederman
22083d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			if (!t)
22093d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger				continue;
22103d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
22113d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			fib_table_print(seq, tb);
22123d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
22133d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			trie_collect_stats(t, &stat);
22143d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			trie_show_stats(seq, &stat);
22153d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger#ifdef CONFIG_IP_FIB_TRIE_STATS
22163d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			trie_show_usage(seq, &t->stats);
22173d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger#endif
22183d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		}
22193d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	}
222019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2221cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return 0;
222219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
222319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2224cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_triestat_seq_open(struct inode *inode, struct file *file)
222519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2226de05c557b24c7dffc6d392e3db120cf11c9f6ae7Pavel Emelyanov	return single_open_net(inode, file, fib_triestat_seq_show);
22271c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev}
22281c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev
22299a32144e9d7b4e21341174b1a83b82a82353be86Arjan van de Venstatic const struct file_operations fib_triestat_fops = {
2230cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.owner	= THIS_MODULE,
2231cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.open	= fib_triestat_seq_open,
2232cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.read	= seq_read,
2233cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.llseek	= seq_lseek,
2234b6fcbdb4f283f7ba67cec3cda6be23da8e959031Pavel Emelyanov	.release = single_release_net,
2235cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger};
2236cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2237b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic struct rt_trie_node *fib_trie_get_idx(struct seq_file *seq, loff_t pos)
223819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
22391218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki	struct fib_trie_iter *iter = seq->private;
22401218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki	struct net *net = seq_file_net(seq);
2241cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	loff_t idx = 0;
22423d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	unsigned int h;
2243cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
22443d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
22453d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
22463d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct hlist_node *node;
22473d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct fib_table *tb;
2248cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
22493d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
2250b299e4f001cfa16205f9121f4630970049652268David S. Miller			struct rt_trie_node *n;
22513d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
22523d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			for (n = fib_trie_get_first(iter,
22533d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger						    (struct trie *) tb->tb_data);
22543d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			     n; n = fib_trie_get_next(iter))
22553d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger				if (pos == idx++) {
22563d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger					iter->tb = tb;
22573d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger					return n;
22583d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger				}
22593d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		}
2260cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
22613d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
226219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return NULL;
226319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
226419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2265cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
2266c95aaf9af5a1f6dee56d1f2ab4915cd722d608daStephen Hemminger	__acquires(RCU)
226719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2268cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	rcu_read_lock();
22691218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki	return fib_trie_get_idx(seq, *pos);
227019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
227119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2272cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
227319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2274cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct fib_trie_iter *iter = seq->private;
22751218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki	struct net *net = seq_file_net(seq);
22763d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	struct fib_table *tb = iter->tb;
22773d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	struct hlist_node *tb_node;
22783d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	unsigned int h;
2279b299e4f001cfa16205f9121f4630970049652268David S. Miller	struct rt_trie_node *n;
2280cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
228119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	++*pos;
22823d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	/* next node in same table */
22833d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	n = fib_trie_get_next(iter);
22843d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	if (n)
22853d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		return n;
228619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
22873d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	/* walk rest of this hash chain */
22883d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	h = tb->tb_id & (FIB_TABLE_HASHSZ - 1);
22890a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet	while ((tb_node = rcu_dereference(hlist_next_rcu(&tb->tb_hlist)))) {
22903d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		tb = hlist_entry(tb_node, struct fib_table, tb_hlist);
22913d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
22923d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		if (n)
22933d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			goto found;
22943d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	}
229519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
22963d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	/* new hash chain */
22973d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	while (++h < FIB_TABLE_HASHSZ) {
22983d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
22993d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		hlist_for_each_entry_rcu(tb, tb_node, head, tb_hlist) {
23003d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
23013d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			if (n)
23023d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger				goto found;
23033d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		}
23043d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	}
2305cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return NULL;
23063d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
23073d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemmingerfound:
23083d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	iter->tb = tb;
23093d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	return n;
2310cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
231119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2312cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void fib_trie_seq_stop(struct seq_file *seq, void *v)
2313c95aaf9af5a1f6dee56d1f2ab4915cd722d608daStephen Hemminger	__releases(RCU)
231419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2315cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	rcu_read_unlock();
2316cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
231791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2318cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void seq_indent(struct seq_file *seq, int n)
2319cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
2320a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet	while (n-- > 0)
2321a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet		seq_puts(seq, "   ");
2322cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
232319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
232428d36e3702fcbed73c38e877bcf2a8f8946b7f3dEric Dumazetstatic inline const char *rtn_scope(char *buf, size_t len, enum rt_scope_t s)
2325cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
2326132adf54639cf7dd9315e8df89c2faa59f6e46d9Stephen Hemminger	switch (s) {
2327cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_UNIVERSE: return "universe";
2328cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_SITE:	return "site";
2329cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_LINK:	return "link";
2330cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_HOST:	return "host";
2331cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_NOWHERE:	return "nowhere";
2332cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	default:
233328d36e3702fcbed73c38e877bcf2a8f8946b7f3dEric Dumazet		snprintf(buf, len, "scope=%d", s);
2334cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return buf;
2335cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
2336cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
233719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
233836cbd3dcc10384f813ec0814255f576c84f2bcd4Jan Engelhardtstatic const char *const rtn_type_names[__RTN_MAX] = {
2339cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_UNSPEC] = "UNSPEC",
2340cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_UNICAST] = "UNICAST",
2341cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_LOCAL] = "LOCAL",
2342cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_BROADCAST] = "BROADCAST",
2343cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_ANYCAST] = "ANYCAST",
2344cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_MULTICAST] = "MULTICAST",
2345cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_BLACKHOLE] = "BLACKHOLE",
2346cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_UNREACHABLE] = "UNREACHABLE",
2347cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_PROHIBIT] = "PROHIBIT",
2348cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_THROW] = "THROW",
2349cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_NAT] = "NAT",
2350cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_XRESOLVE] = "XRESOLVE",
2351cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger};
235219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2353a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazetstatic inline const char *rtn_type(char *buf, size_t len, unsigned int t)
2354cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
2355cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (t < __RTN_MAX && rtn_type_names[t])
2356cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return rtn_type_names[t];
235728d36e3702fcbed73c38e877bcf2a8f8946b7f3dEric Dumazet	snprintf(buf, len, "type %u", t);
2358cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return buf;
235919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
236019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2361cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/* Pretty print the trie */
2362cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_trie_seq_show(struct seq_file *seq, void *v)
236319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2364cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	const struct fib_trie_iter *iter = seq->private;
2365b299e4f001cfa16205f9121f4630970049652268David S. Miller	struct rt_trie_node *n = v;
2366c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
23673d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	if (!node_parent_rcu(n))
23683d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		fib_table_print(seq, iter->tb);
2369095b8501e4168ae5a879fcb9420ac48cbd43f95aRobert Olsson
2370cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (IS_TNODE(n)) {
2371cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		struct tnode *tn = (struct tnode *) n;
2372ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger		__be32 prf = htonl(mask_pfx(tn->key, tn->pos));
237391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
23741d25cd6cc2528e4af12ab18e84fe95ed78f3f21aRobert Olsson		seq_indent(seq, iter->depth-1);
2375673d57e72398edfedc93fb50ff58048077c9d587Harvey Harrison		seq_printf(seq, "  +-- %pI4/%d %d %d %d\n",
2376673d57e72398edfedc93fb50ff58048077c9d587Harvey Harrison			   &prf, tn->pos, tn->bits, tn->full_children,
23771d25cd6cc2528e4af12ab18e84fe95ed78f3f21aRobert Olsson			   tn->empty_children);
2378e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki
2379cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	} else {
2380cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		struct leaf *l = (struct leaf *) n;
23811328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger		struct leaf_info *li;
23821328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger		struct hlist_node *node;
238332ab5f80334fc067386c4c56c434010c01cff6b9Al Viro		__be32 val = htonl(l->key);
2384cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2385cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		seq_indent(seq, iter->depth);
2386673d57e72398edfedc93fb50ff58048077c9d587Harvey Harrison		seq_printf(seq, "  |-- %pI4\n", &val);
23871328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger
23881328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger		hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
23891328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger			struct fib_alias *fa;
23901328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger
23911328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger			list_for_each_entry_rcu(fa, &li->falh, fa_list) {
23921328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger				char buf1[32], buf2[32];
23931328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger
23941328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger				seq_indent(seq, iter->depth+1);
23951328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger				seq_printf(seq, "  /%d %s %s", li->plen,
23961328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger					   rtn_scope(buf1, sizeof(buf1),
239737e826c513883099c298317bad1b3b677b2905fbDavid S. Miller						     fa->fa_info->fib_scope),
23981328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger					   rtn_type(buf2, sizeof(buf2),
23991328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger						    fa->fa_type));
24001328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger				if (fa->fa_tos)
2401b9c4d82a853713d49ac53b507964d7cf30ee408dDenis V. Lunev					seq_printf(seq, " tos=%d", fa->fa_tos);
24021328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger				seq_putc(seq, '\n');
2403cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			}
2404cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		}
240519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
2406cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
240719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return 0;
240819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
240919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2410f690808e17925fc45217eb22e8670902ecee5c1bStephen Hemmingerstatic const struct seq_operations fib_trie_seq_ops = {
2411cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.start  = fib_trie_seq_start,
2412cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.next   = fib_trie_seq_next,
2413cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.stop   = fib_trie_seq_stop,
2414cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.show   = fib_trie_seq_show,
241519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
241619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2417cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_trie_seq_open(struct inode *inode, struct file *file)
241819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
24191c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	return seq_open_net(inode, file, &fib_trie_seq_ops,
24201c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev			    sizeof(struct fib_trie_iter));
242119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
242219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
24239a32144e9d7b4e21341174b1a83b82a82353be86Arjan van de Venstatic const struct file_operations fib_trie_fops = {
2424cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.owner  = THIS_MODULE,
2425cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.open   = fib_trie_seq_open,
2426cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.read   = seq_read,
2427cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.llseek = seq_lseek,
24281c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	.release = seq_release_net,
242919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
243019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
24318315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstruct fib_route_iter {
24328315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct seq_net_private p;
24338315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct trie *main_trie;
24348315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	loff_t	pos;
24358315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	t_key	key;
24368315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger};
24378315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
24388315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstatic struct leaf *fib_route_get_idx(struct fib_route_iter *iter, loff_t pos)
24398315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger{
24408315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct leaf *l = NULL;
24418315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct trie *t = iter->main_trie;
24428315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
24438315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	/* use cache location of last found key */
24448315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	if (iter->pos > 0 && pos >= iter->pos && (l = fib_find_node(t, iter->key)))
24458315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		pos -= iter->pos;
24468315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	else {
24478315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->pos = 0;
24488315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		l = trie_firstleaf(t);
24498315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	}
24508315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
24518315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	while (l && pos-- > 0) {
24528315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->pos++;
24538315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		l = trie_nextleaf(l);
24548315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	}
24558315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
24568315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	if (l)
24578315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->key = pos;	/* remember it */
24588315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	else
24598315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->pos = 0;		/* forget it */
24608315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
24618315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	return l;
24628315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger}
24638315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
24648315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstatic void *fib_route_seq_start(struct seq_file *seq, loff_t *pos)
24658315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	__acquires(RCU)
24668315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger{
24678315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct fib_route_iter *iter = seq->private;
24688315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct fib_table *tb;
24698315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
24708315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	rcu_read_lock();
24711218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki	tb = fib_get_table(seq_file_net(seq), RT_TABLE_MAIN);
24728315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	if (!tb)
24738315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		return NULL;
24748315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
24758315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	iter->main_trie = (struct trie *) tb->tb_data;
24768315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	if (*pos == 0)
24778315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		return SEQ_START_TOKEN;
24788315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	else
24798315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		return fib_route_get_idx(iter, *pos - 1);
24808315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger}
24818315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
24828315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstatic void *fib_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
24838315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger{
24848315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct fib_route_iter *iter = seq->private;
24858315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct leaf *l = v;
24868315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
24878315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	++*pos;
24888315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	if (v == SEQ_START_TOKEN) {
24898315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->pos = 0;
24908315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		l = trie_firstleaf(iter->main_trie);
24918315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	} else {
24928315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->pos++;
24938315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		l = trie_nextleaf(l);
24948315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	}
24958315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
24968315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	if (l)
24978315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->key = l->key;
24988315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	else
24998315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->pos = 0;
25008315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	return l;
25018315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger}
25028315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
25038315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstatic void fib_route_seq_stop(struct seq_file *seq, void *v)
25048315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	__releases(RCU)
25058315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger{
25068315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	rcu_read_unlock();
25078315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger}
25088315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
2509a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazetstatic unsigned int fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
251019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2511a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet	unsigned int flags = 0;
251219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2513a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet	if (type == RTN_UNREACHABLE || type == RTN_PROHIBIT)
2514a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet		flags = RTF_REJECT;
2515cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (fi && fi->fib_nh->nh_gw)
2516cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		flags |= RTF_GATEWAY;
251732ab5f80334fc067386c4c56c434010c01cff6b9Al Viro	if (mask == htonl(0xFFFFFFFF))
2518cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		flags |= RTF_HOST;
2519cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	flags |= RTF_UP;
2520cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return flags;
252119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
252219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2523cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/*
2524cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger *	This outputs /proc/net/route.
2525cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger *	The format of the file is not supposed to be changed
2526a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet *	and needs to be same as fib_hash output to avoid breaking
2527cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger *	legacy utilities
2528cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger */
2529cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_route_seq_show(struct seq_file *seq, void *v)
253019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2531cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct leaf *l = v;
25321328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger	struct leaf_info *li;
25331328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger	struct hlist_node *node;
253419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2535cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (v == SEQ_START_TOKEN) {
2536cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
2537cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			   "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
2538cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			   "\tWindow\tIRTT");
2539cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return 0;
2540cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
254119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
25421328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger	hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
2543cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		struct fib_alias *fa;
254432ab5f80334fc067386c4c56c434010c01cff6b9Al Viro		__be32 mask, prefix;
254591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2546cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		mask = inet_make_mask(li->plen);
2547cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		prefix = htonl(l->key);
254819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2549cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		list_for_each_entry_rcu(fa, &li->falh, fa_list) {
25501371e37da299d4df6267ad0ddf010435782c28e9Herbert Xu			const struct fib_info *fi = fa->fa_info;
2551a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet			unsigned int flags = fib_flag_trans(fa->fa_type, mask, fi);
25525e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov			int len;
255319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2554cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (fa->fa_type == RTN_BROADCAST
2555cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			    || fa->fa_type == RTN_MULTICAST)
2556cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				continue;
255719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2558cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (fi)
25595e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov				seq_printf(seq,
25605e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov					 "%s\t%08X\t%08X\t%04X\t%d\t%u\t"
25615e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov					 "%d\t%08X\t%d\t%u\t%u%n",
2562cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 fi->fib_dev ? fi->fib_dev->name : "*",
2563cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 prefix,
2564cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 fi->fib_nh->nh_gw, flags, 0, 0,
2565cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 fi->fib_priority,
2566cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 mask,
2567a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger					 (fi->fib_advmss ?
2568a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger					  fi->fib_advmss + 40 : 0),
2569cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 fi->fib_window,
25705e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov					 fi->fib_rtt >> 3, &len);
2571cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			else
25725e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov				seq_printf(seq,
25735e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov					 "*\t%08X\t%08X\t%04X\t%d\t%u\t"
25745e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov					 "%d\t%08X\t%d\t%u\t%u%n",
2575cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 prefix, 0, flags, 0, 0, 0,
25765e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov					 mask, 0, 0, 0, &len);
257719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
25785e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov			seq_printf(seq, "%*s\n", 127 - len, "");
2579cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		}
258019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
258119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
258219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return 0;
258319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
258419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2585f690808e17925fc45217eb22e8670902ecee5c1bStephen Hemmingerstatic const struct seq_operations fib_route_seq_ops = {
25868315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	.start  = fib_route_seq_start,
25878315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	.next   = fib_route_seq_next,
25888315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	.stop   = fib_route_seq_stop,
2589cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.show   = fib_route_seq_show,
259019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
259119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2592cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_route_seq_open(struct inode *inode, struct file *file)
259319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
25941c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	return seq_open_net(inode, file, &fib_route_seq_ops,
25958315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger			    sizeof(struct fib_route_iter));
259619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
259719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
25989a32144e9d7b4e21341174b1a83b82a82353be86Arjan van de Venstatic const struct file_operations fib_route_fops = {
2599cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.owner  = THIS_MODULE,
2600cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.open   = fib_route_seq_open,
2601cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.read   = seq_read,
2602cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.llseek = seq_lseek,
26031c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	.release = seq_release_net,
260419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
260519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
260661a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunevint __net_init fib_proc_init(struct net *net)
260719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
260861a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	if (!proc_net_fops_create(net, "fib_trie", S_IRUGO, &fib_trie_fops))
2609cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto out1;
2610cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
261161a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	if (!proc_net_fops_create(net, "fib_triestat", S_IRUGO,
261261a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev				  &fib_triestat_fops))
2613cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto out2;
2614cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
261561a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	if (!proc_net_fops_create(net, "route", S_IRUGO, &fib_route_fops))
2616cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto out3;
2617cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
261819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return 0;
2619cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2620cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerout3:
262161a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	proc_net_remove(net, "fib_triestat");
2622cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerout2:
262361a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	proc_net_remove(net, "fib_trie");
2624cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerout1:
2625cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return -ENOMEM;
262619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
262719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
262861a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunevvoid __net_exit fib_proc_exit(struct net *net)
262919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
263061a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	proc_net_remove(net, "fib_trie");
263161a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	proc_net_remove(net, "fib_triestat");
263261a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	proc_net_remove(net, "route");
263319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
263419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
263519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif /* CONFIG_PROC_FS */
2636