119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson/* 219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * This program is free software; you can redistribute it and/or 319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * modify it under the terms of the GNU General Public License 419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * as published by the Free Software Foundation; either version 519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 2 of the License, or (at your option) any later version. 619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Robert Olsson <robert.olsson@its.uu.se> Uppsala Universitet 819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * & Swedish University of Agricultural Sciences. 919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 10e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki * Jens Laas <jens.laas@data.slu.se> Swedish University of 1119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Agricultural Sciences. 12e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki * 1319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Hans Liss <hans.liss@its.uu.se> Uppsala Universitet 1419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 1525985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * This work is based on the LPC-trie which is originally described in: 16e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki * 1719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * An experimental study of compression methods for dynamic tries 1819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002. 19631dd1a885b6d7e9f6f51b4e5b311c2bb04c323cJustin P. Mattock * http://www.csc.kth.se/~snilsson/software/dyntrie2/ 2019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 2119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 2219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson 2319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, June 1999 2419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 2519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 2619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Code from fib_hash has been reused which includes the following header: 2719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 2819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 2919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * INET An implementation of the TCP/IP protocol suite for the LINUX 3019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * operating system. INET is implemented using the BSD Socket 3119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * interface as the means of communication with the user level. 3219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 3319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * IPv4 FIB: lookup engine and maintenance routines. 3419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 3519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 3619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 3719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 3819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * This program is free software; you can redistribute it and/or 3919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * modify it under the terms of the GNU General Public License 4019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * as published by the Free Software Foundation; either version 4119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 2 of the License, or (at your option) any later version. 42fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson * 43fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson * Substantial contributions to this work comes from: 44fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson * 45fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson * David S. Miller, <davem@davemloft.net> 46fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson * Stephen Hemminger <shemminger@osdl.org> 47fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson * Paul E. McKenney <paulmck@us.ibm.com> 48fd9662555cc35f8bf9242cd7bba8b44ae168a68bRobert Olsson * Patrick McHardy <kaber@trash.net> 4919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */ 5019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 5180b71b80df14d885f7e50e115c1348398f418759Jens Låås#define VERSION "0.409" 5219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 5319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <asm/uaccess.h> 541977f032722c27ee3730284582fd3991ad9ac81bJiri Slaby#include <linux/bitops.h> 5519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/types.h> 5619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/kernel.h> 5719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/mm.h> 5819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/string.h> 5919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/socket.h> 6019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/sockios.h> 6119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/errno.h> 6219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/in.h> 6319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/inet.h> 64cd8787ab04d23f925f440b712b43a6fd5cb31eceStephen Hemminger#include <linux/inetdevice.h> 6519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/netdevice.h> 6619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/if_arp.h> 6719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/proc_fs.h> 682373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson#include <linux/rcupdate.h> 6919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/skbuff.h> 7019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/netlink.h> 7119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/init.h> 7219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <linux/list.h> 735a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 74bc3b2d7fb9b014d75ebb79ba371a763dbab5e8cfPaul Gortmaker#include <linux/export.h> 75457c4cbc5a3dde259d2a1f15d5f9785290397267Eric W. Biederman#include <net/net_namespace.h> 7619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/ip.h> 7719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/protocol.h> 7819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/route.h> 7919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/tcp.h> 8019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/sock.h> 8119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include <net/ip_fib.h> 8219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#include "fib_lookup.h" 8319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 8406ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson#define MAX_STAT_DEPTH 32 8519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 8619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define KEYLENGTH (8*sizeof(t_key)) 8719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 8819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssontypedef unsigned int t_key; 8919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 9019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define T_TNODE 0 9119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define T_LEAF 1 9219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#define NODE_TYPE_MASK 0x1UL 932373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson#define NODE_TYPE(node) ((node)->parent & NODE_TYPE_MASK) 942373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 9591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson#define IS_TNODE(n) (!(n->parent & T_LEAF)) 9691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson#define IS_LEAF(n) (n->parent & T_LEAF) 9719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 98b299e4f001cfa16205f9121f4630970049652268David S. Millerstruct rt_trie_node { 9991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson unsigned long parent; 1008d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet t_key key; 10119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}; 10219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 10319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct leaf { 10491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson unsigned long parent; 1058d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet t_key key; 10619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct hlist_head list; 1072373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson struct rcu_head rcu; 10819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}; 10919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 11019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct leaf_info { 11119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct hlist_node hlist; 11219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int plen; 1135c74501f76360ce6f410730b9b5e5976f38e8504Eric Dumazet u32 mask_plen; /* ntohl(inet_make_mask(plen)) */ 11419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct list_head falh; 1155c74501f76360ce6f410730b9b5e5976f38e8504Eric Dumazet struct rcu_head rcu; 11619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}; 11719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 11819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct tnode { 11991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson unsigned long parent; 1208d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet t_key key; 121112d8cfcbf4f5ef0cf669cb5864f1206972076d6Eric Dumazet unsigned char pos; /* 2log(KEYLENGTH) bits needed */ 122112d8cfcbf4f5ef0cf669cb5864f1206972076d6Eric Dumazet unsigned char bits; /* 2log(KEYLENGTH) bits needed */ 1238d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet unsigned int full_children; /* KEYLENGTH bits needed */ 1248d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet unsigned int empty_children; /* KEYLENGTH bits needed */ 12515be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger union { 12615be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger struct rcu_head rcu; 127e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski struct tnode *tnode_free; 12815be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger }; 1290a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet struct rt_trie_node __rcu *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; 149936722922f6d2366378de606a40c14f96915474dStephen Hemminger unsigned int prefixes; 15006ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson unsigned int nodesizes[MAX_STAT_DEPTH]; 151c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger}; 15219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 15319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstruct trie { 1540a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet struct rt_trie_node __rcu *trie; 15519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS 15619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct trie_use_stats stats; 15719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif 15819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}; 15919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 160b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n, 161a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger int wasfull); 162b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic struct rt_trie_node *resize(struct trie *t, struct tnode *tn); 1632f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *inflate(struct trie *t, struct tnode *tn); 1642f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *halve(struct trie *t, struct tnode *tn); 165e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski/* tnodes to free after resize(); protected by RTNL */ 166e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawskistatic struct tnode *tnode_free_head; 167c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawskistatic size_t tnode_free_size; 168c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski 169c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski/* 170c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski * synchronize_rcu after call_rcu for that many pages; it should be especially 171c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski * useful before resizing the root node with PREEMPT_NONE configs; the value was 172c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski * obtained experimentally, aiming to avoid visible slowdown. 173c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski */ 174c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawskistatic const int sync_pages = 128; 17519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 176e18b890bb0881bbab6f4f1a6cd20d9c60d66b003Christoph Lameterstatic struct kmem_cache *fn_alias_kmem __read_mostly; 177bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemmingerstatic struct kmem_cache *trie_leaf_kmem __read_mostly; 17819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1790a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet/* 1800a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet * caller must hold RTNL 1810a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet */ 1820a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazetstatic inline struct tnode *node_parent(const struct rt_trie_node *node) 1830680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger{ 1840a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet unsigned long parent; 1850a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet 1860a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet parent = rcu_dereference_index_check(node->parent, lockdep_rtnl_is_held()); 1870a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet 1880a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet return (struct tnode *)(parent & ~NODE_TYPE_MASK); 189b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet} 190b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet 1910a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet/* 1920a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet * caller must hold RCU read lock or RTNL 1930a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet */ 1940a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazetstatic inline struct tnode *node_parent_rcu(const struct rt_trie_node *node) 195b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet{ 1960a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet unsigned long parent; 1970a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet 1980a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet parent = rcu_dereference_index_check(node->parent, rcu_read_lock_held() || 1990a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet lockdep_rtnl_is_held()); 2000680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger 2010a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet return (struct tnode *)(parent & ~NODE_TYPE_MASK); 2020680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger} 2030680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger 204cf778b00e96df6d64f8e21b8395d1f8a859ecdc7Eric Dumazet/* Same as rcu_assign_pointer 2056440cc9e0f48ade57af7be28008cbfa6a991f287Stephen Hemminger * but that macro() assumes that value is a pointer. 2066440cc9e0f48ade57af7be28008cbfa6a991f287Stephen Hemminger */ 207b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic inline void node_set_parent(struct rt_trie_node *node, struct tnode *ptr) 2080680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger{ 2096440cc9e0f48ade57af7be28008cbfa6a991f287Stephen Hemminger smp_wmb(); 2106440cc9e0f48ade57af7be28008cbfa6a991f287Stephen Hemminger node->parent = (unsigned long)ptr | NODE_TYPE(node); 2110680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger} 2122373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 2130a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet/* 2140a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet * caller must hold RTNL 2150a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet */ 2160a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazetstatic inline struct rt_trie_node *tnode_get_child(const struct tnode *tn, unsigned int i) 217b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet{ 218b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet BUG_ON(i >= 1U << tn->bits); 2192373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 2200a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet return rtnl_dereference(tn->child[i]); 221b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet} 222b59cfbf77dc8368c2c90b012c79553613f4d70c3Eric Dumazet 2230a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet/* 2240a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet * caller must hold RCU read lock or RTNL 2250a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet */ 2260a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazetstatic inline struct rt_trie_node *tnode_get_child_rcu(const struct tnode *tn, unsigned int i) 22719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 2280a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet BUG_ON(i >= 1U << tn->bits); 22919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2300a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet return rcu_dereference_rtnl(tn->child[i]); 23119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 23219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 233bb435b8d816582064ee0ddb1e2a6fbca67f34108Stephen Hemmingerstatic inline int tnode_child_length(const struct tnode *tn) 23419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 23591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson return 1 << tn->bits; 23619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 23719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2383b004569d86d02786ebae496e75dc0b625be3e9aDavid S. Millerstatic inline t_key mask_pfx(t_key k, unsigned int l) 239ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger{ 240ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger return (l == 0) ? 0 : k >> (KEYLENGTH-l) << (KEYLENGTH-l); 241ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger} 242ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger 2433b004569d86d02786ebae496e75dc0b625be3e9aDavid S. Millerstatic inline t_key tkey_extract_bits(t_key a, unsigned int offset, unsigned int bits) 24419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 24591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (offset < KEYLENGTH) 24619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return ((t_key)(a << offset)) >> (KEYLENGTH - bits); 24791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson else 24819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return 0; 24919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 25019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 25119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline int tkey_equals(t_key a, t_key b) 25219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 253c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger return a == b; 25419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 25519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 25619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline int tkey_sub_equals(t_key a, int offset, int bits, t_key b) 25719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 258c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (bits == 0 || offset >= KEYLENGTH) 259c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger return 1; 26091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson bits = bits > KEYLENGTH ? KEYLENGTH : bits; 26191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson return ((a ^ b) << offset) >> (KEYLENGTH - bits) == 0; 262c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger} 26319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 26419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic inline int tkey_mismatch(t_key a, int offset, t_key b) 26519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 26619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson t_key diff = a ^ b; 26719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int i = offset; 26819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 269c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (!diff) 270c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger return 0; 271c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger while ((diff << i) >> (KEYLENGTH-1) == 0) 27219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson i++; 27319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return i; 27419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 27519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 27619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson/* 277e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki To understand this stuff, an understanding of keys and all their bits is 278e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki necessary. Every node in the trie has a key associated with it, but not 27919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson all of the bits in that key are significant. 28019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 28119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson Consider a node 'n' and its parent 'tp'. 28219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 283e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki If n is a leaf, every bit in its key is significant. Its presence is 284e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki necessitated by path compression, since during a tree traversal (when 285e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki searching for a leaf - unless we are doing an insertion) we will completely 286e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki ignore all skipped bits we encounter. Thus we need to verify, at the end of 287e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki a potentially successful search, that we have indeed been walking the 28819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson correct key path. 28919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 290e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki Note that we can never "miss" the correct key in the tree if present by 291e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki following the wrong path. Path compression ensures that segments of the key 292e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki that are the same for all keys with a given prefix are skipped, but the 293e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki skipped part *is* identical for each node in the subtrie below the skipped 294e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki bit! trie_insert() in this implementation takes care of that - note the 29519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson call to tkey_sub_equals() in trie_insert(). 29619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 297e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki if n is an internal node - a 'tnode' here, the various parts of its key 29819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson have many different meanings. 29919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 300e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki Example: 30119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson _________________________________________________________________ 30219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C | 30319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson ----------------------------------------------------------------- 304e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 30519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 30619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson _________________________________________________________________ 30719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u | 30819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson ----------------------------------------------------------------- 30919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 31019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 31119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tp->pos = 7 31219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tp->bits = 3 31319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson n->pos = 15 31491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson n->bits = 4 31519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 316e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki First, let's just ignore the bits that come before the parent tp, that is 317e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki the bits from 0 to (tp->pos-1). They are *known* but at this point we do 31819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson not use them for anything. 31919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 32019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson The bits from (tp->pos) to (tp->pos + tp->bits - 1) - "N", above - are the 321e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki index into the parent's child array. That is, they will be used to find 32219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 'n' among tp's children. 32319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 32419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson The bits from (tp->pos + tp->bits) to (n->pos - 1) - "S" - are skipped bits 32519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson for the node n. 32619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 327e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki All the bits we have seen so far are significant to the node n. The rest 32819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson of the bits are really not needed or indeed known in n->key. 32919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 330e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki The bits from (n->pos) to (n->pos + n->bits - 1) - "C" - are the index into 33119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson n's child array, and will of course be different for each child. 332e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki 333c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 33419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson The rest of the bits, from (n->pos + n->bits) onward, are completely unknown 33519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson at this point. 33619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 33719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson*/ 33819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 3390c7770c740156c8802c23d24fc094d06967d997dStephen Hemmingerstatic inline void check_tnode(const struct tnode *tn) 34019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 3410c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger WARN_ON(tn && tn->pos+tn->bits > 32); 34219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 34319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 344f5026fabda54e5ab5d469d8cfac5f46b4d321ce9Denis V. Lunevstatic const int halve_threshold = 25; 345f5026fabda54e5ab5d469d8cfac5f46b4d321ce9Denis V. Lunevstatic const int inflate_threshold = 50; 346345aa031207d02d7438c1aa96ed9315911ecd745Jarek Poplawskistatic const int halve_threshold_root = 15; 34780b71b80df14d885f7e50e115c1348398f418759Jens Lååsstatic const int inflate_threshold_root = 30; 3482373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 3492373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __alias_free_mem(struct rcu_head *head) 35019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 3512373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson struct fib_alias *fa = container_of(head, struct fib_alias, rcu); 3522373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson kmem_cache_free(fn_alias_kmem, fa); 35319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 35419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 3552373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic inline void alias_free_mem_rcu(struct fib_alias *fa) 35619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 3572373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson call_rcu(&fa->rcu, __alias_free_mem); 3582373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson} 35991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 3602373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __leaf_free_rcu(struct rcu_head *head) 3612373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{ 362bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger struct leaf *l = container_of(head, struct leaf, rcu); 363bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger kmem_cache_free(trie_leaf_kmem, l); 3642373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson} 36591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 366387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemmingerstatic inline void free_leaf(struct leaf *l) 367387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger{ 3680c03eca3d995e73d691edea8c787e25929ec156dEric Dumazet call_rcu(&l->rcu, __leaf_free_rcu); 369387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger} 370387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger 3712373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic inline void free_leaf_info(struct leaf_info *leaf) 37219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 373bceb0f4512d448763fe98c9f37504c98bbebbed6Lai Jiangshan kfree_rcu(leaf, rcu); 37419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 37519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 3768d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazetstatic struct tnode *tnode_alloc(size_t size) 377f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy{ 3782373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson if (size <= PAGE_SIZE) 3798d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet return kzalloc(size, GFP_KERNEL); 38015be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger else 3817a1c8e5ab120a5f352e78bbc1fa5bb64e6f23639Eric Dumazet return vzalloc(size); 38215be75cdb5db442d0e33d37b20832b88f3ccd383Stephen Hemminger} 3832373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 3842373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic void __tnode_free_rcu(struct rcu_head *head) 385f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy{ 3862373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson struct tnode *tn = container_of(head, struct tnode, rcu); 3878d96544475b236a0f319e492f4828aa8c0801c7fEric Dumazet size_t size = sizeof(struct tnode) + 388b299e4f001cfa16205f9121f4630970049652268David S. Miller (sizeof(struct rt_trie_node *) << tn->bits); 389f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy 390f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy if (size <= PAGE_SIZE) 391f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy kfree(tn); 3920020356355192cbaf6d315515e6c95bd09618c3bAl Viro else 3930020356355192cbaf6d315515e6c95bd09618c3bAl Viro vfree(tn); 394f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy} 395f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy 3962373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic inline void tnode_free(struct tnode *tn) 3972373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{ 398387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger if (IS_LEAF(tn)) 399387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger free_leaf((struct leaf *) tn); 400387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger else 401550e29bc96e6f1ced2bca82dace197b009434367Robert Olsson call_rcu(&tn->rcu, __tnode_free_rcu); 4022373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson} 4032373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 404e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawskistatic void tnode_free_safe(struct tnode *tn) 405e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski{ 406e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski BUG_ON(IS_LEAF(tn)); 4077b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawski tn->tnode_free = tnode_free_head; 4087b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawski tnode_free_head = tn; 409c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski tnode_free_size += sizeof(struct tnode) + 410b299e4f001cfa16205f9121f4630970049652268David S. Miller (sizeof(struct rt_trie_node *) << tn->bits); 411e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski} 412e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski 413e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawskistatic void tnode_free_flush(void) 414e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski{ 415e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski struct tnode *tn; 416e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski 417e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski while ((tn = tnode_free_head)) { 418e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski tnode_free_head = tn->tnode_free; 419e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski tn->tnode_free = NULL; 420e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski tnode_free(tn); 421e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski } 422c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski 423c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski if (tnode_free_size >= PAGE_SIZE * sync_pages) { 424c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski tnode_free_size = 0; 425c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski synchronize_rcu(); 426c3059477fce2d956a0bb3e04357324780c5d8eebJarek Poplawski } 427e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski} 428e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski 4292373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic struct leaf *leaf_new(void) 4302373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{ 431bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger struct leaf *l = kmem_cache_alloc(trie_leaf_kmem, GFP_KERNEL); 4322373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson if (l) { 4332373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson l->parent = T_LEAF; 4342373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson INIT_HLIST_HEAD(&l->list); 4352373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson } 4362373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson return l; 4372373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson} 4382373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 4392373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olssonstatic struct leaf_info *leaf_info_new(int plen) 4402373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson{ 4412373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL); 4422373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson if (li) { 4432373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson li->plen = plen; 4445c74501f76360ce6f410730b9b5e5976f38e8504Eric Dumazet li->mask_plen = ntohl(inet_make_mask(plen)); 4452373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson INIT_LIST_HEAD(&li->falh); 4462373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson } 4472373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson return li; 4482373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson} 4492373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 450a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic struct tnode *tnode_new(t_key key, int pos, int bits) 45119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 452b299e4f001cfa16205f9121f4630970049652268David S. Miller size_t sz = sizeof(struct tnode) + (sizeof(struct rt_trie_node *) << bits); 453f0e36f8cee8101604378085171c980d9cc71d779Patrick McHardy struct tnode *tn = tnode_alloc(sz); 45419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 45591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (tn) { 4562373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson tn->parent = T_TNODE; 45719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn->pos = pos; 45819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn->bits = bits; 45919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn->key = key; 46019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn->full_children = 0; 46119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn->empty_children = 1<<bits; 46219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 463c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 464a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode), 4654ea4bf7ebcbacee2f4736d261efb0693e87a34c9Lin Ming sizeof(struct rt_trie_node *) << bits); 46619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return tn; 46719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 46819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 46919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson/* 47019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Check whether a tnode 'n' is "full", i.e. it is an internal node 47119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * and no bits are skipped. See discussion in dyntree paper p. 6 47219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */ 47319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 474b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic inline int tnode_full(const struct tnode *tn, const struct rt_trie_node *n) 47519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 476c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (n == NULL || IS_LEAF(n)) 47719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return 0; 47819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 47919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return ((struct tnode *) n)->pos == tn->pos + tn->bits; 48019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 48119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 48261648d91fc278fd1d500da8061d17e6920cd3500Lin Mingstatic inline void put_child(struct tnode *tn, int i, 483b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *n) 48419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 48519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tnode_put_child_reorg(tn, i, n, -1); 48619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 48719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 488c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger /* 48919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Add a child at position i overwriting the old value. 49019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Update the value of full_children and empty_children. 49119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */ 49219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 493b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n, 494a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger int wasfull) 49519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 4960a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet struct rt_trie_node *chi = rtnl_dereference(tn->child[i]); 49719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int isfull; 49819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 4990c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger BUG_ON(i >= 1<<tn->bits); 5000c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger 50119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* update emptyChildren */ 50219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (n == NULL && chi != NULL) 50319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn->empty_children++; 50419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson else if (n != NULL && chi == NULL) 50519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn->empty_children--; 506c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 50719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* update fullChildren */ 50891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (wasfull == -1) 50919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson wasfull = tnode_full(tn, chi); 51019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 51119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson isfull = tnode_full(tn, n); 512c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (wasfull && !isfull) 51319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn->full_children--; 514c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger else if (!wasfull && isfull) 51519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn->full_children++; 51691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 517c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (n) 5180680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger node_set_parent(n, tn); 51919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 520cf778b00e96df6d64f8e21b8395d1f8a859ecdc7Eric Dumazet rcu_assign_pointer(tn->child[i], n); 52119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 52219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 52380b71b80df14d885f7e50e115c1348398f418759Jens Låås#define MAX_WORK 10 524b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic struct rt_trie_node *resize(struct trie *t, struct tnode *tn) 52519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 52619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int i; 5272f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson struct tnode *old_tn; 528e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson int inflate_threshold_use; 529e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson int halve_threshold_use; 53080b71b80df14d885f7e50e115c1348398f418759Jens Låås int max_work; 53119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 532e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki if (!tn) 53319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return NULL; 53419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 5350c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger pr_debug("In tnode_resize %p inflate_threshold=%d threshold=%d\n", 5360c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger tn, inflate_threshold, halve_threshold); 53719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 53819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* No children */ 53919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (tn->empty_children == tnode_child_length(tn)) { 540e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski tnode_free_safe(tn); 54119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return NULL; 54219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 54319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* One child */ 54419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (tn->empty_children == tnode_child_length(tn) - 1) 54580b71b80df14d885f7e50e115c1348398f418759Jens Låås goto one_child; 546c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger /* 54719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Double as long as the resulting node has a number of 54819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * nonempty nodes that are above the threshold. 54919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */ 55019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 55119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* 552c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * From "Implementing a dynamic compressed trie" by Stefan Nilsson of 553c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * the Helsinki University of Technology and Matti Tikkanen of Nokia 55419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Telecommunications, page 6: 555c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * "A node is doubled if the ratio of non-empty children to all 55619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * children in the *doubled* node is at least 'high'." 55719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 558c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 'high' in this instance is the variable 'inflate_threshold'. It 559c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * is expressed as a percentage, so we multiply it with 560c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * tnode_child_length() and instead of multiplying by 2 (since the 561c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * child array will be doubled by inflate()) and multiplying 562c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * the left-hand side by 100 (to handle the percentage thing) we 56319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * multiply the left-hand side by 50. 564c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 565c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * The left-hand side may look a bit weird: tnode_child_length(tn) 566c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * - tn->empty_children is of course the number of non-null children 567c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * in the current node. tn->full_children is the number of "full" 56819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * children, that is non-null tnodes with a skip value of 0. 569c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * All of those will be doubled in the resulting inflated tnode, so 57019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * we just count them one extra time here. 571c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 57219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * A clearer way to write this would be: 573c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 57419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * to_be_doubled = tn->full_children; 575c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children - 57619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * tn->full_children; 57719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 57819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * new_child_length = tnode_child_length(tn) * 2; 57919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 580c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) / 58119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * new_child_length; 58219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * if (new_fill_factor >= inflate_threshold) 583c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 584c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * ...and so on, tho it would mess up the while () loop. 585c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 58619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * anyway, 58719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >= 58819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * inflate_threshold 589c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 59019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * avoid a division: 59119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 100 * (not_to_be_doubled + 2*to_be_doubled) >= 59219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * inflate_threshold * new_child_length 593c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 59419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * expand not_to_be_doubled and to_be_doubled, and shorten: 595c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 100 * (tnode_child_length(tn) - tn->empty_children + 59691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * tn->full_children) >= inflate_threshold * new_child_length 597c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 59819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * expand new_child_length: 599c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 100 * (tnode_child_length(tn) - tn->empty_children + 60091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * tn->full_children) >= 60119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * inflate_threshold * tnode_child_length(tn) * 2 602c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 60319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * shorten again: 604c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 50 * (tn->full_children + tnode_child_length(tn) - 60591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * tn->empty_children) >= inflate_threshold * 60619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * tnode_child_length(tn) 607c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * 60819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */ 60919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 61019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson check_tnode(tn); 611c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 612e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson /* Keep root node larger */ 613e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson 614b299e4f001cfa16205f9121f4630970049652268David S. Miller if (!node_parent((struct rt_trie_node *)tn)) { 61580b71b80df14d885f7e50e115c1348398f418759Jens Låås inflate_threshold_use = inflate_threshold_root; 61680b71b80df14d885f7e50e115c1348398f418759Jens Låås halve_threshold_use = halve_threshold_root; 617a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet } else { 618e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson inflate_threshold_use = inflate_threshold; 61980b71b80df14d885f7e50e115c1348398f418759Jens Låås halve_threshold_use = halve_threshold; 62080b71b80df14d885f7e50e115c1348398f418759Jens Låås } 621e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson 62280b71b80df14d885f7e50e115c1348398f418759Jens Låås max_work = MAX_WORK; 62380b71b80df14d885f7e50e115c1348398f418759Jens Låås while ((tn->full_children > 0 && max_work-- && 624a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger 50 * (tn->full_children + tnode_child_length(tn) 625a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger - tn->empty_children) 626a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger >= inflate_threshold_use * tnode_child_length(tn))) { 62719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 6282f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson old_tn = tn; 6292f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson tn = inflate(t, tn); 630a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger 6312f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson if (IS_ERR(tn)) { 6322f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson tn = old_tn; 6332f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS 6342f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson t->stats.resize_node_skipped++; 6352f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#endif 6362f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson break; 6372f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson } 63819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 63919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 64019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson check_tnode(tn); 64119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 64280b71b80df14d885f7e50e115c1348398f418759Jens Låås /* Return if at least one inflate is run */ 643a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet if (max_work != MAX_WORK) 644b299e4f001cfa16205f9121f4630970049652268David S. Miller return (struct rt_trie_node *) tn; 64580b71b80df14d885f7e50e115c1348398f418759Jens Låås 64619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* 64719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Halve as long as the number of empty children in this 64819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * node is above threshold. 64919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */ 6502f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson 65180b71b80df14d885f7e50e115c1348398f418759Jens Låås max_work = MAX_WORK; 65280b71b80df14d885f7e50e115c1348398f418759Jens Låås while (tn->bits > 1 && max_work-- && 65319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 100 * (tnode_child_length(tn) - tn->empty_children) < 654e6308be85afee685347fa3440bed10faaa5d6c1aRobert Olsson halve_threshold_use * tnode_child_length(tn)) { 6552f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson 6562f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson old_tn = tn; 6572f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson tn = halve(t, tn); 6582f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson if (IS_ERR(tn)) { 6592f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson tn = old_tn; 6602f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS 6612f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson t->stats.resize_node_skipped++; 6622f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson#endif 6632f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson break; 6642f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson } 6652f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson } 66619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 667c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 66819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* Only one child remains */ 66980b71b80df14d885f7e50e115c1348398f418759Jens Låås if (tn->empty_children == tnode_child_length(tn) - 1) { 67080b71b80df14d885f7e50e115c1348398f418759Jens Lååsone_child: 67119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson for (i = 0; i < tnode_child_length(tn); i++) { 672b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *n; 67319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 6740a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet n = rtnl_dereference(tn->child[i]); 6752373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson if (!n) 67691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson continue; 67791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 67891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson /* compress one level */ 67991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 6800680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger node_set_parent(n, NULL); 681e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski tnode_free_safe(tn); 68291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson return n; 68319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 68480b71b80df14d885f7e50e115c1348398f418759Jens Låås } 685b299e4f001cfa16205f9121f4630970049652268David S. Miller return (struct rt_trie_node *) tn; 68619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 68719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 6880a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet 6890a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazetstatic void tnode_clean_free(struct tnode *tn) 6900a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet{ 6910a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet int i; 6920a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet struct tnode *tofree; 6930a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet 6940a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet for (i = 0; i < tnode_child_length(tn); i++) { 6950a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet tofree = (struct tnode *)rtnl_dereference(tn->child[i]); 6960a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet if (tofree) 6970a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet tnode_free(tofree); 6980a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet } 6990a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet tnode_free(tn); 7000a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet} 7010a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet 7022f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *inflate(struct trie *t, struct tnode *tn) 70319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 70419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct tnode *oldtnode = tn; 70519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int olen = tnode_child_length(tn); 70619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int i; 70719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 7080c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger pr_debug("In inflate\n"); 70919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 71019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits + 1); 71119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 7120c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger if (!tn) 7132f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson return ERR_PTR(-ENOMEM); 7142f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson 7152f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson /* 716c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * Preallocate and store tnodes before the actual work so we 717c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * don't get into an inconsistent state if memory allocation 718c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * fails. In case of failure we return the oldnode and inflate 7192f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson * of tnode is ignored. 7202f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson */ 72191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 72291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson for (i = 0; i < olen; i++) { 723a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger struct tnode *inode; 7242f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson 725a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger inode = (struct tnode *) tnode_get_child(oldtnode, i); 7262f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson if (inode && 7272f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson IS_TNODE(inode) && 7282f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson inode->pos == oldtnode->pos + oldtnode->bits && 7292f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson inode->bits > 1) { 7302f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson struct tnode *left, *right; 731ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger t_key m = ~0U << (KEYLENGTH - 1) >> inode->pos; 732c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 7332f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson left = tnode_new(inode->key&(~m), inode->pos + 1, 7342f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson inode->bits - 1); 7352f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson if (!left) 7362f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson goto nomem; 73791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 7382f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson right = tnode_new(inode->key|m, inode->pos + 1, 7392f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson inode->bits - 1); 7402f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson 741e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki if (!right) { 7422f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson tnode_free(left); 7432f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson goto nomem; 744e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki } 7452f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson 74661648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, 2*i, (struct rt_trie_node *) left); 74761648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, 2*i+1, (struct rt_trie_node *) right); 7482f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson } 7492f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson } 7502f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson 75191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson for (i = 0; i < olen; i++) { 752c95aaf9af5a1f6dee56d1f2ab4915cd722d608daStephen Hemminger struct tnode *inode; 753b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *node = tnode_get_child(oldtnode, i); 75491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson struct tnode *left, *right; 75591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson int size, j; 756c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 75719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* An empty child */ 75819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (node == NULL) 75919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson continue; 76019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 76119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* A leaf or an internal node with skipped bits */ 76219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 763c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (IS_LEAF(node) || ((struct tnode *) node)->pos > 76419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn->pos + tn->bits - 1) { 765bbe34cf8a1a2cc174e6516fc230b91b531da7ddfbaker.zhang put_child(tn, 766bbe34cf8a1a2cc174e6516fc230b91b531da7ddfbaker.zhang tkey_extract_bits(node->key, oldtnode->pos, oldtnode->bits + 1), 767bbe34cf8a1a2cc174e6516fc230b91b531da7ddfbaker.zhang node); 76819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson continue; 76919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 77019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 77119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* An internal node with two children */ 77219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson inode = (struct tnode *) node; 77319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 77419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (inode->bits == 1) { 77561648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, 2*i, rtnl_dereference(inode->child[0])); 77661648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, 2*i+1, rtnl_dereference(inode->child[1])); 77719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 778e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski tnode_free_safe(inode); 77991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson continue; 78019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 78119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 78291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson /* An internal node with more than two children */ 78391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 78491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson /* We will replace this node 'inode' with two new 78591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * ones, 'left' and 'right', each with half of the 78691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * original children. The two new nodes will have 78791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * a position one bit further down the key and this 78891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * means that the "significant" part of their keys 78991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * (see the discussion near the top of this file) 79091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * will differ by one bit, which will be "0" in 79191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * left's key and "1" in right's key. Since we are 79291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * moving the key position by one step, the bit that 79391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * we are moving away from - the bit at position 79491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * (inode->pos) - is the one that will differ between 79591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * left and right. So... we synthesize that bit in the 79691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * two new keys. 79791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * The mask 'm' below will be a single "one" bit at 79891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * the position (inode->pos) 79991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson */ 80019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 80191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson /* Use the old key, but set the new significant 80291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * bit to zero. 80391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson */ 8042f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson 80591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson left = (struct tnode *) tnode_get_child(tn, 2*i); 80661648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, 2*i, NULL); 8072f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson 80891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson BUG_ON(!left); 8092f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson 81091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson right = (struct tnode *) tnode_get_child(tn, 2*i+1); 81161648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, 2*i+1, NULL); 81219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 81391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson BUG_ON(!right); 81419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 81591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson size = tnode_child_length(left); 81691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson for (j = 0; j < size; j++) { 81761648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(left, j, rtnl_dereference(inode->child[j])); 81861648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(right, j, rtnl_dereference(inode->child[j + size])); 81919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 82061648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, 2*i, resize(t, left)); 82161648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, 2*i+1, resize(t, right)); 82291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 823e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski tnode_free_safe(inode); 82419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 825e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski tnode_free_safe(oldtnode); 82619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return tn; 8272f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonnomem: 8280a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet tnode_clean_free(tn); 8290a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet return ERR_PTR(-ENOMEM); 83019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 83119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 8322f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonstatic struct tnode *halve(struct trie *t, struct tnode *tn) 83319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 83419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct tnode *oldtnode = tn; 835b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *left, *right; 83619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int i; 83719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int olen = tnode_child_length(tn); 83819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 8390c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger pr_debug("In halve\n"); 840c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 841c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits - 1); 84219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 8432f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson if (!tn) 8442f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson return ERR_PTR(-ENOMEM); 8452f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson 8462f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson /* 847c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * Preallocate and store tnodes before the actual work so we 848c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * don't get into an inconsistent state if memory allocation 849c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * fails. In case of failure we return the oldnode and halve 8502f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson * of tnode is ignored. 8512f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson */ 8522f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson 85391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson for (i = 0; i < olen; i += 2) { 8542f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson left = tnode_get_child(oldtnode, i); 8552f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson right = tnode_get_child(oldtnode, i+1); 856c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 8572f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson /* Two nonempty children */ 8580c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger if (left && right) { 8592f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson struct tnode *newn; 8600c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger 8612f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson newn = tnode_new(left->key, tn->pos + tn->bits, 1); 8620c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger 8630c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger if (!newn) 8642f80b3c8262d0d646812f776db024d88d569a0c1Robert Olsson goto nomem; 8650c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger 86661648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, i/2, (struct rt_trie_node *)newn); 8672f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson } 8682f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson 8692f36895aa774cf4d1c3d68921e0209e796b66600Robert Olsson } 87019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 87191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson for (i = 0; i < olen; i += 2) { 87291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson struct tnode *newBinNode; 87391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 87419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson left = tnode_get_child(oldtnode, i); 87519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson right = tnode_get_child(oldtnode, i+1); 876c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 87719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* At least one of the children is empty */ 87819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (left == NULL) { 87919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (right == NULL) /* Both are empty */ 88019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson continue; 88161648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, i/2, right); 88291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson continue; 8830c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger } 88491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 88591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (right == NULL) { 88661648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, i/2, left); 88791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson continue; 88891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson } 889c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 89019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* Two nonempty children */ 89191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson newBinNode = (struct tnode *) tnode_get_child(tn, i/2); 89261648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, i/2, NULL); 89361648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(newBinNode, 0, left); 89461648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(newBinNode, 1, right); 89561648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, i/2, resize(t, newBinNode)); 89619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 897e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski tnode_free_safe(oldtnode); 89819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return tn; 8992f80b3c8262d0d646812f776db024d88d569a0c1Robert Olssonnomem: 9000a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet tnode_clean_free(tn); 9010a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet return ERR_PTR(-ENOMEM); 90219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 90319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 904772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson/* readside must use rcu_read_lock currently dump routines 9052373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson via get_fa_head and dump */ 9062373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 907772cb712b1373d335ef2874ea357ec681edc754bRobert Olssonstatic struct leaf_info *find_leaf_info(struct leaf *l, int plen) 90819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 909772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson struct hlist_head *head = &l->list; 91019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct leaf_info *li; 91119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 912b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin hlist_for_each_entry_rcu(li, head, hlist) 913c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (li->plen == plen) 91419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return li; 91591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 91619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return NULL; 91719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 91819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 919a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic inline struct list_head *get_fa_head(struct leaf *l, int plen) 92019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 921772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson struct leaf_info *li = find_leaf_info(l, plen); 922c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 92391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (!li) 92491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson return NULL; 925c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 92691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson return &li->falh; 92719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 92819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 92919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic void insert_leaf_info(struct hlist_head *head, struct leaf_info *new) 93019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 931e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki struct leaf_info *li = NULL, *last = NULL; 932e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki 933e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki if (hlist_empty(head)) { 934e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki hlist_add_head_rcu(&new->hlist, head); 935e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki } else { 936b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin hlist_for_each_entry(li, head, hlist) { 937e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki if (new->plen > li->plen) 938e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki break; 939e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki 940e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki last = li; 941e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki } 942e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki if (last) 9431d023284c31a4e40a94d5bbcb7dbb7a35ee0bcbcKen Helias hlist_add_behind_rcu(&new->hlist, &last->hlist); 944e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki else 945e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki hlist_add_before_rcu(&new->hlist, &li->hlist); 946e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki } 94719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 94819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 9492373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson/* rcu_read_lock needs to be hold by caller from readside */ 9502373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 95119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonstatic struct leaf * 95219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfib_find_node(struct trie *t, u32 key) 95319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 95419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int pos; 95519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct tnode *tn; 956b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *n; 95719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 95819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson pos = 0; 959a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet n = rcu_dereference_rtnl(t->trie); 96019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 96119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson while (n != NULL && NODE_TYPE(n) == T_TNODE) { 96219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn = (struct tnode *) n; 96391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 96419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson check_tnode(tn); 96591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 966c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) { 96791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson pos = tn->pos + tn->bits; 968a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger n = tnode_get_child_rcu(tn, 969a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger tkey_extract_bits(key, 970a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger tn->pos, 971a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger tn->bits)); 97291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson } else 97319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson break; 97419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 97519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* Case we have found a leaf. Compare prefixes */ 97619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 97791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) 97891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson return (struct leaf *)n; 97991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 98019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return NULL; 98119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 98219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 9837b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawskistatic void trie_rebalance(struct trie *t, struct tnode *tn) 98419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 98519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int wasfull; 9863ed18d76d959e5cbfa5d70c8f7ba95476582a556Robert Olsson t_key cindex, key; 9870680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger struct tnode *tp; 98819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 9893ed18d76d959e5cbfa5d70c8f7ba95476582a556Robert Olsson key = tn->key; 9903ed18d76d959e5cbfa5d70c8f7ba95476582a556Robert Olsson 991b299e4f001cfa16205f9121f4630970049652268David S. Miller while (tn != NULL && (tp = node_parent((struct rt_trie_node *)tn)) != NULL) { 99219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson cindex = tkey_extract_bits(key, tp->pos, tp->bits); 99319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson wasfull = tnode_full(tp, tnode_get_child(tp, cindex)); 994e3192690a3c889767d1161b228374f4926d92af0Joe Perches tn = (struct tnode *)resize(t, tn); 995a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger 996e3192690a3c889767d1161b228374f4926d92af0Joe Perches tnode_put_child_reorg(tp, cindex, 997b299e4f001cfa16205f9121f4630970049652268David S. Miller (struct rt_trie_node *)tn, wasfull); 99891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 999b299e4f001cfa16205f9121f4630970049652268David S. Miller tp = node_parent((struct rt_trie_node *) tn); 1000008440e3ad4b72f5048d1b1f6f5ed894fdc5ad08Jarek Poplawski if (!tp) 1001cf778b00e96df6d64f8e21b8395d1f8a859ecdc7Eric Dumazet rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); 1002008440e3ad4b72f5048d1b1f6f5ed894fdc5ad08Jarek Poplawski 1003e0f7cb8c8cc6cccce28d2ce39ad8c60d23c3799fJarek Poplawski tnode_free_flush(); 10040680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger if (!tp) 100519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson break; 10060680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger tn = tp; 100719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 10080680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger 100919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* Handle last (top) tnode */ 10107b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawski if (IS_TNODE(tn)) 1011e3192690a3c889767d1161b228374f4926d92af0Joe Perches tn = (struct tnode *)resize(t, tn); 101219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1013cf778b00e96df6d64f8e21b8395d1f8a859ecdc7Eric Dumazet rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); 10147b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawski tnode_free_flush(); 101519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 101619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 10172373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson/* only used from updater-side */ 10182373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 1019fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemmingerstatic struct list_head *fib_insert_node(struct trie *t, u32 key, int plen) 102019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 102119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int pos, newpos; 102219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct tnode *tp = NULL, *tn = NULL; 1023b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *n; 102419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct leaf *l; 102519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int missbit; 1026c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger struct list_head *fa_head = NULL; 102719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct leaf_info *li; 102819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson t_key cindex; 102919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 103019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson pos = 0; 10310a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet n = rtnl_dereference(t->trie); 103219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1033c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger /* If we point to NULL, stop. Either the tree is empty and we should 1034c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * just put a new leaf in if, or we have reached an empty child slot, 103519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * and we should just put our new leaf in that. 1036c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * If we point to a T_TNODE, check if it matches our key. Note that 1037c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * a T_TNODE might be skipping any number of bits - its 'pos' need 103819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * not be the parent's 'pos'+'bits'! 103919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 1040c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * If it does match the current key, get pos/bits from it, extract 104119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * the index from our key, push the T_TNODE and walk the tree. 104219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 104319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * If it doesn't, we have to replace it with a new T_TNODE. 104419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 1045c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * If we point to a T_LEAF, it might or might not have the same key 1046c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * as we do. If it does, just change the value, update the T_LEAF's 1047c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * value, and return it. 104819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * If it doesn't, we need to replace it with a T_TNODE. 104919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */ 105019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 105119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson while (n != NULL && NODE_TYPE(n) == T_TNODE) { 105219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn = (struct tnode *) n; 105391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 1054c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger check_tnode(tn); 105591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 1056c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) { 105719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tp = tn; 105891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson pos = tn->pos + tn->bits; 1059a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger n = tnode_get_child(tn, 1060a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger tkey_extract_bits(key, 1061a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger tn->pos, 1062a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger tn->bits)); 106319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 10640680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger BUG_ON(n && node_parent(n) != tn); 106591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson } else 106619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson break; 106719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 106819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 106919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* 107019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * n ----> NULL, LEAF or TNODE 107119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 1072c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * tp is n's (parent) ----> NULL or TNODE 107319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */ 107419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 107591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson BUG_ON(tp && IS_LEAF(tp)); 107619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 107719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* Case 1: n is a leaf. Compare prefixes */ 107819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1079c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) { 1080c95aaf9af5a1f6dee56d1f2ab4915cd722d608daStephen Hemminger l = (struct leaf *) n; 108119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson li = leaf_info_new(plen); 108291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 1083fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger if (!li) 1084fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger return NULL; 108519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 108619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson fa_head = &li->falh; 108719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson insert_leaf_info(&l->list, li); 108819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson goto done; 108919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 109019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson l = leaf_new(); 109119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1092fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger if (!l) 1093fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger return NULL; 109419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 109519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson l->key = key; 109619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson li = leaf_info_new(plen); 109719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1098c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (!li) { 1099387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger free_leaf(l); 1100fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger return NULL; 1101f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson } 110219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 110319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson fa_head = &li->falh; 110419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson insert_leaf_info(&l->list, li); 110519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 110619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (t->trie && n == NULL) { 110791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson /* Case 2: n is NULL, and will just insert a new leaf */ 110819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1109b299e4f001cfa16205f9121f4630970049652268David S. Miller node_set_parent((struct rt_trie_node *)l, tp); 111019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 111191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson cindex = tkey_extract_bits(key, tp->pos, tp->bits); 111261648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tp, cindex, (struct rt_trie_node *)l); 111391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson } else { 111491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson /* Case 3: n is a LEAF or a TNODE and the key doesn't match. */ 1115c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger /* 1116c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * Add a new tnode here 111719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * first tnode need some special handling 111819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */ 111919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1120c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (n) { 11214c60f1d67fae632743df9324301e3cb2682f54d4baker.zhang pos = tp ? tp->pos+tp->bits : 0; 112219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson newpos = tkey_mismatch(key, pos, n->key); 112319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tn = tnode_new(n->key, newpos, 1); 112491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson } else { 112519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson newpos = 0; 1126c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger tn = tnode_new(key, newpos, 1); /* First tnode */ 112719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 112819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1129c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (!tn) { 1130f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson free_leaf_info(li); 1131387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger free_leaf(l); 1132fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger return NULL; 113391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson } 113491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 1135b299e4f001cfa16205f9121f4630970049652268David S. Miller node_set_parent((struct rt_trie_node *)tn, tp); 113619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 113791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson missbit = tkey_extract_bits(key, newpos, 1); 113861648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, missbit, (struct rt_trie_node *)l); 113961648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tn, 1-missbit, n); 114019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1141c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (tp) { 114219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson cindex = tkey_extract_bits(key, tp->pos, tp->bits); 114361648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tp, cindex, (struct rt_trie_node *)tn); 114491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson } else { 1145cf778b00e96df6d64f8e21b8395d1f8a859ecdc7Eric Dumazet rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); 114619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tp = tn; 114719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 114819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 114991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 115091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (tp && tp->pos + tp->bits > 32) 1151058bd4d2a4ff0aaa4a5381c67e776729d840c785Joe Perches pr_warn("fib_trie tp=%p pos=%d, bits=%d, key=%0x plen=%d\n", 1152058bd4d2a4ff0aaa4a5381c67e776729d840c785Joe Perches tp, tp->pos, tp->bits, key, plen); 115391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 115419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* Rebalance the trie */ 11552373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 11567b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawski trie_rebalance(t, tp); 1157f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olssondone: 115819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return fa_head; 115919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 116019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1161d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson/* 1162d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson * Caller must hold RTNL. 1163d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson */ 116416c6cf8bb471392fd09b48b7c27e7d83a446b4bcStephen Hemmingerint fib_table_insert(struct fib_table *tb, struct fib_config *cfg) 116519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 116619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct trie *t = (struct trie *) tb->tb_data; 116719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct fib_alias *fa, *new_fa; 1168c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger struct list_head *fa_head = NULL; 116919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct fib_info *fi; 11704e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf int plen = cfg->fc_dst_len; 11714e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf u8 tos = cfg->fc_tos; 117219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson u32 key, mask; 117319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int err; 117419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct leaf *l; 117519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 117619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (plen > 32) 117719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return -EINVAL; 117819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 11794e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf key = ntohl(cfg->fc_dst); 118019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 11812dfe55b47e3d66ded5a84caf71e0da5710edf48bPatrick McHardy pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen); 118219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 118391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson mask = ntohl(inet_make_mask(plen)); 118419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1185c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (key & ~mask) 118619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return -EINVAL; 118719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 118819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson key = key & mask; 118919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 11904e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf fi = fib_create_info(cfg); 11914e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf if (IS_ERR(fi)) { 11924e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf err = PTR_ERR(fi); 119319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson goto err; 11944e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf } 119519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 119619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson l = fib_find_node(t, key); 1197c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger fa = NULL; 119819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1199c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (l) { 120019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson fa_head = get_fa_head(l, plen); 120119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson fa = fib_find_alias(fa_head, tos, fi->fib_priority); 120219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 120319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 120419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* Now fa, if non-NULL, points to the first fib alias 120519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * with the same keys [prefix,tos,priority], if such key already 120619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * exists or to the node before which we will insert new one. 120719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 120819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * If fa is NULL, we will need to allocate a new one and 120919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * insert to the head of f. 121019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * 121119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * If f is NULL, no fib node matched the destination key 121219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * and we need to allocate a new one of those as well. 121319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */ 121419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1215936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov if (fa && fa->fa_tos == tos && 1216936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov fa->fa_info->fib_priority == fi->fib_priority) { 1217936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov struct fib_alias *fa_first, *fa_match; 121819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 121919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson err = -EEXIST; 12204e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf if (cfg->fc_nlflags & NLM_F_EXCL) 122119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson goto out; 122219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1223936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov /* We have 2 goals: 1224936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov * 1. Find exact match for type, scope, fib_info to avoid 1225936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov * duplicate routes 1226936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov * 2. Find next 'fa' (or head), NLM_F_APPEND inserts before it 1227936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov */ 1228936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov fa_match = NULL; 1229936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov fa_first = fa; 1230936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list); 1231936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov list_for_each_entry_continue(fa, fa_head, fa_list) { 1232936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov if (fa->fa_tos != tos) 1233936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov break; 1234936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov if (fa->fa_info->fib_priority != fi->fib_priority) 1235936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov break; 1236936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov if (fa->fa_type == cfg->fc_type && 1237936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov fa->fa_info == fi) { 1238936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov fa_match = fa; 1239936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov break; 1240936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov } 1241936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov } 1242936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov 12434e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf if (cfg->fc_nlflags & NLM_F_REPLACE) { 124419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct fib_info *fi_drop; 124519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson u8 state; 124619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1247936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov fa = fa_first; 1248936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov if (fa_match) { 1249936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov if (fa == fa_match) 1250936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov err = 0; 12516725033fa27c8f49e1221d2badbaaaf1ef459519Joonwoo Park goto out; 1252936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov } 12532373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson err = -ENOBUFS; 1254e94b1766097d53e6f3ccfb36c8baa562ffeda3fcChristoph Lameter new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL); 12552373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson if (new_fa == NULL) 12562373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson goto out; 125719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 125819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson fi_drop = fa->fa_info; 12592373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson new_fa->fa_tos = fa->fa_tos; 12602373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson new_fa->fa_info = fi; 12614e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf new_fa->fa_type = cfg->fc_type; 126219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson state = fa->fa_state; 1263936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov new_fa->fa_state = state & ~FA_S_ACCESSED; 126419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 12652373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson list_replace_rcu(&fa->fa_list, &new_fa->fa_list); 12662373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson alias_free_mem_rcu(fa); 126719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 126819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson fib_release_info(fi_drop); 126919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (state & FA_S_ACCESSED) 12704ccfe6d4109252dfadcd6885f33ed600ee03dbf8Nicolas Dichtel rt_cache_flush(cfg->fc_nlinfo.nl_net); 1271b8f558313506b5bc435f2e031f3bec4b1725098eMilan Kocian rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, 1272b8f558313506b5bc435f2e031f3bec4b1725098eMilan Kocian tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE); 127319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 127491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson goto succeeded; 127519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 127619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* Error if we find a perfect match which 127719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * uses the same scope, type, and nexthop 127819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * information. 127919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */ 1280936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov if (fa_match) 1281936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov goto out; 1282a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger 12834e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf if (!(cfg->fc_nlflags & NLM_F_APPEND)) 1284936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov fa = fa_first; 128519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 128619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson err = -ENOENT; 12874e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf if (!(cfg->fc_nlflags & NLM_F_CREATE)) 128819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson goto out; 128919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 129019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson err = -ENOBUFS; 1291e94b1766097d53e6f3ccfb36c8baa562ffeda3fcChristoph Lameter new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL); 129219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (new_fa == NULL) 129319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson goto out; 129419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 129519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson new_fa->fa_info = fi; 129619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson new_fa->fa_tos = tos; 12974e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf new_fa->fa_type = cfg->fc_type; 129819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson new_fa->fa_state = 0; 129919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* 130019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * Insert new entry to the list. 130119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */ 130219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1303c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (!fa_head) { 1304fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger fa_head = fib_insert_node(t, key, plen); 1305fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger if (unlikely(!fa_head)) { 1306fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger err = -ENOMEM; 1307f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson goto out_free_new_fa; 1308fea86ad8123df0d49188cbc1dd2f48da6ae49d65Stephen Hemminger } 1309f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson } 131019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 131121d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller if (!plen) 131221d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller tb->tb_num_default++; 131321d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller 13142373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson list_add_tail_rcu(&new_fa->fa_list, 13152373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson (fa ? &fa->fa_list : fa_head)); 131619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 13174ccfe6d4109252dfadcd6885f33ed600ee03dbf8Nicolas Dichtel rt_cache_flush(cfg->fc_nlinfo.nl_net); 13184e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, 1319b8f558313506b5bc435f2e031f3bec4b1725098eMilan Kocian &cfg->fc_nlinfo, 0); 132019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonsucceeded: 132119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return 0; 1322f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson 1323f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olssonout_free_new_fa: 1324f835e471b557c45d2e5701ea5215f6e739b4eb39Robert Olsson kmem_cache_free(fn_alias_kmem, new_fa); 132519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonout: 132619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson fib_release_info(fi); 132791b9a277fc4d207249e459a455abf804ebb5499dOlof Johanssonerr: 132819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return err; 132919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 133019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1331772cb712b1373d335ef2874ea357ec681edc754bRobert Olsson/* should be called with rcu_read_lock */ 13325b4704419cbd0b7597a91c19f9e8e8b17c1af071David S. Millerstatic int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l, 133322bd5b9b13f2931ac80949f8bfbc40e8cab05be7David S. Miller t_key key, const struct flowi4 *flp, 1334ebc0ffae5dfb4447e0a431ffe7fe1d467c48bbb9Eric Dumazet struct fib_result *res, int fib_flags) 133519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 133619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct leaf_info *li; 133719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct hlist_head *hhead = &l->list; 1338c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 1339b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin hlist_for_each_entry_rcu(li, hhead, hlist) { 13403be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller struct fib_alias *fa; 1341a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger 13425c74501f76360ce6f410730b9b5e5976f38e8504Eric Dumazet if (l->key != (key & li->mask_plen)) 134319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson continue; 134419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 13453be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller list_for_each_entry_rcu(fa, &li->falh, fa_list) { 13463be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller struct fib_info *fi = fa->fa_info; 13473be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller int nhsel, err; 1348a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger 134922bd5b9b13f2931ac80949f8bfbc40e8cab05be7David S. Miller if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos) 13503be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller continue; 1351dccd9ecc374462e5d6a5b8f8110415a86c2213d8David S. Miller if (fi->fib_dead) 1352dccd9ecc374462e5d6a5b8f8110415a86c2213d8David S. Miller continue; 135337e826c513883099c298317bad1b3b677b2905fbDavid S. Miller if (fa->fa_info->fib_scope < flp->flowi4_scope) 13543be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller continue; 13553be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller fib_alias_accessed(fa); 13563be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller err = fib_props[fa->fa_type].error; 13573be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller if (err) { 135819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS 13591fbc78439291627642517f15b9b91f3125588143Julian Anastasov t->stats.semantic_match_passed++; 13603be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller#endif 13611fbc78439291627642517f15b9b91f3125588143Julian Anastasov return err; 13623be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller } 13633be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller if (fi->fib_flags & RTNH_F_DEAD) 13643be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller continue; 13653be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) { 13663be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller const struct fib_nh *nh = &fi->fib_nh[nhsel]; 13673be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller 13683be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller if (nh->nh_flags & RTNH_F_DEAD) 13693be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller continue; 137022bd5b9b13f2931ac80949f8bfbc40e8cab05be7David S. Miller if (flp->flowi4_oif && flp->flowi4_oif != nh->nh_oif) 13713be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller continue; 13723be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller 13733be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller#ifdef CONFIG_IP_FIB_TRIE_STATS 13743be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller t->stats.semantic_match_passed++; 13753be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller#endif 13765c74501f76360ce6f410730b9b5e5976f38e8504Eric Dumazet res->prefixlen = li->plen; 13773be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller res->nh_sel = nhsel; 13783be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller res->type = fa->fa_type; 137937e826c513883099c298317bad1b3b677b2905fbDavid S. Miller res->scope = fa->fa_info->fib_scope; 13803be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller res->fi = fi; 13813be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller res->table = tb; 13823be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller res->fa_head = &li->falh; 13833be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller if (!(fib_flags & FIB_LOOKUP_NOREF)) 13845c74501f76360ce6f410730b9b5e5976f38e8504Eric Dumazet atomic_inc(&fi->fib_clntref); 13853be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller return 0; 13863be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller } 13873be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller } 13883be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller 13893be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller#ifdef CONFIG_IP_FIB_TRIE_STATS 13903be0686b6e2f953afe83626e871b4a7b0ceae49bDavid S. Miller t->stats.semantic_match_miss++; 139119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif 139219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 1393a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger 13942e655571c618434c24ac2ca989374fdd84470d6dBen Hutchings return 1; 139519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 139619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 139722bd5b9b13f2931ac80949f8bfbc40e8cab05be7David S. Millerint fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, 1398ebc0ffae5dfb4447e0a431ffe7fe1d467c48bbb9Eric Dumazet struct fib_result *res, int fib_flags) 139919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 140019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct trie *t = (struct trie *) tb->tb_data; 14012e655571c618434c24ac2ca989374fdd84470d6dBen Hutchings int ret; 1402b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *n; 140319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct tnode *pn; 14043b004569d86d02786ebae496e75dc0b625be3e9aDavid S. Miller unsigned int pos, bits; 140522bd5b9b13f2931ac80949f8bfbc40e8cab05be7David S. Miller t_key key = ntohl(flp->daddr); 14063b004569d86d02786ebae496e75dc0b625be3e9aDavid S. Miller unsigned int chopped_off; 140719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson t_key cindex = 0; 14083b004569d86d02786ebae496e75dc0b625be3e9aDavid S. Miller unsigned int current_prefix_length = KEYLENGTH; 140991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson struct tnode *cn; 1410874ffa8f72444d6253d2669fed304875c128f86bEric Dumazet t_key pref_mismatch; 141191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 14122373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson rcu_read_lock(); 141391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 14142373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson n = rcu_dereference(t->trie); 1415c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (!n) 141619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson goto failed; 141719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 141819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS 141919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson t->stats.gets++; 142019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif 142119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 142219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* Just a leaf? */ 142319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (IS_LEAF(n)) { 14245b4704419cbd0b7597a91c19f9e8e8b17c1af071David S. Miller ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags); 1425a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger goto found; 142619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 1427a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger 142819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson pn = (struct tnode *) n; 142919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson chopped_off = 0; 1430c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 143191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson while (pn) { 143219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson pos = pn->pos; 143319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson bits = pn->bits; 143419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1435c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (!chopped_off) 1436ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger cindex = tkey_extract_bits(mask_pfx(key, current_prefix_length), 1437ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger pos, bits); 143819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1439b902e5735272b6a79fe2853180b2ad6658aa9678Jarek Poplawski n = tnode_get_child_rcu(pn, cindex); 144019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 144119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (n == NULL) { 144219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS 144319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson t->stats.null_node_hit++; 144419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif 144519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson goto backtrace; 144619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 144719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 144891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (IS_LEAF(n)) { 14495b4704419cbd0b7597a91c19f9e8e8b17c1af071David S. Miller ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags); 14502e655571c618434c24ac2ca989374fdd84470d6dBen Hutchings if (ret > 0) 145191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson goto backtrace; 1452a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger goto found; 145391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson } 145491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 145591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson cn = (struct tnode *)n; 145619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 145791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson /* 145891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * It's a tnode, and we can do some extra checks here if we 145991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * like, to avoid descending into a dead-end branch. 146091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * This tnode is in the parent's child array at index 146191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * key[p_pos..p_pos+p_bits] but potentially with some bits 146291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * chopped off, so in reality the index may be just a 146391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * subprefix, padded with zero at the end. 146491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * We can also take a look at any skipped bits in this 146591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * tnode - everything up to p_pos is supposed to be ok, 146691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * and the non-chopped bits of the index (se previous 146791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * paragraph) are also guaranteed ok, but the rest is 146891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * considered unknown. 146991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * 147091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * The skipped bits are key[pos+bits..cn->pos]. 147191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson */ 147219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 147391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson /* If current_prefix_length < pos+bits, we are already doing 147491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * actual prefix matching, which means everything from 147591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * pos+(bits-chopped_off) onward must be zero along some 147691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * branch of this subtree - otherwise there is *no* valid 147791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * prefix present. Here we can only check the skipped 147891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * bits. Remember, since we have already indexed into the 147991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * parent's child array, we know that the bits we chopped of 148091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * *are* zero. 148191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson */ 148219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1483a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger /* NOTA BENE: Checking only skipped bits 1484a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger for the new node here */ 148519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 148691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (current_prefix_length < pos+bits) { 148791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (tkey_extract_bits(cn->key, current_prefix_length, 1488a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger cn->pos - current_prefix_length) 1489a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger || !(cn->child[0])) 149091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson goto backtrace; 149191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson } 149219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 149391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson /* 149491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * If chopped_off=0, the index is fully validated and we 149591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * only need to look at the skipped bits for this, the new, 149691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * tnode. What we actually want to do is to find out if 149791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * these skipped bits match our key perfectly, or if we will 149891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * have to count on finding a matching prefix further down, 149991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * because if we do, we would like to have some way of 150091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * verifying the existence of such a prefix at this point. 150191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson */ 150219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 150391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson /* The only thing we can do at this point is to verify that 150491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * any such matching prefix can indeed be a prefix to our 150591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * key, and if the bits in the node we are inspecting that 150691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * do not match our key are not ZERO, this cannot be true. 150791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * Thus, find out where there is a mismatch (before cn->pos) 150891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * and verify that all the mismatching bits are zero in the 150991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson * new tnode's key. 151091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson */ 151119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1512a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger /* 1513a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger * Note: We aren't very concerned about the piece of 1514a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger * the key that precede pn->pos+pn->bits, since these 1515a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger * have already been checked. The bits after cn->pos 1516a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger * aren't checked since these are by definition 1517a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger * "unknown" at this point. Thus, what we want to see 1518a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger * is if we are about to enter the "prefix matching" 1519a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger * state, and in that case verify that the skipped 1520a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger * bits that will prevail throughout this subtree are 1521a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger * zero, as they have to be if we are to find a 1522a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger * matching prefix. 152391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson */ 152491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 1525874ffa8f72444d6253d2669fed304875c128f86bEric Dumazet pref_mismatch = mask_pfx(cn->key ^ key, cn->pos); 152691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 1527a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger /* 1528a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger * In short: If skipped bits in this node do not match 1529a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger * the search key, enter the "prefix matching" 1530a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger * state.directly. 153191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson */ 153291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (pref_mismatch) { 153379cda75a107da0d49732b5cb642b456264dd7e0eEric Dumazet /* fls(x) = __fls(x) + 1 */ 153479cda75a107da0d49732b5cb642b456264dd7e0eEric Dumazet int mp = KEYLENGTH - __fls(pref_mismatch) - 1; 153591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 1536874ffa8f72444d6253d2669fed304875c128f86bEric Dumazet if (tkey_extract_bits(cn->key, mp, cn->pos - mp) != 0) 153791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson goto backtrace; 153891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 153991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (current_prefix_length >= cn->pos) 154091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson current_prefix_length = mp; 1541c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger } 1542a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger 154391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson pn = (struct tnode *)n; /* Descend */ 154491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson chopped_off = 0; 154591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson continue; 154691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 154719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonbacktrace: 154819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson chopped_off++; 154919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 155019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* As zero don't change the child key (cindex) */ 1551a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger while ((chopped_off <= pn->bits) 1552a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger && !(cindex & (1<<(chopped_off-1)))) 155319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson chopped_off++; 155419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 155519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* Decrease current_... with bits chopped off */ 155619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (current_prefix_length > pn->pos + pn->bits - chopped_off) 1557a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger current_prefix_length = pn->pos + pn->bits 1558a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger - chopped_off; 155991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 156019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* 1561c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger * Either we do the actual chop off according or if we have 156219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson * chopped off all bits in this tnode walk up to our parent. 156319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson */ 156419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 156591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (chopped_off <= pn->bits) { 156619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson cindex &= ~(1 << (chopped_off-1)); 156791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson } else { 1568b299e4f001cfa16205f9121f4630970049652268David S. Miller struct tnode *parent = node_parent_rcu((struct rt_trie_node *) pn); 15690680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger if (!parent) 157019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson goto failed; 157191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 157219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson /* Get Child's index */ 15730680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger cindex = tkey_extract_bits(pn->key, parent->pos, parent->bits); 15740680191642c27c81c9be4557d9c6aa3487c15f69Stephen Hemminger pn = parent; 157519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson chopped_off = 0; 157619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 157719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#ifdef CONFIG_IP_FIB_TRIE_STATS 157819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson t->stats.backtrack++; 157919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif 158019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson goto backtrace; 1581c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger } 158219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 158319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfailed: 1584c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger ret = 1; 158519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olssonfound: 15862373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson rcu_read_unlock(); 158719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return ret; 158819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 15896fc01438a94702bd160cb1b89203d9b97ae68cedFlorian WestphalEXPORT_SYMBOL_GPL(fib_table_lookup); 159019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 15919195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger/* 15929195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger * Remove the leaf and return parent. 15939195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger */ 15949195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemmingerstatic void trie_leaf_remove(struct trie *t, struct leaf *l) 159519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 1596b299e4f001cfa16205f9121f4630970049652268David S. Miller struct tnode *tp = node_parent((struct rt_trie_node *) l); 1597c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 15989195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger pr_debug("entering trie_leaf_remove(%p)\n", l); 159919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1600c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (tp) { 16019195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger t_key cindex = tkey_extract_bits(l->key, tp->pos, tp->bits); 160261648d91fc278fd1d500da8061d17e6920cd3500Lin Ming put_child(tp, cindex, NULL); 16037b85576d15bf2574b0a451108f59f9ad4170dd3fJarek Poplawski trie_rebalance(t, tp); 160491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson } else 1605a9b3cd7f323b2e57593e7215362a7b02fc933e3aStephen Hemminger RCU_INIT_POINTER(t->trie, NULL); 160619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1607387a5487f5a1f8bfc3b2c5818e50dfd19eeb4f3fStephen Hemminger free_leaf(l); 160819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 160919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1610d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson/* 1611d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson * Caller must hold RTNL. 1612d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson */ 161316c6cf8bb471392fd09b48b7c27e7d83a446b4bcStephen Hemmingerint fib_table_delete(struct fib_table *tb, struct fib_config *cfg) 161419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 161519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct trie *t = (struct trie *) tb->tb_data; 161619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson u32 key, mask; 16174e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf int plen = cfg->fc_dst_len; 16184e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf u8 tos = cfg->fc_tos; 161919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct fib_alias *fa, *fa_to_delete; 162019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct list_head *fa_head; 162119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct leaf *l; 162291b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson struct leaf_info *li; 162391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 1624c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (plen > 32) 162519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return -EINVAL; 162619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 16274e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf key = ntohl(cfg->fc_dst); 162891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson mask = ntohl(inet_make_mask(plen)); 162919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1630c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (key & ~mask) 163119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return -EINVAL; 163219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 163319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson key = key & mask; 163419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson l = fib_find_node(t, key); 163519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1636c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (!l) 163719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return -ESRCH; 163819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1639ad5b310228da567e35a2ea5dcb2fd62e3a36654eIgor Maravic li = find_leaf_info(l, plen); 1640ad5b310228da567e35a2ea5dcb2fd62e3a36654eIgor Maravic 1641ad5b310228da567e35a2ea5dcb2fd62e3a36654eIgor Maravic if (!li) 1642ad5b310228da567e35a2ea5dcb2fd62e3a36654eIgor Maravic return -ESRCH; 1643ad5b310228da567e35a2ea5dcb2fd62e3a36654eIgor Maravic 1644ad5b310228da567e35a2ea5dcb2fd62e3a36654eIgor Maravic fa_head = &li->falh; 164519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson fa = fib_find_alias(fa_head, tos, 0); 164619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 164719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (!fa) 164819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return -ESRCH; 164919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 16500c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger pr_debug("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t); 165119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 165219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson fa_to_delete = NULL; 1653936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list); 1654936f6f8e1bc46834bbb3e3fa3ac13ab44f1e7ba6Julian Anastasov list_for_each_entry_continue(fa, fa_head, fa_list) { 165519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct fib_info *fi = fa->fa_info; 165619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 165719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (fa->fa_tos != tos) 165819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson break; 165919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 16604e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) && 16614e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf (cfg->fc_scope == RT_SCOPE_NOWHERE || 166237e826c513883099c298317bad1b3b677b2905fbDavid S. Miller fa->fa_info->fib_scope == cfg->fc_scope) && 166374cb3c108bc0f599a4eb40980db8580cfba725c9Julian Anastasov (!cfg->fc_prefsrc || 166474cb3c108bc0f599a4eb40980db8580cfba725c9Julian Anastasov fi->fib_prefsrc == cfg->fc_prefsrc) && 16654e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf (!cfg->fc_protocol || 16664e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf fi->fib_protocol == cfg->fc_protocol) && 16674e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf fib_nh_match(cfg, fi) == 0) { 166819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson fa_to_delete = fa; 166919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson break; 167019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 167119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 167219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 167391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (!fa_to_delete) 167491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson return -ESRCH; 167519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 167691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson fa = fa_to_delete; 16774e902c57417c4c285b98ba2722468d1c3ed83d1bThomas Graf rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, 1678b8f558313506b5bc435f2e031f3bec4b1725098eMilan Kocian &cfg->fc_nlinfo, 0); 167991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 16802373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson list_del_rcu(&fa->fa_list); 168119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 168221d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller if (!plen) 168321d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller tb->tb_num_default--; 168421d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller 168591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (list_empty(fa_head)) { 16862373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson hlist_del_rcu(&li->hlist); 168791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson free_leaf_info(li); 16882373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson } 168919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 169091b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (hlist_empty(&l->list)) 16919195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger trie_leaf_remove(t, l); 169219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 169391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson if (fa->fa_state & FA_S_ACCESSED) 16944ccfe6d4109252dfadcd6885f33ed600ee03dbf8Nicolas Dichtel rt_cache_flush(cfg->fc_nlinfo.nl_net); 169519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 16962373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson fib_release_info(fa->fa_info); 16972373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson alias_free_mem_rcu(fa); 169891b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson return 0; 169919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 170019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1701ef3660ce0649fa10265455f539b72607cff53d02Stephen Hemmingerstatic int trie_flush_list(struct list_head *head) 170219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 170319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct fib_alias *fa, *fa_node; 170419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int found = 0; 170519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 170619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson list_for_each_entry_safe(fa, fa_node, head, fa_list) { 170719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct fib_info *fi = fa->fa_info; 170819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 17092373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson if (fi && (fi->fib_flags & RTNH_F_DEAD)) { 17102373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson list_del_rcu(&fa->fa_list); 17112373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson fib_release_info(fa->fa_info); 17122373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson alias_free_mem_rcu(fa); 171319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson found++; 171419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 171519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 171619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return found; 171719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 171819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1719ef3660ce0649fa10265455f539b72607cff53d02Stephen Hemmingerstatic int trie_flush_leaf(struct leaf *l) 172019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 172119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int found = 0; 172219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct hlist_head *lih = &l->list; 1723b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin struct hlist_node *tmp; 172419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct leaf_info *li = NULL; 172519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1726b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin hlist_for_each_entry_safe(li, tmp, lih, hlist) { 1727ef3660ce0649fa10265455f539b72607cff53d02Stephen Hemminger found += trie_flush_list(&li->falh); 172819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 172919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (list_empty(&li->falh)) { 17302373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson hlist_del_rcu(&li->hlist); 173119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson free_leaf_info(li); 173219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 173319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 173419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return found; 173519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 173619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 173782cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger/* 173882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger * Scan for the next right leaf starting at node p->child[idx] 173982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger * Since we have back pointer, no recursion necessary. 174082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger */ 1741b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c) 174219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 174382cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger do { 174482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger t_key idx; 1745c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 1746c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger if (c) 174782cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger idx = tkey_extract_bits(c->key, p->pos, p->bits) + 1; 1748c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger else 174982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger idx = 0; 17502373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 175182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger while (idx < 1u << p->bits) { 175282cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger c = tnode_get_child_rcu(p, idx++); 17532373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson if (!c) 175491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson continue; 175591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 1756aab515d7c32a34300312416c50314e755ea6f765Eric Dumazet if (IS_LEAF(c)) 175782cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger return (struct leaf *) c; 175882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger 175982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger /* Rescan start scanning in new node */ 176082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger p = (struct tnode *) c; 176182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger idx = 0; 176219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 176382cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger 176482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger /* Node empty, walk back up to parent */ 1765b299e4f001cfa16205f9121f4630970049652268David S. Miller c = (struct rt_trie_node *) p; 1766a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet } while ((p = node_parent_rcu(c)) != NULL); 176782cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger 176882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger return NULL; /* Root of trie */ 176982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger} 177082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger 177182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemmingerstatic struct leaf *trie_firstleaf(struct trie *t) 177282cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger{ 1773a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet struct tnode *n = (struct tnode *)rcu_dereference_rtnl(t->trie); 177482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger 177582cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger if (!n) 177682cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger return NULL; 177782cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger 177882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger if (IS_LEAF(n)) /* trie is just a leaf */ 177982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger return (struct leaf *) n; 178082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger 178182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger return leaf_walk_rcu(n, NULL); 178282cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger} 178382cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger 178482cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemmingerstatic struct leaf *trie_nextleaf(struct leaf *l) 178582cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger{ 1786b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *c = (struct rt_trie_node *) l; 1787b902e5735272b6a79fe2853180b2ad6658aa9678Jarek Poplawski struct tnode *p = node_parent_rcu(c); 178882cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger 178982cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger if (!p) 179082cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger return NULL; /* trie with just one leaf */ 179182cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger 179282cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger return leaf_walk_rcu(p, c); 179319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 179419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 179571d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemmingerstatic struct leaf *trie_leafindex(struct trie *t, int index) 179671d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger{ 179771d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger struct leaf *l = trie_firstleaf(t); 179871d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger 1799ec28cf738d899e9d0652108e1986101771aacb2eStephen Hemminger while (l && index-- > 0) 180071d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger l = trie_nextleaf(l); 1801ec28cf738d899e9d0652108e1986101771aacb2eStephen Hemminger 180271d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger return l; 180371d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger} 180471d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger 180571d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger 1806d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson/* 1807d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson * Caller must hold RTNL. 1808d562f1f8a92035d5d4681c178fccb991ce57f33aRobert Olsson */ 180916c6cf8bb471392fd09b48b7c27e7d83a446b4bcStephen Hemmingerint fib_table_flush(struct fib_table *tb) 181019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 181119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct trie *t = (struct trie *) tb->tb_data; 18129195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger struct leaf *l, *ll = NULL; 181382cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger int found = 0; 181419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 181582cfbb008572b1a953091ef78f767aa3ca213092Stephen Hemminger for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) { 1816ef3660ce0649fa10265455f539b72607cff53d02Stephen Hemminger found += trie_flush_leaf(l); 181719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 181819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (ll && hlist_empty(&ll->list)) 18199195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger trie_leaf_remove(t, ll); 182019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson ll = l; 182119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 182219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 182319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (ll && hlist_empty(&ll->list)) 18249195bef7fb0ba0a91d5ffa566bcf8e007e3c7172Stephen Hemminger trie_leaf_remove(t, ll); 182519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 18260c7770c740156c8802c23d24fc094d06967d997dStephen Hemminger pr_debug("trie_flush found=%d\n", found); 182719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return found; 182819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 182919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 18304aa2c466a7733af093a526e9d1cdd0b3b90d47e9Pavel Emelyanovvoid fib_free_table(struct fib_table *tb) 18314aa2c466a7733af093a526e9d1cdd0b3b90d47e9Pavel Emelyanov{ 18324aa2c466a7733af093a526e9d1cdd0b3b90d47e9Pavel Emelyanov kfree(tb); 18334aa2c466a7733af093a526e9d1cdd0b3b90d47e9Pavel Emelyanov} 18344aa2c466a7733af093a526e9d1cdd0b3b90d47e9Pavel Emelyanov 1835a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemmingerstatic int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, 1836a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger struct fib_table *tb, 183719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct sk_buff *skb, struct netlink_callback *cb) 183819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 183919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson int i, s_i; 184019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct fib_alias *fa; 184132ab5f80334fc067386c4c56c434010c01cff6b9Al Viro __be32 xkey = htonl(key); 184219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 184371d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger s_i = cb->args[5]; 184419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson i = 0; 184519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 18462373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson /* rcu_read_lock is hold by caller */ 18472373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 18482373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson list_for_each_entry_rcu(fa, fah, fa_list) { 184919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (i < s_i) { 185019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson i++; 185119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson continue; 185219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 185319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 185415e473046cb6e5d18a4d0057e61d76315230382bEric W. Biederman if (fib_dump_info(skb, NETLINK_CB(cb->skb).portid, 185519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson cb->nlh->nlmsg_seq, 185619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson RTM_NEWROUTE, 185719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tb->tb_id, 185819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson fa->fa_type, 1859be403ea1856f1428b5912b42184acbba808c41d6Thomas Graf xkey, 186019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson plen, 186119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson fa->fa_tos, 186264347f786d13349d6a6f812f3a83c269e26c0136Stephen Hemminger fa->fa_info, NLM_F_MULTI) < 0) { 186371d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger cb->args[5] = i; 186419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return -1; 186591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson } 186619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson i++; 186719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 186871d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger cb->args[5] = i; 186919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return skb->len; 187019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 187119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1872a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemmingerstatic int fn_trie_dump_leaf(struct leaf *l, struct fib_table *tb, 1873a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger struct sk_buff *skb, struct netlink_callback *cb) 187419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 1875a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger struct leaf_info *li; 1876a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger int i, s_i; 187719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 187871d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger s_i = cb->args[4]; 1879a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger i = 0; 188019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1881a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger /* rcu_read_lock is hold by caller */ 1882b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin hlist_for_each_entry_rcu(li, &l->list, hlist) { 1883a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger if (i < s_i) { 1884a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger i++; 188519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson continue; 1886a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger } 188791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 1888a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger if (i > s_i) 188971d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger cb->args[5] = 0; 189019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1891a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger if (list_empty(&li->falh)) 189219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson continue; 189319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1894a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger if (fn_trie_dump_fa(l->key, li->plen, &li->falh, tb, skb, cb) < 0) { 189571d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger cb->args[4] = i; 189619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return -1; 189719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 1898a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger i++; 189919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 1900a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger 190171d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger cb->args[4] = i; 190219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return skb->len; 190319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 190419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 190516c6cf8bb471392fd09b48b7c27e7d83a446b4bcStephen Hemmingerint fib_table_dump(struct fib_table *tb, struct sk_buff *skb, 190616c6cf8bb471392fd09b48b7c27e7d83a446b4bcStephen Hemminger struct netlink_callback *cb) 190719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 1908a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger struct leaf *l; 190919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct trie *t = (struct trie *) tb->tb_data; 1910d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger t_key key = cb->args[2]; 191171d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger int count = cb->args[3]; 191219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 19132373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson rcu_read_lock(); 1914d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger /* Dump starting at last key. 1915d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger * Note: 0.0.0.0/0 (ie default) is first key. 1916d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger */ 191771d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger if (count == 0) 1918d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger l = trie_firstleaf(t); 1919d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger else { 192071d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger /* Normally, continue from last key, but if that is missing 192171d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger * fallback to using slow rescan 192271d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger */ 1923d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger l = fib_find_node(t, key); 192471d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger if (!l) 192571d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger l = trie_leafindex(t, count); 1926d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger } 1927a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger 1928d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger while (l) { 1929d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger cb->args[2] = l->key; 1930a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) { 193171d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger cb->args[3] = count; 1932a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger rcu_read_unlock(); 1933a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger return -1; 193419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 1935d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger 193671d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger ++count; 1937d5ce8a0e97073169b5fe0b7c52bd020cdb017dfaStephen Hemminger l = trie_nextleaf(l); 193871d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger memset(&cb->args[4], 0, 193971d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger sizeof(cb->args) - 4*sizeof(cb->args[0])); 194019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 194171d67e666e73e3b7e9ef124745ee2e454ac04be8Stephen Hemminger cb->args[3] = count; 19422373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson rcu_read_unlock(); 1943a88ee229253b31e3a844b30525ff77fbfe3111d3Stephen Hemminger 194419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return skb->len; 194519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 194619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 19475348ba85a02ffe80a8af33a524b6610966760d3dDavid S. Millervoid __init fib_trie_init(void) 19487f9b80529b8a2ad8b3273b15fb444a0e34b760a9Stephen Hemminger{ 1949a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger fn_alias_kmem = kmem_cache_create("ip_fib_alias", 1950a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger sizeof(struct fib_alias), 1951bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger 0, SLAB_PANIC, NULL); 1952bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger 1953bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger trie_leaf_kmem = kmem_cache_create("ip_fib_trie", 1954bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger max(sizeof(struct leaf), 1955bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger sizeof(struct leaf_info)), 1956bc3c8c1e02ae89668239742fd592f21e1998fa46Stephen Hemminger 0, SLAB_PANIC, NULL); 19577f9b80529b8a2ad8b3273b15fb444a0e34b760a9Stephen Hemminger} 195819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 19597f9b80529b8a2ad8b3273b15fb444a0e34b760a9Stephen Hemminger 19605348ba85a02ffe80a8af33a524b6610966760d3dDavid S. Millerstruct fib_table *fib_trie_table(u32 id) 196119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 196219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct fib_table *tb; 196319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson struct trie *t; 196419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 196519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tb = kmalloc(sizeof(struct fib_table) + sizeof(struct trie), 196619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson GFP_KERNEL); 196719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson if (tb == NULL) 196819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return NULL; 196919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 197019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson tb->tb_id = id; 1971971b893e79db0f7dccfcea15dbdebca3ca64a84dDenis V. Lunev tb->tb_default = -1; 197221d8c49e01a0c1c6eb6c750cd04110db4a539284David S. Miller tb->tb_num_default = 0; 197319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 197419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson t = (struct trie *) tb->tb_data; 1975c28a1cf448e59019fa681741963c3acaeaeb6d27Stephen Hemminger memset(t, 0, sizeof(*t)); 197619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 197719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return tb; 197819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 197919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1980cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger#ifdef CONFIG_PROC_FS 1981cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/* Depth first Trie walk iterator */ 1982cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstruct fib_trie_iter { 19831c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev struct seq_net_private p; 19843d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger struct fib_table *tb; 1985cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger struct tnode *tnode; 1986a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet unsigned int index; 1987a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet unsigned int depth; 1988cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}; 198919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 1990b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic struct rt_trie_node *fib_trie_get_next(struct fib_trie_iter *iter) 199119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 1992cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger struct tnode *tn = iter->tnode; 1993a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet unsigned int cindex = iter->index; 1994cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger struct tnode *p; 199519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 19966640e69731b42fd5e3d2b26201c8b34fc897a0eeEric W. Biederman /* A single entry routing table */ 19976640e69731b42fd5e3d2b26201c8b34fc897a0eeEric W. Biederman if (!tn) 19986640e69731b42fd5e3d2b26201c8b34fc897a0eeEric W. Biederman return NULL; 19996640e69731b42fd5e3d2b26201c8b34fc897a0eeEric W. Biederman 2000cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger pr_debug("get_next iter={node=%p index=%d depth=%d}\n", 2001cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger iter->tnode, iter->index, iter->depth); 2002cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerrescan: 2003cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger while (cindex < (1<<tn->bits)) { 2004b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *n = tnode_get_child_rcu(tn, cindex); 200519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2006cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (n) { 2007cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (IS_LEAF(n)) { 2008cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger iter->tnode = tn; 2009cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger iter->index = cindex + 1; 2010cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger } else { 2011cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger /* push down one level */ 2012cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger iter->tnode = (struct tnode *) n; 2013cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger iter->index = 0; 2014cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger ++iter->depth; 2015cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger } 2016cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger return n; 2017cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger } 201819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2019cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger ++cindex; 2020cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger } 202191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 2022cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger /* Current node exhausted, pop back up */ 2023b299e4f001cfa16205f9121f4630970049652268David S. Miller p = node_parent_rcu((struct rt_trie_node *)tn); 2024cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (p) { 2025cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1; 2026cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger tn = p; 2027cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger --iter->depth; 2028cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger goto rescan; 202919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 2030cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger 2031cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger /* got root? */ 2032cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger return NULL; 203319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 203419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2035b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic struct rt_trie_node *fib_trie_get_first(struct fib_trie_iter *iter, 2036cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger struct trie *t) 203719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 2038b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *n; 20395ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson 2040132adf54639cf7dd9315e8df89c2faa59f6e46d9Stephen Hemminger if (!t) 20415ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson return NULL; 20425ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson 20435ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson n = rcu_dereference(t->trie); 20443d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger if (!n) 20455ddf0eb2bfd613e941dd8748870c71da2e5ad409Robert Olsson return NULL; 204619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 20473d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger if (IS_TNODE(n)) { 20483d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger iter->tnode = (struct tnode *) n; 20493d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger iter->index = 0; 20503d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger iter->depth = 1; 20513d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger } else { 20523d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger iter->tnode = NULL; 20533d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger iter->index = 0; 20543d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger iter->depth = 0; 205591b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson } 20563d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger 20573d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger return n; 2058cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger} 205991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 2060cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void trie_collect_stats(struct trie *t, struct trie_stat *s) 2061cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{ 2062b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *n; 2063cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger struct fib_trie_iter iter; 206491b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 2065cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger memset(s, 0, sizeof(*s)); 206691b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 2067cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger rcu_read_lock(); 20683d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger for (n = fib_trie_get_first(&iter, t); n; n = fib_trie_get_next(&iter)) { 2069cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (IS_LEAF(n)) { 2070936722922f6d2366378de606a40c14f96915474dStephen Hemminger struct leaf *l = (struct leaf *)n; 2071936722922f6d2366378de606a40c14f96915474dStephen Hemminger struct leaf_info *li; 2072936722922f6d2366378de606a40c14f96915474dStephen Hemminger 2073cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger s->leaves++; 2074cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger s->totdepth += iter.depth; 2075cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (iter.depth > s->maxdepth) 2076cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger s->maxdepth = iter.depth; 2077936722922f6d2366378de606a40c14f96915474dStephen Hemminger 2078b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin hlist_for_each_entry_rcu(li, &l->list, hlist) 2079936722922f6d2366378de606a40c14f96915474dStephen Hemminger ++s->prefixes; 2080cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger } else { 2081cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger const struct tnode *tn = (const struct tnode *) n; 2082cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger int i; 2083cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger 2084cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger s->tnodes++; 2085132adf54639cf7dd9315e8df89c2faa59f6e46d9Stephen Hemminger if (tn->bits < MAX_STAT_DEPTH) 208606ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson s->nodesizes[tn->bits]++; 208706ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson 2088cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger for (i = 0; i < (1<<tn->bits); i++) 2089cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (!tn->child[i]) 2090cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger s->nullpointers++; 209119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 209219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 20932373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson rcu_read_unlock(); 209419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 209519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2096cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/* 2097cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger * This outputs /proc/net/fib_triestats 2098cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger */ 2099cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void trie_show_stats(struct seq_file *seq, struct trie_stat *stat) 210019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 2101a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet unsigned int i, max, pointers, bytes, avdepth; 2102c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 2103cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (stat->leaves) 2104cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger avdepth = stat->totdepth*100 / stat->leaves; 2105cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger else 2106cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger avdepth = 0; 210791b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 2108a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger seq_printf(seq, "\tAver depth: %u.%02d\n", 2109a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger avdepth / 100, avdepth % 100); 2110cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger seq_printf(seq, "\tMax depth: %u\n", stat->maxdepth); 211191b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 2112cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger seq_printf(seq, "\tLeaves: %u\n", stat->leaves); 2113cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger bytes = sizeof(struct leaf) * stat->leaves; 2114936722922f6d2366378de606a40c14f96915474dStephen Hemminger 2115936722922f6d2366378de606a40c14f96915474dStephen Hemminger seq_printf(seq, "\tPrefixes: %u\n", stat->prefixes); 2116936722922f6d2366378de606a40c14f96915474dStephen Hemminger bytes += sizeof(struct leaf_info) * stat->prefixes; 2117936722922f6d2366378de606a40c14f96915474dStephen Hemminger 2118187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger seq_printf(seq, "\tInternal nodes: %u\n\t", stat->tnodes); 2119cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger bytes += sizeof(struct tnode) * stat->tnodes; 212019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 212106ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson max = MAX_STAT_DEPTH; 212206ef921d60bbf6f765d1b9492fb4fc88ac7814bdRobert Olsson while (max > 0 && stat->nodesizes[max-1] == 0) 2123cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger max--; 212419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2125cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger pointers = 0; 2126f585a991e1d1612265f0d4e812f77e40dd54975bJerry Snitselaar for (i = 1; i < max; i++) 2127cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (stat->nodesizes[i] != 0) { 2128187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger seq_printf(seq, " %u: %u", i, stat->nodesizes[i]); 2129cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger pointers += (1<<i) * stat->nodesizes[i]; 2130cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger } 2131cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger seq_putc(seq, '\n'); 2132187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger seq_printf(seq, "\tPointers: %u\n", pointers); 21332373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 2134b299e4f001cfa16205f9121f4630970049652268David S. Miller bytes += sizeof(struct rt_trie_node *) * pointers; 2135187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger seq_printf(seq, "Null ptrs: %u\n", stat->nullpointers); 2136187b5188a78694fa6608fa1252d5197a7b3ab076Stephen Hemminger seq_printf(seq, "Total size: %u kB\n", (bytes + 1023) / 1024); 213766a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger} 21382373ce1ca04dd46bf2b8b0f9a799eb2a90da92fbRobert Olsson 2139cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger#ifdef CONFIG_IP_FIB_TRIE_STATS 214066a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemmingerstatic void trie_show_usage(struct seq_file *seq, 214166a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger const struct trie_use_stats *stats) 214266a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger{ 214366a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger seq_printf(seq, "\nCounters:\n---------\n"); 2144a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger seq_printf(seq, "gets = %u\n", stats->gets); 2145a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger seq_printf(seq, "backtracks = %u\n", stats->backtrack); 2146a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger seq_printf(seq, "semantic match passed = %u\n", 2147a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger stats->semantic_match_passed); 2148a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger seq_printf(seq, "semantic match miss = %u\n", 2149a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger stats->semantic_match_miss); 2150a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger seq_printf(seq, "null node hit= %u\n", stats->null_node_hit); 2151a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger seq_printf(seq, "skipped node resize = %u\n\n", 2152a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger stats->resize_node_skipped); 2153cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger} 215466a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger#endif /* CONFIG_IP_FIB_TRIE_STATS */ 215566a2f7fd2fddee1ddc5d1d286cd832e50a97258eStephen Hemminger 21563d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemmingerstatic void fib_table_print(struct seq_file *seq, struct fib_table *tb) 2157d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger{ 21583d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger if (tb->tb_id == RT_TABLE_LOCAL) 21593d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger seq_puts(seq, "Local:\n"); 21603d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger else if (tb->tb_id == RT_TABLE_MAIN) 21613d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger seq_puts(seq, "Main:\n"); 21623d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger else 21633d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger seq_printf(seq, "Id %d:\n", tb->tb_id); 2164d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger} 216519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 21663d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger 2167cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_triestat_seq_show(struct seq_file *seq, void *v) 2168cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{ 21691c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev struct net *net = (struct net *)seq->private; 21703d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger unsigned int h; 2171877a9bff3889512d7326d6bf0ba6ed3ddda6d772Eric W. Biederman 2172d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger seq_printf(seq, 2173a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger "Basic info: size of leaf:" 2174a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger " %Zd bytes, size of tnode: %Zd bytes.\n", 2175d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger sizeof(struct leaf), sizeof(struct tnode)); 2176d717a9a62049a03e85c3c2dd3399416eeb34a8beStephen Hemminger 21773d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger for (h = 0; h < FIB_TABLE_HASHSZ; h++) { 21783d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger struct hlist_head *head = &net->ipv4.fib_table_hash[h]; 21793d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger struct fib_table *tb; 21803d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger 2181b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin hlist_for_each_entry_rcu(tb, head, tb_hlist) { 21823d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger struct trie *t = (struct trie *) tb->tb_data; 21833d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger struct trie_stat stat; 2184877a9bff3889512d7326d6bf0ba6ed3ddda6d772Eric W. Biederman 21853d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger if (!t) 21863d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger continue; 21873d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger 21883d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger fib_table_print(seq, tb); 21893d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger 21903d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger trie_collect_stats(t, &stat); 21913d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger trie_show_stats(seq, &stat); 21923d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger#ifdef CONFIG_IP_FIB_TRIE_STATS 21933d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger trie_show_usage(seq, &t->stats); 21943d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger#endif 21953d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger } 21963d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger } 219719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2198cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger return 0; 219919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 220019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2201cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_triestat_seq_open(struct inode *inode, struct file *file) 220219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 2203de05c557b24c7dffc6d392e3db120cf11c9f6ae7Pavel Emelyanov return single_open_net(inode, file, fib_triestat_seq_show); 22041c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev} 22051c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev 22069a32144e9d7b4e21341174b1a83b82a82353be86Arjan van de Venstatic const struct file_operations fib_triestat_fops = { 2207cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .owner = THIS_MODULE, 2208cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .open = fib_triestat_seq_open, 2209cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .read = seq_read, 2210cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .llseek = seq_lseek, 2211b6fcbdb4f283f7ba67cec3cda6be23da8e959031Pavel Emelyanov .release = single_release_net, 2212cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}; 2213cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger 2214b299e4f001cfa16205f9121f4630970049652268David S. Millerstatic struct rt_trie_node *fib_trie_get_idx(struct seq_file *seq, loff_t pos) 221519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 22161218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki struct fib_trie_iter *iter = seq->private; 22171218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki struct net *net = seq_file_net(seq); 2218cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger loff_t idx = 0; 22193d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger unsigned int h; 2220cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger 22213d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger for (h = 0; h < FIB_TABLE_HASHSZ; h++) { 22223d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger struct hlist_head *head = &net->ipv4.fib_table_hash[h]; 22233d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger struct fib_table *tb; 2224cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger 2225b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin hlist_for_each_entry_rcu(tb, head, tb_hlist) { 2226b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *n; 22273d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger 22283d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger for (n = fib_trie_get_first(iter, 22293d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger (struct trie *) tb->tb_data); 22303d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger n; n = fib_trie_get_next(iter)) 22313d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger if (pos == idx++) { 22323d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger iter->tb = tb; 22333d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger return n; 22343d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger } 22353d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger } 2236cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger } 22373d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger 223819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return NULL; 223919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 224019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2241cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos) 2242c95aaf9af5a1f6dee56d1f2ab4915cd722d608daStephen Hemminger __acquires(RCU) 224319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 2244cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger rcu_read_lock(); 22451218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki return fib_trie_get_idx(seq, *pos); 224619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 224719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2248cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos) 224919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 2250cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger struct fib_trie_iter *iter = seq->private; 22511218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki struct net *net = seq_file_net(seq); 22523d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger struct fib_table *tb = iter->tb; 22533d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger struct hlist_node *tb_node; 22543d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger unsigned int h; 2255b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *n; 2256cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger 225719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson ++*pos; 22583d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger /* next node in same table */ 22593d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger n = fib_trie_get_next(iter); 22603d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger if (n) 22613d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger return n; 226219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 22633d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger /* walk rest of this hash chain */ 22643d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger h = tb->tb_id & (FIB_TABLE_HASHSZ - 1); 22650a5c047507aaaf00519921336d19c0f8f5f9f363Eric Dumazet while ((tb_node = rcu_dereference(hlist_next_rcu(&tb->tb_hlist)))) { 22663d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger tb = hlist_entry(tb_node, struct fib_table, tb_hlist); 22673d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger n = fib_trie_get_first(iter, (struct trie *) tb->tb_data); 22683d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger if (n) 22693d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger goto found; 22703d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger } 227119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 22723d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger /* new hash chain */ 22733d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger while (++h < FIB_TABLE_HASHSZ) { 22743d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger struct hlist_head *head = &net->ipv4.fib_table_hash[h]; 2275b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin hlist_for_each_entry_rcu(tb, head, tb_hlist) { 22763d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger n = fib_trie_get_first(iter, (struct trie *) tb->tb_data); 22773d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger if (n) 22783d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger goto found; 22793d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger } 22803d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger } 2281cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger return NULL; 22823d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger 22833d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemmingerfound: 22843d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger iter->tb = tb; 22853d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger return n; 2286cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger} 228719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2288cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void fib_trie_seq_stop(struct seq_file *seq, void *v) 2289c95aaf9af5a1f6dee56d1f2ab4915cd722d608daStephen Hemminger __releases(RCU) 229019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 2291cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger rcu_read_unlock(); 2292cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger} 229391b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 2294cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic void seq_indent(struct seq_file *seq, int n) 2295cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{ 2296a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet while (n-- > 0) 2297a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet seq_puts(seq, " "); 2298cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger} 229919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 230028d36e3702fcbed73c38e877bcf2a8f8946b7f3dEric Dumazetstatic inline const char *rtn_scope(char *buf, size_t len, enum rt_scope_t s) 2301cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{ 2302132adf54639cf7dd9315e8df89c2faa59f6e46d9Stephen Hemminger switch (s) { 2303cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger case RT_SCOPE_UNIVERSE: return "universe"; 2304cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger case RT_SCOPE_SITE: return "site"; 2305cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger case RT_SCOPE_LINK: return "link"; 2306cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger case RT_SCOPE_HOST: return "host"; 2307cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger case RT_SCOPE_NOWHERE: return "nowhere"; 2308cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger default: 230928d36e3702fcbed73c38e877bcf2a8f8946b7f3dEric Dumazet snprintf(buf, len, "scope=%d", s); 2310cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger return buf; 2311cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger } 2312cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger} 231319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 231436cbd3dcc10384f813ec0814255f576c84f2bcd4Jan Engelhardtstatic const char *const rtn_type_names[__RTN_MAX] = { 2315cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger [RTN_UNSPEC] = "UNSPEC", 2316cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger [RTN_UNICAST] = "UNICAST", 2317cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger [RTN_LOCAL] = "LOCAL", 2318cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger [RTN_BROADCAST] = "BROADCAST", 2319cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger [RTN_ANYCAST] = "ANYCAST", 2320cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger [RTN_MULTICAST] = "MULTICAST", 2321cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger [RTN_BLACKHOLE] = "BLACKHOLE", 2322cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger [RTN_UNREACHABLE] = "UNREACHABLE", 2323cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger [RTN_PROHIBIT] = "PROHIBIT", 2324cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger [RTN_THROW] = "THROW", 2325cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger [RTN_NAT] = "NAT", 2326cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger [RTN_XRESOLVE] = "XRESOLVE", 2327cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger}; 232819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2329a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazetstatic inline const char *rtn_type(char *buf, size_t len, unsigned int t) 2330cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger{ 2331cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (t < __RTN_MAX && rtn_type_names[t]) 2332cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger return rtn_type_names[t]; 233328d36e3702fcbed73c38e877bcf2a8f8946b7f3dEric Dumazet snprintf(buf, len, "type %u", t); 2334cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger return buf; 233519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 233619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2337cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/* Pretty print the trie */ 2338cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_trie_seq_show(struct seq_file *seq, void *v) 233919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 2340cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger const struct fib_trie_iter *iter = seq->private; 2341b299e4f001cfa16205f9121f4630970049652268David S. Miller struct rt_trie_node *n = v; 2342c877efb207bf4629cfa97ac13412f7392a873485Stephen Hemminger 23433d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger if (!node_parent_rcu(n)) 23443d3b2d25a4debaff05a9e6f5c55a0d31e4334234Stephen Hemminger fib_table_print(seq, iter->tb); 2345095b8501e4168ae5a879fcb9420ac48cbd43f95aRobert Olsson 2346cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (IS_TNODE(n)) { 2347cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger struct tnode *tn = (struct tnode *) n; 2348ab66b4a7a3969077f6e2a18a0d2d849d3b84a337Stephen Hemminger __be32 prf = htonl(mask_pfx(tn->key, tn->pos)); 234991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 23501d25cd6cc2528e4af12ab18e84fe95ed78f3f21aRobert Olsson seq_indent(seq, iter->depth-1); 2351673d57e72398edfedc93fb50ff58048077c9d587Harvey Harrison seq_printf(seq, " +-- %pI4/%d %d %d %d\n", 2352673d57e72398edfedc93fb50ff58048077c9d587Harvey Harrison &prf, tn->pos, tn->bits, tn->full_children, 23531d25cd6cc2528e4af12ab18e84fe95ed78f3f21aRobert Olsson tn->empty_children); 2354e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki 2355cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger } else { 2356cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger struct leaf *l = (struct leaf *) n; 23571328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger struct leaf_info *li; 235832ab5f80334fc067386c4c56c434010c01cff6b9Al Viro __be32 val = htonl(l->key); 2359cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger 2360cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger seq_indent(seq, iter->depth); 2361673d57e72398edfedc93fb50ff58048077c9d587Harvey Harrison seq_printf(seq, " |-- %pI4\n", &val); 23621328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger 2363b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin hlist_for_each_entry_rcu(li, &l->list, hlist) { 23641328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger struct fib_alias *fa; 23651328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger 23661328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger list_for_each_entry_rcu(fa, &li->falh, fa_list) { 23671328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger char buf1[32], buf2[32]; 23681328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger 23691328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger seq_indent(seq, iter->depth+1); 23701328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger seq_printf(seq, " /%d %s %s", li->plen, 23711328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger rtn_scope(buf1, sizeof(buf1), 237237e826c513883099c298317bad1b3b677b2905fbDavid S. Miller fa->fa_info->fib_scope), 23731328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger rtn_type(buf2, sizeof(buf2), 23741328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger fa->fa_type)); 23751328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger if (fa->fa_tos) 2376b9c4d82a853713d49ac53b507964d7cf30ee408dDenis V. Lunev seq_printf(seq, " tos=%d", fa->fa_tos); 23771328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger seq_putc(seq, '\n'); 2378cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger } 2379cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger } 238019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 2381cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger 238219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return 0; 238319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 238419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2385f690808e17925fc45217eb22e8670902ecee5c1bStephen Hemmingerstatic const struct seq_operations fib_trie_seq_ops = { 2386cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .start = fib_trie_seq_start, 2387cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .next = fib_trie_seq_next, 2388cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .stop = fib_trie_seq_stop, 2389cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .show = fib_trie_seq_show, 239019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}; 239119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2392cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_trie_seq_open(struct inode *inode, struct file *file) 239319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 23941c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev return seq_open_net(inode, file, &fib_trie_seq_ops, 23951c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev sizeof(struct fib_trie_iter)); 239619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 239719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 23989a32144e9d7b4e21341174b1a83b82a82353be86Arjan van de Venstatic const struct file_operations fib_trie_fops = { 2399cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .owner = THIS_MODULE, 2400cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .open = fib_trie_seq_open, 2401cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .read = seq_read, 2402cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .llseek = seq_lseek, 24031c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev .release = seq_release_net, 240419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}; 240519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 24068315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstruct fib_route_iter { 24078315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger struct seq_net_private p; 24088315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger struct trie *main_trie; 24098315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger loff_t pos; 24108315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger t_key key; 24118315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger}; 24128315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger 24138315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstatic struct leaf *fib_route_get_idx(struct fib_route_iter *iter, loff_t pos) 24148315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger{ 24158315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger struct leaf *l = NULL; 24168315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger struct trie *t = iter->main_trie; 24178315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger 24188315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger /* use cache location of last found key */ 24198315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger if (iter->pos > 0 && pos >= iter->pos && (l = fib_find_node(t, iter->key))) 24208315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger pos -= iter->pos; 24218315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger else { 24228315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger iter->pos = 0; 24238315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger l = trie_firstleaf(t); 24248315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger } 24258315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger 24268315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger while (l && pos-- > 0) { 24278315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger iter->pos++; 24288315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger l = trie_nextleaf(l); 24298315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger } 24308315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger 24318315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger if (l) 24328315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger iter->key = pos; /* remember it */ 24338315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger else 24348315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger iter->pos = 0; /* forget it */ 24358315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger 24368315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger return l; 24378315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger} 24388315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger 24398315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstatic void *fib_route_seq_start(struct seq_file *seq, loff_t *pos) 24408315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger __acquires(RCU) 24418315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger{ 24428315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger struct fib_route_iter *iter = seq->private; 24438315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger struct fib_table *tb; 24448315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger 24458315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger rcu_read_lock(); 24461218854afa6f659be90b748cf1bc7badee954a35YOSHIFUJI Hideaki tb = fib_get_table(seq_file_net(seq), RT_TABLE_MAIN); 24478315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger if (!tb) 24488315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger return NULL; 24498315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger 24508315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger iter->main_trie = (struct trie *) tb->tb_data; 24518315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger if (*pos == 0) 24528315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger return SEQ_START_TOKEN; 24538315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger else 24548315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger return fib_route_get_idx(iter, *pos - 1); 24558315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger} 24568315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger 24578315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstatic void *fib_route_seq_next(struct seq_file *seq, void *v, loff_t *pos) 24588315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger{ 24598315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger struct fib_route_iter *iter = seq->private; 24608315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger struct leaf *l = v; 24618315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger 24628315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger ++*pos; 24638315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger if (v == SEQ_START_TOKEN) { 24648315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger iter->pos = 0; 24658315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger l = trie_firstleaf(iter->main_trie); 24668315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger } else { 24678315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger iter->pos++; 24688315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger l = trie_nextleaf(l); 24698315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger } 24708315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger 24718315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger if (l) 24728315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger iter->key = l->key; 24738315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger else 24748315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger iter->pos = 0; 24758315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger return l; 24768315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger} 24778315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger 24788315f5d80a90247bf92232f92ca49933ac49327bStephen Hemmingerstatic void fib_route_seq_stop(struct seq_file *seq, void *v) 24798315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger __releases(RCU) 24808315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger{ 24818315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger rcu_read_unlock(); 24828315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger} 24838315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger 2484a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazetstatic unsigned int fib_flag_trans(int type, __be32 mask, const struct fib_info *fi) 248519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 2486a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet unsigned int flags = 0; 248719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2488a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet if (type == RTN_UNREACHABLE || type == RTN_PROHIBIT) 2489a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet flags = RTF_REJECT; 2490cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (fi && fi->fib_nh->nh_gw) 2491cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger flags |= RTF_GATEWAY; 249232ab5f80334fc067386c4c56c434010c01cff6b9Al Viro if (mask == htonl(0xFFFFFFFF)) 2493cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger flags |= RTF_HOST; 2494cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger flags |= RTF_UP; 2495cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger return flags; 249619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 249719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2498cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger/* 2499cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger * This outputs /proc/net/route. 2500cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger * The format of the file is not supposed to be changed 2501a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet * and needs to be same as fib_hash output to avoid breaking 2502cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger * legacy utilities 2503cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger */ 2504cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_route_seq_show(struct seq_file *seq, void *v) 250519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 2506cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger struct leaf *l = v; 25071328042e268c936189f15eba5bd9a5a4605a8581Stephen Hemminger struct leaf_info *li; 250819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2509cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (v == SEQ_START_TOKEN) { 2510cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway " 2511cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU" 2512cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger "\tWindow\tIRTT"); 2513cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger return 0; 2514cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger } 251519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2516b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin hlist_for_each_entry_rcu(li, &l->list, hlist) { 2517cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger struct fib_alias *fa; 251832ab5f80334fc067386c4c56c434010c01cff6b9Al Viro __be32 mask, prefix; 251991b9a277fc4d207249e459a455abf804ebb5499dOlof Johansson 2520cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger mask = inet_make_mask(li->plen); 2521cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger prefix = htonl(l->key); 252219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2523cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger list_for_each_entry_rcu(fa, &li->falh, fa_list) { 25241371e37da299d4df6267ad0ddf010435782c28e9Herbert Xu const struct fib_info *fi = fa->fa_info; 2525a034ee3cca5726b14107f281f4bed1c0fd44472aEric Dumazet unsigned int flags = fib_flag_trans(fa->fa_type, mask, fi); 252619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2527cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (fa->fa_type == RTN_BROADCAST 2528cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger || fa->fa_type == RTN_MULTICAST) 2529cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger continue; 253019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2531652586df95e5d76b37d07a11839126dcfede1621Tetsuo Handa seq_setwidth(seq, 127); 2532652586df95e5d76b37d07a11839126dcfede1621Tetsuo Handa 2533cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger if (fi) 25345e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov seq_printf(seq, 25355e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov "%s\t%08X\t%08X\t%04X\t%d\t%u\t" 2536652586df95e5d76b37d07a11839126dcfede1621Tetsuo Handa "%d\t%08X\t%d\t%u\t%u", 2537cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger fi->fib_dev ? fi->fib_dev->name : "*", 2538cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger prefix, 2539cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger fi->fib_nh->nh_gw, flags, 0, 0, 2540cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger fi->fib_priority, 2541cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger mask, 2542a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger (fi->fib_advmss ? 2543a07f5f508a4d9728c8e57d7f66294bf5b254ff7fStephen Hemminger fi->fib_advmss + 40 : 0), 2544cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger fi->fib_window, 2545652586df95e5d76b37d07a11839126dcfede1621Tetsuo Handa fi->fib_rtt >> 3); 2546cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger else 25475e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov seq_printf(seq, 25485e659e4cb0eedacdc1f621a61e400a4611ddef8aPavel Emelyanov "*\t%08X\t%08X\t%04X\t%d\t%u\t" 2549652586df95e5d76b37d07a11839126dcfede1621Tetsuo Handa "%d\t%08X\t%d\t%u\t%u", 2550cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger prefix, 0, flags, 0, 0, 0, 2551652586df95e5d76b37d07a11839126dcfede1621Tetsuo Handa mask, 0, 0, 0); 255219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2553652586df95e5d76b37d07a11839126dcfede1621Tetsuo Handa seq_pad(seq, '\n'); 2554cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger } 255519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson } 255619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 255719baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return 0; 255819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 255919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2560f690808e17925fc45217eb22e8670902ecee5c1bStephen Hemmingerstatic const struct seq_operations fib_route_seq_ops = { 25618315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger .start = fib_route_seq_start, 25628315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger .next = fib_route_seq_next, 25638315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger .stop = fib_route_seq_stop, 2564cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .show = fib_route_seq_show, 256519baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}; 256619baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 2567cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerstatic int fib_route_seq_open(struct inode *inode, struct file *file) 256819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 25691c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev return seq_open_net(inode, file, &fib_route_seq_ops, 25708315f5d80a90247bf92232f92ca49933ac49327bStephen Hemminger sizeof(struct fib_route_iter)); 257119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 257219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 25739a32144e9d7b4e21341174b1a83b82a82353be86Arjan van de Venstatic const struct file_operations fib_route_fops = { 2574cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .owner = THIS_MODULE, 2575cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .open = fib_route_seq_open, 2576cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .read = seq_read, 2577cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger .llseek = seq_lseek, 25781c340b2fd73880136c438e6e7978288fbec8273fDenis V. Lunev .release = seq_release_net, 257919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson}; 258019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 258161a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunevint __net_init fib_proc_init(struct net *net) 258219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 2583d4beaa66add8aebf83ab16d2fde4e4de8dac36dfGao feng if (!proc_create("fib_trie", S_IRUGO, net->proc_net, &fib_trie_fops)) 2584cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger goto out1; 2585cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger 2586d4beaa66add8aebf83ab16d2fde4e4de8dac36dfGao feng if (!proc_create("fib_triestat", S_IRUGO, net->proc_net, 2587d4beaa66add8aebf83ab16d2fde4e4de8dac36dfGao feng &fib_triestat_fops)) 2588cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger goto out2; 2589cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger 2590d4beaa66add8aebf83ab16d2fde4e4de8dac36dfGao feng if (!proc_create("route", S_IRUGO, net->proc_net, &fib_route_fops)) 2591cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger goto out3; 2592cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger 259319baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson return 0; 2594cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger 2595cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerout3: 2596ece31ffd539e8e2b586b1ca5f50bc4f4591e3893Gao feng remove_proc_entry("fib_triestat", net->proc_net); 2597cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerout2: 2598ece31ffd539e8e2b586b1ca5f50bc4f4591e3893Gao feng remove_proc_entry("fib_trie", net->proc_net); 2599cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemmingerout1: 2600cb7b593c2c808b32a1ea188599713c434b95f849Stephen Hemminger return -ENOMEM; 260119baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 260219baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 260361a0265344786a548e8a0b26cb668e78a71f9602Denis V. Lunevvoid __net_exit fib_proc_exit(struct net *net) 260419baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson{ 2605ece31ffd539e8e2b586b1ca5f50bc4f4591e3893Gao feng remove_proc_entry("fib_trie", net->proc_net); 2606ece31ffd539e8e2b586b1ca5f50bc4f4591e3893Gao feng remove_proc_entry("fib_triestat", net->proc_net); 2607ece31ffd539e8e2b586b1ca5f50bc4f4591e3893Gao feng remove_proc_entry("route", net->proc_net); 260819baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson} 260919baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson 261019baf839ff4a8daa1f2a7400897094fc18e4f5e9Robert Olsson#endif /* CONFIG_PROC_FS */ 2611