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