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        struct nlattr           *fc_encap;
  48        u16                     fc_encap_type;
  49};
  50
  51struct fib_info;
  52struct rtable;
  53
  54struct fib_nh_exception {
  55        struct fib_nh_exception __rcu   *fnhe_next;
  56        int                             fnhe_genid;
  57        __be32                          fnhe_daddr;
  58        u32                             fnhe_pmtu;
  59        __be32                          fnhe_gw;
  60        unsigned long                   fnhe_expires;
  61        struct rtable __rcu             *fnhe_rth_input;
  62        struct rtable __rcu             *fnhe_rth_output;
  63        unsigned long                   fnhe_stamp;
  64        struct rcu_head                 rcu;
  65};
  66
  67struct fnhe_hash_bucket {
  68        struct fib_nh_exception __rcu   *chain;
  69};
  70
  71#define FNHE_HASH_SHIFT         11
  72#define FNHE_HASH_SIZE          (1 << FNHE_HASH_SHIFT)
  73#define FNHE_RECLAIM_DEPTH      5
  74
  75struct fib_nh {
  76        struct net_device       *nh_dev;
  77        struct hlist_node       nh_hash;
  78        struct fib_info         *nh_parent;
  79        unsigned int            nh_flags;
  80        unsigned char           nh_scope;
  81#ifdef CONFIG_IP_ROUTE_MULTIPATH
  82        int                     nh_weight;
  83        atomic_t                nh_upper_bound;
  84#endif
  85#ifdef CONFIG_IP_ROUTE_CLASSID
  86        __u32                   nh_tclassid;
  87#endif
  88        int                     nh_oif;
  89        __be32                  nh_gw;
  90        __be32                  nh_saddr;
  91        int                     nh_saddr_genid;
  92        struct rtable __rcu * __percpu *nh_pcpu_rth_output;
  93        struct rtable __rcu     *nh_rth_input;
  94        struct fnhe_hash_bucket __rcu *nh_exceptions;
  95        struct lwtunnel_state   *nh_lwtstate;
  96};
  97
  98/*
  99 * This structure contains data shared by many of routes.
 100 */
 101
 102struct fib_info {
 103        struct hlist_node       fib_hash;
 104        struct hlist_node       fib_lhash;
 105        struct net              *fib_net;
 106        int                     fib_treeref;
 107        atomic_t                fib_clntref;
 108        unsigned int            fib_flags;
 109        unsigned char           fib_dead;
 110        unsigned char           fib_protocol;
 111        unsigned char           fib_scope;
 112        unsigned char           fib_type;
 113        __be32                  fib_prefsrc;
 114        u32                     fib_tb_id;
 115        u32                     fib_priority;
 116        u32                     *fib_metrics;
 117#define fib_mtu fib_metrics[RTAX_MTU-1]
 118#define fib_window fib_metrics[RTAX_WINDOW-1]
 119#define fib_rtt fib_metrics[RTAX_RTT-1]
 120#define fib_advmss fib_metrics[RTAX_ADVMSS-1]
 121        int                     fib_nhs;
 122#ifdef CONFIG_IP_ROUTE_MULTIPATH
 123        int                     fib_weight;
 124#endif
 125        struct rcu_head         rcu;
 126        struct fib_nh           fib_nh[0];
 127#define fib_dev         fib_nh[0].nh_dev
 128};
 129
 130
 131#ifdef CONFIG_IP_MULTIPLE_TABLES
 132struct fib_rule;
 133#endif
 134
 135struct fib_table;
 136struct fib_result {
 137        unsigned char   prefixlen;
 138        unsigned char   nh_sel;
 139        unsigned char   type;
 140        unsigned char   scope;
 141        u32             tclassid;
 142        struct fib_info *fi;
 143        struct fib_table *table;
 144        struct hlist_head *fa_head;
 145};
 146
 147struct fib_result_nl {
 148        __be32          fl_addr;   /* To be looked up*/
 149        u32             fl_mark;
 150        unsigned char   fl_tos;
 151        unsigned char   fl_scope;
 152        unsigned char   tb_id_in;
 153
 154        unsigned char   tb_id;      /* Results */
 155        unsigned char   prefixlen;
 156        unsigned char   nh_sel;
 157        unsigned char   type;
 158        unsigned char   scope;
 159        int             err;      
 160};
 161
 162#ifdef CONFIG_IP_ROUTE_MULTIPATH
 163#define FIB_RES_NH(res)         ((res).fi->fib_nh[(res).nh_sel])
 164#else /* CONFIG_IP_ROUTE_MULTIPATH */
 165#define FIB_RES_NH(res)         ((res).fi->fib_nh[0])
 166#endif /* CONFIG_IP_ROUTE_MULTIPATH */
 167
 168#ifdef CONFIG_IP_MULTIPLE_TABLES
 169#define FIB_TABLE_HASHSZ 256
 170#else
 171#define FIB_TABLE_HASHSZ 2
 172#endif
 173
 174__be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
 175
 176#define FIB_RES_SADDR(net, res)                         \
 177        ((FIB_RES_NH(res).nh_saddr_genid ==             \
 178          atomic_read(&(net)->ipv4.dev_addr_genid)) ?   \
 179         FIB_RES_NH(res).nh_saddr :                     \
 180         fib_info_update_nh_saddr((net), &FIB_RES_NH(res)))
 181#define FIB_RES_GW(res)                 (FIB_RES_NH(res).nh_gw)
 182#define FIB_RES_DEV(res)                (FIB_RES_NH(res).nh_dev)
 183#define FIB_RES_OIF(res)                (FIB_RES_NH(res).nh_oif)
 184
 185#define FIB_RES_PREFSRC(net, res)       ((res).fi->fib_prefsrc ? : \
 186                                         FIB_RES_SADDR(net, res))
 187
 188struct fib_table {
 189        struct hlist_node       tb_hlist;
 190        u32                     tb_id;
 191        int                     tb_num_default;
 192        struct rcu_head         rcu;
 193        unsigned long           *tb_data;
 194        unsigned long           __data[0];
 195};
 196
 197int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
 198                     struct fib_result *res, int fib_flags);
 199int fib_table_insert(struct fib_table *, struct fib_config *);
 200int fib_table_delete(struct fib_table *, struct fib_config *);
 201int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
 202                   struct netlink_callback *cb);
 203int fib_table_flush(struct fib_table *table);
 204struct fib_table *fib_trie_unmerge(struct fib_table *main_tb);
 205void fib_table_flush_external(struct fib_table *table);
 206void fib_free_table(struct fib_table *tb);
 207
 208#ifndef CONFIG_IP_MULTIPLE_TABLES
 209
 210#define TABLE_LOCAL_INDEX       (RT_TABLE_LOCAL & (FIB_TABLE_HASHSZ - 1))
 211#define TABLE_MAIN_INDEX        (RT_TABLE_MAIN  & (FIB_TABLE_HASHSZ - 1))
 212
 213static inline struct fib_table *fib_get_table(struct net *net, u32 id)
 214{
 215        struct hlist_node *tb_hlist;
 216        struct hlist_head *ptr;
 217
 218        ptr = id == RT_TABLE_LOCAL ?
 219                &net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] :
 220                &net->ipv4.fib_table_hash[TABLE_MAIN_INDEX];
 221
 222        tb_hlist = rcu_dereference_rtnl(hlist_first_rcu(ptr));
 223
 224        return hlist_entry(tb_hlist, struct fib_table, tb_hlist);
 225}
 226
 227static inline struct fib_table *fib_new_table(struct net *net, u32 id)
 228{
 229        return fib_get_table(net, id);
 230}
 231
 232static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
 233                             struct fib_result *res, unsigned int flags)
 234{
 235        struct fib_table *tb;
 236        int err = -ENETUNREACH;
 237
 238        rcu_read_lock();
 239
 240        tb = fib_get_table(net, RT_TABLE_MAIN);
 241        if (tb)
 242                err = fib_table_lookup(tb, flp, res, flags | FIB_LOOKUP_NOREF);
 243
 244        if (err == -EAGAIN)
 245                err = -ENETUNREACH;
 246
 247        rcu_read_unlock();
 248
 249        return err;
 250}
 251
 252#else /* CONFIG_IP_MULTIPLE_TABLES */
 253int __net_init fib4_rules_init(struct net *net);
 254void __net_exit fib4_rules_exit(struct net *net);
 255
 256struct fib_table *fib_new_table(struct net *net, u32 id);
 257struct fib_table *fib_get_table(struct net *net, u32 id);
 258
 259int __fib_lookup(struct net *net, struct flowi4 *flp,
 260                 struct fib_result *res, unsigned int flags);
 261
 262static inline int fib_lookup(struct net *net, struct flowi4 *flp,
 263                             struct fib_result *res, unsigned int flags)
 264{
 265        struct fib_table *tb;
 266        int err = -ENETUNREACH;
 267
 268        flags |= FIB_LOOKUP_NOREF;
 269        if (net->ipv4.fib_has_custom_rules)
 270                return __fib_lookup(net, flp, res, flags);
 271
 272        rcu_read_lock();
 273
 274        res->tclassid = 0;
 275
 276        tb = rcu_dereference_rtnl(net->ipv4.fib_main);
 277        if (tb)
 278                err = fib_table_lookup(tb, flp, res, flags);
 279
 280        if (!err)
 281                goto out;
 282
 283        tb = rcu_dereference_rtnl(net->ipv4.fib_default);
 284        if (tb)
 285                err = fib_table_lookup(tb, flp, res, flags);
 286
 287out:
 288        if (err == -EAGAIN)
 289                err = -ENETUNREACH;
 290
 291        rcu_read_unlock();
 292
 293        return err;
 294}
 295
 296#endif /* CONFIG_IP_MULTIPLE_TABLES */
 297
 298/* Exported by fib_frontend.c */
 299extern const struct nla_policy rtm_ipv4_policy[];
 300void ip_fib_init(void);
 301__be32 fib_compute_spec_dst(struct sk_buff *skb);
 302int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 303                        u8 tos, int oif, struct net_device *dev,
 304                        struct in_device *idev, u32 *itag);
 305void fib_select_default(const struct flowi4 *flp, struct fib_result *res);
 306#ifdef CONFIG_IP_ROUTE_CLASSID
 307static inline int fib_num_tclassid_users(struct net *net)
 308{
 309        return net->ipv4.fib_num_tclassid_users;
 310}
 311#else
 312static inline int fib_num_tclassid_users(struct net *net)
 313{
 314        return 0;
 315}
 316#endif
 317int fib_unmerge(struct net *net);
 318void fib_flush_external(struct net *net);
 319
 320/* Exported by fib_semantics.c */
 321int ip_fib_check_default(__be32 gw, struct net_device *dev);
 322int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force);
 323int fib_sync_down_addr(struct net_device *dev, __be32 local);
 324int fib_sync_up(struct net_device *dev, unsigned int nh_flags);
 325
 326extern u32 fib_multipath_secret __read_mostly;
 327
 328static inline int fib_multipath_hash(__be32 saddr, __be32 daddr)
 329{
 330        return jhash_2words((__force u32)saddr, (__force u32)daddr,
 331                            fib_multipath_secret) >> 1;
 332}
 333
 334void fib_select_multipath(struct fib_result *res, int hash);
 335void fib_select_path(struct net *net, struct fib_result *res,
 336                     struct flowi4 *fl4, int mp_hash);
 337
 338/* Exported by fib_trie.c */
 339void fib_trie_init(void);
 340struct fib_table *fib_trie_table(u32 id, struct fib_table *alias);
 341
 342static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
 343{
 344#ifdef CONFIG_IP_ROUTE_CLASSID
 345#ifdef CONFIG_IP_MULTIPLE_TABLES
 346        u32 rtag;
 347#endif
 348        *itag = FIB_RES_NH(*res).nh_tclassid<<16;
 349#ifdef CONFIG_IP_MULTIPLE_TABLES
 350        rtag = res->tclassid;
 351        if (*itag == 0)
 352                *itag = (rtag<<16);
 353        *itag |= (rtag>>16);
 354#endif
 355#endif
 356}
 357
 358void free_fib_info(struct fib_info *fi);
 359
 360static inline void fib_info_put(struct fib_info *fi)
 361{
 362        if (atomic_dec_and_test(&fi->fib_clntref))
 363                free_fib_info(fi);
 364}
 365
 366#ifdef CONFIG_PROC_FS
 367int __net_init fib_proc_init(struct net *net);
 368void __net_exit fib_proc_exit(struct net *net);
 369#else
 370static inline int fib_proc_init(struct net *net)
 371{
 372        return 0;
 373}
 374static inline void fib_proc_exit(struct net *net)
 375{
 376}
 377#endif
 378
 379#endif  /* _NET_FIB_H */
 380