linux/include/net/ip_fib.h
<<
>>
Prefs
   1/*
   2 * INET         An implementation of the TCP/IP protocol suite for the LINUX
   3 *              operating system.  INET  is implemented using the  BSD Socket
   4 *              interface as the means of communication with the user level.
   5 *
   6 *              Definitions for the Forwarding Information Base.
   7 *
   8 * Authors:     A.N.Kuznetsov, <kuznet@ms2.inr.ac.ru>
   9 *
  10 *              This program is free software; you can redistribute it and/or
  11 *              modify it under the terms of the GNU General Public License
  12 *              as published by the Free Software Foundation; either version
  13 *              2 of the License, or (at your option) any later version.
  14 */
  15
  16#ifndef _NET_IP_FIB_H
  17#define _NET_IP_FIB_H
  18
  19#include <net/flow.h>
  20#include <linux/seq_file.h>
  21#include <linux/rcupdate.h>
  22#include <net/fib_rules.h>
  23#include <net/inetpeer.h>
  24#include <linux/percpu.h>
  25
  26struct fib_config {
  27        u8                      fc_dst_len;
  28        u8                      fc_tos;
  29        u8                      fc_protocol;
  30        u8                      fc_scope;
  31        u8                      fc_type;
  32        /* 3 bytes unused */
  33        u32                     fc_table;
  34        __be32                  fc_dst;
  35        __be32                  fc_gw;
  36        int                     fc_oif;
  37        u32                     fc_flags;
  38        u32                     fc_priority;
  39        __be32                  fc_prefsrc;
  40        struct nlattr           *fc_mx;
  41        struct rtnexthop        *fc_mp;
  42        int                     fc_mx_len;
  43        int                     fc_mp_len;
  44        u32                     fc_flow;
  45        u32                     fc_nlflags;
  46        struct nl_info          fc_nlinfo;
  47 };
  48
  49struct fib_info;
  50struct rtable;
  51
  52struct fib_nh_exception {
  53        struct fib_nh_exception __rcu   *fnhe_next;
  54        __be32                          fnhe_daddr;
  55        u32                             fnhe_pmtu;
  56        __be32                          fnhe_gw;
  57        unsigned long                   fnhe_expires;
  58        struct rtable __rcu             *fnhe_rth;
  59        unsigned long                   fnhe_stamp;
  60};
  61
  62struct fnhe_hash_bucket {
  63        struct fib_nh_exception __rcu   *chain;
  64};
  65
  66#define FNHE_HASH_SIZE          2048
  67#define FNHE_RECLAIM_DEPTH      5
  68
  69struct fib_nh {
  70        struct net_device       *nh_dev;
  71        struct hlist_node       nh_hash;
  72        struct fib_info         *nh_parent;
  73        unsigned int            nh_flags;
  74        unsigned char           nh_scope;
  75#ifdef CONFIG_IP_ROUTE_MULTIPATH
  76        int                     nh_weight;
  77        int                     nh_power;
  78#endif
  79#ifdef CONFIG_IP_ROUTE_CLASSID
  80        __u32                   nh_tclassid;
  81#endif
  82        int                     nh_oif;
  83        __be32                  nh_gw;
  84        __be32                  nh_saddr;
  85        int                     nh_saddr_genid;
  86        struct rtable __rcu * __percpu *nh_pcpu_rth_output;
  87        struct rtable __rcu     *nh_rth_input;
  88        struct fnhe_hash_bucket *nh_exceptions;
  89};
  90
  91/*
  92 * This structure contains data shared by many of routes.
  93 */
  94
  95struct fib_info {
  96        struct hlist_node       fib_hash;
  97        struct hlist_node       fib_lhash;
  98        struct net              *fib_net;
  99        int                     fib_treeref;
 100        atomic_t                fib_clntref;
 101        unsigned int            fib_flags;
 102        unsigned char           fib_dead;
 103        unsigned char           fib_protocol;
 104        unsigned char           fib_scope;
 105        __be32                  fib_prefsrc;
 106        u32                     fib_priority;
 107        u32                     *fib_metrics;
 108#define fib_mtu fib_metrics[RTAX_MTU-1]
 109#define fib_window fib_metrics[RTAX_WINDOW-1]
 110#define fib_rtt fib_metrics[RTAX_RTT-1]
 111#define fib_advmss fib_metrics[RTAX_ADVMSS-1]
 112        int                     fib_nhs;
 113#ifdef CONFIG_IP_ROUTE_MULTIPATH
 114        int                     fib_power;
 115#endif
 116        struct rcu_head         rcu;
 117        struct fib_nh           fib_nh[0];
 118#define fib_dev         fib_nh[0].nh_dev
 119};
 120
 121
 122#ifdef CONFIG_IP_MULTIPLE_TABLES
 123struct fib_rule;
 124#endif
 125
 126struct fib_table;
 127struct fib_result {
 128        unsigned char   prefixlen;
 129        unsigned char   nh_sel;
 130        unsigned char   type;
 131        unsigned char   scope;
 132        u32             tclassid;
 133        struct fib_info *fi;
 134        struct fib_table *table;
 135        struct list_head *fa_head;
 136};
 137
 138struct fib_result_nl {
 139        __be32          fl_addr;   /* To be looked up*/
 140        u32             fl_mark;
 141        unsigned char   fl_tos;
 142        unsigned char   fl_scope;
 143        unsigned char   tb_id_in;
 144
 145        unsigned char   tb_id;      /* Results */
 146        unsigned char   prefixlen;
 147        unsigned char   nh_sel;
 148        unsigned char   type;
 149        unsigned char   scope;
 150        int             err;      
 151};
 152
 153#ifdef CONFIG_IP_ROUTE_MULTIPATH
 154
 155#define FIB_RES_NH(res)         ((res).fi->fib_nh[(res).nh_sel])
 156
 157#define FIB_TABLE_HASHSZ 2
 158
 159#else /* CONFIG_IP_ROUTE_MULTIPATH */
 160
 161#define FIB_RES_NH(res)         ((res).fi->fib_nh[0])
 162
 163#define FIB_TABLE_HASHSZ 256
 164
 165#endif /* CONFIG_IP_ROUTE_MULTIPATH */
 166
 167extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
 168
 169#define FIB_RES_SADDR(net, res)                         \
 170        ((FIB_RES_NH(res).nh_saddr_genid ==             \
 171          atomic_read(&(net)->ipv4.dev_addr_genid)) ?   \
 172         FIB_RES_NH(res).nh_saddr :                     \
 173         fib_info_update_nh_saddr((net), &FIB_RES_NH(res)))
 174#define FIB_RES_GW(res)                 (FIB_RES_NH(res).nh_gw)
 175#define FIB_RES_DEV(res)                (FIB_RES_NH(res).nh_dev)
 176#define FIB_RES_OIF(res)                (FIB_RES_NH(res).nh_oif)
 177
 178#define FIB_RES_PREFSRC(net, res)       ((res).fi->fib_prefsrc ? : \
 179                                         FIB_RES_SADDR(net, res))
 180
 181struct fib_table {
 182        struct hlist_node       tb_hlist;
 183        u32                     tb_id;
 184        int                     tb_default;
 185        int                     tb_num_default;
 186        unsigned long           tb_data[0];
 187};
 188
 189extern int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
 190                            struct fib_result *res, int fib_flags);
 191extern int fib_table_insert(struct fib_table *, struct fib_config *);
 192extern int fib_table_delete(struct fib_table *, struct fib_config *);
 193extern int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
 194                          struct netlink_callback *cb);
 195extern int fib_table_flush(struct fib_table *table);
 196extern void fib_free_table(struct fib_table *tb);
 197
 198
 199
 200#ifndef CONFIG_IP_MULTIPLE_TABLES
 201
 202#define TABLE_LOCAL_INDEX       0
 203#define TABLE_MAIN_INDEX        1
 204
 205static inline struct fib_table *fib_get_table(struct net *net, u32 id)
 206{
 207        struct hlist_head *ptr;
 208
 209        ptr = id == RT_TABLE_LOCAL ?
 210                &net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] :
 211                &net->ipv4.fib_table_hash[TABLE_MAIN_INDEX];
 212        return hlist_entry(ptr->first, struct fib_table, tb_hlist);
 213}
 214
 215static inline struct fib_table *fib_new_table(struct net *net, u32 id)
 216{
 217        return fib_get_table(net, id);
 218}
 219
 220static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
 221                             struct fib_result *res)
 222{
 223        struct fib_table *table;
 224
 225        table = fib_get_table(net, RT_TABLE_LOCAL);
 226        if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
 227                return 0;
 228
 229        table = fib_get_table(net, RT_TABLE_MAIN);
 230        if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
 231                return 0;
 232        return -ENETUNREACH;
 233}
 234
 235#else /* CONFIG_IP_MULTIPLE_TABLES */
 236extern int __net_init fib4_rules_init(struct net *net);
 237extern void __net_exit fib4_rules_exit(struct net *net);
 238
 239extern struct fib_table *fib_new_table(struct net *net, u32 id);
 240extern struct fib_table *fib_get_table(struct net *net, u32 id);
 241
 242extern int __fib_lookup(struct net *net, struct flowi4 *flp,
 243                        struct fib_result *res);
 244
 245static inline int fib_lookup(struct net *net, struct flowi4 *flp,
 246                             struct fib_result *res)
 247{
 248        if (!net->ipv4.fib_has_custom_rules) {
 249                res->tclassid = 0;
 250                if (net->ipv4.fib_local &&
 251                    !fib_table_lookup(net->ipv4.fib_local, flp, res,
 252                                      FIB_LOOKUP_NOREF))
 253                        return 0;
 254                if (net->ipv4.fib_main &&
 255                    !fib_table_lookup(net->ipv4.fib_main, flp, res,
 256                                      FIB_LOOKUP_NOREF))
 257                        return 0;
 258                if (net->ipv4.fib_default &&
 259                    !fib_table_lookup(net->ipv4.fib_default, flp, res,
 260                                      FIB_LOOKUP_NOREF))
 261                        return 0;
 262                return -ENETUNREACH;
 263        }
 264        return __fib_lookup(net, flp, res);
 265}
 266
 267#endif /* CONFIG_IP_MULTIPLE_TABLES */
 268
 269/* Exported by fib_frontend.c */
 270extern const struct nla_policy rtm_ipv4_policy[];
 271extern void             ip_fib_init(void);
 272extern __be32 fib_compute_spec_dst(struct sk_buff *skb);
 273extern int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 274                               u8 tos, int oif, struct net_device *dev,
 275                               struct in_device *idev, u32 *itag);
 276extern void fib_select_default(struct fib_result *res);
 277#ifdef CONFIG_IP_ROUTE_CLASSID
 278static inline int fib_num_tclassid_users(struct net *net)
 279{
 280        return net->ipv4.fib_num_tclassid_users;
 281}
 282#else
 283static inline int fib_num_tclassid_users(struct net *net)
 284{
 285        return 0;
 286}
 287#endif
 288
 289/* Exported by fib_semantics.c */
 290extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
 291extern int fib_sync_down_dev(struct net_device *dev, int force);
 292extern int fib_sync_down_addr(struct net *net, __be32 local);
 293extern void fib_update_nh_saddrs(struct net_device *dev);
 294extern int fib_sync_up(struct net_device *dev);
 295extern void fib_select_multipath(struct fib_result *res);
 296
 297/* Exported by fib_trie.c */
 298extern void fib_trie_init(void);
 299extern struct fib_table *fib_trie_table(u32 id);
 300
 301static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
 302{
 303#ifdef CONFIG_IP_ROUTE_CLASSID
 304#ifdef CONFIG_IP_MULTIPLE_TABLES
 305        u32 rtag;
 306#endif
 307        *itag = FIB_RES_NH(*res).nh_tclassid<<16;
 308#ifdef CONFIG_IP_MULTIPLE_TABLES
 309        rtag = res->tclassid;
 310        if (*itag == 0)
 311                *itag = (rtag<<16);
 312        *itag |= (rtag>>16);
 313#endif
 314#endif
 315}
 316
 317extern void free_fib_info(struct fib_info *fi);
 318
 319static inline void fib_info_put(struct fib_info *fi)
 320{
 321        if (atomic_dec_and_test(&fi->fib_clntref))
 322                free_fib_info(fi);
 323}
 324
 325#ifdef CONFIG_PROC_FS
 326extern int __net_init  fib_proc_init(struct net *net);
 327extern void __net_exit fib_proc_exit(struct net *net);
 328#else
 329static inline int fib_proc_init(struct net *net)
 330{
 331        return 0;
 332}
 333static inline void fib_proc_exit(struct net *net)
 334{
 335}
 336#endif
 337
 338#endif  /* _NET_FIB_H */
 339