fib_trie.c revision 1d25cd6cc2528e4af12ab18e84fe95ed78f3f21a
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 *
1019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *   Jens Laas <jens.laas@data.slu.se> Swedish University of
1119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *     Agricultural Sciences.
1219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
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:
1619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
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 * Version:	$Id: fib_trie.c,v 1.3 2005/06/08 14:20:01 robert Exp $
2619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
2719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
2819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Code from fib_hash has been reused which includes the following header:
2919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
3019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
3119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * INET		An implementation of the TCP/IP protocol suite for the LINUX
3219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		operating system.  INET is implemented using the  BSD Socket
3319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		interface as the means of communication with the user level.
3419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
3519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		IPv4 FIB: lookup engine and maintenance routines.
3619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
3719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
3819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
3919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *
4019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		This program is free software; you can redistribute it and/or
4119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		modify it under the terms of the GNU General Public License
4219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		as published by the Free Software Foundation; either version
4319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson *		2 of the License, or (at your option) any later version.
4419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */
4519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
46cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger#define VERSION "0.403"
4719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
4819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/config.h>
4919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <asm/uaccess.h>
5019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <asm/system.h>
5119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <asm/bitops.h>
5219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/types.h>
5319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/kernel.h>
5419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/sched.h>
5519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/mm.h>
5619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/string.h>
5719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/socket.h>
5819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/sockios.h>
5919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/errno.h>
6019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/in.h>
6119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/inet.h>
6219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/netdevice.h>
6319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/if_arp.h>
6419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/proc_fs.h>
652373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson#include <linux/rcupdate.h>
6619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/skbuff.h>
6719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/netlink.h>
6819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/init.h>
6919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/list.h>
7019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/ip.h>
7119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/protocol.h>
7219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/route.h>
7319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/tcp.h>
7419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/sock.h>
7519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/ip_fib.h>
7619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include "fib_lookup.h"
7719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
7819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#undef CONFIG_IP_FIB_TRIE_STATS
7919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define MAX_CHILDS 16384
8019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define KEYLENGTH (8*sizeof(t_key))
8219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define MASK_PFX(k, l) (((l)==0)?0:(k >> (KEYLENGTH-l)) << (KEYLENGTH-l))
8319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define TKEY_GET_MASK(offset, bits) (((bits)==0)?0:((t_key)(-1) << (KEYLENGTH - bits) >> offset))
8419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssontypedef unsigned int t_key;
8619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define T_TNODE 0
8819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define T_LEAF  1
8919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define NODE_TYPE_MASK	0x1UL
9091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson#define NODE_PARENT(node) \
912373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	((struct tnode *)rcu_dereference(((node)->parent & ~NODE_TYPE_MASK)))
922373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
932373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson#define NODE_TYPE(node) ((node)->parent & NODE_TYPE_MASK)
942373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
952373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson#define NODE_SET_PARENT(node, ptr)		\
962373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_assign_pointer((node)->parent,	\
972373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			   ((unsigned long)(ptr)) | NODE_TYPE(node))
9891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
9991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson#define IS_TNODE(n) (!(n->parent & T_LEAF))
10091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson#define IS_LEAF(n) (n->parent & T_LEAF)
10119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
10219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct node {
10391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	t_key key;
10491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	unsigned long parent;
10519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
10619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
10719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct leaf {
10891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	t_key key;
10991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	unsigned long parent;
11019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_head list;
1112373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct rcu_head rcu;
11219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
11319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
11419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct leaf_info {
11519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_node hlist;
1162373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct rcu_head rcu;
11719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int plen;
11819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct list_head falh;
11919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
12019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
12119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct tnode {
12291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	t_key key;
12391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	unsigned long parent;
12491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	unsigned short pos:5;		/* 2log(KEYLENGTH) bits needed */
12591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	unsigned short bits:5;		/* 2log(KEYLENGTH) bits needed */
12691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	unsigned short full_children;	/* KEYLENGTH bits needed */
12791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	unsigned short empty_children;	/* KEYLENGTH bits needed */
1282373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct rcu_head rcu;
12991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	struct node *child[0];
13019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
13119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
13219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
13319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct trie_use_stats {
13419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int gets;
13519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int backtrack;
13619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int semantic_match_passed;
13719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int semantic_match_miss;
13819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int null_node_hit;
1392f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	unsigned int resize_node_skipped;
14019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
14119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
14219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
14319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct trie_stat {
14419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int totdepth;
14519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int maxdepth;
14619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int tnodes;
14719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int leaves;
14819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int nullpointers;
14919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int nodesizes[MAX_CHILDS];
150c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger};
15119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
15219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct trie {
15391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	struct node *trie;
15419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
15519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie_use_stats stats;
15619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
15791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	int size;
15819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	unsigned int revision;
15919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
16019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic void put_child(struct trie *t, struct tnode *tn, int i, struct node *n);
16219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull);
16319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic struct node *resize(struct trie *t, struct tnode *tn);
1642f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *inflate(struct trie *t, struct tnode *tn);
1652f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *halve(struct trie *t, struct tnode *tn);
16619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic void tnode_free(struct tnode *tn);
16719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
168ba89966c1984513f4f2cc0a6c182266be44ddd03Eric Dumazetstatic kmem_cache_t *fn_alias_kmem __read_mostly;
16919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic struct trie *trie_local = NULL, *trie_main = NULL;
17019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1712373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
1722373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson/* rcu_read_lock needs to be hold by caller from readside */
1732373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
174c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemmingerstatic inline struct node *tnode_get_child(struct tnode *tn, int i)
17519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
17691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	BUG_ON(i >= 1 << tn->bits);
17719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1782373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	return rcu_dereference(tn->child[i]);
17919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
18019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
181bb435b8d816582064ee0ddb1e2a6fbca67f34108Stephen Hemmingerstatic inline int tnode_child_length(const struct tnode *tn)
18219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
18391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	return 1 << tn->bits;
18419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
18519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
18619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline t_key tkey_extract_bits(t_key a, int offset, int bits)
18719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
18891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (offset < KEYLENGTH)
18919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return ((t_key)(a << offset)) >> (KEYLENGTH - bits);
19091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	else
19119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return 0;
19219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
19319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
19419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline int tkey_equals(t_key a, t_key b)
19519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
196c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	return a == b;
19719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
19819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
19919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline int tkey_sub_equals(t_key a, int offset, int bits, t_key b)
20019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
201c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (bits == 0 || offset >= KEYLENGTH)
202c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		return 1;
20391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	bits = bits > KEYLENGTH ? KEYLENGTH : bits;
20491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	return ((a ^ b) << offset) >> (KEYLENGTH - bits) == 0;
205c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger}
20619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
20719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline int tkey_mismatch(t_key a, int offset, t_key b)
20819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
20919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t_key diff = a ^ b;
21019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i = offset;
21119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
212c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!diff)
213c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		return 0;
214c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	while ((diff << i) >> (KEYLENGTH-1) == 0)
21519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		i++;
21619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return i;
21719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
21819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
21919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson/*
22019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  To understand this stuff, an understanding of keys and all their bits is
22119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  necessary. Every node in the trie has a key associated with it, but not
22219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  all of the bits in that key are significant.
22319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
22419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  Consider a node 'n' and its parent 'tp'.
22519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
22619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  If n is a leaf, every bit in its key is significant. Its presence is
22719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  necessitaded by path compression, since during a tree traversal (when
22819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  searching for a leaf - unless we are doing an insertion) we will completely
22919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  ignore all skipped bits we encounter. Thus we need to verify, at the end of
23019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  a potentially successful search, that we have indeed been walking the
23119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  correct key path.
23219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
23319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  Note that we can never "miss" the correct key in the tree if present by
23419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  following the wrong path. Path compression ensures that segments of the key
23519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  that are the same for all keys with a given prefix are skipped, but the
23619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  skipped part *is* identical for each node in the subtrie below the skipped
23719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  bit! trie_insert() in this implementation takes care of that - note the
23819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  call to tkey_sub_equals() in trie_insert().
23919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
24019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  if n is an internal node - a 'tnode' here, the various parts of its key
24119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  have many different meanings.
24219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
24319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  Example:
24419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  _________________________________________________________________
24519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C |
24619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  -----------------------------------------------------------------
24719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson    0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
24819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
24919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  _________________________________________________________________
25019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u |
25119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  -----------------------------------------------------------------
25219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson   16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31
25319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
25419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  tp->pos = 7
25519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  tp->bits = 3
25619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  n->pos = 15
25791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson  n->bits = 4
25819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
25919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  First, let's just ignore the bits that come before the parent tp, that is
26019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  the bits from 0 to (tp->pos-1). They are *known* but at this point we do
26119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  not use them for anything.
26219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
26319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  The bits from (tp->pos) to (tp->pos + tp->bits - 1) - "N", above - are the
26419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  index into the parent's child array. That is, they will be used to find
26519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  'n' among tp's children.
26619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
26719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  The bits from (tp->pos + tp->bits) to (n->pos - 1) - "S" - are skipped bits
26819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  for the node n.
26919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
27019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  All the bits we have seen so far are significant to the node n. The rest
27119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  of the bits are really not needed or indeed known in n->key.
27219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
27319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  The bits from (n->pos) to (n->pos + n->bits - 1) - "C" - are the index into
27419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  n's child array, and will of course be different for each child.
27519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
276c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
27719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  The rest of the bits, from (n->pos + n->bits) onward, are completely unknown
27819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  at this point.
27919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
28019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson*/
28119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2820c7770c740156c8802c23d24fc094d06967d997dStephen Hemmingerstatic inline void check_tnode(const struct tnode *tn)
28319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2840c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	WARN_ON(tn && tn->pos+tn->bits > 32);
28519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
28619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
28719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic int halve_threshold = 25;
28819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic int inflate_threshold = 50;
28919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2902373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
2912373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __alias_free_mem(struct rcu_head *head)
29219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2932373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct fib_alias *fa = container_of(head, struct fib_alias, rcu);
2942373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	kmem_cache_free(fn_alias_kmem, fa);
29519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
29619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2972373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic inline void alias_free_mem_rcu(struct fib_alias *fa)
29819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2992373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	call_rcu(&fa->rcu, __alias_free_mem);
3002373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
30191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
3022373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __leaf_free_rcu(struct rcu_head *head)
3032373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{
3042373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	kfree(container_of(head, struct leaf, rcu));
3052373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
30691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
3072373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic inline void free_leaf(struct leaf *leaf)
3082373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{
3092373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	call_rcu(&leaf->rcu, __leaf_free_rcu);
31019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
31119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
3122373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __leaf_info_free_rcu(struct rcu_head *head)
31319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
3142373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	kfree(container_of(head, struct leaf_info, rcu));
31519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
31619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
3172373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic inline void free_leaf_info(struct leaf_info *leaf)
31819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
3192373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	call_rcu(&leaf->rcu, __leaf_info_free_rcu);
32019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
32119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
322f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardystatic struct tnode *tnode_alloc(unsigned int size)
323f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy{
3242373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct page *pages;
3252373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
3262373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	if (size <= PAGE_SIZE)
3272373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		return kcalloc(size, 1, GFP_KERNEL);
3282373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
3292373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	pages = alloc_pages(GFP_KERNEL|__GFP_ZERO, get_order(size));
3302373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	if (!pages)
3312373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		return NULL;
3322373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
3332373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	return page_address(pages);
334f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy}
335f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy
3362373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __tnode_free_rcu(struct rcu_head *head)
337f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy{
3382373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct tnode *tn = container_of(head, struct tnode, rcu);
339f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy	unsigned int size = sizeof(struct tnode) +
3402373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		(1 << tn->bits) * sizeof(struct node *);
341f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy
342f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy	if (size <= PAGE_SIZE)
343f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy		kfree(tn);
344f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy	else
345f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy		free_pages((unsigned long)tn, get_order(size));
346f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy}
347f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy
3482373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic inline void tnode_free(struct tnode *tn)
3492373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{
3502373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	call_rcu(&tn->rcu, __tnode_free_rcu);
3512373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
3522373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
3532373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic struct leaf *leaf_new(void)
3542373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{
3552373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct leaf *l = kmalloc(sizeof(struct leaf),  GFP_KERNEL);
3562373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	if (l) {
3572373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		l->parent = T_LEAF;
3582373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		INIT_HLIST_HEAD(&l->list);
3592373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	}
3602373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	return l;
3612373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
3622373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
3632373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic struct leaf_info *leaf_info_new(int plen)
3642373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{
3652373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct leaf_info *li = kmalloc(sizeof(struct leaf_info),  GFP_KERNEL);
3662373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	if (li) {
3672373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		li->plen = plen;
3682373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		INIT_LIST_HEAD(&li->falh);
3692373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	}
3702373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	return li;
3712373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson}
3722373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
37319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic struct tnode* tnode_new(t_key key, int pos, int bits)
37419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
37519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int nchildren = 1<<bits;
37619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int sz = sizeof(struct tnode) + nchildren * sizeof(struct node *);
377f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy	struct tnode *tn = tnode_alloc(sz);
37819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
37991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (tn) {
38019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		memset(tn, 0, sz);
3812373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		tn->parent = T_TNODE;
38219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->pos = pos;
38319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->bits = bits;
38419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->key = key;
38519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->full_children = 0;
38619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->empty_children = 1<<bits;
38719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
388c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
3890c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("AT %p s=%u %u\n", tn, (unsigned int) sizeof(struct tnode),
3900c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		 (unsigned int) (sizeof(struct node) * 1<<bits));
39119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return tn;
39219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
39319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
39419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson/*
39519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Check whether a tnode 'n' is "full", i.e. it is an internal node
39619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * and no bits are skipped. See discussion in dyntree paper p. 6
39719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */
39819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
399bb435b8d816582064ee0ddb1e2a6fbca67f34108Stephen Hemmingerstatic inline int tnode_full(const struct tnode *tn, const struct node *n)
40019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
401c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (n == NULL || IS_LEAF(n))
40219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return 0;
40319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
40419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return ((struct tnode *) n)->pos == tn->pos + tn->bits;
40519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
40619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
407c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemmingerstatic inline void put_child(struct trie *t, struct tnode *tn, int i, struct node *n)
40819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
40919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tnode_put_child_reorg(tn, i, n, -1);
41019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
41119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
412c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger /*
41319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  * Add a child at position i overwriting the old value.
41419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  * Update the value of full_children and empty_children.
41519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson  */
41619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
417c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemmingerstatic void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull)
41819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
4192373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct node *chi = tn->child[i];
42019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int isfull;
42119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
4220c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	BUG_ON(i >= 1<<tn->bits);
4230c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
42419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
42519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* update emptyChildren */
42619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (n == NULL && chi != NULL)
42719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->empty_children++;
42819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	else if (n != NULL && chi == NULL)
42919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->empty_children--;
430c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
43119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* update fullChildren */
43291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (wasfull == -1)
43319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		wasfull = tnode_full(tn, chi);
43419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
43519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	isfull = tnode_full(tn, n);
436c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (wasfull && !isfull)
43719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->full_children--;
438c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	else if (!wasfull && isfull)
43919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn->full_children++;
44091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
441c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (n)
442c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		NODE_SET_PARENT(n, tn);
44319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
4442373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_assign_pointer(tn->child[i], n);
44519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
44619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
447c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemmingerstatic struct node *resize(struct trie *t, struct tnode *tn)
44819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
44919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i;
4502f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	int err = 0;
4512f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	struct tnode *old_tn;
45219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
45319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 	if (!tn)
45419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return NULL;
45519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
4560c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("In tnode_resize %p inflate_threshold=%d threshold=%d\n",
4570c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		 tn, inflate_threshold, halve_threshold);
45819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
45919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* No children */
46019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (tn->empty_children == tnode_child_length(tn)) {
46119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tnode_free(tn);
46219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return NULL;
46319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
46419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* One child */
46519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (tn->empty_children == tnode_child_length(tn) - 1)
46619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		for (i = 0; i < tnode_child_length(tn); i++) {
46791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			struct node *n;
46819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
46991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			n = tn->child[i];
4702373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			if (!n)
47191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				continue;
47291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
47391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			/* compress one level */
4742373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			NODE_SET_PARENT(n, NULL);
47591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			tnode_free(tn);
47691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			return n;
47719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
478c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	/*
47919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * Double as long as the resulting node has a number of
48019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * nonempty nodes that are above the threshold.
48119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
48219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
48319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/*
484c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * From "Implementing a dynamic compressed trie" by Stefan Nilsson of
485c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * the Helsinki University of Technology and Matti Tikkanen of Nokia
48619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * Telecommunications, page 6:
487c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * "A node is doubled if the ratio of non-empty children to all
48819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * children in the *doubled* node is at least 'high'."
48919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
490c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * 'high' in this instance is the variable 'inflate_threshold'. It
491c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * is expressed as a percentage, so we multiply it with
492c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * tnode_child_length() and instead of multiplying by 2 (since the
493c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * child array will be doubled by inflate()) and multiplying
494c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * the left-hand side by 100 (to handle the percentage thing) we
49519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * multiply the left-hand side by 50.
496c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
497c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * The left-hand side may look a bit weird: tnode_child_length(tn)
498c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * - tn->empty_children is of course the number of non-null children
499c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * in the current node. tn->full_children is the number of "full"
50019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * children, that is non-null tnodes with a skip value of 0.
501c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * All of those will be doubled in the resulting inflated tnode, so
50219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * we just count them one extra time here.
503c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
50419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * A clearer way to write this would be:
505c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
50619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * to_be_doubled = tn->full_children;
507c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children -
50819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *     tn->full_children;
50919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
51019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * new_child_length = tnode_child_length(tn) * 2;
51119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
512c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) /
51319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *      new_child_length;
51419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * if (new_fill_factor >= inflate_threshold)
515c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
516c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * ...and so on, tho it would mess up the while () loop.
517c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
51819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * anyway,
51919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >=
52019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *      inflate_threshold
521c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
52219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * avoid a division:
52319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * 100 * (not_to_be_doubled + 2*to_be_doubled) >=
52419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *      inflate_threshold * new_child_length
525c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
52619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * expand not_to_be_doubled and to_be_doubled, and shorten:
527c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * 100 * (tnode_child_length(tn) - tn->empty_children +
52891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	 *    tn->full_children) >= inflate_threshold * new_child_length
529c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
53019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * expand new_child_length:
531c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * 100 * (tnode_child_length(tn) - tn->empty_children +
53291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	 *    tn->full_children) >=
53319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *      inflate_threshold * tnode_child_length(tn) * 2
534c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
53519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * shorten again:
536c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * 50 * (tn->full_children + tnode_child_length(tn) -
53791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	 *    tn->empty_children) >= inflate_threshold *
53819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *    tnode_child_length(tn)
539c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 *
54019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
54119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
54219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	check_tnode(tn);
543c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
5442f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	err = 0;
54519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	while ((tn->full_children > 0 &&
54619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	       50 * (tn->full_children + tnode_child_length(tn) - tn->empty_children) >=
54719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				inflate_threshold * tnode_child_length(tn))) {
54819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
5492f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		old_tn = tn;
5502f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		tn = inflate(t, tn);
5512f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		if (IS_ERR(tn)) {
5522f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			tn = old_tn;
5532f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
5542f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			t->stats.resize_node_skipped++;
5552f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#endif
5562f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			break;
5572f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		}
55819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
55919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
56019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	check_tnode(tn);
56119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
56219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/*
56319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * Halve as long as the number of empty children in this
56419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * node is above threshold.
56519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
5662f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
5672f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	err = 0;
56819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	while (tn->bits > 1 &&
56919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	       100 * (tnode_child_length(tn) - tn->empty_children) <
5702f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	       halve_threshold * tnode_child_length(tn)) {
5712f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
5722f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		old_tn = tn;
5732f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		tn = halve(t, tn);
5742f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		if (IS_ERR(tn)) {
5752f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			tn = old_tn;
5762f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
5772f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			t->stats.resize_node_skipped++;
5782f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#endif
5792f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			break;
5802f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		}
5812f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	}
58219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
583c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
58419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Only one child remains */
58519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (tn->empty_children == tnode_child_length(tn) - 1)
58619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		for (i = 0; i < tnode_child_length(tn); i++) {
58791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			struct node *n;
58819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
58991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			n = tn->child[i];
5902373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			if (!n)
59191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				continue;
59291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
59391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			/* compress one level */
59491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
5952373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			NODE_SET_PARENT(n, NULL);
59691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			tnode_free(tn);
59791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			return n;
59819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
59919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
60019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return (struct node *) tn;
60119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
60219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
6032f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *inflate(struct trie *t, struct tnode *tn)
60419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
60519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *inode;
60619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *oldtnode = tn;
60719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int olen = tnode_child_length(tn);
60819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i;
60919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
6100c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("In inflate\n");
61119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
61219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits + 1);
61319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
6140c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	if (!tn)
6152f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		return ERR_PTR(-ENOMEM);
6162f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
6172f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	/*
618c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * Preallocate and store tnodes before the actual work so we
619c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * don't get into an inconsistent state if memory allocation
620c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * fails. In case of failure we return the oldnode and  inflate
6212f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	 * of tnode is ignored.
6222f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	 */
62391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
62491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (i = 0; i < olen; i++) {
6252f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		struct tnode *inode = (struct tnode *) tnode_get_child(oldtnode, i);
6262f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
6272f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		if (inode &&
6282f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		    IS_TNODE(inode) &&
6292f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		    inode->pos == oldtnode->pos + oldtnode->bits &&
6302f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		    inode->bits > 1) {
6312f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			struct tnode *left, *right;
6322f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			t_key m = TKEY_GET_MASK(inode->pos, 1);
633c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
6342f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			left = tnode_new(inode->key&(~m), inode->pos + 1,
6352f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson					 inode->bits - 1);
6362f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			if (!left)
6372f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				goto nomem;
63891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
6392f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			right = tnode_new(inode->key|m, inode->pos + 1,
6402f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson					  inode->bits - 1);
6412f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
6422f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson                        if (!right) {
6432f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				tnode_free(left);
6442f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				goto nomem;
6452f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson                        }
6462f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
6472f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			put_child(t, tn, 2*i, (struct node *) left);
6482f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson			put_child(t, tn, 2*i+1, (struct node *) right);
6492f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		}
6502f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	}
6512f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
65291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (i = 0; i < olen; i++) {
65319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		struct node *node = tnode_get_child(oldtnode, i);
65491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		struct tnode *left, *right;
65591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		int size, j;
656c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
65719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* An empty child */
65819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (node == NULL)
65919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
66019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
66119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* A leaf or an internal node with skipped bits */
66219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
663c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (IS_LEAF(node) || ((struct tnode *) node)->pos >
66419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		   tn->pos + tn->bits - 1) {
665c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger			if (tkey_extract_bits(node->key, oldtnode->pos + oldtnode->bits,
66619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson					     1) == 0)
66719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				put_child(t, tn, 2*i, node);
66819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			else
66919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				put_child(t, tn, 2*i+1, node);
67019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
67119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
67219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
67319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* An internal node with two children */
67419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		inode = (struct tnode *) node;
67519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
67619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (inode->bits == 1) {
67719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			put_child(t, tn, 2*i, inode->child[0]);
67819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			put_child(t, tn, 2*i+1, inode->child[1]);
67919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
68019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			tnode_free(inode);
68191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			continue;
68219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
68319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
68491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* An internal node with more than two children */
68591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
68691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* We will replace this node 'inode' with two new
68791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * ones, 'left' and 'right', each with half of the
68891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * original children. The two new nodes will have
68991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * a position one bit further down the key and this
69091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * means that the "significant" part of their keys
69191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * (see the discussion near the top of this file)
69291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * will differ by one bit, which will be "0" in
69391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * left's key and "1" in right's key. Since we are
69491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * moving the key position by one step, the bit that
69591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * we are moving away from - the bit at position
69691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * (inode->pos) - is the one that will differ between
69791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * left and right. So... we synthesize that bit in the
69891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * two  new keys.
69991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * The mask 'm' below will be a single "one" bit at
70091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * the position (inode->pos)
70191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
70219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
70391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* Use the old key, but set the new significant
70491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 *   bit to zero.
70591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
7062f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
70791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		left = (struct tnode *) tnode_get_child(tn, 2*i);
70891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, 2*i, NULL);
7092f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
71091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		BUG_ON(!left);
7112f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
71291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		right = (struct tnode *) tnode_get_child(tn, 2*i+1);
71391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, 2*i+1, NULL);
71419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
71591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		BUG_ON(!right);
71619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
71791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		size = tnode_child_length(left);
71891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		for (j = 0; j < size; j++) {
71991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			put_child(t, left, j, inode->child[j]);
72091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			put_child(t, right, j, inode->child[j + size]);
72119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
72291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, 2*i, resize(t, left));
72391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, 2*i+1, resize(t, right));
72491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
72591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		tnode_free(inode);
72619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
72719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tnode_free(oldtnode);
72819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return tn;
7292f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonnomem:
7302f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	{
7312f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		int size = tnode_child_length(tn);
7322f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		int j;
7332f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson
7340c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		for (j = 0; j < size; j++)
7352f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			if (tn->child[j])
7362f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				tnode_free((struct tnode *)tn->child[j]);
7372f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson
7382f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		tnode_free(tn);
7390c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
7402f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		return ERR_PTR(-ENOMEM);
7412f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	}
74219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
74319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
7442f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *halve(struct trie *t, struct tnode *tn)
74519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
74619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *oldtnode = tn;
74719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct node *left, *right;
74819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i;
74919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int olen = tnode_child_length(tn);
75019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
7510c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("In halve\n");
752c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
753c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits - 1);
75419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
7552f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	if (!tn)
7562f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		return ERR_PTR(-ENOMEM);
7572f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
7582f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	/*
759c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * Preallocate and store tnodes before the actual work so we
760c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * don't get into an inconsistent state if memory allocation
761c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * fails. In case of failure we return the oldnode and halve
7622f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	 * of tnode is ignored.
7632f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	 */
7642f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
76591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (i = 0; i < olen; i += 2) {
7662f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		left = tnode_get_child(oldtnode, i);
7672f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		right = tnode_get_child(oldtnode, i+1);
768c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
7692f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		/* Two nonempty children */
7700c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		if (left && right) {
7712f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			struct tnode *newn;
7720c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
7732f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			newn = tnode_new(left->key, tn->pos + tn->bits, 1);
7740c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
7750c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger			if (!newn)
7762f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				goto nomem;
7770c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
7782f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			put_child(t, tn, i/2, (struct node *)newn);
7792f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson		}
7802f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson
7812f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson	}
78219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
78391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (i = 0; i < olen; i += 2) {
78491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		struct tnode *newBinNode;
78591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
78619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		left = tnode_get_child(oldtnode, i);
78719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		right = tnode_get_child(oldtnode, i+1);
788c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
78919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* At least one of the children is empty */
79019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (left == NULL) {
79119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			if (right == NULL)    /* Both are empty */
79219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				continue;
79319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			put_child(t, tn, i/2, right);
79491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			continue;
7950c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		}
79691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
79791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (right == NULL) {
79819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			put_child(t, tn, i/2, left);
79991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			continue;
80091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
801c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
80219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* Two nonempty children */
80391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		newBinNode = (struct tnode *) tnode_get_child(tn, i/2);
80491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, i/2, NULL);
80591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, newBinNode, 0, left);
80691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, newBinNode, 1, right);
80791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, tn, i/2, resize(t, newBinNode));
80819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
80919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tnode_free(oldtnode);
81019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return tn;
8112f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonnomem:
8122f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	{
8132f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		int size = tnode_child_length(tn);
8142f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		int j;
8152f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson
8160c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		for (j = 0; j < size; j++)
8172f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson			if (tn->child[j])
8182f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson				tnode_free((struct tnode *)tn->child[j]);
8192f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson
8202f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		tnode_free(tn);
8210c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger
8222f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson		return ERR_PTR(-ENOMEM);
8232f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson	}
82419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
82519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
82691b9a277fc4d207249e459a455abf804ebb5499dOlof Johanssonstatic void trie_init(struct trie *t)
82719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
82891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (!t)
82991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		return;
83091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
83191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	t->size = 0;
8322373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_assign_pointer(t->trie, NULL);
83391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	t->revision = 0;
83419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
83591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	memset(&t->stats, 0, sizeof(struct trie_use_stats));
83619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
83719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
83819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8392373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson/* readside most use rcu_read_lock currently dump routines
8402373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson via get_fa_head and dump */
8412373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
84219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic struct leaf_info *find_leaf_info(struct hlist_head *head, int plen)
84319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
84419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_node *node;
84519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf_info *li;
84619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8472373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	hlist_for_each_entry_rcu(li, node, head, hlist)
848c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (li->plen == plen)
84919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			return li;
85091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
85119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return NULL;
85219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
85319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
85419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline struct list_head * get_fa_head(struct leaf *l, int plen)
85519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
85619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf_info *li = find_leaf_info(&l->list, plen);
857c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
85891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (!li)
85991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		return NULL;
860c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
86191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	return &li->falh;
86219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
86319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
86419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic void insert_leaf_info(struct hlist_head *head, struct leaf_info *new)
86519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
8662373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson        struct leaf_info *li = NULL, *last = NULL;
8672373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson        struct hlist_node *node;
8682373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
8692373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson        if (hlist_empty(head)) {
8702373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson                hlist_add_head_rcu(&new->hlist, head);
8712373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson        } else {
8722373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson                hlist_for_each_entry(li, node, head, hlist) {
8732373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson                        if (new->plen > li->plen)
8742373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson                                break;
8752373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
8762373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson                        last = li;
8772373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson                }
8782373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson                if (last)
8792373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson                        hlist_add_after_rcu(&last->hlist, &new->hlist);
8802373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson                else
8812373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson                        hlist_add_before_rcu(&new->hlist, &li->hlist);
8822373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson        }
88319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
88419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
8852373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson/* rcu_read_lock needs to be hold by caller from readside */
8862373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
88719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic struct leaf *
88819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfib_find_node(struct trie *t, u32 key)
88919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
89019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int pos;
89119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *tn;
89219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct node *n;
89319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
89419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	pos = 0;
8952373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	n = rcu_dereference(t->trie);
89619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
89719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	while (n != NULL &&  NODE_TYPE(n) == T_TNODE) {
89819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn = (struct tnode *) n;
89991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
90019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		check_tnode(tn);
90191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
902c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
90391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			pos = tn->pos + tn->bits;
90419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits));
90591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else
90619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
90719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
90819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Case we have found a leaf. Compare prefixes */
90919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
91091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key))
91191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		return (struct leaf *)n;
91291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
91319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return NULL;
91419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
91519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
91619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic struct node *trie_rebalance(struct trie *t, struct tnode *tn)
91719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
91819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int wasfull;
91919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t_key cindex, key;
92019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *tp = NULL;
92119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
92219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	key = tn->key;
92319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
92419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	while (tn != NULL && NODE_PARENT(tn) != NULL) {
92519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
92619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tp = NODE_PARENT(tn);
92719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		cindex = tkey_extract_bits(key, tp->pos, tp->bits);
92819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		wasfull = tnode_full(tp, tnode_get_child(tp, cindex));
92919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn = (struct tnode *) resize (t, (struct tnode *)tn);
93019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tnode_put_child_reorg((struct tnode *)tp, cindex,(struct node*)tn, wasfull);
93191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
932c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (!NODE_PARENT(tn))
93319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
93419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
93519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn = NODE_PARENT(tn);
93619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
93719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Handle last (top) tnode */
938c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (IS_TNODE(tn))
93919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn = (struct tnode*) resize(t, (struct tnode *)tn);
94019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
94119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return (struct node*) tn;
94219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
94319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
9442373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson/* only used from updater-side */
9452373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
946f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olssonstatic  struct list_head *
947f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olssonfib_insert_node(struct trie *t, int *err, u32 key, int plen)
94819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
94919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int pos, newpos;
95019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *tp = NULL, *tn = NULL;
95119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct node *n;
95219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *l;
95319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int missbit;
954c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	struct list_head *fa_head = NULL;
95519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf_info *li;
95619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t_key cindex;
95719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
95819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	pos = 0;
959c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	n = t->trie;
96019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
961c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	/* If we point to NULL, stop. Either the tree is empty and we should
962c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * just put a new leaf in if, or we have reached an empty child slot,
96319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * and we should just put our new leaf in that.
964c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * If we point to a T_TNODE, check if it matches our key. Note that
965c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * a T_TNODE might be skipping any number of bits - its 'pos' need
96619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * not be the parent's 'pos'+'bits'!
96719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
968c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * If it does match the current key, get pos/bits from it, extract
96919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * the index from our key, push the T_TNODE and walk the tree.
97019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
97119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * If it doesn't, we have to replace it with a new T_TNODE.
97219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
973c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * If we point to a T_LEAF, it might or might not have the same key
974c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * as we do. If it does, just change the value, update the T_LEAF's
975c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * value, and return it.
97619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * If it doesn't, we need to replace it with a T_TNODE.
97719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
97819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
97919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	while (n != NULL &&  NODE_TYPE(n) == T_TNODE) {
98019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		tn = (struct tnode *) n;
98191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
982c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		check_tnode(tn);
98391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
984c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
98519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			tp = tn;
98691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			pos = tn->pos + tn->bits;
98719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits));
98819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
9890c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger			BUG_ON(n && NODE_PARENT(n) != tn);
99091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else
99119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
99219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
99319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
99419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/*
99519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * n  ----> NULL, LEAF or TNODE
99619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
997c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * tp is n's (parent) ----> NULL or TNODE
99819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
99919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
100091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	BUG_ON(tp && IS_LEAF(tp));
100119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
100219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Case 1: n is a leaf. Compare prefixes */
100319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1004c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) {
100591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		struct leaf *l = (struct leaf *) n;
100691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
100719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		li = leaf_info_new(plen);
100891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1009c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (!li) {
1010f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson			*err = -ENOMEM;
1011f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson			goto err;
1012f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson		}
101319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
101419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fa_head = &li->falh;
101519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		insert_leaf_info(&l->list, li);
101619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto done;
101719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
101819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t->size++;
101919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l = leaf_new();
102019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1021c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!l) {
1022f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson		*err = -ENOMEM;
1023f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson		goto err;
1024f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson	}
102519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
102619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l->key = key;
102719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	li = leaf_info_new(plen);
102819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1029c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!li) {
1030f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson		tnode_free((struct tnode *) l);
1031f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson		*err = -ENOMEM;
1032f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson		goto err;
1033f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson	}
103419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
103519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa_head = &li->falh;
103619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	insert_leaf_info(&l->list, li);
103719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
103819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (t->trie && n == NULL) {
103991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* Case 2: n is NULL, and will just insert a new leaf */
104019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
104119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		NODE_SET_PARENT(l, tp);
104219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
104391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		cindex = tkey_extract_bits(key, tp->pos, tp->bits);
104491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		put_child(t, (struct tnode *)tp, cindex, (struct node *)l);
104591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	} else {
104691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* Case 3: n is a LEAF or a TNODE and the key doesn't match. */
1047c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		/*
1048c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		 *  Add a new tnode here
104919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 *  first tnode need some special handling
105019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 */
105119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
105219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (tp)
105391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			pos = tp->pos+tp->bits;
105419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		else
105591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			pos = 0;
105691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1057c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (n) {
105819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			newpos = tkey_mismatch(key, pos, n->key);
105919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			tn = tnode_new(n->key, newpos, 1);
106091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else {
106119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			newpos = 0;
1062c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger			tn = tnode_new(key, newpos, 1); /* First tnode */
106319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
106419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1065c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (!tn) {
1066f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson			free_leaf_info(li);
1067f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson			tnode_free((struct tnode *) l);
1068f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson			*err = -ENOMEM;
1069f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson			goto err;
107091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
107191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
107219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		NODE_SET_PARENT(tn, tp);
107319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
107491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		missbit = tkey_extract_bits(key, newpos, 1);
107519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		put_child(t, tn, missbit, (struct node *)l);
107619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		put_child(t, tn, 1-missbit, n);
107719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1078c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (tp) {
107919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			cindex = tkey_extract_bits(key, tp->pos, tp->bits);
108019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			put_child(t, (struct tnode *)tp, cindex, (struct node *)tn);
108191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else {
10822373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			rcu_assign_pointer(t->trie, (struct node *)tn); /* First tnode */
108319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			tp = tn;
108419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
108519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
108691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
108791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (tp && tp->pos + tp->bits > 32)
1088c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		printk("ERROR tp=%p pos=%d, bits=%d, key=%0x plen=%d\n",
108919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		       tp, tp->pos, tp->bits, key, plen);
109091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
109119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Rebalance the trie */
10922373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
10932373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_assign_pointer(t->trie, trie_rebalance(t, tp));
1094f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olssondone:
1095f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson	t->revision++;
109691b9a277fc4d207249e459a455abf804ebb5499dOlof Johanssonerr:
109719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return fa_head;
109819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
109919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
110019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic int
110119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
110219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	       struct nlmsghdr *nlhdr, struct netlink_skb_parms *req)
110319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
110419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
110519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa, *new_fa;
1106c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	struct list_head *fa_head = NULL;
110719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_info *fi;
110819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int plen = r->rtm_dst_len;
110919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int type = r->rtm_type;
111019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	u8 tos = r->rtm_tos;
111119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	u32 key, mask;
111219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int err;
111319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *l;
111419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
111519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (plen > 32)
111619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -EINVAL;
111719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
111819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	key = 0;
1119c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (rta->rta_dst)
112019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		memcpy(&key, rta->rta_dst, 4);
112119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
112219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	key = ntohl(key);
112319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
11240c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("Insert table=%d %08x/%d\n", tb->tb_id, key, plen);
112519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
112691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	mask = ntohl(inet_make_mask(plen));
112719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1128c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (key & ~mask)
112919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -EINVAL;
113019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
113119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	key = key & mask;
113219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
113391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	fi = fib_create_info(r, rta, nlhdr, &err);
113491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
113591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (!fi)
113619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto err;
113719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
113819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l = fib_find_node(t, key);
1139c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	fa = NULL;
114019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1141c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (l) {
114219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fa_head = get_fa_head(l, plen);
114319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fa = fib_find_alias(fa_head, tos, fi->fib_priority);
114419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
114519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
114619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Now fa, if non-NULL, points to the first fib alias
114719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * with the same keys [prefix,tos,priority], if such key already
114819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * exists or to the node before which we will insert new one.
114919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
115019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * If fa is NULL, we will need to allocate a new one and
115119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * insert to the head of f.
115219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 *
115319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * If f is NULL, no fib node matched the destination key
115419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * and we need to allocate a new one of those as well.
115519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
115619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
115791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (fa && fa->fa_info->fib_priority == fi->fib_priority) {
115819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		struct fib_alias *fa_orig;
115919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
116019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		err = -EEXIST;
116119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (nlhdr->nlmsg_flags & NLM_F_EXCL)
116219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			goto out;
116319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
116419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (nlhdr->nlmsg_flags & NLM_F_REPLACE) {
116519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			struct fib_info *fi_drop;
116619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			u8 state;
116719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
11682373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			err = -ENOBUFS;
11692373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			new_fa = kmem_cache_alloc(fn_alias_kmem, SLAB_KERNEL);
11702373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			if (new_fa == NULL)
11712373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson				goto out;
117219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
117319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			fi_drop = fa->fa_info;
11742373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			new_fa->fa_tos = fa->fa_tos;
11752373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			new_fa->fa_info = fi;
11762373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			new_fa->fa_type = type;
11772373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			new_fa->fa_scope = r->rtm_scope;
117819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			state = fa->fa_state;
11792373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			new_fa->fa_state &= ~FA_S_ACCESSED;
118019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
11812373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			list_replace_rcu(&fa->fa_list, &new_fa->fa_list);
11822373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			alias_free_mem_rcu(fa);
118319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
118419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			fib_release_info(fi_drop);
118519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			if (state & FA_S_ACCESSED)
118691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				rt_cache_flush(-1);
118719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
118891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			goto succeeded;
118919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
119019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* Error if we find a perfect match which
119119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 * uses the same scope, type, and nexthop
119219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 * information.
119319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 */
119419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fa_orig = fa;
119519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		list_for_each_entry(fa, fa_orig->fa_list.prev, fa_list) {
119619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			if (fa->fa_tos != tos)
119719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				break;
119819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			if (fa->fa_info->fib_priority != fi->fib_priority)
119919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				break;
120019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			if (fa->fa_type == type &&
120119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			    fa->fa_scope == r->rtm_scope &&
120219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			    fa->fa_info == fi) {
120319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				goto out;
120419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			}
120519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
120619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (!(nlhdr->nlmsg_flags & NLM_F_APPEND))
120719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			fa = fa_orig;
120819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
120919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	err = -ENOENT;
121091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (!(nlhdr->nlmsg_flags & NLM_F_CREATE))
121119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
121219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
121319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	err = -ENOBUFS;
121419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	new_fa = kmem_cache_alloc(fn_alias_kmem, SLAB_KERNEL);
121519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (new_fa == NULL)
121619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
121719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
121819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	new_fa->fa_info = fi;
121919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	new_fa->fa_tos = tos;
122019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	new_fa->fa_type = type;
122119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	new_fa->fa_scope = r->rtm_scope;
122219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	new_fa->fa_state = 0;
122319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/*
122419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * Insert new entry to the list.
122519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
122619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1227c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!fa_head) {
1228f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson		fa_head = fib_insert_node(t, &err, key, plen);
1229f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson		err = 0;
1230c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (err)
1231f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson			goto out_free_new_fa;
1232f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson	}
123319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
12342373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	list_add_tail_rcu(&new_fa->fa_list,
12352373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			  (fa ? &fa->fa_list : fa_head));
123619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
123719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	rt_cache_flush(-1);
123819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req);
123919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonsucceeded:
124019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return 0;
1241f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson
1242f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olssonout_free_new_fa:
1243f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson	kmem_cache_free(fn_alias_kmem, new_fa);
124419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonout:
124519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fib_release_info(fi);
124691b9a277fc4d207249e459a455abf804ebb5499dOlof Johanssonerr:
124719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return err;
124819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
124919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
12502373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
12512373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson/* should be clalled with rcu_read_lock */
12520c7770c740156c8802c23d24fc094d06967d997dStephen Hemmingerstatic inline int check_leaf(struct trie *t, struct leaf *l,
12530c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger			     t_key key, int *plen, const struct flowi *flp,
125406c7427021f1cc83703f14659d8405ca773ba1efPatrick McHardy			     struct fib_result *res)
125519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
125606c7427021f1cc83703f14659d8405ca773ba1efPatrick McHardy	int err, i;
125719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t_key mask;
125819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf_info *li;
125919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_head *hhead = &l->list;
126019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_node *node;
1261c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
12622373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	hlist_for_each_entry_rcu(li, node, hhead, hlist) {
126319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		i = li->plen;
126419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		mask = ntohl(inet_make_mask(i));
1265c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (l->key != (key & mask))
126619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
126719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
126806c7427021f1cc83703f14659d8405ca773ba1efPatrick McHardy		if ((err = fib_semantic_match(&li->falh, flp, res, l->key, mask, i)) <= 0) {
126919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			*plen = i;
127019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
127119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			t->stats.semantic_match_passed++;
127219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
127306c7427021f1cc83703f14659d8405ca773ba1efPatrick McHardy			return err;
127419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
127519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
127619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		t->stats.semantic_match_miss++;
127719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
127819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
127906c7427021f1cc83703f14659d8405ca773ba1efPatrick McHardy	return 1;
128019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
128119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
128219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic int
128319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfn_trie_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
128419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
128519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
128619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int plen, ret = 0;
128719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct node *n;
128819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *pn;
128919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int pos, bits;
129091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	t_key key = ntohl(flp->fl4_dst);
129119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int chopped_off;
129219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t_key cindex = 0;
129319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int current_prefix_length = KEYLENGTH;
129491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	struct tnode *cn;
129591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	t_key node_prefix, key_prefix, pref_mismatch;
129691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	int mp;
129791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
12982373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_lock();
129991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
13002373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	n = rcu_dereference(t->trie);
1301c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!n)
130219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto failed;
130319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
130419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
130519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t->stats.gets++;
130619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
130719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
130819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Just a leaf? */
130919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (IS_LEAF(n)) {
131006c7427021f1cc83703f14659d8405ca773ba1efPatrick McHardy		if ((ret = check_leaf(t, (struct leaf *)n, key, &plen, flp, res)) <= 0)
131119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			goto found;
131219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto failed;
131319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
131419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	pn = (struct tnode *) n;
131519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	chopped_off = 0;
1316c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
131791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	while (pn) {
131819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		pos = pn->pos;
131919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		bits = pn->bits;
132019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1321c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (!chopped_off)
132219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			cindex = tkey_extract_bits(MASK_PFX(key, current_prefix_length), pos, bits);
132319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
132419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		n = tnode_get_child(pn, cindex);
132519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
132619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (n == NULL) {
132719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
132819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			t->stats.null_node_hit++;
132919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
133019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			goto backtrace;
133119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
133219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
133391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (IS_LEAF(n)) {
133491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			if ((ret = check_leaf(t, (struct leaf *)n, key, &plen, flp, res)) <= 0)
133591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				goto found;
133691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			else
133791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				goto backtrace;
133891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
133991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
134019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define HL_OPTIMIZE
134119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef HL_OPTIMIZE
134291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		cn = (struct tnode *)n;
134319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
134491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/*
134591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * It's a tnode, and we can do some extra checks here if we
134691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * like, to avoid descending into a dead-end branch.
134791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * This tnode is in the parent's child array at index
134891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * key[p_pos..p_pos+p_bits] but potentially with some bits
134991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * chopped off, so in reality the index may be just a
135091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * subprefix, padded with zero at the end.
135191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * We can also take a look at any skipped bits in this
135291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * tnode - everything up to p_pos is supposed to be ok,
135391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * and the non-chopped bits of the index (se previous
135491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * paragraph) are also guaranteed ok, but the rest is
135591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * considered unknown.
135691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 *
135791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * The skipped bits are key[pos+bits..cn->pos].
135891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
135919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
136091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* If current_prefix_length < pos+bits, we are already doing
136191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * actual prefix  matching, which means everything from
136291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * pos+(bits-chopped_off) onward must be zero along some
136391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * branch of this subtree - otherwise there is *no* valid
136491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * prefix present. Here we can only check the skipped
136591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * bits. Remember, since we have already indexed into the
136691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * parent's child array, we know that the bits we chopped of
136791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * *are* zero.
136891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
136919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
137091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* NOTA BENE: CHECKING ONLY SKIPPED BITS FOR THE NEW NODE HERE */
137119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
137291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (current_prefix_length < pos+bits) {
137391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			if (tkey_extract_bits(cn->key, current_prefix_length,
137491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson						cn->pos - current_prefix_length) != 0 ||
137591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			    !(cn->child[0]))
137691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				goto backtrace;
137791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
137819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
137991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/*
138091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * If chopped_off=0, the index is fully validated and we
138191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * only need to look at the skipped bits for this, the new,
138291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * tnode. What we actually want to do is to find out if
138391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * these skipped bits match our key perfectly, or if we will
138491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * have to count on finding a matching prefix further down,
138591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * because if we do, we would like to have some way of
138691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * verifying the existence of such a prefix at this point.
138791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
138819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
138991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* The only thing we can do at this point is to verify that
139091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * any such matching prefix can indeed be a prefix to our
139191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * key, and if the bits in the node we are inspecting that
139291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * do not match our key are not ZERO, this cannot be true.
139391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * Thus, find out where there is a mismatch (before cn->pos)
139491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * and verify that all the mismatching bits are zero in the
139591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * new tnode's key.
139691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
139719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
139891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* Note: We aren't very concerned about the piece of the key
139991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * that precede pn->pos+pn->bits, since these have already been
140091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * checked. The bits after cn->pos aren't checked since these are
140191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * by definition "unknown" at this point. Thus, what we want to
140291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * see is if we are about to enter the "prefix matching" state,
140391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * and in that case verify that the skipped bits that will prevail
140491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * throughout this subtree are zero, as they have to be if we are
140591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * to find a matching prefix.
140691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
140791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
140891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		node_prefix = MASK_PFX(cn->key, cn->pos);
140991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		key_prefix = MASK_PFX(key, cn->pos);
141091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		pref_mismatch = key_prefix^node_prefix;
141191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		mp = 0;
141291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
141391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		/* In short: If skipped bits in this node do not match the search
141491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 * key, enter the "prefix matching" state.directly.
141591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		 */
141691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (pref_mismatch) {
141791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			while (!(pref_mismatch & (1<<(KEYLENGTH-1)))) {
141891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				mp++;
141991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				pref_mismatch = pref_mismatch <<1;
142091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			}
142191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			key_prefix = tkey_extract_bits(cn->key, mp, cn->pos-mp);
142291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
142391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			if (key_prefix != 0)
142491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				goto backtrace;
142591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
142691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			if (current_prefix_length >= cn->pos)
142791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				current_prefix_length = mp;
1428c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		}
142991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson#endif
143091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		pn = (struct tnode *)n; /* Descend */
143191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		chopped_off = 0;
143291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		continue;
143391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
143419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonbacktrace:
143519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		chopped_off++;
143619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
143719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* As zero don't change the child key (cindex) */
143891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		while ((chopped_off <= pn->bits) && !(cindex & (1<<(chopped_off-1))))
143919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			chopped_off++;
144019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
144119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* Decrease current_... with bits chopped off */
144219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (current_prefix_length > pn->pos + pn->bits - chopped_off)
144319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			current_prefix_length = pn->pos + pn->bits - chopped_off;
144491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
144519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/*
1446c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		 * Either we do the actual chop off according or if we have
144719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 * chopped off all bits in this tnode walk up to our parent.
144819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		 */
144919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
145091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		if (chopped_off <= pn->bits) {
145119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			cindex &= ~(1 << (chopped_off-1));
145291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		} else {
1453c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger			if (NODE_PARENT(pn) == NULL)
145419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				goto failed;
145591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
145619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			/* Get Child's index */
145719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			cindex = tkey_extract_bits(pn->key, NODE_PARENT(pn)->pos, NODE_PARENT(pn)->bits);
145819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			pn = NODE_PARENT(pn);
145919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			chopped_off = 0;
146019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
146119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS
146219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			t->stats.backtrack++;
146319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
146419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			goto backtrace;
1465c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		}
146619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
146719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfailed:
1468c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	ret = 1;
146919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfound:
14702373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_unlock();
147119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return ret;
147219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
147319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
14742373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson/* only called from updater side */
147519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic int trie_leaf_remove(struct trie *t, t_key key)
147619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
147719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t_key cindex;
147819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *tp = NULL;
147919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct node *n = t->trie;
148019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *l;
148119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
14820c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("entering trie_leaf_remove(%p)\n", n);
148319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
148419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	/* Note that in the case skipped bits, those bits are *not* checked!
1485c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * When we finish this, we will have NULL or a T_LEAF, and the
148619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 * T_LEAF may or may not match our key.
148719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
148819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
148991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	while (n != NULL && IS_TNODE(n)) {
149019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		struct tnode *tn = (struct tnode *) n;
149119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		check_tnode(tn);
149219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		n = tnode_get_child(tn ,tkey_extract_bits(key, tn->pos, tn->bits));
149319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
14940c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger		BUG_ON(n && NODE_PARENT(n) != tn);
149591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	}
149619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l = (struct leaf *) n;
149719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1498c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!n || !tkey_equals(l->key, key))
149919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return 0;
1500c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
1501c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	/*
1502c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * Key found.
1503c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	 * Remove the leaf and rebalance the tree
150419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	 */
150519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
150619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t->revision++;
150719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t->size--;
150819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
15092373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	preempt_disable();
151019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tp = NODE_PARENT(n);
151119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tnode_free((struct tnode *) n);
151219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1513c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (tp) {
151419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		cindex = tkey_extract_bits(key, tp->pos, tp->bits);
151519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		put_child(t, (struct tnode *)tp, cindex, NULL);
15162373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		rcu_assign_pointer(t->trie, trie_rebalance(t, tp));
151791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	} else
15182373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		rcu_assign_pointer(t->trie, NULL);
15192373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	preempt_enable();
152019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
152119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return 1;
152219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
152319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
152419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic int
152519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
152691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		struct nlmsghdr *nlhdr, struct netlink_skb_parms *req)
152719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
152819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
152919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	u32 key, mask;
153019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int plen = r->rtm_dst_len;
153119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	u8 tos = r->rtm_tos;
153219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa, *fa_to_delete;
153319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct list_head *fa_head;
153419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *l;
153591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	struct leaf_info *li;
153691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
153719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1538c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (plen > 32)
153919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -EINVAL;
154019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
154119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	key = 0;
1542c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (rta->rta_dst)
154319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		memcpy(&key, rta->rta_dst, 4);
154419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
154519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	key = ntohl(key);
154691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	mask = ntohl(inet_make_mask(plen));
154719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1548c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (key & ~mask)
154919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -EINVAL;
155019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
155119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	key = key & mask;
155219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l = fib_find_node(t, key);
155319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1554c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!l)
155519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -ESRCH;
155619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
155719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa_head = get_fa_head(l, plen);
155819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa = fib_find_alias(fa_head, tos, 0);
155919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
156019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (!fa)
156119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return -ESRCH;
156219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
15630c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t);
156419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
156519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa_to_delete = NULL;
156619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa_head = fa->fa_list.prev;
15672373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
156819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	list_for_each_entry(fa, fa_head, fa_list) {
156919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		struct fib_info *fi = fa->fa_info;
157019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
157119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fa->fa_tos != tos)
157219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
157319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
157419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if ((!r->rtm_type ||
157519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		     fa->fa_type == r->rtm_type) &&
157619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		    (r->rtm_scope == RT_SCOPE_NOWHERE ||
157719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		     fa->fa_scope == r->rtm_scope) &&
157819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		    (!r->rtm_protocol ||
157919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		     fi->fib_protocol == r->rtm_protocol) &&
158019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		    fib_nh_match(r, nlhdr, rta, fi) == 0) {
158119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			fa_to_delete = fa;
158219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
158319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
158419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
158519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
158691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (!fa_to_delete)
158791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		return -ESRCH;
158819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
158991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	fa = fa_to_delete;
159091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req);
159191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
159291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	l = fib_find_node(t, key);
159391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	li = find_leaf_info(&l->list, plen);
159419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
15952373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	list_del_rcu(&fa->fa_list);
159619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
159791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (list_empty(fa_head)) {
15982373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		hlist_del_rcu(&li->hlist);
159991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		free_leaf_info(li);
16002373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	}
160119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
160291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (hlist_empty(&l->list))
160391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		trie_leaf_remove(t, key);
160419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
160591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (fa->fa_state & FA_S_ACCESSED)
160691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		rt_cache_flush(-1);
160719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16082373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	fib_release_info(fa->fa_info);
16092373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	alias_free_mem_rcu(fa);
161091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	return 0;
161119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
161219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
161319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic int trie_flush_list(struct trie *t, struct list_head *head)
161419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
161519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa, *fa_node;
161619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int found = 0;
161719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
161819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	list_for_each_entry_safe(fa, fa_node, head, fa_list) {
161919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		struct fib_info *fi = fa->fa_info;
162019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16212373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		if (fi && (fi->fib_flags & RTNH_F_DEAD)) {
16222373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			list_del_rcu(&fa->fa_list);
16232373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			fib_release_info(fa->fa_info);
16242373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			alias_free_mem_rcu(fa);
162519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			found++;
162619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
162719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
162819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return found;
162919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
163019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
163119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic int trie_flush_leaf(struct trie *t, struct leaf *l)
163219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
163319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int found = 0;
163419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_head *lih = &l->list;
163519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct hlist_node *node, *tmp;
163619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf_info *li = NULL;
163719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
163819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	hlist_for_each_entry_safe(li, node, tmp, lih, hlist) {
163919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		found += trie_flush_list(t, &li->falh);
164019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
164119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (list_empty(&li->falh)) {
16422373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			hlist_del_rcu(&li->hlist);
164319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			free_leaf_info(li);
164419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
164519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
164619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return found;
164719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
164819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16492373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson/* rcu_read_lock needs to be hold by caller from readside */
16502373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
165119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic struct leaf *nextleaf(struct trie *t, struct leaf *thisleaf)
165219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
165319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct node *c = (struct node *) thisleaf;
165419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct tnode *p;
165519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int idx;
16562373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	struct node *trie = rcu_dereference(t->trie);
165719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1658c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (c == NULL) {
16592373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		if (trie == NULL)
166019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			return NULL;
166119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16622373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		if (IS_LEAF(trie))          /* trie w. just a leaf */
16632373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			return (struct leaf *) trie;
166419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
16652373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson		p = (struct tnode*) trie;  /* Start */
166691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	} else
166719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		p = (struct tnode *) NODE_PARENT(c);
1668c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
166919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	while (p) {
167019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		int pos, last;
167119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
167219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/*  Find the next child of the parent */
1673c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (c)
1674c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger			pos = 1 + tkey_extract_bits(c->key, p->pos, p->bits);
1675c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		else
167619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			pos = 0;
167719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
167819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		last = 1 << p->bits;
167991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		for (idx = pos; idx < last ; idx++) {
16802373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			c = rcu_dereference(p->child[idx]);
16812373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
16822373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			if (!c)
168391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				continue;
168491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
168591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			/* Decend if tnode */
16862373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			while (IS_TNODE(c)) {
16872373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson				p = (struct tnode *) c;
16882373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson  				idx = 0;
168991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
169091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				/* Rightmost non-NULL branch */
169191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				if (p && IS_TNODE(p))
16922373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson					while (!(c = rcu_dereference(p->child[idx]))
16932373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson					       && idx < (1<<p->bits)) idx++;
169491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
169591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				/* Done with this tnode? */
16962373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson				if (idx >= (1 << p->bits) || !c)
169791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson					goto up;
169819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			}
16992373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson			return (struct leaf *) c;
170019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
170119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonup:
170219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		/* No more children go up one step  */
170391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		c = (struct node *) p;
170419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		p = (struct tnode *) NODE_PARENT(p);
170519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
170619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return NULL; /* Ready. Root of trie */
170719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
170819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
170919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic int fn_trie_flush(struct fib_table *tb)
171019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
171119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
171219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *ll = NULL, *l = NULL;
171319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int found = 0, h;
171419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
171519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t->revision++;
171619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
17172373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_lock();
171891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (h = 0; (l = nextleaf(t, l)) != NULL; h++) {
171919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		found += trie_flush_leaf(t, l);
172019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
172119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (ll && hlist_empty(&ll->list))
172219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			trie_leaf_remove(t, ll->key);
172319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		ll = l;
172419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
17252373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_unlock();
172619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
172719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (ll && hlist_empty(&ll->list))
172819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		trie_leaf_remove(t, ll->key);
172919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
17300c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger	pr_debug("trie_flush found=%d\n", found);
173119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return found;
173219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
173319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
173491b9a277fc4d207249e459a455abf804ebb5499dOlof Johanssonstatic int trie_last_dflt = -1;
173519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
173619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic void
173719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
173819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
173919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
174019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int order, last_idx;
174119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_info *fi = NULL;
174219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_info *last_resort;
174319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa = NULL;
174419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct list_head *fa_head;
174519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *l;
174619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
174719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	last_idx = -1;
174819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	last_resort = NULL;
174919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	order = -1;
175019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
17512373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_lock();
1752c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
175319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	l = fib_find_node(t, 0);
1754c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!l)
175519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
175619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
175719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	fa_head = get_fa_head(l, 0);
1758c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (!fa_head)
175919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
176019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1761c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (list_empty(fa_head))
176219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
176319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
17642373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	list_for_each_entry_rcu(fa, fa_head, fa_list) {
176519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		struct fib_info *next_fi = fa->fa_info;
176691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
176719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fa->fa_scope != res->scope ||
176819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		    fa->fa_type != RTN_UNICAST)
176919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
177091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
177119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (next_fi->fib_priority > res->fi->fib_priority)
177219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			break;
177319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (!next_fi->fib_nh[0].nh_gw ||
177419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		    next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
177519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
177619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fa->fa_state |= FA_S_ACCESSED;
177791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
177819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fi == NULL) {
177919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			if (next_fi != res->fi)
178019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				break;
178119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		} else if (!fib_detect_death(fi, order, &last_resort,
178219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson					     &last_idx, &trie_last_dflt)) {
178319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			if (res->fi)
178419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				fib_info_put(res->fi);
178519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			res->fi = fi;
178619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			atomic_inc(&fi->fib_clntref);
178719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			trie_last_dflt = order;
178819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			goto out;
178919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
179019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fi = next_fi;
179119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		order++;
179219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
179319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (order <= 0 || fi == NULL) {
179419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		trie_last_dflt = -1;
179519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
179619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
179719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
179819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (!fib_detect_death(fi, order, &last_resort, &last_idx, &trie_last_dflt)) {
179919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (res->fi)
180019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			fib_info_put(res->fi);
180119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		res->fi = fi;
180219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		atomic_inc(&fi->fib_clntref);
180319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		trie_last_dflt = order;
180419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out;
180519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
180619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (last_idx >= 0) {
180719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (res->fi)
180819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			fib_info_put(res->fi);
180919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		res->fi = last_resort;
181019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (last_resort)
181119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			atomic_inc(&last_resort->fib_clntref);
181219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
181319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	trie_last_dflt = last_idx;
181419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson out:;
18152373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_unlock();
181619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
181719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1818c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemmingerstatic int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fib_table *tb,
181919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			   struct sk_buff *skb, struct netlink_callback *cb)
182019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
182119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int i, s_i;
182219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_alias *fa;
182319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
182491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	u32 xkey = htonl(key);
182519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
182691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	s_i = cb->args[3];
182719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	i = 0;
182819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
18292373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	/* rcu_read_lock is hold by caller */
18302373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
18312373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	list_for_each_entry_rcu(fa, fah, fa_list) {
183219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (i < s_i) {
183319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			i++;
183419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
183519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
183619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fa->fa_info->fib_nh == NULL) {
183719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			printk("Trie error _fib_nh=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen);
183819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			i++;
183919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
184019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
184119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fa->fa_info == NULL) {
184219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			printk("Trie error fa_info=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen);
184319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			i++;
184419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
184519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
184619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
184719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid,
184819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  cb->nlh->nlmsg_seq,
184919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  RTM_NEWROUTE,
185019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  tb->tb_id,
185119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  fa->fa_type,
185219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  fa->fa_scope,
185319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  &xkey,
185419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  plen,
185519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson				  fa->fa_tos,
185690f66914c89b0be63548d4387d1211280aa7bc8eDavid S. Miller				  fa->fa_info, 0) < 0) {
185719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			cb->args[3] = i;
185819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			return -1;
185991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		}
186019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		i++;
186119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
186291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	cb->args[3] = i;
186319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return skb->len;
186419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
186519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1866c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemmingerstatic int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, struct sk_buff *skb,
186719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			     struct netlink_callback *cb)
186819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
186919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int h, s_h;
187019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct list_head *fa_head;
187119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct leaf *l = NULL;
187219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
187391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	s_h = cb->args[2];
187419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
187591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (h = 0; (l = nextleaf(t, l)) != NULL; h++) {
187619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (h < s_h)
187719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
187819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (h > s_h)
187919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			memset(&cb->args[3], 0,
188019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			       sizeof(cb->args) - 3*sizeof(cb->args[0]));
188119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
188219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fa_head = get_fa_head(l, plen);
188391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
1884c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (!fa_head)
188519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
188619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1887c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger		if (list_empty(fa_head))
188819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
188919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
189019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb)<0) {
189191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson			cb->args[2] = h;
189219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			return -1;
189319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
189419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
189591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	cb->args[2] = h;
189619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return skb->len;
189719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
189819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
189919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, struct netlink_callback *cb)
190019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
190119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int m, s_m;
190219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t = (struct trie *) tb->tb_data;
190319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
190419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	s_m = cb->args[1];
190519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
19062373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_lock();
190791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	for (m = 0; m <= 32; m++) {
190819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (m < s_m)
190919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			continue;
191019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (m > s_m)
191119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			memset(&cb->args[2], 0,
191291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson				sizeof(cb->args) - 2*sizeof(cb->args[0]));
191319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
191419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		if (fn_trie_dump_plen(t, 32-m, tb, skb, cb)<0) {
191519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			cb->args[1] = m;
191619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson			goto out;
191719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
191819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
19192373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_unlock();
192019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	cb->args[1] = m;
192119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return skb->len;
192291b9a277fc4d207249e459a455abf804ebb5499dOlof Johanssonout:
19232373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_unlock();
192419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return -1;
192519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
192619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
192719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson/* Fix more generic FIB names for init later */
192819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
192919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_MULTIPLE_TABLES
193019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct fib_table * fib_hash_init(int id)
193119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#else
193219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct fib_table * __init fib_hash_init(int id)
193319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif
193419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
193519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct fib_table *tb;
193619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct trie *t;
193719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
193819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (fn_alias_kmem == NULL)
193919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		fn_alias_kmem = kmem_cache_create("ip_fib_alias",
194019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson						  sizeof(struct fib_alias),
194119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson						  0, SLAB_HWCACHE_ALIGN,
194219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson						  NULL, NULL);
194319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
194419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb = kmalloc(sizeof(struct fib_table) + sizeof(struct trie),
194519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		     GFP_KERNEL);
194619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (tb == NULL)
194719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		return NULL;
194819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
194919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_id = id;
195019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_lookup = fn_trie_lookup;
195119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_insert = fn_trie_insert;
195219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_delete = fn_trie_delete;
195319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_flush = fn_trie_flush;
195419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_select_default = fn_trie_select_default;
195519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	tb->tb_dump = fn_trie_dump;
195619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	memset(tb->tb_data, 0, sizeof(struct trie));
195719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
195819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	t = (struct trie *) tb->tb_data;
195919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
196019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	trie_init(t);
196119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1962c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	if (id == RT_TABLE_LOCAL)
196391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		trie_local = t;
1964c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	else if (id == RT_TABLE_MAIN)
196591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		trie_main = t;
196619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
196719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (id == RT_TABLE_LOCAL)
196819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		printk("IPv4 FIB: Using LC-trie version %s\n", VERSION);
196919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
197019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return tb;
197119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
197219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1973cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger#ifdef CONFIG_PROC_FS
1974cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/* Depth first Trie walk iterator */
1975cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstruct fib_trie_iter {
1976cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct tnode *tnode;
1977cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct trie *trie;
1978cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	unsigned index;
1979cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	unsigned depth;
1980cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger};
198119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1982cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic struct node *fib_trie_get_next(struct fib_trie_iter *iter)
198319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
1984cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct tnode *tn = iter->tnode;
1985cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	unsigned cindex = iter->index;
1986cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct tnode *p;
198719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1988cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	pr_debug("get_next iter={node=%p index=%d depth=%d}\n",
1989cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		 iter->tnode, iter->index, iter->depth);
1990cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerrescan:
1991cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	while (cindex < (1<<tn->bits)) {
1992cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		struct node *n = tnode_get_child(tn, cindex);
199319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
1994cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		if (n) {
1995cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (IS_LEAF(n)) {
1996cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				iter->tnode = tn;
1997cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				iter->index = cindex + 1;
1998cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			} else {
1999cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				/* push down one level */
2000cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				iter->tnode = (struct tnode *) n;
2001cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				iter->index = 0;
2002cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				++iter->depth;
2003cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			}
2004cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			return n;
2005cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		}
200619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2007cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		++cindex;
2008cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
200991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2010cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	/* Current node exhausted, pop back up */
2011cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	p = NODE_PARENT(tn);
2012cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (p) {
2013cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1;
2014cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		tn = p;
2015cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		--iter->depth;
2016cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto rescan;
201719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
2018cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2019cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	/* got root? */
2020cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return NULL;
202119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
202219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2023cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic struct node *fib_trie_get_first(struct fib_trie_iter *iter,
2024cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				       struct trie *t)
202519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2026cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct node *n = rcu_dereference(t->trie);
202719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2028cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (n && IS_TNODE(n)) {
2029cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		iter->tnode = (struct tnode *) n;
2030cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		iter->trie = t;
2031cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		iter->index = 0;
20321d25cd6cc2528e4af12ab18e84fe95ed78f3f21aRobert Olsson		iter->depth = 1;
2033cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return n;
203491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	}
2035cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return NULL;
2036cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
203791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2038cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void trie_collect_stats(struct trie *t, struct trie_stat *s)
2039cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
2040cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct node *n;
2041cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct fib_trie_iter iter;
204291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2043cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	memset(s, 0, sizeof(*s));
204491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2045cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	rcu_read_lock();
2046cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	for (n = fib_trie_get_first(&iter, t); n;
2047cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	     n = fib_trie_get_next(&iter)) {
2048cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		if (IS_LEAF(n)) {
2049cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			s->leaves++;
2050cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			s->totdepth += iter.depth;
2051cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (iter.depth > s->maxdepth)
2052cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				s->maxdepth = iter.depth;
2053cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		} else {
2054cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			const struct tnode *tn = (const struct tnode *) n;
2055cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			int i;
2056cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2057cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			s->tnodes++;
2058cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			s->nodesizes[tn->bits]++;
2059cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			for (i = 0; i < (1<<tn->bits); i++)
2060cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				if (!tn->child[i])
2061cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					s->nullpointers++;
206219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		}
206319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
20642373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson	rcu_read_unlock();
206519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
206619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2067cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/*
2068cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger *	This outputs /proc/net/fib_triestats
2069cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger */
2070cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
207119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2072cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	unsigned i, max, pointers, bytes, avdepth;
2073c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
2074cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (stat->leaves)
2075cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		avdepth = stat->totdepth*100 / stat->leaves;
2076cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	else
2077cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		avdepth = 0;
207891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2079cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq, "\tAver depth:     %d.%02d\n", avdepth / 100, avdepth % 100 );
2080cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq, "\tMax depth:      %u\n", stat->maxdepth);
208191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2082cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq, "\tLeaves:         %u\n", stat->leaves);
208391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2084cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	bytes = sizeof(struct leaf) * stat->leaves;
2085cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq, "\tInternal nodes: %d\n\t", stat->tnodes);
2086cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	bytes += sizeof(struct tnode) * stat->tnodes;
208719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2088cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	max = MAX_CHILDS-1;
2089cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	while (max >= 0 && stat->nodesizes[max] == 0)
2090cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		max--;
209119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2092cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	pointers = 0;
2093cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	for (i = 1; i <= max; i++)
2094cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		if (stat->nodesizes[i] != 0) {
2095cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			seq_printf(seq, "  %d: %d",  i, stat->nodesizes[i]);
2096cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			pointers += (1<<i) * stat->nodesizes[i];
2097cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		}
2098cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_putc(seq, '\n');
2099cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq, "\tPointers: %d\n", pointers);
21002373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
2101cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	bytes += sizeof(struct node *) * pointers;
2102cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq, "Null ptrs: %d\n", stat->nullpointers);
2103cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq, "Total size: %d  kB\n", (bytes + 1023) / 1024);
21042373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson
2105cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger#ifdef CONFIG_IP_FIB_TRIE_STATS
2106cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq, "Counters:\n---------\n");
2107cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq,"gets = %d\n", t->stats.gets);
2108cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq,"backtracks = %d\n", t->stats.backtrack);
2109cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq,"semantic match passed = %d\n", t->stats.semantic_match_passed);
2110cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq,"semantic match miss = %d\n", t->stats.semantic_match_miss);
2111cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq,"null node hit= %d\n", t->stats.null_node_hit);
2112cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq,"skipped node resize = %d\n", t->stats.resize_node_skipped);
2113cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger#ifdef CLEAR_STATS
2114cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	memset(&(t->stats), 0, sizeof(t->stats));
2115cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger#endif
2116cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger#endif /*  CONFIG_IP_FIB_TRIE_STATS */
2117cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
211819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2119cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_triestat_seq_show(struct seq_file *seq, void *v)
2120cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
2121cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct trie_stat *stat;
212291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2123cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	stat = kmalloc(sizeof(*stat), GFP_KERNEL);
2124cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (!stat)
2125cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return -ENOMEM;
212691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2127cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq_printf(seq, "Basic info: size of leaf: %Zd bytes, size of tnode: %Zd bytes.\n",
2128cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		   sizeof(struct leaf), sizeof(struct tnode));
212991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2130cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (trie_local) {
2131cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		seq_printf(seq, "Local:\n");
2132cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		trie_collect_stats(trie_local, stat);
2133cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		trie_show_stats(seq, stat);
2134cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
213591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2136cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (trie_main) {
2137cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		seq_printf(seq, "Main:\n");
2138cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		trie_collect_stats(trie_main, stat);
2139cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		trie_show_stats(seq, stat);
214019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
2141cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	kfree(stat);
214219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2143cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return 0;
214419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
214519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2146cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_triestat_seq_open(struct inode *inode, struct file *file)
214719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2148cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return single_open(file, fib_triestat_seq_show, NULL);
214919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
215019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2151cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic struct file_operations fib_triestat_fops = {
2152cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.owner	= THIS_MODULE,
2153cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.open	= fib_triestat_seq_open,
2154cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.read	= seq_read,
2155cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.llseek	= seq_lseek,
2156cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.release = single_release,
2157cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger};
2158cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2159cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic struct node *fib_trie_get_idx(struct fib_trie_iter *iter,
2160cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				      loff_t pos)
216119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2162cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	loff_t idx = 0;
2163cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct node *n;
2164cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2165cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	for (n = fib_trie_get_first(iter, trie_local);
2166cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	     n; ++idx, n = fib_trie_get_next(iter)) {
2167cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		if (pos == idx)
2168cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			return n;
2169cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
2170cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2171cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	for (n = fib_trie_get_first(iter, trie_main);
2172cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	     n; ++idx, n = fib_trie_get_next(iter)) {
2173cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		if (pos == idx)
2174cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			return n;
2175cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
217619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return NULL;
217719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
217819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2179cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
218019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2181cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	rcu_read_lock();
2182cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (*pos == 0)
218391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson		return SEQ_START_TOKEN;
2184cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return fib_trie_get_idx(seq->private, *pos - 1);
218519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
218619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2187cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
218819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2189cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct fib_trie_iter *iter = seq->private;
2190cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	void *l = v;
2191cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
219219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	++*pos;
219391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson	if (v == SEQ_START_TOKEN)
2194cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return fib_trie_get_idx(iter, 0);
219519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2196cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	v = fib_trie_get_next(iter);
2197cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	BUG_ON(v == l);
2198cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (v)
2199cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return v;
220019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2201cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	/* continue scan in next trie */
2202cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (iter->trie == trie_local)
2203cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return fib_trie_get_first(iter, trie_main);
220419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2205cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return NULL;
2206cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
220719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2208cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void fib_trie_seq_stop(struct seq_file *seq, void *v)
220919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2210cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	rcu_read_unlock();
2211cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
221291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2213cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void seq_indent(struct seq_file *seq, int n)
2214cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
2215cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	while (n-- > 0) seq_puts(seq, "   ");
2216cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
221719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2218cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic inline const char *rtn_scope(enum rt_scope_t s)
2219cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
2220cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	static char buf[32];
222119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2222cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	switch(s) {
2223cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_UNIVERSE: return "universe";
2224cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_SITE:	return "site";
2225cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_LINK:	return "link";
2226cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_HOST:	return "host";
2227cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	case RT_SCOPE_NOWHERE:	return "nowhere";
2228cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	default:
2229cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		snprintf(buf, sizeof(buf), "scope=%d", s);
2230cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return buf;
2231cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
2232cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}
223319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2234cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic const char *rtn_type_names[__RTN_MAX] = {
2235cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_UNSPEC] = "UNSPEC",
2236cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_UNICAST] = "UNICAST",
2237cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_LOCAL] = "LOCAL",
2238cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_BROADCAST] = "BROADCAST",
2239cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_ANYCAST] = "ANYCAST",
2240cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_MULTICAST] = "MULTICAST",
2241cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_BLACKHOLE] = "BLACKHOLE",
2242cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_UNREACHABLE] = "UNREACHABLE",
2243cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_PROHIBIT] = "PROHIBIT",
2244cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_THROW] = "THROW",
2245cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_NAT] = "NAT",
2246cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	[RTN_XRESOLVE] = "XRESOLVE",
2247cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger};
224819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2249cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic inline const char *rtn_type(unsigned t)
2250cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{
2251cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	static char buf[32];
225219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2253cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (t < __RTN_MAX && rtn_type_names[t])
2254cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return rtn_type_names[t];
2255cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	snprintf(buf, sizeof(buf), "type %d", t);
2256cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return buf;
225719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
225819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2259cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/* Pretty print the trie */
2260cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_trie_seq_show(struct seq_file *seq, void *v)
226119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2262cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	const struct fib_trie_iter *iter = seq->private;
2263cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct node *n = v;
2264c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger
2265cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (v == SEQ_START_TOKEN)
2266cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return 0;
226719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2268cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (IS_TNODE(n)) {
2269cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		struct tnode *tn = (struct tnode *) n;
2270cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		t_key prf = ntohl(MASK_PFX(tn->key, tn->pos));
227191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2272cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		if (!NODE_PARENT(n)) {
2273cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (iter->trie == trie_local)
2274cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				seq_puts(seq, "<local>:\n");
2275cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			else
2276cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				seq_puts(seq, "<main>:\n");
22771d25cd6cc2528e4af12ab18e84fe95ed78f3f21aRobert Olsson		}
22781d25cd6cc2528e4af12ab18e84fe95ed78f3f21aRobert Olsson		seq_indent(seq, iter->depth-1);
22791d25cd6cc2528e4af12ab18e84fe95ed78f3f21aRobert Olsson		seq_printf(seq, "  +-- %d.%d.%d.%d/%d %d %d %d\n",
22801d25cd6cc2528e4af12ab18e84fe95ed78f3f21aRobert Olsson			   NIPQUAD(prf), tn->pos, tn->bits, tn->full_children,
22811d25cd6cc2528e4af12ab18e84fe95ed78f3f21aRobert Olsson			   tn->empty_children);
22821d25cd6cc2528e4af12ab18e84fe95ed78f3f21aRobert Olsson
2283cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	} else {
2284cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		struct leaf *l = (struct leaf *) n;
2285cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		int i;
2286cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		u32 val = ntohl(l->key);
2287cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2288cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		seq_indent(seq, iter->depth);
2289cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		seq_printf(seq, "  |-- %d.%d.%d.%d\n", NIPQUAD(val));
2290cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		for (i = 32; i >= 0; i--) {
2291cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			struct leaf_info *li = find_leaf_info(&l->list, i);
2292cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (li) {
2293cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				struct fib_alias *fa;
2294cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				list_for_each_entry_rcu(fa, &li->falh, fa_list) {
2295cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					seq_indent(seq, iter->depth+1);
2296cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					seq_printf(seq, "  /%d %s %s", i,
2297cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger						   rtn_scope(fa->fa_scope),
2298cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger						   rtn_type(fa->fa_type));
2299cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					if (fa->fa_tos)
2300cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger						seq_printf(seq, "tos =%d\n",
2301cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger							   fa->fa_tos);
2302cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					seq_putc(seq, '\n');
2303cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				}
2304cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			}
2305cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		}
230619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
2307cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
230819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return 0;
230919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
231019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2311cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic struct seq_operations fib_trie_seq_ops = {
2312cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.start  = fib_trie_seq_start,
2313cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.next   = fib_trie_seq_next,
2314cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.stop   = fib_trie_seq_stop,
2315cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.show   = fib_trie_seq_show,
231619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
231719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2318cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_trie_seq_open(struct inode *inode, struct file *file)
231919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
232019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct seq_file *seq;
232119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int rc = -ENOMEM;
2322cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct fib_trie_iter *s = kmalloc(sizeof(*s), GFP_KERNEL);
232319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2324cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (!s)
2325cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto out;
2326cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2327cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	rc = seq_open(file, &fib_trie_seq_ops);
232819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (rc)
232919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out_kfree;
233019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2331cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq	     = file->private_data;
2332cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq->private = s;
2333cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	memset(s, 0, sizeof(*s));
233419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonout:
233519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return rc;
233619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonout_kfree:
2337cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	kfree(s);
233819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	goto out;
233919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
234019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2341cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic struct file_operations fib_trie_fops = {
2342cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.owner  = THIS_MODULE,
2343cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.open   = fib_trie_seq_open,
2344cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.read   = seq_read,
2345cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.llseek = seq_lseek,
2346c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger	.release = seq_release_private,
234719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
234819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2349cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic unsigned fib_flag_trans(int type, u32 mask, const struct fib_info *fi)
235019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2351cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	static unsigned type2flags[RTN_MAX + 1] = {
2352cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		[7] = RTF_REJECT, [8] = RTF_REJECT,
2353cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	};
2354cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	unsigned flags = type2flags[type];
235519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2356cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (fi && fi->fib_nh->nh_gw)
2357cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		flags |= RTF_GATEWAY;
2358cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (mask == 0xFFFFFFFF)
2359cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		flags |= RTF_HOST;
2360cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	flags |= RTF_UP;
2361cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return flags;
236219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
236319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2364cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/*
2365cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger *	This outputs /proc/net/route.
2366cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger *	The format of the file is not supposed to be changed
2367cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger * 	and needs to be same as fib_hash output to avoid breaking
2368cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger *	legacy utilities
2369cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger */
2370cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_route_seq_show(struct seq_file *seq, void *v)
237119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2372cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct leaf *l = v;
2373cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	int i;
2374cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	char bf[128];
237519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2376cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (v == SEQ_START_TOKEN) {
2377cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
2378cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			   "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
2379cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			   "\tWindow\tIRTT");
2380cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return 0;
2381cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	}
238219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2383cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (IS_TNODE(l))
2384cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		return 0;
238519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2386cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	for (i=32; i>=0; i--) {
2387cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		struct leaf_info *li = find_leaf_info(&l->list, i);
2388cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		struct fib_alias *fa;
2389cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		u32 mask, prefix;
239091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson
2391cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		if (!li)
2392cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			continue;
239319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2394cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		mask = inet_make_mask(li->plen);
2395cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		prefix = htonl(l->key);
239619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2397cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		list_for_each_entry_rcu(fa, &li->falh, fa_list) {
2398cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			const struct fib_info *fi = rcu_dereference(fa->fa_info);
2399cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
240019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2401cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (fa->fa_type == RTN_BROADCAST
2402cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			    || fa->fa_type == RTN_MULTICAST)
2403cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				continue;
240419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2405cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			if (fi)
2406cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				snprintf(bf, sizeof(bf),
2407cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
2408cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 fi->fib_dev ? fi->fib_dev->name : "*",
2409cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 prefix,
2410cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 fi->fib_nh->nh_gw, flags, 0, 0,
2411cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 fi->fib_priority,
2412cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 mask,
2413cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 (fi->fib_advmss ? fi->fib_advmss + 40 : 0),
2414cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 fi->fib_window,
2415cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 fi->fib_rtt >> 3);
2416cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			else
2417cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger				snprintf(bf, sizeof(bf),
2418cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
2419cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 prefix, 0, flags, 0, 0, 0,
2420cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger					 mask, 0, 0, 0);
242119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2422cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger			seq_printf(seq, "%-127s\n", bf);
2423cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		}
242419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	}
242519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
242619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return 0;
242719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
242819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2429cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic struct seq_operations fib_route_seq_ops = {
2430cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.start  = fib_trie_seq_start,
2431cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.next   = fib_trie_seq_next,
2432cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.stop   = fib_trie_seq_stop,
2433cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.show   = fib_route_seq_show,
243419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
243519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2436cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_route_seq_open(struct inode *inode, struct file *file)
243719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
243819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	struct seq_file *seq;
243919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	int rc = -ENOMEM;
2440cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	struct fib_trie_iter *s = kmalloc(sizeof(*s), GFP_KERNEL);
244119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2442cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (!s)
2443cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto out;
2444cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2445cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	rc = seq_open(file, &fib_route_seq_ops);
244619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	if (rc)
244719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson		goto out_kfree;
244819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2449cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq	     = file->private_data;
2450cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	seq->private = s;
2451cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	memset(s, 0, sizeof(*s));
245219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonout:
245319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return rc;
245419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonout_kfree:
2455cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	kfree(s);
245619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	goto out;
245719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
245819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
2459cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic struct file_operations fib_route_fops = {
2460cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.owner  = THIS_MODULE,
2461cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.open   = fib_route_seq_open,
2462cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.read   = seq_read,
2463cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.llseek = seq_lseek,
2464cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	.release = seq_release_private,
246519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson};
246619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
246719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonint __init fib_proc_init(void)
246819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
2469cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (!proc_net_fops_create("fib_trie", S_IRUGO, &fib_trie_fops))
2470cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto out1;
2471cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2472cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (!proc_net_fops_create("fib_triestat", S_IRUGO, &fib_triestat_fops))
2473cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto out2;
2474cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2475cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	if (!proc_net_fops_create("route", S_IRUGO, &fib_route_fops))
2476cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger		goto out3;
2477cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
247819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	return 0;
2479cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger
2480cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerout3:
2481cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	proc_net_remove("fib_triestat");
2482cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerout2:
2483cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	proc_net_remove("fib_trie");
2484cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerout1:
2485cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	return -ENOMEM;
248619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
248719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
248819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonvoid __init fib_proc_exit(void)
248919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{
249019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson	proc_net_remove("fib_trie");
2491cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	proc_net_remove("fib_triestat");
2492cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger	proc_net_remove("route");
249319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}
249419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson
249519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif /* CONFIG_PROC_FS */
2496