2005-04-17 02:20:36 +04:00
/*
* INET An implementation of the TCP / IP protocol suite for the LINUX
* operating system . INET is implemented using the BSD Socket
* interface as the means of communication with the user level .
*
* Definitions for the Forwarding Information Base .
*
* Authors : A . N . Kuznetsov , < kuznet @ ms2 . inr . ac . ru >
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*/
# ifndef _NET_IP_FIB_H
# define _NET_IP_FIB_H
# include <net/flow.h>
# include <linux/seq_file.h>
2012-07-17 15:19:00 +04:00
# include <linux/rcupdate.h>
2006-08-04 14:39:22 +04:00
# include <net/fib_rules.h>
2012-06-11 11:01:52 +04:00
# include <net/inetpeer.h>
2012-07-31 09:45:30 +04:00
# include <linux/percpu.h>
2016-09-26 13:52:29 +03:00
# include <linux/notifier.h>
2005-04-17 02:20:36 +04:00
2006-08-18 05:14:52 +04:00
struct fib_config {
u8 fc_dst_len ;
u8 fc_tos ;
u8 fc_protocol ;
u8 fc_scope ;
u8 fc_type ;
2006-10-19 07:26:36 +04:00
/* 3 bytes unused */
2006-08-18 05:14:52 +04:00
u32 fc_table ;
2006-09-27 09:15:46 +04:00
__be32 fc_dst ;
__be32 fc_gw ;
2006-08-18 05:14:52 +04:00
int fc_oif ;
u32 fc_flags ;
u32 fc_priority ;
2006-09-27 09:15:46 +04:00
__be32 fc_prefsrc ;
2006-08-18 05:14:52 +04:00
struct nlattr * fc_mx ;
struct rtnexthop * fc_mp ;
int fc_mx_len ;
int fc_mp_len ;
u32 fc_flow ;
u32 fc_nlflags ;
struct nl_info fc_nlinfo ;
2015-07-21 11:43:47 +03:00
struct nlattr * fc_encap ;
u16 fc_encap_type ;
} ;
2005-04-17 02:20:36 +04:00
struct fib_info ;
2012-07-17 23:20:47 +04:00
struct rtable ;
2005-04-17 02:20:36 +04:00
2012-07-17 15:19:00 +04:00
struct fib_nh_exception {
struct fib_nh_exception __rcu * fnhe_next ;
2013-05-28 00:46:33 +04:00
int fnhe_genid ;
2012-07-17 15:19:00 +04:00
__be32 fnhe_daddr ;
u32 fnhe_pmtu ;
2012-07-18 14:15:35 +04:00
__be32 fnhe_gw ;
2012-07-17 15:19:00 +04:00
unsigned long fnhe_expires ;
2013-06-27 11:27:05 +04:00
struct rtable __rcu * fnhe_rth_input ;
struct rtable __rcu * fnhe_rth_output ;
2012-07-17 15:19:00 +04:00
unsigned long fnhe_stamp ;
2016-02-18 16:21:19 +03:00
struct rcu_head rcu ;
2012-07-17 15:19:00 +04:00
} ;
struct fnhe_hash_bucket {
struct fib_nh_exception __rcu * chain ;
} ;
2014-09-04 19:21:31 +04:00
# define FNHE_HASH_SHIFT 11
# define FNHE_HASH_SIZE (1 << FNHE_HASH_SHIFT)
2012-07-17 15:19:00 +04:00
# define FNHE_RECLAIM_DEPTH 5
2005-04-17 02:20:36 +04:00
struct fib_nh {
struct net_device * nh_dev ;
struct hlist_node nh_hash ;
struct fib_info * nh_parent ;
2012-04-15 09:58:06 +04:00
unsigned int nh_flags ;
2005-04-17 02:20:36 +04:00
unsigned char nh_scope ;
# ifdef CONFIG_IP_ROUTE_MULTIPATH
int nh_weight ;
2015-09-30 11:12:21 +03:00
atomic_t nh_upper_bound ;
2005-04-17 02:20:36 +04:00
# endif
2011-01-14 15:36:42 +03:00
# ifdef CONFIG_IP_ROUTE_CLASSID
2005-04-17 02:20:36 +04:00
__u32 nh_tclassid ;
# endif
int nh_oif ;
2006-09-27 09:13:54 +04:00
__be32 nh_gw ;
2011-03-08 07:54:48 +03:00
__be32 nh_saddr ;
2011-03-25 03:42:21 +03:00
int nh_saddr_genid ;
2012-07-31 09:45:30 +04:00
struct rtable __rcu * __percpu * nh_pcpu_rth_output ;
2012-07-31 05:08:23 +04:00
struct rtable __rcu * nh_rth_input ;
2014-09-04 09:21:56 +04:00
struct fnhe_hash_bucket __rcu * nh_exceptions ;
2015-07-21 11:43:47 +03:00
struct lwtunnel_state * nh_lwtstate ;
2005-04-17 02:20:36 +04:00
} ;
/*
* This structure contains data shared by many of routes .
*/
struct fib_info {
struct hlist_node fib_hash ;
struct hlist_node fib_lhash ;
2008-02-01 05:49:32 +03:00
struct net * fib_net ;
2005-04-17 02:20:36 +04:00
int fib_treeref ;
atomic_t fib_clntref ;
2012-04-15 09:58:06 +04:00
unsigned int fib_flags ;
2011-03-25 04:06:47 +03:00
unsigned char fib_dead ;
unsigned char fib_protocol ;
unsigned char fib_scope ;
2012-10-04 05:25:26 +04:00
unsigned char fib_type ;
2006-09-27 09:14:15 +04:00
__be32 fib_prefsrc ;
2016-09-05 01:20:20 +03:00
u32 fib_tb_id ;
2005-04-17 02:20:36 +04:00
u32 fib_priority ;
2011-01-29 01:01:25 +03:00
u32 * fib_metrics ;
2005-04-17 02:20:36 +04:00
# define fib_mtu fib_metrics[RTAX_MTU-1]
# define fib_window fib_metrics[RTAX_WINDOW-1]
# define fib_rtt fib_metrics[RTAX_RTT-1]
# define fib_advmss fib_metrics[RTAX_ADVMSS-1]
int fib_nhs ;
# ifdef CONFIG_IP_ROUTE_MULTIPATH
2015-09-30 11:12:21 +03:00
int fib_weight ;
2005-04-17 02:20:36 +04:00
# endif
2010-10-05 14:41:36 +04:00
struct rcu_head rcu ;
2005-04-17 02:20:36 +04:00
struct fib_nh fib_nh [ 0 ] ;
# define fib_dev fib_nh[0].nh_dev
} ;
# ifdef CONFIG_IP_MULTIPLE_TABLES
struct fib_rule ;
# endif
2011-02-01 03:10:03 +03:00
struct fib_table ;
2005-04-17 02:20:36 +04:00
struct fib_result {
unsigned char prefixlen ;
unsigned char nh_sel ;
unsigned char type ;
unsigned char scope ;
2012-07-13 19:21:29 +04:00
u32 tclassid ;
2005-04-17 02:20:36 +04:00
struct fib_info * fi ;
2011-02-01 03:10:03 +03:00
struct fib_table * table ;
2015-02-26 02:31:31 +03:00
struct hlist_head * fa_head ;
2005-04-17 02:20:36 +04:00
} ;
2005-06-21 00:36:39 +04:00
struct fib_result_nl {
2006-09-27 09:19:36 +04:00
__be32 fl_addr ; /* To be looked up*/
2006-11-10 02:21:41 +03:00
u32 fl_mark ;
2005-06-21 00:36:39 +04:00
unsigned char fl_tos ;
unsigned char fl_scope ;
unsigned char tb_id_in ;
unsigned char tb_id ; /* Results */
unsigned char prefixlen ;
unsigned char nh_sel ;
unsigned char type ;
unsigned char scope ;
int err ;
} ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_IP_ROUTE_MULTIPATH
# define FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
# else /* CONFIG_IP_ROUTE_MULTIPATH */
# define FIB_RES_NH(res) ((res).fi->fib_nh[0])
2013-03-13 04:24:15 +04:00
# endif /* CONFIG_IP_ROUTE_MULTIPATH */
2005-04-17 02:20:36 +04:00
2013-03-13 04:24:15 +04:00
# ifdef CONFIG_IP_MULTIPLE_TABLES
2008-01-10 14:23:38 +03:00
# define FIB_TABLE_HASHSZ 256
2013-03-13 04:24:15 +04:00
# else
# define FIB_TABLE_HASHSZ 2
# endif
2005-04-17 02:20:36 +04:00
2013-09-21 21:22:42 +04:00
__be32 fib_info_update_nh_saddr ( struct net * net , struct fib_nh * nh ) ;
2011-03-25 03:42:21 +03:00
# define FIB_RES_SADDR(net, res) \
( ( FIB_RES_NH ( res ) . nh_saddr_genid = = \
atomic_read ( & ( net ) - > ipv4 . dev_addr_genid ) ) ? \
FIB_RES_NH ( res ) . nh_saddr : \
fib_info_update_nh_saddr ( ( net ) , & FIB_RES_NH ( res ) ) )
2005-04-17 02:20:36 +04:00
# define FIB_RES_GW(res) (FIB_RES_NH(res).nh_gw)
# define FIB_RES_DEV(res) (FIB_RES_NH(res).nh_dev)
# define FIB_RES_OIF(res) (FIB_RES_NH(res).nh_oif)
2011-03-25 03:42:21 +03:00
# define FIB_RES_PREFSRC(net, res) ((res).fi->fib_prefsrc ? : \
FIB_RES_SADDR ( net , res ) )
2011-03-08 07:54:48 +03:00
2016-09-26 13:52:29 +03:00
struct fib_notifier_info {
struct net * net ;
} ;
struct fib_entry_notifier_info {
struct fib_notifier_info info ; /* must be first */
u32 dst ;
int dst_len ;
struct fib_info * fi ;
u8 tos ;
u8 type ;
u32 tb_id ;
u32 nlflags ;
} ;
enum fib_event_type {
FIB_EVENT_ENTRY_ADD ,
FIB_EVENT_ENTRY_DEL ,
FIB_EVENT_RULE_ADD ,
FIB_EVENT_RULE_DEL ,
} ;
int register_fib_notifier ( struct notifier_block * nb ) ;
int unregister_fib_notifier ( struct notifier_block * nb ) ;
int call_fib_notifiers ( struct net * net , enum fib_event_type event_type ,
struct fib_notifier_info * info ) ;
2005-04-17 02:20:36 +04:00
struct fib_table {
2012-06-11 11:01:52 +04:00
struct hlist_node tb_hlist ;
u32 tb_id ;
int tb_num_default ;
2015-03-05 02:02:44 +03:00
struct rcu_head rcu ;
2015-03-07 00:47:00 +03:00
unsigned long * tb_data ;
unsigned long __data [ 0 ] ;
2005-04-17 02:20:36 +04:00
} ;
2013-09-21 21:22:42 +04:00
int fib_table_lookup ( struct fib_table * tb , const struct flowi4 * flp ,
struct fib_result * res , int fib_flags ) ;
2016-09-26 13:52:29 +03:00
int fib_table_insert ( struct net * , struct fib_table * , struct fib_config * ) ;
int fib_table_delete ( struct net * , struct fib_table * , struct fib_config * ) ;
2013-09-21 21:22:42 +04:00
int fib_table_dump ( struct fib_table * table , struct sk_buff * skb ,
struct netlink_callback * cb ) ;
2016-09-26 13:52:29 +03:00
int fib_table_flush ( struct net * net , struct fib_table * table ) ;
2015-03-07 00:47:00 +03:00
struct fib_table * fib_trie_unmerge ( struct fib_table * main_tb ) ;
2015-03-06 08:21:16 +03:00
void fib_table_flush_external ( struct fib_table * table ) ;
2013-09-21 21:22:42 +04:00
void fib_free_table ( struct fib_table * tb ) ;
2010-10-28 06:00:43 +04:00
2005-04-17 02:20:36 +04:00
# ifndef CONFIG_IP_MULTIPLE_TABLES
2014-12-02 21:58:21 +03:00
# define TABLE_LOCAL_INDEX (RT_TABLE_LOCAL & (FIB_TABLE_HASHSZ - 1))
# define TABLE_MAIN_INDEX (RT_TABLE_MAIN & (FIB_TABLE_HASHSZ - 1))
2005-04-17 02:20:36 +04:00
2008-01-10 14:24:11 +03:00
static inline struct fib_table * fib_get_table ( struct net * net , u32 id )
2005-04-17 02:20:36 +04:00
{
2015-03-05 02:02:44 +03:00
struct hlist_node * tb_hlist ;
2008-01-10 14:23:38 +03:00
struct hlist_head * ptr ;
ptr = id = = RT_TABLE_LOCAL ?
2008-01-10 14:28:24 +03:00
& net - > ipv4 . fib_table_hash [ TABLE_LOCAL_INDEX ] :
& net - > ipv4 . fib_table_hash [ TABLE_MAIN_INDEX ] ;
2015-03-05 02:02:44 +03:00
tb_hlist = rcu_dereference_rtnl ( hlist_first_rcu ( ptr ) ) ;
return hlist_entry ( tb_hlist , struct fib_table , tb_hlist ) ;
2005-04-17 02:20:36 +04:00
}
2008-01-10 14:24:11 +03:00
static inline struct fib_table * fib_new_table ( struct net * net , u32 id )
2005-04-17 02:20:36 +04:00
{
2008-01-10 14:24:11 +03:00
return fib_get_table ( net , id ) ;
2005-04-17 02:20:36 +04:00
}
2011-03-12 03:54:08 +03:00
static inline int fib_lookup ( struct net * net , const struct flowi4 * flp ,
2015-06-23 20:45:37 +03:00
struct fib_result * res , unsigned int flags )
2005-04-17 02:20:36 +04:00
{
2015-03-05 02:02:44 +03:00
struct fib_table * tb ;
2015-03-07 00:47:00 +03:00
int err = - ENETUNREACH ;
2014-12-31 21:56:24 +03:00
rcu_read_lock ( ) ;
2015-03-07 00:47:00 +03:00
tb = fib_get_table ( net , RT_TABLE_MAIN ) ;
2015-09-17 17:01:32 +03:00
if ( tb )
err = fib_table_lookup ( tb , flp , res , flags | FIB_LOOKUP_NOREF ) ;
if ( err = = - EAGAIN )
err = - ENETUNREACH ;
2008-01-10 14:23:38 +03:00
2014-12-31 21:56:24 +03:00
rcu_read_unlock ( ) ;
2008-01-10 14:23:38 +03:00
2014-12-31 21:56:24 +03:00
return err ;
2005-04-17 02:20:36 +04:00
}
# else /* CONFIG_IP_MULTIPLE_TABLES */
2013-09-21 21:22:42 +04:00
int __net_init fib4_rules_init ( struct net * net ) ;
void __net_exit fib4_rules_exit ( struct net * net ) ;
2007-11-07 10:34:04 +03:00
2013-09-21 21:22:42 +04:00
struct fib_table * fib_new_table ( struct net * net , u32 id ) ;
struct fib_table * fib_get_table ( struct net * net , u32 id ) ;
2005-04-17 02:20:36 +04:00
2015-06-23 20:45:37 +03:00
int __fib_lookup ( struct net * net , struct flowi4 * flp ,
struct fib_result * res , unsigned int flags ) ;
2012-07-06 09:13:13 +04:00
static inline int fib_lookup ( struct net * net , struct flowi4 * flp ,
2015-06-23 20:45:37 +03:00
struct fib_result * res , unsigned int flags )
2012-07-06 09:13:13 +04:00
{
2015-03-05 02:02:44 +03:00
struct fib_table * tb ;
2015-09-17 17:01:32 +03:00
int err = - ENETUNREACH ;
2015-03-05 02:02:44 +03:00
2015-06-23 20:45:37 +03:00
flags | = FIB_LOOKUP_NOREF ;
2015-03-05 02:02:44 +03:00
if ( net - > ipv4 . fib_has_custom_rules )
2015-06-23 20:45:37 +03:00
return __fib_lookup ( net , flp , res , flags ) ;
2015-03-05 02:02:44 +03:00
rcu_read_lock ( ) ;
res - > tclassid = 0 ;
2015-09-17 17:01:32 +03:00
tb = rcu_dereference_rtnl ( net - > ipv4 . fib_main ) ;
if ( tb )
err = fib_table_lookup ( tb , flp , res , flags ) ;
if ( ! err )
goto out ;
tb = rcu_dereference_rtnl ( net - > ipv4 . fib_default ) ;
if ( tb )
err = fib_table_lookup ( tb , flp , res , flags ) ;
2015-03-05 02:02:44 +03:00
2015-09-17 17:01:32 +03:00
out :
if ( err = = - EAGAIN )
err = - ENETUNREACH ;
2015-03-05 02:02:44 +03:00
rcu_read_unlock ( ) ;
return err ;
2012-07-06 09:13:13 +04:00
}
2005-04-17 02:20:36 +04:00
# endif /* CONFIG_IP_MULTIPLE_TABLES */
/* Exported by fib_frontend.c */
2007-06-05 23:38:30 +04:00
extern const struct nla_policy rtm_ipv4_policy [ ] ;
2013-09-21 21:22:42 +04:00
void ip_fib_init ( void ) ;
__be32 fib_compute_spec_dst ( struct sk_buff * skb ) ;
int fib_validate_source ( struct sk_buff * skb , __be32 src , __be32 dst ,
u8 tos , int oif , struct net_device * dev ,
struct in_device * idev , u32 * itag ) ;
2015-07-22 10:43:23 +03:00
void fib_select_default ( const struct flowi4 * flp , struct fib_result * res ) ;
2012-06-29 12:32:45 +04:00
# ifdef CONFIG_IP_ROUTE_CLASSID
2012-07-06 09:13:13 +04:00
static inline int fib_num_tclassid_users ( struct net * net )
{
return net - > ipv4 . fib_num_tclassid_users ;
}
2012-06-29 12:32:45 +04:00
# else
2012-07-06 09:13:13 +04:00
static inline int fib_num_tclassid_users ( struct net * net )
{
return 0 ;
}
2012-06-29 12:32:45 +04:00
# endif
2015-03-07 00:47:00 +03:00
int fib_unmerge ( struct net * net ) ;
2015-03-06 08:21:16 +03:00
void fib_flush_external ( struct net * net ) ;
2005-12-27 07:43:12 +03:00
2005-04-17 02:20:36 +04:00
/* Exported by fib_semantics.c */
2013-09-21 21:22:42 +04:00
int ip_fib_check_default ( __be32 gw , struct net_device * dev ) ;
2015-10-30 11:23:33 +03:00
int fib_sync_down_dev ( struct net_device * dev , unsigned long event , bool force ) ;
2016-09-05 01:20:20 +03:00
int fib_sync_down_addr ( struct net_device * dev , __be32 local ) ;
2015-06-23 20:45:36 +03:00
int fib_sync_up ( struct net_device * dev , unsigned int nh_flags ) ;
2015-09-30 11:12:21 +03:00
extern u32 fib_multipath_secret __read_mostly ;
static inline int fib_multipath_hash ( __be32 saddr , __be32 daddr )
{
2016-01-07 01:22:46 +03:00
return jhash_2words ( ( __force u32 ) saddr , ( __force u32 ) daddr ,
fib_multipath_secret ) > > 1 ;
2015-09-30 11:12:21 +03:00
}
void fib_select_multipath ( struct fib_result * res , int hash ) ;
2015-10-05 18:51:25 +03:00
void fib_select_path ( struct net * net , struct fib_result * res ,
struct flowi4 * fl4 , int mp_hash ) ;
2005-04-17 02:20:36 +04:00
2011-02-02 02:30:56 +03:00
/* Exported by fib_trie.c */
2013-09-21 21:22:42 +04:00
void fib_trie_init ( void ) ;
2015-03-07 00:47:00 +03:00
struct fib_table * fib_trie_table ( u32 id , struct fib_table * alias ) ;
2005-04-17 02:20:36 +04:00
2011-02-17 09:04:57 +03:00
static inline void fib_combine_itag ( u32 * itag , const struct fib_result * res )
2005-04-17 02:20:36 +04:00
{
2011-01-14 15:36:42 +03:00
# ifdef CONFIG_IP_ROUTE_CLASSID
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_IP_MULTIPLE_TABLES
u32 rtag ;
# endif
* itag = FIB_RES_NH ( * res ) . nh_tclassid < < 16 ;
# ifdef CONFIG_IP_MULTIPLE_TABLES
2012-07-13 19:21:29 +04:00
rtag = res - > tclassid ;
2005-04-17 02:20:36 +04:00
if ( * itag = = 0 )
* itag = ( rtag < < 16 ) ;
* itag | = ( rtag > > 16 ) ;
# endif
# endif
}
2013-09-21 21:22:42 +04:00
void free_fib_info ( struct fib_info * fi ) ;
2005-04-17 02:20:36 +04:00
static inline void fib_info_put ( struct fib_info * fi )
{
if ( atomic_dec_and_test ( & fi - > fib_clntref ) )
free_fib_info ( fi ) ;
}
2005-08-16 09:18:02 +04:00
# ifdef CONFIG_PROC_FS
2013-09-21 21:22:42 +04:00
int __net_init fib_proc_init ( struct net * net ) ;
void __net_exit fib_proc_exit ( struct net * net ) ;
2008-02-05 13:54:16 +03:00
# else
static inline int fib_proc_init ( struct net * net )
{
return 0 ;
}
static inline void fib_proc_exit ( struct net * net )
{
}
2005-08-16 09:18:02 +04:00
# endif
2005-04-17 02:20:36 +04:00
# endif /* _NET_FIB_H */