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        int                             fnhe_genid;
  55        __be32                          fnhe_daddr;
  56        u32                             fnhe_pmtu;
  57        __be32                          fnhe_gw;
  58        unsigned long                   fnhe_expires;
  59        struct rtable __rcu             *fnhe_rth_input;
  60        struct rtable __rcu             *fnhe_rth_output;
  61        unsigned long                   fnhe_stamp;
  62};
  63
  64struct fnhe_hash_bucket {
  65        struct fib_nh_exception __rcu   *chain;
  66};
  67
  68#define FNHE_HASH_SIZE          2048
  69#define FNHE_RECLAIM_DEPTH      5
  70
  71struct fib_nh {
  72        struct net_device       *nh_dev;
  73        struct hlist_node       nh_hash;
  74        struct fib_info         *nh_parent;
  75        unsigned int            nh_flags;
  76        unsigned char           nh_scope;
  77#ifdef CONFIG_IP_ROUTE_MULTIPATH
  78        int                     nh_weight;
  79        int                     nh_power;
  80#endif
  81#ifdef CONFIG_IP_ROUTE_CLASSID
  82        __u32                   nh_tclassid;
  83#endif
  84        int                     nh_oif;
  85        __be32                  nh_gw;
  86        __be32                  nh_saddr;
  87        int                     nh_saddr_genid;
  88        struct rtable __rcu * __percpu *nh_pcpu_rth_output;
  89        struct rtable __rcu     *nh_rth_input;
  90        struct fnhe_hash_bucket *nh_exceptions;
  91};
  92
  93/*
  94 * This structure contains data shared by many of routes.
  95 */
  96
  97struct fib_info {
  98        struct hlist_node       fib_hash;
  99        struct hlist_node       fib_lhash;
 100        struct net              *fib_net;
 101        int                     fib_treeref;
 102        atomic_t                fib_clntref;
 103        unsigned int            fib_flags;
 104        unsigned char           fib_dead;
 105        unsigned char           fib_protocol;
 106        unsigned char           fib_scope;
 107        unsigned char           fib_type;
 108        __be32                  fib_prefsrc;
 109        u32                     fib_priority;
 110        u32                     *fib_metrics;
 111#define fib_mtu fib_metrics[RTAX_MTU-1]
 112#define fib_window fib_metrics[RTAX_WINDOW-1]
 113#define fib_rtt fib_metrics[RTAX_RTT-1]
 114#define fib_advmss fib_metrics[RTAX_ADVMSS-1]
 115        int                     fib_nhs;
 116#ifdef CONFIG_IP_ROUTE_MULTIPATH
 117        int                     fib_power;
 118#endif
 119        struct rcu_head         rcu;
 120        struct fib_nh           fib_nh[0];
 121#define fib_dev         fib_nh[0].nh_dev
 122};
 123
 124
 125#ifdef CONFIG_IP_MULTIPLE_TABLES
 126struct fib_rule;
 127#endif
 128
 129struct fib_table;
 130struct fib_result {
 131        unsigned char   prefixlen;
 132        unsigned char   nh_sel;
 133        unsigned char   type;
 134        unsigned char   scope;
 135        u32             tclassid;
 136        struct fib_info *fi;
 137        struct fib_table *table;
 138        struct list_head *fa_head;
 139};
 140
 141struct fib_result_nl {
 142        __be32          fl_addr;   /* To be looked up*/
 143        u32             fl_mark;
 144        unsigned char   fl_tos;
 145        unsigned char   fl_scope;
 146        unsigned char   tb_id_in;
 147
 148        unsigned char   tb_id;      /* Results */
 149        unsigned char   prefixlen;
 150        unsigned char   nh_sel;
 151        unsigned char   type;
 152        unsigned char   scope;
 153        int             err;      
 154};
 155
 156#ifdef CONFIG_IP_ROUTE_MULTIPATH
 157#define FIB_RES_NH(res)         ((res).fi->fib_nh[(res).nh_sel])
 158#else /* CONFIG_IP_ROUTE_MULTIPATH */
 159#define FIB_RES_NH(res)         ((res).fi->fib_nh[0])
 160#endif /* CONFIG_IP_ROUTE_MULTIPATH */
 161
 162#ifdef CONFIG_IP_MULTIPLE_TABLES
 163#define FIB_TABLE_HASHSZ 256
 164#else
 165#define FIB_TABLE_HASHSZ 2
 166#endif
 167
 168extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
 169
 170#define FIB_RES_SADDR(net, res)                         \
 171        ((FIB_RES_NH(res).nh_saddr_genid ==             \
 172          atomic_read(&(net)->ipv4.dev_addr_genid)) ?   \
 173         FIB_RES_NH(res).nh_saddr :                     \
 174         fib_info_update_nh_saddr((net), &FIB_RES_NH(res)))
 175#define FIB_RES_GW(res)                 (FIB_RES_NH(res).nh_gw)
 176#define FIB_RES_DEV(res)                (FIB_RES_NH(res).nh_dev)
 177#define FIB_RES_OIF(res)                (FIB_RES_NH(res).nh_oif)
 178
 179#define FIB_RES_PREFSRC(net, res)       ((res).fi->fib_prefsrc ? : \
 180                                         FIB_RES_SADDR(net, res))
 181
 182struct fib_table {
 183        struct hlist_node       tb_hlist;
 184        u32                     tb_id;
 185        int                     tb_default;
 186        int                     tb_num_default;
 187        unsigned long           tb_data[0];
 188};
 189
 190extern int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
 191                            struct fib_result *res, int fib_flags);
 192extern int fib_table_insert(struct fib_table *, struct fib_config *);
 193extern int fib_table_delete(struct fib_table *, struct fib_config *);
 194extern int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
 195                          struct netlink_callback *cb);
 196extern int fib_table_flush(struct fib_table *table);
 197extern void fib_free_table(struct fib_table *tb);
 198
 199
 200
 201#ifndef CONFIG_IP_MULTIPLE_TABLES
 202
 203#define TABLE_LOCAL_INDEX       0
 204#define TABLE_MAIN_INDEX        1
 205
 206static inline struct fib_table *fib_get_table(struct net *net, u32 id)
 207{
 208        struct hlist_head *ptr;
 209
 210        ptr = id == RT_TABLE_LOCAL ?
 211                &net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] :
 212                &net->ipv4.fib_table_hash[TABLE_MAIN_INDEX];
 213        return hlist_entry(ptr->first, struct fib_table, tb_hlist);
 214}
 215
 216static inline struct fib_table *fib_new_table(struct net *net, u32 id)
 217{
 218        return fib_get_table(net, id);
 219}
 220
 221static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
 222                             struct fib_result *res)
 223{
 224        struct fib_table *table;
 225
 226        table = fib_get_table(net, RT_TABLE_LOCAL);
 227        if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
 228                return 0;
 229
 230        table = fib_get_table(net, RT_TABLE_MAIN);
 231        if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
 232                return 0;
 233        return -ENETUNREACH;
 234}
 235
 236#else /* CONFIG_IP_MULTIPLE_TABLES */
 237extern int __net_init fib4_rules_init(struct net *net);
 238extern void __net_exit fib4_rules_exit(struct net *net);
 239
 240extern struct fib_table *fib_new_table(struct net *net, u32 id);
 241extern struct fib_table *fib_get_table(struct net *net, u32 id);
 242
 243extern int __fib_lookup(struct net *net, struct flowi4 *flp,
 244                        struct fib_result *res);
 245
 246static inline int fib_lookup(struct net *net, struct flowi4 *flp,
 247                             struct fib_result *res)
 248{
 249        if (!net->ipv4.fib_has_custom_rules) {
 250                res->tclassid = 0;
 251                if (net->ipv4.fib_local &&
 252                    !fib_table_lookup(net->ipv4.fib_local, flp, res,
 253                                      FIB_LOOKUP_NOREF))
 254                        return 0;
 255                if (net->ipv4.fib_main &&
 256                    !fib_table_lookup(net->ipv4.fib_main, flp, res,
 257                                      FIB_LOOKUP_NOREF))
 258                        return 0;
 259                if (net->ipv4.fib_default &&
 260                    !fib_table_lookup(net->ipv4.fib_default, flp, res,
 261                                      FIB_LOOKUP_NOREF))
 262                        return 0;
 263                return -ENETUNREACH;
 264        }
 265        return __fib_lookup(net, flp, res);
 266}
 267
 268#endif /* CONFIG_IP_MULTIPLE_TABLES */
 269
 270/* Exported by fib_frontend.c */
 271extern const struct nla_policy rtm_ipv4_policy[];
 272extern void             ip_fib_init(void);
 273extern __be32 fib_compute_spec_dst(struct sk_buff *skb);
 274extern int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 275                               u8 tos, int oif, struct net_device *dev,
 276                               struct in_device *idev, u32 *itag);
 277extern void fib_select_default(struct fib_result *res);
 278#ifdef CONFIG_IP_ROUTE_CLASSID
 279static inline int fib_num_tclassid_users(struct net *net)
 280{
 281        return net->ipv4.fib_num_tclassid_users;
 282}
 283#else
 284static inline int fib_num_tclassid_users(struct net *net)
 285{
 286        return 0;
 287}
 288#endif
 289
 290/* Exported by fib_semantics.c */
 291extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
 292extern int fib_sync_down_dev(struct net_device *dev, int force);
 293extern int fib_sync_down_addr(struct net *net, __be32 local);
 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