fib_trie.c revision 76e6ebfb40a2455c18234dcb0f9df37533215461
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 *
1519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * This work is based on the LPC-trie which is originally descibed 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.
1919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * http://www.nada.kth.se/~snilsson/public/papers/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
5105eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson#define VERSION "0.408"
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>
74457c4cbc5a3dde259d2a1f15d5f9785290397267Eric W. Biederman#include <net/net_namespace.h>
7519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/ip.h>
7619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/protocol.h>
7719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/route.h>
7819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/tcp.h>
7919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/sock.h>
8019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/ip_fib.h>
8119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include "fib_lookup.h"
8219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8306ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson#define MAX_STAT_DEPTH 32
8419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define KEYLENGTH (8*sizeof(t_key))
8619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssontypedef unsigned int t_key;
8819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define T_TNODE 0
9019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define T_LEAF  1
9119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define NODE_TYPE_MASK	0x1UL
922373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson#define NODE_TYPE(node) ((node)->parent & NODE_TYPE_MASK)
932373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
9491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson#define IS_TNODE(n) (!(n->parent & T_LEAF))
9591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson#define IS_LEAF(n) (n->parent & T_LEAF)
9619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
9719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct node {
9891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	unsigned long parent;
998d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	t_key key;
10019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
10119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
10219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct leaf {
10391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	unsigned long parent;
1048d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	t_key key;
10519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_head list;
1062373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct rcu_head rcu;
10719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
10819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
10919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct leaf_info {
11019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_node hlist;
1112373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct rcu_head rcu;
11219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int plen;
11319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct list_head falh;
11419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
11519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
11619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct tnode {
11791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	unsigned long parent;
1188d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	t_key key;
119112d8cfcbf4f5ef0cf669cb5864f1206972076d6Eric Dumazet	unsigned char pos;		/* 2log(KEYLENGTH) bits needed */
120112d8cfcbf4f5ef0cf669cb5864f1206972076d6Eric Dumazet	unsigned char bits;		/* 2log(KEYLENGTH) bits needed */
1218d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	unsigned int full_children;	/* KEYLENGTH bits needed */
1228d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	unsigned int empty_children;	/* KEYLENGTH bits needed */
12315be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	union {
12415be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger		struct rcu_head rcu;
12515be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger		struct work_struct work;
12615be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	};
12791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	struct node *child[0];
12819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
12919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
13019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
13119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct trie_use_stats {
13219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int gets;
13319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int backtrack;
13419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int semantic_match_passed;
13519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int semantic_match_miss;
13619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int null_node_hit;
1372f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	unsigned int resize_node_skipped;
13819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
13919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
14019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
14119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct trie_stat {
14219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int totdepth;
14319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int maxdepth;
14419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int tnodes;
14519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int leaves;
14619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int nullpointers;
147936722922f6d2366378de606a40c14f96915474dStephen Hemminger	unsigned int prefixes;
14806ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson	unsigned int nodesizes[MAX_STAT_DEPTH];
149c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger};
15019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
15119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct trie {
15291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	struct node *trie;
15319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
15419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie_use_stats stats;
15519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
15619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
15719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
15819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic void put_child(struct trie *t, struct tnode *tn, int i, struct node *n);
159a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n,
160a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				  int wasfull);
16119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic struct node *resize(struct trie *t, struct tnode *tn);
1622f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *inflate(struct trie *t, struct tnode *tn);
1632f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *halve(struct trie *t, struct tnode *tn);
16419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
165e18b890bb0881bbab6f4f1a6cd20d9c60d66b003Christoph Lameterstatic struct kmem_cache *fn_alias_kmem __read_mostly;
166bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemmingerstatic struct kmem_cache *trie_leaf_kmem __read_mostly;
16719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1680680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemmingerstatic inline struct tnode *node_parent(struct node *node)
1690680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger{
170b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet	return (struct tnode *)(node->parent & ~NODE_TYPE_MASK);
171b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet}
172b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet
173b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazetstatic inline struct tnode *node_parent_rcu(struct node *node)
174b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet{
175b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet	struct tnode *ret = node_parent(node);
1760680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger
1770680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger	return rcu_dereference(ret);
1780680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger}
1790680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger
1806440cc9e0f48ade57af7be28008cbfa6a991f287Stephen Hemminger/* Same as rcu_assign_pointer
1816440cc9e0f48ade57af7be28008cbfa6a991f287Stephen Hemminger * but that macro() assumes that value is a pointer.
1826440cc9e0f48ade57af7be28008cbfa6a991f287Stephen Hemminger */
1830680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemmingerstatic inline void node_set_parent(struct node *node, struct tnode *ptr)
1840680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger{
1856440cc9e0f48ade57af7be28008cbfa6a991f287Stephen Hemminger	smp_wmb();
1866440cc9e0f48ade57af7be28008cbfa6a991f287Stephen Hemminger	node->parent = (unsigned long)ptr | NODE_TYPE(node);
1870680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger}
1882373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
189b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazetstatic inline struct node *tnode_get_child(struct tnode *tn, unsigned int i)
190b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet{
191b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet	BUG_ON(i >= 1U << tn->bits);
1922373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
193b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet	return tn->child[i];
194b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet}
195b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet
196b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazetstatic inline struct node *tnode_get_child_rcu(struct tnode *tn, unsigned int i)
19719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
198b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet	struct node *ret = tnode_get_child(tn, i);
19919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
200b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet	return rcu_dereference(ret);
20119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
20219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
203bb435b8d816582064ee0ddb1e2a6fbca67f34108Stephen Hemmingerstatic inline int tnode_child_length(const struct tnode *tn)
20419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
20591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	return 1 << tn->bits;
20619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
20719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
208ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemmingerstatic inline t_key mask_pfx(t_key k, unsigned short l)
209ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger{
210ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger	return (l == 0) ? 0 : k >> (KEYLENGTH-l) << (KEYLENGTH-l);
211ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger}
212ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger
21319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline t_key tkey_extract_bits(t_key a, int offset, int bits)
21419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
21591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (offset < KEYLENGTH)
21619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return ((t_key)(a << offset)) >> (KEYLENGTH - bits);
21791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	else
21819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return 0;
21919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
22019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
22119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline int tkey_equals(t_key a, t_key b)
22219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
223c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	return a == b;
22419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
22519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
22619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline int tkey_sub_equals(t_key a, int offset, int bits, t_key b)
22719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
228c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (bits == 0 || offset >= KEYLENGTH)
229c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		return 1;
23091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	bits = bits > KEYLENGTH ? KEYLENGTH : bits;
23191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	return ((a ^ b) << offset) >> (KEYLENGTH - bits) == 0;
232c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger}
23319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
23419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline int tkey_mismatch(t_key a, int offset, t_key b)
23519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
23619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t_key diff = a ^ b;
23719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i = offset;
23819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
239c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!diff)
240c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		return 0;
241c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	while ((diff << i) >> (KEYLENGTH-1) == 0)
24219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		i++;
24319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return i;
24419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
24519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
24619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson/*
247e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  To understand this stuff, an understanding of keys and all their bits is
248e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  necessary. Every node in the trie has a key associated with it, but not
24919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  all of the bits in that key are significant.
25019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
25119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  Consider a node 'n' and its parent 'tp'.
25219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
253e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  If n is a leaf, every bit in its key is significant. Its presence is
254e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  necessitated by path compression, since during a tree traversal (when
255e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  searching for a leaf - unless we are doing an insertion) we will completely
256e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  ignore all skipped bits we encounter. Thus we need to verify, at the end of
257e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  a potentially successful search, that we have indeed been walking the
25819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  correct key path.
25919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
260e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  Note that we can never "miss" the correct key in the tree if present by
261e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  following the wrong path. Path compression ensures that segments of the key
262e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  that are the same for all keys with a given prefix are skipped, but the
263e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  skipped part *is* identical for each node in the subtrie below the skipped
264e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  bit! trie_insert() in this implementation takes care of that - note the
26519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  call to tkey_sub_equals() in trie_insert().
26619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
267e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  if n is an internal node - a 'tnode' here, the various parts of its key
26819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  have many different meanings.
26919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
270e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  Example:
27119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  _________________________________________________________________
27219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C |
27319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  -----------------------------------------------------------------
274e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki    0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
27519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
27619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  _________________________________________________________________
27719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u |
27819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  -----------------------------------------------------------------
27919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson   16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31
28019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
28119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  tp->pos = 7
28219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  tp->bits = 3
28319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  n->pos = 15
28491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson  n->bits = 4
28519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
286e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  First, let's just ignore the bits that come before the parent tp, that is
287e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  the bits from 0 to (tp->pos-1). They are *known* but at this point we do
28819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  not use them for anything.
28919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
29019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  The bits from (tp->pos) to (tp->pos + tp->bits - 1) - "N", above - are the
291e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  index into the parent's child array. That is, they will be used to find
29219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  'n' among tp's children.
29319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
29419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  The bits from (tp->pos + tp->bits) to (n->pos - 1) - "S" - are skipped bits
29519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  for the node n.
29619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
297e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  All the bits we have seen so far are significant to the node n. The rest
29819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  of the bits are really not needed or indeed known in n->key.
29919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
300e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki  The bits from (n->pos) to (n->pos + n->bits - 1) - "C" - are the index into
30119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  n's child array, and will of course be different for each child.
302e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki
303c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
30419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  The rest of the bits, from (n->pos + n->bits) onward, are completely unknown
30519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  at this point.
30619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
30719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson*/
30819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
3090c7770c740156c8802c23d24fc094d06967d997dStephen Hemmingerstatic inline void check_tnode(const struct tnode *tn)
31019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
3110c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	WARN_ON(tn && tn->pos+tn->bits > 32);
31219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
31319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
314f5026fabda54e5ab5d469d8cfac5f46b4d321ce9Denis V. Lunevstatic const int halve_threshold = 25;
315f5026fabda54e5ab5d469d8cfac5f46b4d321ce9Denis V. Lunevstatic const int inflate_threshold = 50;
316f5026fabda54e5ab5d469d8cfac5f46b4d321ce9Denis V. Lunevstatic const int halve_threshold_root = 8;
317f5026fabda54e5ab5d469d8cfac5f46b4d321ce9Denis V. Lunevstatic const int inflate_threshold_root = 15;
31819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
3192373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
3202373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __alias_free_mem(struct rcu_head *head)
32119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
3222373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct fib_alias *fa = container_of(head, struct fib_alias, rcu);
3232373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	kmem_cache_free(fn_alias_kmem, fa);
32419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
32519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
3262373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic inline void alias_free_mem_rcu(struct fib_alias *fa)
32719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
3282373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	call_rcu(&fa->rcu, __alias_free_mem);
3292373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
33091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
3312373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __leaf_free_rcu(struct rcu_head *head)
3322373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{
333bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger	struct leaf *l = container_of(head, struct leaf, rcu);
334bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger	kmem_cache_free(trie_leaf_kmem, l);
3352373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
33691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
337387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemmingerstatic inline void free_leaf(struct leaf *l)
338387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger{
339387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger	call_rcu_bh(&l->rcu, __leaf_free_rcu);
340387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger}
341387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger
3422373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __leaf_info_free_rcu(struct rcu_head *head)
34319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
3442373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	kfree(container_of(head, struct leaf_info, rcu));
34519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
34619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
3472373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic inline void free_leaf_info(struct leaf_info *leaf)
34819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
3492373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	call_rcu(&leaf->rcu, __leaf_info_free_rcu);
35019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
35119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
3528d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazetstatic struct tnode *tnode_alloc(size_t size)
353f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy{
3542373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	if (size <= PAGE_SIZE)
3558d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet		return kzalloc(size, GFP_KERNEL);
35615be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	else
35715be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger		return __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
35815be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger}
3592373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
36015be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemmingerstatic void __tnode_vfree(struct work_struct *arg)
36115be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger{
36215be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	struct tnode *tn = container_of(arg, struct tnode, work);
36315be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	vfree(tn);
364f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy}
365f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy
3662373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __tnode_free_rcu(struct rcu_head *head)
367f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy{
3682373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct tnode *tn = container_of(head, struct tnode, rcu);
3698d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	size_t size = sizeof(struct tnode) +
3708d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet		      (sizeof(struct node *) << tn->bits);
371f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy
372f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy	if (size <= PAGE_SIZE)
373f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy		kfree(tn);
37415be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	else {
37515be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger		INIT_WORK(&tn->work, __tnode_vfree);
37615be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger		schedule_work(&tn->work);
37715be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger	}
378f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy}
379f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy
3802373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic inline void tnode_free(struct tnode *tn)
3812373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{
382387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger	if (IS_LEAF(tn))
383387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger		free_leaf((struct leaf *) tn);
384387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger	else
385550e29bc96e6f1ced2bca82dace197b009434367Robert Olsson		call_rcu(&tn->rcu, __tnode_free_rcu);
3862373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
3872373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
3882373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic struct leaf *leaf_new(void)
3892373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{
390bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger	struct leaf *l = kmem_cache_alloc(trie_leaf_kmem, GFP_KERNEL);
3912373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	if (l) {
3922373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		l->parent = T_LEAF;
3932373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		INIT_HLIST_HEAD(&l->list);
3942373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	}
3952373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	return l;
3962373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
3972373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
3982373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic struct leaf_info *leaf_info_new(int plen)
3992373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{
4002373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct leaf_info *li = kmalloc(sizeof(struct leaf_info),  GFP_KERNEL);
4012373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	if (li) {
4022373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		li->plen = plen;
4032373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		INIT_LIST_HEAD(&li->falh);
4042373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	}
4052373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	return li;
4062373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
4072373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
408a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic struct tnode *tnode_new(t_key key, int pos, int bits)
40919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
4108d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	size_t sz = sizeof(struct tnode) + (sizeof(struct node *) << bits);
411f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy	struct tnode *tn = tnode_alloc(sz);
41219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
41391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (tn) {
4142373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		tn->parent = T_TNODE;
41519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->pos = pos;
41619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->bits = bits;
41719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->key = key;
41819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->full_children = 0;
41919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->empty_children = 1<<bits;
42019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
421c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
4228d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet	pr_debug("AT %p s=%u %lu\n", tn, (unsigned int) sizeof(struct tnode),
4238d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet		 (unsigned long) (sizeof(struct node) << bits));
42419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return tn;
42519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
42619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
42719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson/*
42819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Check whether a tnode 'n' is "full", i.e. it is an internal node
42919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * and no bits are skipped. See discussion in dyntree paper p. 6
43019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */
43119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
432bb435b8d816582064ee0ddb1e2a6fbca67f34108Stephen Hemmingerstatic inline int tnode_full(const struct tnode *tn, const struct node *n)
43319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
434c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (n == NULL || IS_LEAF(n))
43519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return 0;
43619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
43719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return ((struct tnode *) n)->pos == tn->pos + tn->bits;
43819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
43919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
440a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic inline void put_child(struct trie *t, struct tnode *tn, int i,
441a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			     struct node *n)
44219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
44319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tnode_put_child_reorg(tn, i, n, -1);
44419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
44519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
446c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger /*
44719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  * Add a child at position i overwriting the old value.
44819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  * Update the value of full_children and empty_children.
44919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  */
45019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
451a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n,
452a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				  int wasfull)
45319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
4542373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct node *chi = tn->child[i];
45519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int isfull;
45619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
4570c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	BUG_ON(i >= 1<<tn->bits);
4580c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
45919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* update emptyChildren */
46019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (n == NULL && chi != NULL)
46119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->empty_children++;
46219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	else if (n != NULL && chi == NULL)
46319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->empty_children--;
464c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
46519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* update fullChildren */
46691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (wasfull == -1)
46719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		wasfull = tnode_full(tn, chi);
46819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
46919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	isfull = tnode_full(tn, n);
470c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (wasfull && !isfull)
47119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->full_children--;
472c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	else if (!wasfull && isfull)
47319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->full_children++;
47491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
475c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (n)
4760680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger		node_set_parent(n, tn);
47719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
4782373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_assign_pointer(tn->child[i], n);
47919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
48019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
481c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemmingerstatic struct node *resize(struct trie *t, struct tnode *tn)
48219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
48319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i;
4842f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	int err = 0;
4852f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	struct tnode *old_tn;
486e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson	int inflate_threshold_use;
487e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson	int halve_threshold_use;
48805eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson	int max_resize;
48919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
490e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	if (!tn)
49119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return NULL;
49219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
4930c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("In tnode_resize %p inflate_threshold=%d threshold=%d\n",
4940c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		 tn, inflate_threshold, halve_threshold);
49519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
49619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* No children */
49719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (tn->empty_children == tnode_child_length(tn)) {
49819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tnode_free(tn);
49919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return NULL;
50019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
50119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* One child */
50219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (tn->empty_children == tnode_child_length(tn) - 1)
50319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		for (i = 0; i < tnode_child_length(tn); i++) {
50491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			struct node *n;
50519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
50691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			n = tn->child[i];
5072373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			if (!n)
50891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				continue;
50991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
51091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			/* compress one level */
5110680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger			node_set_parent(n, NULL);
51291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			tnode_free(tn);
51391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			return n;
51419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
515c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	/*
51619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * Double as long as the resulting node has a number of
51719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * nonempty nodes that are above the threshold.
51819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
51919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
52019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/*
521c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * From "Implementing a dynamic compressed trie" by Stefan Nilsson of
522c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * the Helsinki University of Technology and Matti Tikkanen of Nokia
52319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * Telecommunications, page 6:
524c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * "A node is doubled if the ratio of non-empty children to all
52519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * children in the *doubled* node is at least 'high'."
52619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
527c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * 'high' in this instance is the variable 'inflate_threshold'. It
528c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * is expressed as a percentage, so we multiply it with
529c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * tnode_child_length() and instead of multiplying by 2 (since the
530c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * child array will be doubled by inflate()) and multiplying
531c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * the left-hand side by 100 (to handle the percentage thing) we
53219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * multiply the left-hand side by 50.
533c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
534c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * The left-hand side may look a bit weird: tnode_child_length(tn)
535c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * - tn->empty_children is of course the number of non-null children
536c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * in the current node. tn->full_children is the number of "full"
53719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * children, that is non-null tnodes with a skip value of 0.
538c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * All of those will be doubled in the resulting inflated tnode, so
53919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * we just count them one extra time here.
540c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
54119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * A clearer way to write this would be:
542c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
54319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * to_be_doubled = tn->full_children;
544c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children -
54519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *     tn->full_children;
54619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
54719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * new_child_length = tnode_child_length(tn) * 2;
54819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
549c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) /
55019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *      new_child_length;
55119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * if (new_fill_factor >= inflate_threshold)
552c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
553c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * ...and so on, tho it would mess up the while () loop.
554c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
55519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * anyway,
55619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >=
55719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *      inflate_threshold
558c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
55919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * avoid a division:
56019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * 100 * (not_to_be_doubled + 2*to_be_doubled) >=
56119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *      inflate_threshold * new_child_length
562c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
56319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * expand not_to_be_doubled and to_be_doubled, and shorten:
564c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * 100 * (tnode_child_length(tn) - tn->empty_children +
56591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	 *    tn->full_children) >= inflate_threshold * new_child_length
566c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
56719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * expand new_child_length:
568c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * 100 * (tnode_child_length(tn) - tn->empty_children +
56991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	 *    tn->full_children) >=
57019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *      inflate_threshold * tnode_child_length(tn) * 2
571c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
57219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * shorten again:
573c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * 50 * (tn->full_children + tnode_child_length(tn) -
57491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	 *    tn->empty_children) >= inflate_threshold *
57519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *    tnode_child_length(tn)
576c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
57719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
57819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
57919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	check_tnode(tn);
580c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
581e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson	/* Keep root node larger  */
582e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson
583132adf54639cf7dd9315e8df89c2faa59f6e46d9Stephen Hemminger	if (!tn->parent)
584e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson		inflate_threshold_use = inflate_threshold_root;
585e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	else
586e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson		inflate_threshold_use = inflate_threshold;
587e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson
5882f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	err = 0;
58905eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson	max_resize = 10;
59005eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson	while ((tn->full_children > 0 &&  max_resize-- &&
591a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		50 * (tn->full_children + tnode_child_length(tn)
592a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		      - tn->empty_children)
593a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		>= inflate_threshold_use * tnode_child_length(tn))) {
59419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
5952f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		old_tn = tn;
5962f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		tn = inflate(t, tn);
597a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
5982f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		if (IS_ERR(tn)) {
5992f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			tn = old_tn;
6002f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
6012f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			t->stats.resize_node_skipped++;
6022f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#endif
6032f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			break;
6042f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		}
60519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
60619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
60705eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson	if (max_resize < 0) {
60805eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson		if (!tn->parent)
609a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			pr_warning("Fix inflate_threshold_root."
610a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				   " Now=%d size=%d bits\n",
611a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				   inflate_threshold_root, tn->bits);
61205eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson		else
613a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			pr_warning("Fix inflate_threshold."
614a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				   " Now=%d size=%d bits\n",
615a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				   inflate_threshold, tn->bits);
61605eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson	}
61705eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson
61819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	check_tnode(tn);
61919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
62019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/*
62119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * Halve as long as the number of empty children in this
62219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * node is above threshold.
62319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
6242f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
625e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson
626e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson	/* Keep root node larger  */
627e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson
628132adf54639cf7dd9315e8df89c2faa59f6e46d9Stephen Hemminger	if (!tn->parent)
629e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson		halve_threshold_use = halve_threshold_root;
630e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	else
631e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson		halve_threshold_use = halve_threshold;
632e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson
6332f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	err = 0;
63405eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson	max_resize = 10;
63505eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson	while (tn->bits > 1 &&  max_resize-- &&
63619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	       100 * (tnode_child_length(tn) - tn->empty_children) <
637e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson	       halve_threshold_use * tnode_child_length(tn)) {
6382f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
6392f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		old_tn = tn;
6402f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		tn = halve(t, tn);
6412f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		if (IS_ERR(tn)) {
6422f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			tn = old_tn;
6432f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
6442f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			t->stats.resize_node_skipped++;
6452f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#endif
6462f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			break;
6472f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		}
6482f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	}
64919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
65005eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson	if (max_resize < 0) {
65105eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson		if (!tn->parent)
652a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			pr_warning("Fix halve_threshold_root."
653a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				   " Now=%d size=%d bits\n",
654a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				   halve_threshold_root, tn->bits);
65505eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson		else
656a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			pr_warning("Fix halve_threshold."
657a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				   " Now=%d size=%d bits\n",
658a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				   halve_threshold, tn->bits);
65905eee48c5af8213a71bd908ce17f577b2b776f79Robert Olsson	}
660c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
66119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Only one child remains */
66219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (tn->empty_children == tnode_child_length(tn) - 1)
66319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		for (i = 0; i < tnode_child_length(tn); i++) {
66491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			struct node *n;
66519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
66691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			n = tn->child[i];
6672373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			if (!n)
66891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				continue;
66991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
67091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			/* compress one level */
67191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
6720680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger			node_set_parent(n, NULL);
67391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			tnode_free(tn);
67491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			return n;
67519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
67619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
67719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return (struct node *) tn;
67819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
67919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
6802f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *inflate(struct trie *t, struct tnode *tn)
68119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
68219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *oldtnode = tn;
68319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int olen = tnode_child_length(tn);
68419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i;
68519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
6860c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("In inflate\n");
68719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
68819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits + 1);
68919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
6900c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	if (!tn)
6912f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		return ERR_PTR(-ENOMEM);
6922f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
6932f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	/*
694c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * Preallocate and store tnodes before the actual work so we
695c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * don't get into an inconsistent state if memory allocation
696c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * fails. In case of failure we return the oldnode and  inflate
6972f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	 * of tnode is ignored.
6982f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	 */
69991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
70091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (i = 0; i < olen; i++) {
701a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		struct tnode *inode;
7022f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
703a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		inode = (struct tnode *) tnode_get_child(oldtnode, i);
7042f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		if (inode &&
7052f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		    IS_TNODE(inode) &&
7062f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		    inode->pos == oldtnode->pos + oldtnode->bits &&
7072f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		    inode->bits > 1) {
7082f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			struct tnode *left, *right;
709ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger			t_key m = ~0U << (KEYLENGTH - 1) >> inode->pos;
710c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
7112f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			left = tnode_new(inode->key&(~m), inode->pos + 1,
7122f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson					 inode->bits - 1);
7132f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			if (!left)
7142f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				goto nomem;
71591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
7162f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			right = tnode_new(inode->key|m, inode->pos + 1,
7172f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson					  inode->bits - 1);
7182f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
719e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki			if (!right) {
7202f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				tnode_free(left);
7212f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				goto nomem;
722e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki			}
7232f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
7242f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			put_child(t, tn, 2*i, (struct node *) left);
7252f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			put_child(t, tn, 2*i+1, (struct node *) right);
7262f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		}
7272f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	}
7282f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
72991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (i = 0; i < olen; i++) {
730c95aaf9af5a1f6dee56d1f2ab4915cd722d608daStephen Hemminger		struct tnode *inode;
73119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		struct node *node = tnode_get_child(oldtnode, i);
73291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		struct tnode *left, *right;
73391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		int size, j;
734c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
73519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* An empty child */
73619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (node == NULL)
73719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
73819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
73919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* A leaf or an internal node with skipped bits */
74019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
741c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (IS_LEAF(node) || ((struct tnode *) node)->pos >
74219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		   tn->pos + tn->bits - 1) {
743a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			if (tkey_extract_bits(node->key,
744a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger					      oldtnode->pos + oldtnode->bits,
745a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger					      1) == 0)
74619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				put_child(t, tn, 2*i, node);
74719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			else
74819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				put_child(t, tn, 2*i+1, node);
74919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
75019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
75119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
75219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* An internal node with two children */
75319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		inode = (struct tnode *) node;
75419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
75519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (inode->bits == 1) {
75619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			put_child(t, tn, 2*i, inode->child[0]);
75719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			put_child(t, tn, 2*i+1, inode->child[1]);
75819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
75919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			tnode_free(inode);
76091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			continue;
76119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
76219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
76391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* An internal node with more than two children */
76491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
76591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* We will replace this node 'inode' with two new
76691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * ones, 'left' and 'right', each with half of the
76791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * original children. The two new nodes will have
76891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * a position one bit further down the key and this
76991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * means that the "significant" part of their keys
77091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * (see the discussion near the top of this file)
77191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * will differ by one bit, which will be "0" in
77291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * left's key and "1" in right's key. Since we are
77391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * moving the key position by one step, the bit that
77491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * we are moving away from - the bit at position
77591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * (inode->pos) - is the one that will differ between
77691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * left and right. So... we synthesize that bit in the
77791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * two  new keys.
77891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * The mask 'm' below will be a single "one" bit at
77991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * the position (inode->pos)
78091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
78119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
78291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* Use the old key, but set the new significant
78391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 *   bit to zero.
78491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
7852f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
78691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		left = (struct tnode *) tnode_get_child(tn, 2*i);
78791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, 2*i, NULL);
7882f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
78991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		BUG_ON(!left);
7902f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
79191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		right = (struct tnode *) tnode_get_child(tn, 2*i+1);
79291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, 2*i+1, NULL);
79319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
79491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		BUG_ON(!right);
79519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
79691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		size = tnode_child_length(left);
79791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		for (j = 0; j < size; j++) {
79891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			put_child(t, left, j, inode->child[j]);
79991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			put_child(t, right, j, inode->child[j + size]);
80019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
80191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, 2*i, resize(t, left));
80291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, 2*i+1, resize(t, right));
80391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
80491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		tnode_free(inode);
80519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
80619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tnode_free(oldtnode);
80719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return tn;
8082f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonnomem:
8092f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	{
8102f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		int size = tnode_child_length(tn);
8112f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		int j;
8122f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson
8130c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		for (j = 0; j < size; j++)
8142f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			if (tn->child[j])
8152f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				tnode_free((struct tnode *)tn->child[j]);
8162f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson
8172f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		tnode_free(tn);
8180c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
8192f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		return ERR_PTR(-ENOMEM);
8202f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	}
82119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
82219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8232f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *halve(struct trie *t, struct tnode *tn)
82419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
82519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *oldtnode = tn;
82619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct node *left, *right;
82719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i;
82819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int olen = tnode_child_length(tn);
82919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8300c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("In halve\n");
831c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
832c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits - 1);
83319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8342f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	if (!tn)
8352f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		return ERR_PTR(-ENOMEM);
8362f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
8372f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	/*
838c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * Preallocate and store tnodes before the actual work so we
839c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * don't get into an inconsistent state if memory allocation
840c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * fails. In case of failure we return the oldnode and halve
8412f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	 * of tnode is ignored.
8422f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	 */
8432f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
84491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (i = 0; i < olen; i += 2) {
8452f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		left = tnode_get_child(oldtnode, i);
8462f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		right = tnode_get_child(oldtnode, i+1);
847c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
8482f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		/* Two nonempty children */
8490c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		if (left && right) {
8502f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			struct tnode *newn;
8510c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
8522f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			newn = tnode_new(left->key, tn->pos + tn->bits, 1);
8530c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
8540c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger			if (!newn)
8552f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				goto nomem;
8560c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
8572f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			put_child(t, tn, i/2, (struct node *)newn);
8582f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		}
8592f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
8602f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	}
86119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
86291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (i = 0; i < olen; i += 2) {
86391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		struct tnode *newBinNode;
86491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
86519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		left = tnode_get_child(oldtnode, i);
86619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		right = tnode_get_child(oldtnode, i+1);
867c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
86819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* At least one of the children is empty */
86919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (left == NULL) {
87019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			if (right == NULL)    /* Both are empty */
87119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				continue;
87219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			put_child(t, tn, i/2, right);
87391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			continue;
8740c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		}
87591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
87691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (right == NULL) {
87719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			put_child(t, tn, i/2, left);
87891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			continue;
87991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
880c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
88119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* Two nonempty children */
88291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		newBinNode = (struct tnode *) tnode_get_child(tn, i/2);
88391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, i/2, NULL);
88491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, newBinNode, 0, left);
88591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, newBinNode, 1, right);
88691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, i/2, resize(t, newBinNode));
88719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
88819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tnode_free(oldtnode);
88919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return tn;
8902f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonnomem:
8912f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	{
8922f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		int size = tnode_child_length(tn);
8932f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		int j;
8942f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson
8950c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		for (j = 0; j < size; j++)
8962f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			if (tn->child[j])
8972f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				tnode_free((struct tnode *)tn->child[j]);
8982f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson
8992f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		tnode_free(tn);
9000c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
9012f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		return ERR_PTR(-ENOMEM);
9022f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	}
90319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
90419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
905772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson/* readside must use rcu_read_lock currently dump routines
9062373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson via get_fa_head and dump */
9072373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
908772cb712b1373d335ef2874ea357ec681edc754bRobert Olssonstatic struct leaf_info *find_leaf_info(struct leaf *l, int plen)
90919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
910772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson	struct hlist_head *head = &l->list;
91119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_node *node;
91219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf_info *li;
91319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
9142373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	hlist_for_each_entry_rcu(li, node, head, hlist)
915c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (li->plen == plen)
91619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			return li;
91791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
91819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return NULL;
91919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
92019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
921a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic inline struct list_head *get_fa_head(struct leaf *l, int plen)
92219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
923772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson	struct leaf_info *li = find_leaf_info(l, plen);
924c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
92591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (!li)
92691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		return NULL;
927c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
92891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	return &li->falh;
92919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
93019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
93119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic void insert_leaf_info(struct hlist_head *head, struct leaf_info *new)
93219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
933e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	struct leaf_info *li = NULL, *last = NULL;
934e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	struct hlist_node *node;
935e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki
936e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	if (hlist_empty(head)) {
937e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki		hlist_add_head_rcu(&new->hlist, head);
938e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	} else {
939e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki		hlist_for_each_entry(li, node, head, hlist) {
940e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki			if (new->plen > li->plen)
941e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki				break;
942e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki
943e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki			last = li;
944e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki		}
945e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki		if (last)
946e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki			hlist_add_after_rcu(&last->hlist, &new->hlist);
947e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki		else
948e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki			hlist_add_before_rcu(&new->hlist, &li->hlist);
949e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki	}
95019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
95119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
9522373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson/* rcu_read_lock needs to be hold by caller from readside */
9532373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
95419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic struct leaf *
95519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfib_find_node(struct trie *t, u32 key)
95619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
95719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int pos;
95819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *tn;
95919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct node *n;
96019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
96119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	pos = 0;
9622373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	n = rcu_dereference(t->trie);
96319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
96419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	while (n != NULL &&  NODE_TYPE(n) == T_TNODE) {
96519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn = (struct tnode *) n;
96691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
96719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		check_tnode(tn);
96891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
969c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
97091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			pos = tn->pos + tn->bits;
971a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			n = tnode_get_child_rcu(tn,
972a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger						tkey_extract_bits(key,
973a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger								  tn->pos,
974a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger								  tn->bits));
97591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else
97619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
97719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
97819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Case we have found a leaf. Compare prefixes */
97919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
98091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key))
98191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		return (struct leaf *)n;
98291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
98319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return NULL;
98419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
98519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
98619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic struct node *trie_rebalance(struct trie *t, struct tnode *tn)
98719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
98819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int wasfull;
9890680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger	t_key cindex, key = tn->key;
9900680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger	struct tnode *tp;
99119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
9920680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger	while (tn != NULL && (tp = node_parent((struct node *)tn)) != NULL) {
99319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		cindex = tkey_extract_bits(key, tp->pos, tp->bits);
99419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		wasfull = tnode_full(tp, tnode_get_child(tp, cindex));
995a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		tn = (struct tnode *) resize(t, (struct tnode *)tn);
996a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
997a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		tnode_put_child_reorg((struct tnode *)tp, cindex,
998a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				      (struct node *)tn, wasfull);
99991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
10000680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger		tp = node_parent((struct node *) tn);
10010680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger		if (!tp)
100219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
10030680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger		tn = tp;
100419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
10050680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger
100619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Handle last (top) tnode */
1007c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (IS_TNODE(tn))
1008a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		tn = (struct tnode *)resize(t, (struct tnode *)tn);
100919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1010a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	return (struct node *)tn;
101119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
101219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
10132373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson/* only used from updater-side */
10142373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
1015fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemmingerstatic struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
101619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
101719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int pos, newpos;
101819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *tp = NULL, *tn = NULL;
101919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct node *n;
102019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *l;
102119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int missbit;
1022c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	struct list_head *fa_head = NULL;
102319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf_info *li;
102419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t_key cindex;
102519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
102619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	pos = 0;
1027c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	n = t->trie;
102819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1029c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	/* If we point to NULL, stop. Either the tree is empty and we should
1030c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * just put a new leaf in if, or we have reached an empty child slot,
103119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * and we should just put our new leaf in that.
1032c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * If we point to a T_TNODE, check if it matches our key. Note that
1033c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * a T_TNODE might be skipping any number of bits - its 'pos' need
103419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * not be the parent's 'pos'+'bits'!
103519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
1036c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * If it does match the current key, get pos/bits from it, extract
103719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * the index from our key, push the T_TNODE and walk the tree.
103819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
103919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * If it doesn't, we have to replace it with a new T_TNODE.
104019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
1041c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * If we point to a T_LEAF, it might or might not have the same key
1042c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * as we do. If it does, just change the value, update the T_LEAF's
1043c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * value, and return it.
104419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * If it doesn't, we need to replace it with a T_TNODE.
104519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
104619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
104719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	while (n != NULL &&  NODE_TYPE(n) == T_TNODE) {
104819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn = (struct tnode *) n;
104991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1050c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		check_tnode(tn);
105191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1052c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
105319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			tp = tn;
105491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			pos = tn->pos + tn->bits;
1055a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			n = tnode_get_child(tn,
1056a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger					    tkey_extract_bits(key,
1057a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger							      tn->pos,
1058a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger							      tn->bits));
105919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
10600680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger			BUG_ON(n && node_parent(n) != tn);
106191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else
106219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
106319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
106419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
106519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/*
106619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * n  ----> NULL, LEAF or TNODE
106719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
1068c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * tp is n's (parent) ----> NULL or TNODE
106919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
107019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
107191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	BUG_ON(tp && IS_LEAF(tp));
107219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
107319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Case 1: n is a leaf. Compare prefixes */
107419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1075c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) {
1076c95aaf9af5a1f6dee56d1f2ab4915cd722d608daStephen Hemminger		l = (struct leaf *) n;
107719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		li = leaf_info_new(plen);
107891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1079fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger		if (!li)
1080fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger			return NULL;
108119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
108219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fa_head = &li->falh;
108319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		insert_leaf_info(&l->list, li);
108419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto done;
108519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
108619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l = leaf_new();
108719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1088fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger	if (!l)
1089fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger		return NULL;
109019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
109119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l->key = key;
109219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	li = leaf_info_new(plen);
109319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1094c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!li) {
1095387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger		free_leaf(l);
1096fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger		return NULL;
1097f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson	}
109819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
109919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa_head = &li->falh;
110019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	insert_leaf_info(&l->list, li);
110119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
110219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (t->trie && n == NULL) {
110391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* Case 2: n is NULL, and will just insert a new leaf */
110419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
11050680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger		node_set_parent((struct node *)l, tp);
110619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
110791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		cindex = tkey_extract_bits(key, tp->pos, tp->bits);
110891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, (struct tnode *)tp, cindex, (struct node *)l);
110991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	} else {
111091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* Case 3: n is a LEAF or a TNODE and the key doesn't match. */
1111c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		/*
1112c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		 *  Add a new tnode here
111319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 *  first tnode need some special handling
111419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 */
111519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
111619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (tp)
111791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			pos = tp->pos+tp->bits;
111819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		else
111991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			pos = 0;
112091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1121c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (n) {
112219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			newpos = tkey_mismatch(key, pos, n->key);
112319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			tn = tnode_new(n->key, newpos, 1);
112491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else {
112519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			newpos = 0;
1126c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger			tn = tnode_new(key, newpos, 1); /* First tnode */
112719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
112819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1129c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (!tn) {
1130f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson			free_leaf_info(li);
1131387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger			free_leaf(l);
1132fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger			return NULL;
113391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
113491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
11350680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger		node_set_parent((struct node *)tn, tp);
113619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
113791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		missbit = tkey_extract_bits(key, newpos, 1);
113819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		put_child(t, tn, missbit, (struct node *)l);
113919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		put_child(t, tn, 1-missbit, n);
114019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1141c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (tp) {
114219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			cindex = tkey_extract_bits(key, tp->pos, tp->bits);
1143a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			put_child(t, (struct tnode *)tp, cindex,
1144a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				  (struct node *)tn);
114591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else {
1146a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			rcu_assign_pointer(t->trie, (struct node *)tn);
114719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			tp = tn;
114819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
114919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
115091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
115191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (tp && tp->pos + tp->bits > 32)
1152a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		pr_warning("fib_trie"
1153a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			   " tp=%p pos=%d, bits=%d, key=%0x plen=%d\n",
1154a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			   tp, tp->pos, tp->bits, key, plen);
115591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
115619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Rebalance the trie */
11572373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
11582373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_assign_pointer(t->trie, trie_rebalance(t, tp));
1159f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olssondone:
116019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return fa_head;
116119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
116219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1163d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson/*
1164d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson * Caller must hold RTNL.
1165d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson */
11664e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Grafstatic int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg)
116719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
116819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
116919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa, *new_fa;
1170c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	struct list_head *fa_head = NULL;
117119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_info *fi;
11724e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	int plen = cfg->fc_dst_len;
11734e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	u8 tos = cfg->fc_tos;
117419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	u32 key, mask;
117519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int err;
117619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *l;
117719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
117819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (plen > 32)
117919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -EINVAL;
118019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
11814e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	key = ntohl(cfg->fc_dst);
118219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
11832dfe55b47e3d66ded5a84caf71e0da5710edf48bPatrick McHardy	pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen);
118419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
118591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	mask = ntohl(inet_make_mask(plen));
118619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1187c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (key & ~mask)
118819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -EINVAL;
118919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
119019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	key = key & mask;
119119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
11924e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	fi = fib_create_info(cfg);
11934e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	if (IS_ERR(fi)) {
11944e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		err = PTR_ERR(fi);
119519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto err;
11964e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	}
119719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
119819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l = fib_find_node(t, key);
1199c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	fa = NULL;
120019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1201c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (l) {
120219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fa_head = get_fa_head(l, plen);
120319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fa = fib_find_alias(fa_head, tos, fi->fib_priority);
120419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
120519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
120619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Now fa, if non-NULL, points to the first fib alias
120719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * with the same keys [prefix,tos,priority], if such key already
120819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * exists or to the node before which we will insert new one.
120919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
121019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * If fa is NULL, we will need to allocate a new one and
121119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * insert to the head of f.
121219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
121319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * If f is NULL, no fib node matched the destination key
121419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * and we need to allocate a new one of those as well.
121519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
121619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1217936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov	if (fa && fa->fa_tos == tos &&
1218936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov	    fa->fa_info->fib_priority == fi->fib_priority) {
1219936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		struct fib_alias *fa_first, *fa_match;
122019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
122119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		err = -EEXIST;
12224e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		if (cfg->fc_nlflags & NLM_F_EXCL)
122319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			goto out;
122419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1225936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		/* We have 2 goals:
1226936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		 * 1. Find exact match for type, scope, fib_info to avoid
1227936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		 * duplicate routes
1228936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		 * 2. Find next 'fa' (or head), NLM_F_APPEND inserts before it
1229936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		 */
1230936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		fa_match = NULL;
1231936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		fa_first = fa;
1232936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
1233936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		list_for_each_entry_continue(fa, fa_head, fa_list) {
1234936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			if (fa->fa_tos != tos)
1235936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov				break;
1236936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			if (fa->fa_info->fib_priority != fi->fib_priority)
1237936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov				break;
1238936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			if (fa->fa_type == cfg->fc_type &&
1239936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			    fa->fa_scope == cfg->fc_scope &&
1240936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			    fa->fa_info == fi) {
1241936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov				fa_match = fa;
1242936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov				break;
1243936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			}
1244936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		}
1245936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov
12464e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		if (cfg->fc_nlflags & NLM_F_REPLACE) {
124719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			struct fib_info *fi_drop;
124819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			u8 state;
124919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1250936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			fa = fa_first;
1251936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			if (fa_match) {
1252936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov				if (fa == fa_match)
1253936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov					err = 0;
12546725033fa27c8f49e1221d2badbaaaf1ef459519Joonwoo Park				goto out;
1255936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			}
12562373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			err = -ENOBUFS;
1257e94b1766097d53e6f3ccfb36c8baa562ffeda3fcChristoph Lameter			new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
12582373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			if (new_fa == NULL)
12592373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson				goto out;
126019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
126119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			fi_drop = fa->fa_info;
12622373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			new_fa->fa_tos = fa->fa_tos;
12632373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			new_fa->fa_info = fi;
12644e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf			new_fa->fa_type = cfg->fc_type;
12654e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf			new_fa->fa_scope = cfg->fc_scope;
126619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			state = fa->fa_state;
1267936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			new_fa->fa_state = state & ~FA_S_ACCESSED;
126819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
12692373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			list_replace_rcu(&fa->fa_list, &new_fa->fa_list);
12702373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			alias_free_mem_rcu(fa);
127119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
127219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			fib_release_info(fi_drop);
127319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			if (state & FA_S_ACCESSED)
127476e6ebfb40a2455c18234dcb0f9df37533215461Denis V. Lunev				rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
1275b8f558313506b5bc435f2e031f3bec4b1725098eMilan Kocian			rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
1276b8f558313506b5bc435f2e031f3bec4b1725098eMilan Kocian				tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
127719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
127891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			goto succeeded;
127919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
128019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* Error if we find a perfect match which
128119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 * uses the same scope, type, and nexthop
128219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 * information.
128319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 */
1284936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov		if (fa_match)
1285936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			goto out;
1286a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
12874e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		if (!(cfg->fc_nlflags & NLM_F_APPEND))
1288936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov			fa = fa_first;
128919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
129019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	err = -ENOENT;
12914e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	if (!(cfg->fc_nlflags & NLM_F_CREATE))
129219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
129319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
129419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	err = -ENOBUFS;
1295e94b1766097d53e6f3ccfb36c8baa562ffeda3fcChristoph Lameter	new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
129619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (new_fa == NULL)
129719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
129819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
129919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	new_fa->fa_info = fi;
130019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	new_fa->fa_tos = tos;
13014e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	new_fa->fa_type = cfg->fc_type;
13024e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	new_fa->fa_scope = cfg->fc_scope;
130319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	new_fa->fa_state = 0;
130419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/*
130519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * Insert new entry to the list.
130619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
130719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1308c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!fa_head) {
1309fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger		fa_head = fib_insert_node(t, key, plen);
1310fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger		if (unlikely(!fa_head)) {
1311fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger			err = -ENOMEM;
1312f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson			goto out_free_new_fa;
1313fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger		}
1314f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson	}
131519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
13162373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	list_add_tail_rcu(&new_fa->fa_list,
13172373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			  (fa ? &fa->fa_list : fa_head));
131819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
131976e6ebfb40a2455c18234dcb0f9df37533215461Denis V. Lunev	rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
13204e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id,
1321b8f558313506b5bc435f2e031f3bec4b1725098eMilan Kocian		  &cfg->fc_nlinfo, 0);
132219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonsucceeded:
132319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return 0;
1324f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson
1325f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olssonout_free_new_fa:
1326f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson	kmem_cache_free(fn_alias_kmem, new_fa);
132719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonout:
132819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fib_release_info(fi);
132991b9a277fc4d207249e459a455abf804ebb5499dOlof Johanssonerr:
133019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return err;
133119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
133219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1333772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson/* should be called with rcu_read_lock */
1334a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic int check_leaf(struct trie *t, struct leaf *l,
1335a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		      t_key key,  const struct flowi *flp,
1336a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		      struct fib_result *res)
133719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
133819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf_info *li;
133919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_head *hhead = &l->list;
134019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_node *node;
1341c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
13422373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	hlist_for_each_entry_rcu(li, node, hhead, hlist) {
1343a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		int err;
1344a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		int plen = li->plen;
1345a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		__be32 mask = inet_make_mask(plen);
1346a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
1347888454c57a45511808d3fa52597b3d765df034a6Al Viro		if (l->key != (key & ntohl(mask)))
134819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
134919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1350a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		err = fib_semantic_match(&li->falh, flp, res,
1351a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger					 htonl(l->key), mask, plen);
1352a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
135319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
1354a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		if (err <= 0)
135519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			t->stats.semantic_match_passed++;
1356a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		else
1357a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			t->stats.semantic_match_miss++;
135819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
1359a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		if (err <= 0)
1360a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			return plen;
136119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
1362a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
1363a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	return -1;
136419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
136519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1366a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic int fn_trie_lookup(struct fib_table *tb, const struct flowi *flp,
1367a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			  struct fib_result *res)
136819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
136919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
137019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int plen, ret = 0;
137119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct node *n;
137219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *pn;
137319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int pos, bits;
137491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	t_key key = ntohl(flp->fl4_dst);
137519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int chopped_off;
137619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t_key cindex = 0;
137719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int current_prefix_length = KEYLENGTH;
137891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	struct tnode *cn;
137991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	t_key node_prefix, key_prefix, pref_mismatch;
138091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	int mp;
138191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
13822373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_lock();
138391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
13842373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	n = rcu_dereference(t->trie);
1385c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!n)
138619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto failed;
138719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
138819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
138919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t->stats.gets++;
139019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
139119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
139219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Just a leaf? */
139319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (IS_LEAF(n)) {
1394a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		plen = check_leaf(t, (struct leaf *)n, key, flp, res);
1395a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		if (plen < 0)
1396a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			goto failed;
1397a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		ret = 0;
1398a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		goto found;
139919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
1400a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
140119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	pn = (struct tnode *) n;
140219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	chopped_off = 0;
1403c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
140491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	while (pn) {
140519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		pos = pn->pos;
140619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		bits = pn->bits;
140719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1408c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (!chopped_off)
1409ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger			cindex = tkey_extract_bits(mask_pfx(key, current_prefix_length),
1410ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger						   pos, bits);
141119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
141219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		n = tnode_get_child(pn, cindex);
141319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
141419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (n == NULL) {
141519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
141619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			t->stats.null_node_hit++;
141719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
141819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			goto backtrace;
141919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
142019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
142191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (IS_LEAF(n)) {
1422a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			plen = check_leaf(t, (struct leaf *)n, key, flp, res);
1423a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			if (plen < 0)
142491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				goto backtrace;
1425a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
1426a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			ret = 0;
1427a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			goto found;
142891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
142991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
143091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		cn = (struct tnode *)n;
143119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
143291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/*
143391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * It's a tnode, and we can do some extra checks here if we
143491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * like, to avoid descending into a dead-end branch.
143591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * This tnode is in the parent's child array at index
143691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * key[p_pos..p_pos+p_bits] but potentially with some bits
143791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * chopped off, so in reality the index may be just a
143891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * subprefix, padded with zero at the end.
143991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * We can also take a look at any skipped bits in this
144091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * tnode - everything up to p_pos is supposed to be ok,
144191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * and the non-chopped bits of the index (se previous
144291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * paragraph) are also guaranteed ok, but the rest is
144391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * considered unknown.
144491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 *
144591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * The skipped bits are key[pos+bits..cn->pos].
144691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
144719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
144891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* If current_prefix_length < pos+bits, we are already doing
144991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * actual prefix  matching, which means everything from
145091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * pos+(bits-chopped_off) onward must be zero along some
145191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * branch of this subtree - otherwise there is *no* valid
145291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * prefix present. Here we can only check the skipped
145391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * bits. Remember, since we have already indexed into the
145491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * parent's child array, we know that the bits we chopped of
145591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * *are* zero.
145691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
145719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1458a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		/* NOTA BENE: Checking only skipped bits
1459a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   for the new node here */
146019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
146191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (current_prefix_length < pos+bits) {
146291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			if (tkey_extract_bits(cn->key, current_prefix_length,
1463a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger						cn->pos - current_prefix_length)
1464a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			    || !(cn->child[0]))
146591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				goto backtrace;
146691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
146719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
146891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/*
146991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * If chopped_off=0, the index is fully validated and we
147091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * only need to look at the skipped bits for this, the new,
147191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * tnode. What we actually want to do is to find out if
147291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * these skipped bits match our key perfectly, or if we will
147391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * have to count on finding a matching prefix further down,
147491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * because if we do, we would like to have some way of
147591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * verifying the existence of such a prefix at this point.
147691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
147719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
147891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* The only thing we can do at this point is to verify that
147991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * any such matching prefix can indeed be a prefix to our
148091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * key, and if the bits in the node we are inspecting that
148191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * do not match our key are not ZERO, this cannot be true.
148291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * Thus, find out where there is a mismatch (before cn->pos)
148391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * and verify that all the mismatching bits are zero in the
148491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * new tnode's key.
148591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
148619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1487a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		/*
1488a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * Note: We aren't very concerned about the piece of
1489a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * the key that precede pn->pos+pn->bits, since these
1490a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * have already been checked. The bits after cn->pos
1491a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * aren't checked since these are by definition
1492a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * "unknown" at this point. Thus, what we want to see
1493a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * is if we are about to enter the "prefix matching"
1494a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * state, and in that case verify that the skipped
1495a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * bits that will prevail throughout this subtree are
1496a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * zero, as they have to be if we are to find a
1497a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * matching prefix.
149891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
149991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1500ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger		node_prefix = mask_pfx(cn->key, cn->pos);
1501ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger		key_prefix = mask_pfx(key, cn->pos);
150291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		pref_mismatch = key_prefix^node_prefix;
150391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		mp = 0;
150491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1505a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		/*
1506a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * In short: If skipped bits in this node do not match
1507a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * the search key, enter the "prefix matching"
1508a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		 * state.directly.
150991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
151091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (pref_mismatch) {
151191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			while (!(pref_mismatch & (1<<(KEYLENGTH-1)))) {
151291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				mp++;
1513a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				pref_mismatch = pref_mismatch << 1;
151491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			}
151591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			key_prefix = tkey_extract_bits(cn->key, mp, cn->pos-mp);
151691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
151791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			if (key_prefix != 0)
151891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				goto backtrace;
151991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
152091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			if (current_prefix_length >= cn->pos)
152191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				current_prefix_length = mp;
1522c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		}
1523a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger
152491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		pn = (struct tnode *)n; /* Descend */
152591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		chopped_off = 0;
152691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		continue;
152791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
152819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonbacktrace:
152919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		chopped_off++;
153019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
153119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* As zero don't change the child key (cindex) */
1532a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		while ((chopped_off <= pn->bits)
1533a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		       && !(cindex & (1<<(chopped_off-1))))
153419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			chopped_off++;
153519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
153619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* Decrease current_... with bits chopped off */
153719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (current_prefix_length > pn->pos + pn->bits - chopped_off)
1538a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			current_prefix_length = pn->pos + pn->bits
1539a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				- chopped_off;
154091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
154119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/*
1542c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		 * Either we do the actual chop off according or if we have
154319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 * chopped off all bits in this tnode walk up to our parent.
154419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 */
154519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
154691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (chopped_off <= pn->bits) {
154719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			cindex &= ~(1 << (chopped_off-1));
154891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else {
15490680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger			struct tnode *parent = node_parent((struct node *) pn);
15500680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger			if (!parent)
155119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				goto failed;
155291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
155319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			/* Get Child's index */
15540680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger			cindex = tkey_extract_bits(pn->key, parent->pos, parent->bits);
15550680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger			pn = parent;
155619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			chopped_off = 0;
155719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
155819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
155919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			t->stats.backtrack++;
156019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
156119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			goto backtrace;
1562c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		}
156319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
156419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfailed:
1565c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	ret = 1;
156619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfound:
15672373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_unlock();
156819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return ret;
156919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
157019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
15719195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger/*
15729195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger * Remove the leaf and return parent.
15739195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger */
15749195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemmingerstatic void trie_leaf_remove(struct trie *t, struct leaf *l)
157519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
15769195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger	struct tnode *tp = node_parent((struct node *) l);
1577c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
15789195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger	pr_debug("entering trie_leaf_remove(%p)\n", l);
157919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1580c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (tp) {
15819195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger		t_key cindex = tkey_extract_bits(l->key, tp->pos, tp->bits);
158219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		put_child(t, (struct tnode *)tp, cindex, NULL);
15832373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		rcu_assign_pointer(t->trie, trie_rebalance(t, tp));
158491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	} else
15852373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		rcu_assign_pointer(t->trie, NULL);
158619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1587387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger	free_leaf(l);
158819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
158919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1590d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson/*
1591d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson * Caller must hold RTNL.
1592d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson */
15934e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Grafstatic int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg)
159419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
159519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
159619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	u32 key, mask;
15974e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	int plen = cfg->fc_dst_len;
15984e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	u8 tos = cfg->fc_tos;
159919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa, *fa_to_delete;
160019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct list_head *fa_head;
160119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *l;
160291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	struct leaf_info *li;
160391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1604c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (plen > 32)
160519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -EINVAL;
160619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16074e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	key = ntohl(cfg->fc_dst);
160891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	mask = ntohl(inet_make_mask(plen));
160919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1610c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (key & ~mask)
161119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -EINVAL;
161219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
161319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	key = key & mask;
161419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l = fib_find_node(t, key);
161519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1616c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!l)
161719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -ESRCH;
161819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
161919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa_head = get_fa_head(l, plen);
162019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa = fib_find_alias(fa_head, tos, 0);
162119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
162219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (!fa)
162319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -ESRCH;
162419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16250c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t);
162619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
162719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa_to_delete = NULL;
1628936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov	fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
1629936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov	list_for_each_entry_continue(fa, fa_head, fa_list) {
163019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		struct fib_info *fi = fa->fa_info;
163119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
163219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fa->fa_tos != tos)
163319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
163419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16354e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) &&
16364e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		    (cfg->fc_scope == RT_SCOPE_NOWHERE ||
16374e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		     fa->fa_scope == cfg->fc_scope) &&
16384e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		    (!cfg->fc_protocol ||
16394e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		     fi->fib_protocol == cfg->fc_protocol) &&
16404e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf		    fib_nh_match(cfg, fi) == 0) {
164119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			fa_to_delete = fa;
164219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
164319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
164419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
164519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
164691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (!fa_to_delete)
164791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		return -ESRCH;
164819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
164991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	fa = fa_to_delete;
16504e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf	rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id,
1651b8f558313506b5bc435f2e031f3bec4b1725098eMilan Kocian		  &cfg->fc_nlinfo, 0);
165291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
165391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	l = fib_find_node(t, key);
1654772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson	li = find_leaf_info(l, plen);
165519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16562373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	list_del_rcu(&fa->fa_list);
165719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
165891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (list_empty(fa_head)) {
16592373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		hlist_del_rcu(&li->hlist);
166091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		free_leaf_info(li);
16612373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	}
166219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
166391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (hlist_empty(&l->list))
16649195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger		trie_leaf_remove(t, l);
166519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
166691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (fa->fa_state & FA_S_ACCESSED)
166776e6ebfb40a2455c18234dcb0f9df37533215461Denis V. Lunev		rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
166819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16692373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	fib_release_info(fa->fa_info);
16702373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	alias_free_mem_rcu(fa);
167191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	return 0;
167219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
167319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1674ef3660ce0649fa10265455f539b72607cff53d02Stephen Hemmingerstatic int trie_flush_list(struct list_head *head)
167519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
167619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa, *fa_node;
167719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int found = 0;
167819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
167919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	list_for_each_entry_safe(fa, fa_node, head, fa_list) {
168019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		struct fib_info *fi = fa->fa_info;
168119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16822373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		if (fi && (fi->fib_flags & RTNH_F_DEAD)) {
16832373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			list_del_rcu(&fa->fa_list);
16842373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			fib_release_info(fa->fa_info);
16852373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			alias_free_mem_rcu(fa);
168619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			found++;
168719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
168819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
168919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return found;
169019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
169119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1692ef3660ce0649fa10265455f539b72607cff53d02Stephen Hemmingerstatic int trie_flush_leaf(struct leaf *l)
169319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
169419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int found = 0;
169519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_head *lih = &l->list;
169619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_node *node, *tmp;
169719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf_info *li = NULL;
169819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
169919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	hlist_for_each_entry_safe(li, node, tmp, lih, hlist) {
1700ef3660ce0649fa10265455f539b72607cff53d02Stephen Hemminger		found += trie_flush_list(&li->falh);
170119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
170219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (list_empty(&li->falh)) {
17032373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			hlist_del_rcu(&li->hlist);
170419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			free_leaf_info(li);
170519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
170619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
170719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return found;
170819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
170919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
171082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger/*
171182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger * Scan for the next right leaf starting at node p->child[idx]
171282cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger * Since we have back pointer, no recursion necessary.
171382cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger */
171482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemmingerstatic struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c)
171519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
171682cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	do {
171782cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger		t_key idx;
1718c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
1719c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (c)
172082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			idx = tkey_extract_bits(c->key, p->pos, p->bits) + 1;
1721c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		else
172282cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			idx = 0;
17232373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
172482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger		while (idx < 1u << p->bits) {
172582cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			c = tnode_get_child_rcu(p, idx++);
17262373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			if (!c)
172791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				continue;
172891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
172982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			if (IS_LEAF(c)) {
173082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger				prefetch(p->child[idx]);
173182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger				return (struct leaf *) c;
173219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			}
173382cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
173482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			/* Rescan start scanning in new node */
173582cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			p = (struct tnode *) c;
173682cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger			idx = 0;
173719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
173882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
173982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger		/* Node empty, walk back up to parent */
174091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		c = (struct node *) p;
174182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	} while ( (p = node_parent_rcu(c)) != NULL);
174282cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
174382cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	return NULL; /* Root of trie */
174482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger}
174582cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
174682cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemmingerstatic struct leaf *trie_firstleaf(struct trie *t)
174782cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger{
174882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	struct tnode *n = (struct tnode *) rcu_dereference(t->trie);
174982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
175082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	if (!n)
175182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger		return NULL;
175282cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
175382cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	if (IS_LEAF(n))          /* trie is just a leaf */
175482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger		return (struct leaf *) n;
175582cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
175682cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	return leaf_walk_rcu(n, NULL);
175782cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger}
175882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
175982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemmingerstatic struct leaf *trie_nextleaf(struct leaf *l)
176082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger{
176182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	struct node *c = (struct node *) l;
176282cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	struct tnode *p = node_parent(c);
176382cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
176482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	if (!p)
176582cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger		return NULL;	/* trie with just one leaf */
176682cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger
176782cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	return leaf_walk_rcu(p, c);
176819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
176919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
177071d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemmingerstatic struct leaf *trie_leafindex(struct trie *t, int index)
177171d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger{
177271d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	struct leaf *l = trie_firstleaf(t);
177371d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger
1774ec28cf738d899e9d0652108e1986101771aacb2eStephen Hemminger	while (l && index-- > 0)
177571d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		l = trie_nextleaf(l);
1776ec28cf738d899e9d0652108e1986101771aacb2eStephen Hemminger
177771d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	return l;
177871d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger}
177971d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger
178071d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger
1781d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson/*
1782d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson * Caller must hold RTNL.
1783d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson */
178419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic int fn_trie_flush(struct fib_table *tb)
178519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
178619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
17879195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger	struct leaf *l, *ll = NULL;
178882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	int found = 0;
178919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
179082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger	for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) {
1791ef3660ce0649fa10265455f539b72607cff53d02Stephen Hemminger		found += trie_flush_leaf(l);
179219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
179319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (ll && hlist_empty(&ll->list))
17949195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger			trie_leaf_remove(t, ll);
179519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		ll = l;
179619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
179719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
179819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (ll && hlist_empty(&ll->list))
17999195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger		trie_leaf_remove(t, ll);
180019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
18010c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("trie_flush found=%d\n", found);
180219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return found;
180319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
180419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1805a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic void fn_trie_select_default(struct fib_table *tb,
1806a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				   const struct flowi *flp,
1807a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger				   struct fib_result *res)
180819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
180919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
181019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int order, last_idx;
181119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_info *fi = NULL;
181219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_info *last_resort;
181319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa = NULL;
181419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct list_head *fa_head;
181519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *l;
181619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
181719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	last_idx = -1;
181819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	last_resort = NULL;
181919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	order = -1;
182019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
18212373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_lock();
1822c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
182319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l = fib_find_node(t, 0);
1824c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!l)
182519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
182619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
182719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa_head = get_fa_head(l, 0);
1828c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!fa_head)
182919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
183019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1831c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (list_empty(fa_head))
183219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
183319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
18342373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	list_for_each_entry_rcu(fa, fa_head, fa_list) {
183519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		struct fib_info *next_fi = fa->fa_info;
183691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
183719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fa->fa_scope != res->scope ||
183819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		    fa->fa_type != RTN_UNICAST)
183919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
184091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
184119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (next_fi->fib_priority > res->fi->fib_priority)
184219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
184319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (!next_fi->fib_nh[0].nh_gw ||
184419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		    next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
184519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
184619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fa->fa_state |= FA_S_ACCESSED;
184791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
184819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fi == NULL) {
184919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			if (next_fi != res->fi)
185019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				break;
185119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		} else if (!fib_detect_death(fi, order, &last_resort,
1852971b893e79db0f7dccfcea15dbdebca3ca64a84dDenis V. Lunev					     &last_idx, tb->tb_default)) {
1853a2bbe6822f8928e254452765c07cb863633113b8Denis V. Lunev			fib_result_assign(res, fi);
1854971b893e79db0f7dccfcea15dbdebca3ca64a84dDenis V. Lunev			tb->tb_default = order;
185519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			goto out;
185619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
185719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fi = next_fi;
185819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		order++;
185919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
186019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (order <= 0 || fi == NULL) {
1861971b893e79db0f7dccfcea15dbdebca3ca64a84dDenis V. Lunev		tb->tb_default = -1;
186219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
186319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
186419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1865971b893e79db0f7dccfcea15dbdebca3ca64a84dDenis V. Lunev	if (!fib_detect_death(fi, order, &last_resort, &last_idx,
1866971b893e79db0f7dccfcea15dbdebca3ca64a84dDenis V. Lunev				tb->tb_default)) {
1867a2bbe6822f8928e254452765c07cb863633113b8Denis V. Lunev		fib_result_assign(res, fi);
1868971b893e79db0f7dccfcea15dbdebca3ca64a84dDenis V. Lunev		tb->tb_default = order;
186919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
187019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
1871a2bbe6822f8928e254452765c07cb863633113b8Denis V. Lunev	if (last_idx >= 0)
1872a2bbe6822f8928e254452765c07cb863633113b8Denis V. Lunev		fib_result_assign(res, last_resort);
1873971b893e79db0f7dccfcea15dbdebca3ca64a84dDenis V. Lunev	tb->tb_default = last_idx;
1874971b893e79db0f7dccfcea15dbdebca3ca64a84dDenis V. Lunevout:
18752373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_unlock();
187619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
187719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1878a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
1879a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			   struct fib_table *tb,
188019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			   struct sk_buff *skb, struct netlink_callback *cb)
188119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
188219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i, s_i;
188319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa;
188432ab5f80334fc067386c4c56c434010c01cff6b9Al Viro	__be32 xkey = htonl(key);
188519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
188671d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	s_i = cb->args[5];
188719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	i = 0;
188819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
18892373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	/* rcu_read_lock is hold by caller */
18902373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
18912373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	list_for_each_entry_rcu(fa, fah, fa_list) {
189219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (i < s_i) {
189319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			i++;
189419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
189519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
189619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
189719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid,
189819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  cb->nlh->nlmsg_seq,
189919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  RTM_NEWROUTE,
190019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  tb->tb_id,
190119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  fa->fa_type,
190219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  fa->fa_scope,
1903be403ea1856f1428b5912b42184acbba808c41d6Thomas Graf				  xkey,
190419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  plen,
190519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  fa->fa_tos,
190664347f786d13349d6a6f812f3a83c269e26c0136Stephen Hemminger				  fa->fa_info, NLM_F_MULTI) < 0) {
190771d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger			cb->args[5] = i;
190819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			return -1;
190991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
191019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		i++;
191119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
191271d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	cb->args[5] = i;
191319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return skb->len;
191419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
191519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1916a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemmingerstatic int fn_trie_dump_leaf(struct leaf *l, struct fib_table *tb,
1917a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger			struct sk_buff *skb, struct netlink_callback *cb)
191819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
1919a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	struct leaf_info *li;
1920a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	struct hlist_node *node;
1921a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	int i, s_i;
192219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
192371d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	s_i = cb->args[4];
1924a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	i = 0;
192519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1926a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	/* rcu_read_lock is hold by caller */
1927a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
1928a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		if (i < s_i) {
1929a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger			i++;
193019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
1931a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		}
193291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1933a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		if (i > s_i)
193471d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger			cb->args[5] = 0;
193519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1936a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		if (list_empty(&li->falh))
193719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
193819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1939a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		if (fn_trie_dump_fa(l->key, li->plen, &li->falh, tb, skb, cb) < 0) {
194071d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger			cb->args[4] = i;
194119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			return -1;
194219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
1943a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		i++;
194419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
1945a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger
194671d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	cb->args[4] = i;
194719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return skb->len;
194819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
194919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1950a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb,
1951a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger			struct netlink_callback *cb)
195219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
1953a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger	struct leaf *l;
195419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
1955d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	t_key key = cb->args[2];
195671d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	int count = cb->args[3];
195719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
19582373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_lock();
1959d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	/* Dump starting at last key.
1960d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	 * Note: 0.0.0.0/0 (ie default) is first key.
1961d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	 */
196271d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	if (count == 0)
1963d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger		l = trie_firstleaf(t);
1964d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	else {
196571d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		/* Normally, continue from last key, but if that is missing
196671d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		 * fallback to using slow rescan
196771d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		 */
1968d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger		l = fib_find_node(t, key);
196971d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		if (!l)
197071d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger			l = trie_leafindex(t, count);
1971d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	}
1972a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger
1973d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger	while (l) {
1974d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger		cb->args[2] = l->key;
1975a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger		if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) {
197671d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger			cb->args[3] = count;
1977a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger			rcu_read_unlock();
1978a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger			return -1;
197919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
1980d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger
198171d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		++count;
1982d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger		l = trie_nextleaf(l);
198371d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		memset(&cb->args[4], 0,
198471d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger		       sizeof(cb->args) - 4*sizeof(cb->args[0]));
198519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
198671d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger	cb->args[3] = count;
19872373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_unlock();
1988a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger
198919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return skb->len;
199019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
199119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
19927f9b80529b8a2ad8b3273b15fb444a0e34b760a9Stephen Hemmingervoid __init fib_hash_init(void)
19937f9b80529b8a2ad8b3273b15fb444a0e34b760a9Stephen Hemminger{
1994a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	fn_alias_kmem = kmem_cache_create("ip_fib_alias",
1995a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger					  sizeof(struct fib_alias),
1996bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger					  0, SLAB_PANIC, NULL);
1997bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger
1998bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger	trie_leaf_kmem = kmem_cache_create("ip_fib_trie",
1999bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger					   max(sizeof(struct leaf),
2000bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger					       sizeof(struct leaf_info)),
2001bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger					   0, SLAB_PANIC, NULL);
20027f9b80529b8a2ad8b3273b15fb444a0e34b760a9Stephen Hemminger}
200319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
20047f9b80529b8a2ad8b3273b15fb444a0e34b760a9Stephen Hemminger
20057f9b80529b8a2ad8b3273b15fb444a0e34b760a9Stephen Hemminger/* Fix more generic FIB names for init later */
20067f9b80529b8a2ad8b3273b15fb444a0e34b760a9Stephen Hemmingerstruct fib_table *fib_hash_table(u32 id)
200719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
200819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_table *tb;
200919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t;
201019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
201119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb = kmalloc(sizeof(struct fib_table) + sizeof(struct trie),
201219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		     GFP_KERNEL);
201319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (tb == NULL)
201419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return NULL;
201519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
201619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_id = id;
2017971b893e79db0f7dccfcea15dbdebca3ca64a84dDenis V. Lunev	tb->tb_default = -1;
201819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_lookup = fn_trie_lookup;
201919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_insert = fn_trie_insert;
202019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_delete = fn_trie_delete;
202119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_flush = fn_trie_flush;
202219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_select_default = fn_trie_select_default;
202319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_dump = fn_trie_dump;
202419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
202519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t = (struct trie *) tb->tb_data;
2026c28a1cf448e59019fa681741963c3acaeaeb6d27Stephen Hemminger	memset(t, 0, sizeof(*t));
202719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2028c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (id == RT_TABLE_LOCAL)
2029a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		pr_info("IPv4 FIB: Using LC-trie version %s\n", VERSION);
203019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
203119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return tb;
203219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
203319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2034cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger#ifdef CONFIG_PROC_FS
2035cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/* Depth first Trie walk iterator */
2036cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstruct fib_trie_iter {
20371c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	struct seq_net_private p;
20383d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	struct fib_table *tb;
2039cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct tnode *tnode;
2040cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	unsigned index;
2041cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	unsigned depth;
2042cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger};
204319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2044cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic struct node *fib_trie_get_next(struct fib_trie_iter *iter)
204519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2046cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct tnode *tn = iter->tnode;
2047cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	unsigned cindex = iter->index;
2048cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct tnode *p;
204919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
20506640e69731b42fd5e3d2b26201c8b34fc897a0eeEric W. Biederman	/* A single entry routing table */
20516640e69731b42fd5e3d2b26201c8b34fc897a0eeEric W. Biederman	if (!tn)
20526640e69731b42fd5e3d2b26201c8b34fc897a0eeEric W. Biederman		return NULL;
20536640e69731b42fd5e3d2b26201c8b34fc897a0eeEric W. Biederman
2054cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	pr_debug("get_next iter={node=%p index=%d depth=%d}\n",
2055cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		 iter->tnode, iter->index, iter->depth);
2056cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerrescan:
2057cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	while (cindex < (1<<tn->bits)) {
2058b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet		struct node *n = tnode_get_child_rcu(tn, cindex);
205919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2060cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		if (n) {
2061cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (IS_LEAF(n)) {
2062cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				iter->tnode = tn;
2063cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				iter->index = cindex + 1;
2064cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			} else {
2065cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				/* push down one level */
2066cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				iter->tnode = (struct tnode *) n;
2067cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				iter->index = 0;
2068cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				++iter->depth;
2069cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			}
2070cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			return n;
2071cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		}
207219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2073cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		++cindex;
2074cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
207591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2076cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	/* Current node exhausted, pop back up */
2077b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet	p = node_parent_rcu((struct node *)tn);
2078cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (p) {
2079cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1;
2080cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		tn = p;
2081cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		--iter->depth;
2082cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto rescan;
208319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
2084cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2085cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	/* got root? */
2086cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return NULL;
208719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
208819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2089cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic struct node *fib_trie_get_first(struct fib_trie_iter *iter,
2090cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				       struct trie *t)
209119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
20923d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	struct node *n;
20935ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson
2094132adf54639cf7dd9315e8df89c2faa59f6e46d9Stephen Hemminger	if (!t)
20955ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson		return NULL;
20965ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson
20975ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson	n = rcu_dereference(t->trie);
20983d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	if (!n)
20995ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson		return NULL;
210019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
21013d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	if (IS_TNODE(n)) {
21023d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		iter->tnode = (struct tnode *) n;
21033d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		iter->index = 0;
21043d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		iter->depth = 1;
21053d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	} else {
21063d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		iter->tnode = NULL;
21073d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		iter->index = 0;
21083d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		iter->depth = 0;
210991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	}
21103d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
21113d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	return n;
2112cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
211391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2114cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void trie_collect_stats(struct trie *t, struct trie_stat *s)
2115cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
2116cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct node *n;
2117cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct fib_trie_iter iter;
211891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2119cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	memset(s, 0, sizeof(*s));
212091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2121cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	rcu_read_lock();
21223d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	for (n = fib_trie_get_first(&iter, t); n; n = fib_trie_get_next(&iter)) {
2123cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		if (IS_LEAF(n)) {
2124936722922f6d2366378de606a40c14f96915474dStephen Hemminger			struct leaf *l = (struct leaf *)n;
2125936722922f6d2366378de606a40c14f96915474dStephen Hemminger			struct leaf_info *li;
2126936722922f6d2366378de606a40c14f96915474dStephen Hemminger			struct hlist_node *tmp;
2127936722922f6d2366378de606a40c14f96915474dStephen Hemminger
2128cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			s->leaves++;
2129cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			s->totdepth += iter.depth;
2130cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (iter.depth > s->maxdepth)
2131cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				s->maxdepth = iter.depth;
2132936722922f6d2366378de606a40c14f96915474dStephen Hemminger
2133936722922f6d2366378de606a40c14f96915474dStephen Hemminger			hlist_for_each_entry_rcu(li, tmp, &l->list, hlist)
2134936722922f6d2366378de606a40c14f96915474dStephen Hemminger				++s->prefixes;
2135cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		} else {
2136cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			const struct tnode *tn = (const struct tnode *) n;
2137cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			int i;
2138cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2139cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			s->tnodes++;
2140132adf54639cf7dd9315e8df89c2faa59f6e46d9Stephen Hemminger			if (tn->bits < MAX_STAT_DEPTH)
214106ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson				s->nodesizes[tn->bits]++;
214206ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson
2143cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			for (i = 0; i < (1<<tn->bits); i++)
2144cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				if (!tn->child[i])
2145cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					s->nullpointers++;
214619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
214719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
21482373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_unlock();
214919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
215019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2151cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/*
2152cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger *	This outputs /proc/net/fib_triestats
2153cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger */
2154cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
215519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2156cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	unsigned i, max, pointers, bytes, avdepth;
2157c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
2158cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (stat->leaves)
2159cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		avdepth = stat->totdepth*100 / stat->leaves;
2160cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	else
2161cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		avdepth = 0;
216291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2163a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "\tAver depth:     %u.%02d\n",
2164a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   avdepth / 100, avdepth % 100);
2165cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq, "\tMax depth:      %u\n", stat->maxdepth);
216691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2167cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq, "\tLeaves:         %u\n", stat->leaves);
2168cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	bytes = sizeof(struct leaf) * stat->leaves;
2169936722922f6d2366378de606a40c14f96915474dStephen Hemminger
2170936722922f6d2366378de606a40c14f96915474dStephen Hemminger	seq_printf(seq, "\tPrefixes:       %u\n", stat->prefixes);
2171936722922f6d2366378de606a40c14f96915474dStephen Hemminger	bytes += sizeof(struct leaf_info) * stat->prefixes;
2172936722922f6d2366378de606a40c14f96915474dStephen Hemminger
2173187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger	seq_printf(seq, "\tInternal nodes: %u\n\t", stat->tnodes);
2174cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	bytes += sizeof(struct tnode) * stat->tnodes;
217519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
217606ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson	max = MAX_STAT_DEPTH;
217706ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson	while (max > 0 && stat->nodesizes[max-1] == 0)
2178cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		max--;
217919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2180cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	pointers = 0;
2181cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	for (i = 1; i <= max; i++)
2182cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		if (stat->nodesizes[i] != 0) {
2183187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger			seq_printf(seq, "  %u: %u",  i, stat->nodesizes[i]);
2184cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			pointers += (1<<i) * stat->nodesizes[i];
2185cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		}
2186cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_putc(seq, '\n');
2187187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger	seq_printf(seq, "\tPointers: %u\n", pointers);
21882373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
2189cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	bytes += sizeof(struct node *) * pointers;
2190187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger	seq_printf(seq, "Null ptrs: %u\n", stat->nullpointers);
2191187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger	seq_printf(seq, "Total size: %u  kB\n", (bytes + 1023) / 1024);
219266a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger}
21932373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
2194cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger#ifdef CONFIG_IP_FIB_TRIE_STATS
219566a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemmingerstatic void trie_show_usage(struct seq_file *seq,
219666a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger			    const struct trie_use_stats *stats)
219766a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger{
219866a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger	seq_printf(seq, "\nCounters:\n---------\n");
2199a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "gets = %u\n", stats->gets);
2200a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "backtracks = %u\n", stats->backtrack);
2201a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "semantic match passed = %u\n",
2202a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   stats->semantic_match_passed);
2203a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "semantic match miss = %u\n",
2204a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   stats->semantic_match_miss);
2205a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "null node hit= %u\n", stats->null_node_hit);
2206a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger	seq_printf(seq, "skipped node resize = %u\n\n",
2207a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   stats->resize_node_skipped);
2208cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
220966a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger#endif /*  CONFIG_IP_FIB_TRIE_STATS */
221066a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger
22113d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemmingerstatic void fib_table_print(struct seq_file *seq, struct fib_table *tb)
2212d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger{
22133d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	if (tb->tb_id == RT_TABLE_LOCAL)
22143d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		seq_puts(seq, "Local:\n");
22153d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	else if (tb->tb_id == RT_TABLE_MAIN)
22163d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		seq_puts(seq, "Main:\n");
22173d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	else
22183d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		seq_printf(seq, "Id %d:\n", tb->tb_id);
2219d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger}
222019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
22213d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
2222cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_triestat_seq_show(struct seq_file *seq, void *v)
2223cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
22241c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	struct net *net = (struct net *)seq->private;
22253d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	unsigned int h;
2226877a9bff3889512d7326d6bf0ba6ed3ddda6d772Eric W. Biederman
2227d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger	seq_printf(seq,
2228a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   "Basic info: size of leaf:"
2229a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger		   " %Zd bytes, size of tnode: %Zd bytes.\n",
2230d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger		   sizeof(struct leaf), sizeof(struct tnode));
2231d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger
22323d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
22333d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
22343d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct hlist_node *node;
22353d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct fib_table *tb;
22363d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
22373d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
22383d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			struct trie *t = (struct trie *) tb->tb_data;
22393d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			struct trie_stat stat;
2240877a9bff3889512d7326d6bf0ba6ed3ddda6d772Eric W. Biederman
22413d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			if (!t)
22423d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger				continue;
22433d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
22443d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			fib_table_print(seq, tb);
22453d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
22463d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			trie_collect_stats(t, &stat);
22473d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			trie_show_stats(seq, &stat);
22483d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger#ifdef CONFIG_IP_FIB_TRIE_STATS
22493d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			trie_show_usage(seq, &t->stats);
22503d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger#endif
22513d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		}
22523d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	}
225319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2254cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return 0;
225519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
225619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2257cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_triestat_seq_open(struct inode *inode, struct file *file)
225819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
22591c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	int err;
22601c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	struct net *net;
22611c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev
22621c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	net = get_proc_net(inode);
22631c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	if (net == NULL)
22641c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev		return -ENXIO;
22651c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	err = single_open(file, fib_triestat_seq_show, net);
22661c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	if (err < 0) {
22671c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev		put_net(net);
22681c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev		return err;
22691c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	}
22701c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	return 0;
22711c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev}
22721c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev
22731c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunevstatic int fib_triestat_seq_release(struct inode *ino, struct file *f)
22741c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev{
22751c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	struct seq_file *seq = f->private_data;
22761c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	put_net(seq->private);
22771c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	return single_release(ino, f);
227819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
227919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
22809a32144e9d7b4e21341174b1a83b82a82353be86Arjan van de Venstatic const struct file_operations fib_triestat_fops = {
2281cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.owner	= THIS_MODULE,
2282cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.open	= fib_triestat_seq_open,
2283cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.read	= seq_read,
2284cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.llseek	= seq_lseek,
22851c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	.release = fib_triestat_seq_release,
2286cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger};
2287cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
22881218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideakistatic struct node *fib_trie_get_idx(struct seq_file *seq, loff_t pos)
228919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
22901218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki	struct fib_trie_iter *iter = seq->private;
22911218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki	struct net *net = seq_file_net(seq);
2292cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	loff_t idx = 0;
22933d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	unsigned int h;
2294cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
22953d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
22963d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
22973d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct hlist_node *node;
22983d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct fib_table *tb;
2299cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
23003d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
23013d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			struct node *n;
23023d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
23033d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			for (n = fib_trie_get_first(iter,
23043d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger						    (struct trie *) tb->tb_data);
23053d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			     n; n = fib_trie_get_next(iter))
23063d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger				if (pos == idx++) {
23073d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger					iter->tb = tb;
23083d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger					return n;
23093d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger				}
23103d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		}
2311cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
23123d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
231319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return NULL;
231419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
231519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2316cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
2317c95aaf9af5a1f6dee56d1f2ab4915cd722d608daStephen Hemminger	__acquires(RCU)
231819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2319cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	rcu_read_lock();
23201218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki	return fib_trie_get_idx(seq, *pos);
232119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
232219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2323cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
232419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2325cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct fib_trie_iter *iter = seq->private;
23261218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki	struct net *net = seq_file_net(seq);
23273d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	struct fib_table *tb = iter->tb;
23283d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	struct hlist_node *tb_node;
23293d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	unsigned int h;
23303d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	struct node *n;
2331cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
233219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	++*pos;
23333d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	/* next node in same table */
23343d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	n = fib_trie_get_next(iter);
23353d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	if (n)
23363d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		return n;
233719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
23383d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	/* walk rest of this hash chain */
23393d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	h = tb->tb_id & (FIB_TABLE_HASHSZ - 1);
23403d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	while ( (tb_node = rcu_dereference(tb->tb_hlist.next)) ) {
23413d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		tb = hlist_entry(tb_node, struct fib_table, tb_hlist);
23423d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
23433d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		if (n)
23443d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			goto found;
23453d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	}
234619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
23473d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	/* new hash chain */
23483d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	while (++h < FIB_TABLE_HASHSZ) {
23493d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
23503d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		hlist_for_each_entry_rcu(tb, tb_node, head, tb_hlist) {
23513d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
23523d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger			if (n)
23533d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger				goto found;
23543d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		}
23553d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	}
2356cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return NULL;
23573d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger
23583d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemmingerfound:
23593d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	iter->tb = tb;
23603d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	return n;
2361cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
236219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2363cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void fib_trie_seq_stop(struct seq_file *seq, void *v)
2364c95aaf9af5a1f6dee56d1f2ab4915cd722d608daStephen Hemminger	__releases(RCU)
236519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2366cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	rcu_read_unlock();
2367cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
236891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2369cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void seq_indent(struct seq_file *seq, int n)
2370cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
2371cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	while (n-- > 0) seq_puts(seq, "   ");
2372cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
237319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
237428d36e3702fcbed73c38e877bcf2a8f8946b7f3dEric Dumazetstatic inline const char *rtn_scope(char *buf, size_t len, enum rt_scope_t s)
2375cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
2376132adf54639cf7dd9315e8df89c2faa59f6e46d9Stephen Hemminger	switch (s) {
2377cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_UNIVERSE: return "universe";
2378cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_SITE:	return "site";
2379cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_LINK:	return "link";
2380cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_HOST:	return "host";
2381cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_NOWHERE:	return "nowhere";
2382cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	default:
238328d36e3702fcbed73c38e877bcf2a8f8946b7f3dEric Dumazet		snprintf(buf, len, "scope=%d", s);
2384cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return buf;
2385cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
2386cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
238719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2388cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic const char *rtn_type_names[__RTN_MAX] = {
2389cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_UNSPEC] = "UNSPEC",
2390cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_UNICAST] = "UNICAST",
2391cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_LOCAL] = "LOCAL",
2392cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_BROADCAST] = "BROADCAST",
2393cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_ANYCAST] = "ANYCAST",
2394cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_MULTICAST] = "MULTICAST",
2395cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_BLACKHOLE] = "BLACKHOLE",
2396cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_UNREACHABLE] = "UNREACHABLE",
2397cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_PROHIBIT] = "PROHIBIT",
2398cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_THROW] = "THROW",
2399cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_NAT] = "NAT",
2400cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_XRESOLVE] = "XRESOLVE",
2401cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger};
240219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
240328d36e3702fcbed73c38e877bcf2a8f8946b7f3dEric Dumazetstatic inline const char *rtn_type(char *buf, size_t len, unsigned t)
2404cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
2405cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (t < __RTN_MAX && rtn_type_names[t])
2406cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return rtn_type_names[t];
240728d36e3702fcbed73c38e877bcf2a8f8946b7f3dEric Dumazet	snprintf(buf, len, "type %u", t);
2408cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return buf;
240919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
241019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2411cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/* Pretty print the trie */
2412cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_trie_seq_show(struct seq_file *seq, void *v)
241319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2414cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	const struct fib_trie_iter *iter = seq->private;
2415cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct node *n = v;
2416c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
24173d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger	if (!node_parent_rcu(n))
24183d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger		fib_table_print(seq, iter->tb);
2419095b8501e4168ae5a879fcb9420ac48cbd43f95aRobert Olsson
2420cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (IS_TNODE(n)) {
2421cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		struct tnode *tn = (struct tnode *) n;
2422ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger		__be32 prf = htonl(mask_pfx(tn->key, tn->pos));
242391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
24241d25cd6cc2528e4af12ab18e84fe95ed78f3f21aRobert Olsson		seq_indent(seq, iter->depth-1);
2425a7d632b6b4ad1c92746ed409e41f9dc571ec04e2YOSHIFUJI Hideaki		seq_printf(seq, "  +-- " NIPQUAD_FMT "/%d %d %d %d\n",
2426e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki			   NIPQUAD(prf), tn->pos, tn->bits, tn->full_children,
24271d25cd6cc2528e4af12ab18e84fe95ed78f3f21aRobert Olsson			   tn->empty_children);
2428e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki
2429cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	} else {
2430cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		struct leaf *l = (struct leaf *) n;
24311328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger		struct leaf_info *li;
24321328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger		struct hlist_node *node;
243332ab5f80334fc067386c4c56c434010c01cff6b9Al Viro		__be32 val = htonl(l->key);
2434cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2435cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		seq_indent(seq, iter->depth);
2436a7d632b6b4ad1c92746ed409e41f9dc571ec04e2YOSHIFUJI Hideaki		seq_printf(seq, "  |-- " NIPQUAD_FMT "\n", NIPQUAD(val));
24371328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger
24381328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger		hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
24391328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger			struct fib_alias *fa;
24401328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger
24411328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger			list_for_each_entry_rcu(fa, &li->falh, fa_list) {
24421328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger				char buf1[32], buf2[32];
24431328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger
24441328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger				seq_indent(seq, iter->depth+1);
24451328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger				seq_printf(seq, "  /%d %s %s", li->plen,
24461328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger					   rtn_scope(buf1, sizeof(buf1),
24471328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger						     fa->fa_scope),
24481328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger					   rtn_type(buf2, sizeof(buf2),
24491328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger						    fa->fa_type));
24501328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger				if (fa->fa_tos)
2451b9c4d82a853713d49ac53b507964d7cf30ee408dDenis V. Lunev					seq_printf(seq, " tos=%d", fa->fa_tos);
24521328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger				seq_putc(seq, '\n');
2453cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			}
2454cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		}
245519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
2456cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
245719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return 0;
245819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
245919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2460f690808e17925fc45217eb22e8670902ecee5c1bStephen Hemmingerstatic const struct seq_operations fib_trie_seq_ops = {
2461cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.start  = fib_trie_seq_start,
2462cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.next   = fib_trie_seq_next,
2463cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.stop   = fib_trie_seq_stop,
2464cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.show   = fib_trie_seq_show,
246519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
246619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2467cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_trie_seq_open(struct inode *inode, struct file *file)
246819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
24691c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	return seq_open_net(inode, file, &fib_trie_seq_ops,
24701c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev			    sizeof(struct fib_trie_iter));
247119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
247219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
24739a32144e9d7b4e21341174b1a83b82a82353be86Arjan van de Venstatic const struct file_operations fib_trie_fops = {
2474cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.owner  = THIS_MODULE,
2475cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.open   = fib_trie_seq_open,
2476cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.read   = seq_read,
2477cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.llseek = seq_lseek,
24781c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	.release = seq_release_net,
247919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
248019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
24818315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstruct fib_route_iter {
24828315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct seq_net_private p;
24838315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct trie *main_trie;
24848315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	loff_t	pos;
24858315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	t_key	key;
24868315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger};
24878315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
24888315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstatic struct leaf *fib_route_get_idx(struct fib_route_iter *iter, loff_t pos)
24898315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger{
24908315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct leaf *l = NULL;
24918315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct trie *t = iter->main_trie;
24928315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
24938315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	/* use cache location of last found key */
24948315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	if (iter->pos > 0 && pos >= iter->pos && (l = fib_find_node(t, iter->key)))
24958315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		pos -= iter->pos;
24968315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	else {
24978315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->pos = 0;
24988315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		l = trie_firstleaf(t);
24998315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	}
25008315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
25018315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	while (l && pos-- > 0) {
25028315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->pos++;
25038315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		l = trie_nextleaf(l);
25048315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	}
25058315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
25068315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	if (l)
25078315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->key = pos;	/* remember it */
25088315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	else
25098315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->pos = 0;		/* forget it */
25108315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
25118315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	return l;
25128315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger}
25138315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
25148315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstatic void *fib_route_seq_start(struct seq_file *seq, loff_t *pos)
25158315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	__acquires(RCU)
25168315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger{
25178315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct fib_route_iter *iter = seq->private;
25188315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct fib_table *tb;
25198315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
25208315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	rcu_read_lock();
25211218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki	tb = fib_get_table(seq_file_net(seq), RT_TABLE_MAIN);
25228315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	if (!tb)
25238315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		return NULL;
25248315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
25258315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	iter->main_trie = (struct trie *) tb->tb_data;
25268315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	if (*pos == 0)
25278315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		return SEQ_START_TOKEN;
25288315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	else
25298315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		return fib_route_get_idx(iter, *pos - 1);
25308315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger}
25318315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
25328315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstatic void *fib_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
25338315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger{
25348315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct fib_route_iter *iter = seq->private;
25358315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	struct leaf *l = v;
25368315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
25378315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	++*pos;
25388315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	if (v == SEQ_START_TOKEN) {
25398315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->pos = 0;
25408315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		l = trie_firstleaf(iter->main_trie);
25418315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	} else {
25428315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->pos++;
25438315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		l = trie_nextleaf(l);
25448315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	}
25458315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
25468315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	if (l)
25478315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->key = l->key;
25488315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	else
25498315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger		iter->pos = 0;
25508315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	return l;
25518315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger}
25528315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
25538315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstatic void fib_route_seq_stop(struct seq_file *seq, void *v)
25548315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	__releases(RCU)
25558315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger{
25568315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	rcu_read_unlock();
25578315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger}
25588315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger
255932ab5f80334fc067386c4c56c434010c01cff6b9Al Virostatic unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
256019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2561cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	static unsigned type2flags[RTN_MAX + 1] = {
2562cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		[7] = RTF_REJECT, [8] = RTF_REJECT,
2563cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	};
2564cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	unsigned flags = type2flags[type];
256519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2566cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (fi && fi->fib_nh->nh_gw)
2567cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		flags |= RTF_GATEWAY;
256832ab5f80334fc067386c4c56c434010c01cff6b9Al Viro	if (mask == htonl(0xFFFFFFFF))
2569cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		flags |= RTF_HOST;
2570cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	flags |= RTF_UP;
2571cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return flags;
257219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
257319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2574cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/*
2575cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger *	This outputs /proc/net/route.
2576cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger *	The format of the file is not supposed to be changed
2577cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger * 	and needs to be same as fib_hash output to avoid breaking
2578cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger *	legacy utilities
2579cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger */
2580cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_route_seq_show(struct seq_file *seq, void *v)
258119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2582cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct leaf *l = v;
25831328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger	struct leaf_info *li;
25841328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger	struct hlist_node *node;
258519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2586cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (v == SEQ_START_TOKEN) {
2587cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
2588cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			   "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
2589cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			   "\tWindow\tIRTT");
2590cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return 0;
2591cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
259219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
25931328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger	hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
2594cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		struct fib_alias *fa;
259532ab5f80334fc067386c4c56c434010c01cff6b9Al Viro		__be32 mask, prefix;
259691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2597cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		mask = inet_make_mask(li->plen);
2598cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		prefix = htonl(l->key);
259919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2600cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		list_for_each_entry_rcu(fa, &li->falh, fa_list) {
26011371e37da299d4df6267ad0ddf010435782c28e9Herbert Xu			const struct fib_info *fi = fa->fa_info;
2602cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
26035e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov			int len;
260419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2605cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (fa->fa_type == RTN_BROADCAST
2606cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			    || fa->fa_type == RTN_MULTICAST)
2607cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				continue;
260819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2609cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (fi)
26105e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov				seq_printf(seq,
26115e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov					 "%s\t%08X\t%08X\t%04X\t%d\t%u\t"
26125e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov					 "%d\t%08X\t%d\t%u\t%u%n",
2613cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 fi->fib_dev ? fi->fib_dev->name : "*",
2614cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 prefix,
2615cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 fi->fib_nh->nh_gw, flags, 0, 0,
2616cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 fi->fib_priority,
2617cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 mask,
2618a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger					 (fi->fib_advmss ?
2619a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger					  fi->fib_advmss + 40 : 0),
2620cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 fi->fib_window,
26215e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov					 fi->fib_rtt >> 3, &len);
2622cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			else
26235e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov				seq_printf(seq,
26245e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov					 "*\t%08X\t%08X\t%04X\t%d\t%u\t"
26255e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov					 "%d\t%08X\t%d\t%u\t%u%n",
2626cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 prefix, 0, flags, 0, 0, 0,
26275e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov					 mask, 0, 0, 0, &len);
262819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
26295e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov			seq_printf(seq, "%*s\n", 127 - len, "");
2630cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		}
263119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
263219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
263319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return 0;
263419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
263519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2636f690808e17925fc45217eb22e8670902ecee5c1bStephen Hemmingerstatic const struct seq_operations fib_route_seq_ops = {
26378315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	.start  = fib_route_seq_start,
26388315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	.next   = fib_route_seq_next,
26398315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger	.stop   = fib_route_seq_stop,
2640cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.show   = fib_route_seq_show,
264119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
264219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2643cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_route_seq_open(struct inode *inode, struct file *file)
264419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
26451c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	return seq_open_net(inode, file, &fib_route_seq_ops,
26468315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger			    sizeof(struct fib_route_iter));
264719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
264819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
26499a32144e9d7b4e21341174b1a83b82a82353be86Arjan van de Venstatic const struct file_operations fib_route_fops = {
2650cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.owner  = THIS_MODULE,
2651cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.open   = fib_route_seq_open,
2652cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.read   = seq_read,
2653cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.llseek = seq_lseek,
26541c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev	.release = seq_release_net,
265519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
265619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
265761a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunevint __net_init fib_proc_init(struct net *net)
265819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
265961a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	if (!proc_net_fops_create(net, "fib_trie", S_IRUGO, &fib_trie_fops))
2660cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto out1;
2661cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
266261a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	if (!proc_net_fops_create(net, "fib_triestat", S_IRUGO,
266361a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev				  &fib_triestat_fops))
2664cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto out2;
2665cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
266661a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	if (!proc_net_fops_create(net, "route", S_IRUGO, &fib_route_fops))
2667cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto out3;
2668cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
266919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return 0;
2670cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2671cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerout3:
267261a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	proc_net_remove(net, "fib_triestat");
2673cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerout2:
267461a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	proc_net_remove(net, "fib_trie");
2675cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerout1:
2676cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return -ENOMEM;
267719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
267819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
267961a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunevvoid __net_exit fib_proc_exit(struct net *net)
268019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
268161a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	proc_net_remove(net, "fib_trie");
268261a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	proc_net_remove(net, "fib_triestat");
268361a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunev	proc_net_remove(net, "route");
268419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
268519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
268619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif /* CONFIG_PROC_FS */
2687