linux/include/net/ip6_fib.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-or-later */
   2/*
   3 *      Linux INET6 implementation 
   4 *
   5 *      Authors:
   6 *      Pedro Roque             <roque@di.fc.ul.pt>     
   7 */
   8
   9#ifndef _IP6_FIB_H
  10#define _IP6_FIB_H
  11
  12#include <linux/ipv6_route.h>
  13#include <linux/rtnetlink.h>
  14#include <linux/spinlock.h>
  15#include <linux/notifier.h>
  16#include <net/dst.h>
  17#include <net/flow.h>
  18#include <net/ip_fib.h>
  19#include <net/netlink.h>
  20#include <net/inetpeer.h>
  21#include <net/fib_notifier.h>
  22#include <linux/indirect_call_wrapper.h>
  23
  24#ifdef CONFIG_IPV6_MULTIPLE_TABLES
  25#define FIB6_TABLE_HASHSZ 256
  26#else
  27#define FIB6_TABLE_HASHSZ 1
  28#endif
  29
  30#define RT6_DEBUG 2
  31
  32#if RT6_DEBUG >= 3
  33#define RT6_TRACE(x...) pr_debug(x)
  34#else
  35#define RT6_TRACE(x...) do { ; } while (0)
  36#endif
  37
  38struct rt6_info;
  39struct fib6_info;
  40
  41struct fib6_config {
  42        u32             fc_table;
  43        u32             fc_metric;
  44        int             fc_dst_len;
  45        int             fc_src_len;
  46        int             fc_ifindex;
  47        u32             fc_flags;
  48        u32             fc_protocol;
  49        u16             fc_type;        /* only 8 bits are used */
  50        u16             fc_delete_all_nh : 1,
  51                        fc_ignore_dev_down:1,
  52                        __unused : 14;
  53        u32             fc_nh_id;
  54
  55        struct in6_addr fc_dst;
  56        struct in6_addr fc_src;
  57        struct in6_addr fc_prefsrc;
  58        struct in6_addr fc_gateway;
  59
  60        unsigned long   fc_expires;
  61        struct nlattr   *fc_mx;
  62        int             fc_mx_len;
  63        int             fc_mp_len;
  64        struct nlattr   *fc_mp;
  65
  66        struct nl_info  fc_nlinfo;
  67        struct nlattr   *fc_encap;
  68        u16             fc_encap_type;
  69        bool            fc_is_fdb;
  70};
  71
  72struct fib6_node {
  73        struct fib6_node __rcu  *parent;
  74        struct fib6_node __rcu  *left;
  75        struct fib6_node __rcu  *right;
  76#ifdef CONFIG_IPV6_SUBTREES
  77        struct fib6_node __rcu  *subtree;
  78#endif
  79        struct fib6_info __rcu  *leaf;
  80
  81        __u16                   fn_bit;         /* bit key */
  82        __u16                   fn_flags;
  83        int                     fn_sernum;
  84        struct fib6_info __rcu  *rr_ptr;
  85        struct rcu_head         rcu;
  86};
  87
  88struct fib6_gc_args {
  89        int                     timeout;
  90        int                     more;
  91};
  92
  93#ifndef CONFIG_IPV6_SUBTREES
  94#define FIB6_SUBTREE(fn)        NULL
  95
  96static inline bool fib6_routes_require_src(const struct net *net)
  97{
  98        return false;
  99}
 100
 101static inline void fib6_routes_require_src_inc(struct net *net) {}
 102static inline void fib6_routes_require_src_dec(struct net *net) {}
 103
 104#else
 105
 106static inline bool fib6_routes_require_src(const struct net *net)
 107{
 108        return net->ipv6.fib6_routes_require_src > 0;
 109}
 110
 111static inline void fib6_routes_require_src_inc(struct net *net)
 112{
 113        net->ipv6.fib6_routes_require_src++;
 114}
 115
 116static inline void fib6_routes_require_src_dec(struct net *net)
 117{
 118        net->ipv6.fib6_routes_require_src--;
 119}
 120
 121#define FIB6_SUBTREE(fn)        (rcu_dereference_protected((fn)->subtree, 1))
 122#endif
 123
 124/*
 125 *      routing information
 126 *
 127 */
 128
 129struct rt6key {
 130        struct in6_addr addr;
 131        int             plen;
 132};
 133
 134struct fib6_table;
 135
 136struct rt6_exception_bucket {
 137        struct hlist_head       chain;
 138        int                     depth;
 139};
 140
 141struct rt6_exception {
 142        struct hlist_node       hlist;
 143        struct rt6_info         *rt6i;
 144        unsigned long           stamp;
 145        struct rcu_head         rcu;
 146};
 147
 148#define FIB6_EXCEPTION_BUCKET_SIZE_SHIFT 10
 149#define FIB6_EXCEPTION_BUCKET_SIZE (1 << FIB6_EXCEPTION_BUCKET_SIZE_SHIFT)
 150#define FIB6_MAX_DEPTH 5
 151
 152struct fib6_nh {
 153        struct fib_nh_common    nh_common;
 154
 155#ifdef CONFIG_IPV6_ROUTER_PREF
 156        unsigned long           last_probe;
 157#endif
 158
 159        struct rt6_info * __percpu *rt6i_pcpu;
 160        struct rt6_exception_bucket __rcu *rt6i_exception_bucket;
 161};
 162
 163struct fib6_info {
 164        struct fib6_table               *fib6_table;
 165        struct fib6_info __rcu          *fib6_next;
 166        struct fib6_node __rcu          *fib6_node;
 167
 168        /* Multipath routes:
 169         * siblings is a list of fib6_info that have the same metric/weight,
 170         * destination, but not the same gateway. nsiblings is just a cache
 171         * to speed up lookup.
 172         */
 173        union {
 174                struct list_head        fib6_siblings;
 175                struct list_head        nh_list;
 176        };
 177        unsigned int                    fib6_nsiblings;
 178
 179        refcount_t                      fib6_ref;
 180        unsigned long                   expires;
 181        struct dst_metrics              *fib6_metrics;
 182#define fib6_pmtu               fib6_metrics->metrics[RTAX_MTU-1]
 183
 184        struct rt6key                   fib6_dst;
 185        u32                             fib6_flags;
 186        struct rt6key                   fib6_src;
 187        struct rt6key                   fib6_prefsrc;
 188
 189        u32                             fib6_metric;
 190        u8                              fib6_protocol;
 191        u8                              fib6_type;
 192        u8                              should_flush:1,
 193                                        dst_nocount:1,
 194                                        dst_nopolicy:1,
 195                                        fib6_destroying:1,
 196                                        offload:1,
 197                                        trap:1,
 198                                        offload_failed:1,
 199                                        unused:1;
 200
 201        struct rcu_head                 rcu;
 202        struct nexthop                  *nh;
 203        struct fib6_nh                  fib6_nh[];
 204};
 205
 206struct rt6_info {
 207        struct dst_entry                dst;
 208        struct fib6_info __rcu          *from;
 209        int                             sernum;
 210
 211        struct rt6key                   rt6i_dst;
 212        struct rt6key                   rt6i_src;
 213        struct in6_addr                 rt6i_gateway;
 214        struct inet6_dev                *rt6i_idev;
 215        u32                             rt6i_flags;
 216
 217        struct list_head                rt6i_uncached;
 218        struct uncached_list            *rt6i_uncached_list;
 219
 220        /* more non-fragment space at head required */
 221        unsigned short                  rt6i_nfheader_len;
 222};
 223
 224struct fib6_result {
 225        struct fib6_nh          *nh;
 226        struct fib6_info        *f6i;
 227        u32                     fib6_flags;
 228        u8                      fib6_type;
 229        struct rt6_info         *rt6;
 230};
 231
 232#define for_each_fib6_node_rt_rcu(fn)                                   \
 233        for (rt = rcu_dereference((fn)->leaf); rt;                      \
 234             rt = rcu_dereference(rt->fib6_next))
 235
 236#define for_each_fib6_walker_rt(w)                                      \
 237        for (rt = (w)->leaf; rt;                                        \
 238             rt = rcu_dereference_protected(rt->fib6_next, 1))
 239
 240static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
 241{
 242        return ((struct rt6_info *)dst)->rt6i_idev;
 243}
 244
 245static inline bool fib6_requires_src(const struct fib6_info *rt)
 246{
 247        return rt->fib6_src.plen > 0;
 248}
 249
 250static inline void fib6_clean_expires(struct fib6_info *f6i)
 251{
 252        f6i->fib6_flags &= ~RTF_EXPIRES;
 253        f6i->expires = 0;
 254}
 255
 256static inline void fib6_set_expires(struct fib6_info *f6i,
 257                                    unsigned long expires)
 258{
 259        f6i->expires = expires;
 260        f6i->fib6_flags |= RTF_EXPIRES;
 261}
 262
 263static inline bool fib6_check_expired(const struct fib6_info *f6i)
 264{
 265        if (f6i->fib6_flags & RTF_EXPIRES)
 266                return time_after(jiffies, f6i->expires);
 267        return false;
 268}
 269
 270/* Function to safely get fn->fn_sernum for passed in rt
 271 * and store result in passed in cookie.
 272 * Return true if we can get cookie safely
 273 * Return false if not
 274 */
 275static inline bool fib6_get_cookie_safe(const struct fib6_info *f6i,
 276                                        u32 *cookie)
 277{
 278        struct fib6_node *fn;
 279        bool status = false;
 280
 281        fn = rcu_dereference(f6i->fib6_node);
 282
 283        if (fn) {
 284                *cookie = fn->fn_sernum;
 285                /* pairs with smp_wmb() in __fib6_update_sernum_upto_root() */
 286                smp_rmb();
 287                status = true;
 288        }
 289
 290        return status;
 291}
 292
 293static inline u32 rt6_get_cookie(const struct rt6_info *rt)
 294{
 295        struct fib6_info *from;
 296        u32 cookie = 0;
 297
 298        if (rt->sernum)
 299                return rt->sernum;
 300
 301        rcu_read_lock();
 302
 303        from = rcu_dereference(rt->from);
 304        if (from)
 305                fib6_get_cookie_safe(from, &cookie);
 306
 307        rcu_read_unlock();
 308
 309        return cookie;
 310}
 311
 312static inline void ip6_rt_put(struct rt6_info *rt)
 313{
 314        /* dst_release() accepts a NULL parameter.
 315         * We rely on dst being first structure in struct rt6_info
 316         */
 317        BUILD_BUG_ON(offsetof(struct rt6_info, dst) != 0);
 318        dst_release(&rt->dst);
 319}
 320
 321struct fib6_info *fib6_info_alloc(gfp_t gfp_flags, bool with_fib6_nh);
 322void fib6_info_destroy_rcu(struct rcu_head *head);
 323
 324static inline void fib6_info_hold(struct fib6_info *f6i)
 325{
 326        refcount_inc(&f6i->fib6_ref);
 327}
 328
 329static inline bool fib6_info_hold_safe(struct fib6_info *f6i)
 330{
 331        return refcount_inc_not_zero(&f6i->fib6_ref);
 332}
 333
 334static inline void fib6_info_release(struct fib6_info *f6i)
 335{
 336        if (f6i && refcount_dec_and_test(&f6i->fib6_ref))
 337                call_rcu(&f6i->rcu, fib6_info_destroy_rcu);
 338}
 339
 340enum fib6_walk_state {
 341#ifdef CONFIG_IPV6_SUBTREES
 342        FWS_S,
 343#endif
 344        FWS_L,
 345        FWS_R,
 346        FWS_C,
 347        FWS_U
 348};
 349
 350struct fib6_walker {
 351        struct list_head lh;
 352        struct fib6_node *root, *node;
 353        struct fib6_info *leaf;
 354        enum fib6_walk_state state;
 355        unsigned int skip;
 356        unsigned int count;
 357        unsigned int skip_in_node;
 358        int (*func)(struct fib6_walker *);
 359        void *args;
 360};
 361
 362struct rt6_statistics {
 363        __u32           fib_nodes;              /* all fib6 nodes */
 364        __u32           fib_route_nodes;        /* intermediate nodes */
 365        __u32           fib_rt_entries;         /* rt entries in fib table */
 366        __u32           fib_rt_cache;           /* cached rt entries in exception table */
 367        __u32           fib_discarded_routes;   /* total number of routes delete */
 368
 369        /* The following stats are not protected by any lock */
 370        atomic_t        fib_rt_alloc;           /* total number of routes alloced */
 371        atomic_t        fib_rt_uncache;         /* rt entries in uncached list */
 372};
 373
 374#define RTN_TL_ROOT     0x0001
 375#define RTN_ROOT        0x0002          /* tree root node               */
 376#define RTN_RTINFO      0x0004          /* node with valid routing info */
 377
 378/*
 379 *      priority levels (or metrics)
 380 *
 381 */
 382
 383
 384struct fib6_table {
 385        struct hlist_node       tb6_hlist;
 386        u32                     tb6_id;
 387        spinlock_t              tb6_lock;
 388        struct fib6_node        tb6_root;
 389        struct inet_peer_base   tb6_peers;
 390        unsigned int            flags;
 391        unsigned int            fib_seq;
 392#define RT6_TABLE_HAS_DFLT_ROUTER       BIT(0)
 393};
 394
 395#define RT6_TABLE_UNSPEC        RT_TABLE_UNSPEC
 396#define RT6_TABLE_MAIN          RT_TABLE_MAIN
 397#define RT6_TABLE_DFLT          RT6_TABLE_MAIN
 398#define RT6_TABLE_INFO          RT6_TABLE_MAIN
 399#define RT6_TABLE_PREFIX        RT6_TABLE_MAIN
 400
 401#ifdef CONFIG_IPV6_MULTIPLE_TABLES
 402#define FIB6_TABLE_MIN          1
 403#define FIB6_TABLE_MAX          RT_TABLE_MAX
 404#define RT6_TABLE_LOCAL         RT_TABLE_LOCAL
 405#else
 406#define FIB6_TABLE_MIN          RT_TABLE_MAIN
 407#define FIB6_TABLE_MAX          FIB6_TABLE_MIN
 408#define RT6_TABLE_LOCAL         RT6_TABLE_MAIN
 409#endif
 410
 411typedef struct rt6_info *(*pol_lookup_t)(struct net *,
 412                                         struct fib6_table *,
 413                                         struct flowi6 *,
 414                                         const struct sk_buff *, int);
 415
 416struct fib6_entry_notifier_info {
 417        struct fib_notifier_info info; /* must be first */
 418        struct fib6_info *rt;
 419        unsigned int nsiblings;
 420};
 421
 422/*
 423 *      exported functions
 424 */
 425
 426struct fib6_table *fib6_get_table(struct net *net, u32 id);
 427struct fib6_table *fib6_new_table(struct net *net, u32 id);
 428struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
 429                                   const struct sk_buff *skb,
 430                                   int flags, pol_lookup_t lookup);
 431
 432/* called with rcu lock held; can return error pointer
 433 * caller needs to select path
 434 */
 435int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
 436                struct fib6_result *res, int flags);
 437
 438/* called with rcu lock held; caller needs to select path */
 439int fib6_table_lookup(struct net *net, struct fib6_table *table,
 440                      int oif, struct flowi6 *fl6, struct fib6_result *res,
 441                      int strict);
 442
 443void fib6_select_path(const struct net *net, struct fib6_result *res,
 444                      struct flowi6 *fl6, int oif, bool have_oif_match,
 445                      const struct sk_buff *skb, int strict);
 446struct fib6_node *fib6_node_lookup(struct fib6_node *root,
 447                                   const struct in6_addr *daddr,
 448                                   const struct in6_addr *saddr);
 449
 450struct fib6_node *fib6_locate(struct fib6_node *root,
 451                              const struct in6_addr *daddr, int dst_len,
 452                              const struct in6_addr *saddr, int src_len,
 453                              bool exact_match);
 454
 455void fib6_clean_all(struct net *net, int (*func)(struct fib6_info *, void *arg),
 456                    void *arg);
 457void fib6_clean_all_skip_notify(struct net *net,
 458                                int (*func)(struct fib6_info *, void *arg),
 459                                void *arg);
 460
 461int fib6_add(struct fib6_node *root, struct fib6_info *rt,
 462             struct nl_info *info, struct netlink_ext_ack *extack);
 463int fib6_del(struct fib6_info *rt, struct nl_info *info);
 464
 465static inline
 466void rt6_get_prefsrc(const struct rt6_info *rt, struct in6_addr *addr)
 467{
 468        const struct fib6_info *from;
 469
 470        rcu_read_lock();
 471
 472        from = rcu_dereference(rt->from);
 473        if (from) {
 474                *addr = from->fib6_prefsrc.addr;
 475        } else {
 476                struct in6_addr in6_zero = {};
 477
 478                *addr = in6_zero;
 479        }
 480
 481        rcu_read_unlock();
 482}
 483
 484int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
 485                 struct fib6_config *cfg, gfp_t gfp_flags,
 486                 struct netlink_ext_ack *extack);
 487void fib6_nh_release(struct fib6_nh *fib6_nh);
 488
 489int call_fib6_entry_notifiers(struct net *net,
 490                              enum fib_event_type event_type,
 491                              struct fib6_info *rt,
 492                              struct netlink_ext_ack *extack);
 493int call_fib6_multipath_entry_notifiers(struct net *net,
 494                                        enum fib_event_type event_type,
 495                                        struct fib6_info *rt,
 496                                        unsigned int nsiblings,
 497                                        struct netlink_ext_ack *extack);
 498int call_fib6_entry_notifiers_replace(struct net *net, struct fib6_info *rt);
 499void fib6_rt_update(struct net *net, struct fib6_info *rt,
 500                    struct nl_info *info);
 501void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
 502                     unsigned int flags);
 503
 504void fib6_run_gc(unsigned long expires, struct net *net, bool force);
 505
 506void fib6_gc_cleanup(void);
 507
 508int fib6_init(void);
 509
 510struct ipv6_route_iter {
 511        struct seq_net_private p;
 512        struct fib6_walker w;
 513        loff_t skip;
 514        struct fib6_table *tbl;
 515        int sernum;
 516};
 517
 518extern const struct seq_operations ipv6_route_seq_ops;
 519
 520int call_fib6_notifier(struct notifier_block *nb,
 521                       enum fib_event_type event_type,
 522                       struct fib_notifier_info *info);
 523int call_fib6_notifiers(struct net *net, enum fib_event_type event_type,
 524                        struct fib_notifier_info *info);
 525
 526int __net_init fib6_notifier_init(struct net *net);
 527void __net_exit fib6_notifier_exit(struct net *net);
 528
 529unsigned int fib6_tables_seq_read(struct net *net);
 530int fib6_tables_dump(struct net *net, struct notifier_block *nb,
 531                     struct netlink_ext_ack *extack);
 532
 533void fib6_update_sernum(struct net *net, struct fib6_info *rt);
 534void fib6_update_sernum_upto_root(struct net *net, struct fib6_info *rt);
 535void fib6_update_sernum_stub(struct net *net, struct fib6_info *f6i);
 536
 537void fib6_metric_set(struct fib6_info *f6i, int metric, u32 val);
 538static inline bool fib6_metric_locked(struct fib6_info *f6i, int metric)
 539{
 540        return !!(f6i->fib6_metrics->metrics[RTAX_LOCK - 1] & (1 << metric));
 541}
 542void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i,
 543                            bool offload, bool trap, bool offload_failed);
 544
 545#if IS_BUILTIN(CONFIG_IPV6) && defined(CONFIG_BPF_SYSCALL)
 546struct bpf_iter__ipv6_route {
 547        __bpf_md_ptr(struct bpf_iter_meta *, meta);
 548        __bpf_md_ptr(struct fib6_info *, rt);
 549};
 550#endif
 551
 552INDIRECT_CALLABLE_DECLARE(struct rt6_info *ip6_pol_route_output(struct net *net,
 553                                             struct fib6_table *table,
 554                                             struct flowi6 *fl6,
 555                                             const struct sk_buff *skb,
 556                                             int flags));
 557INDIRECT_CALLABLE_DECLARE(struct rt6_info *ip6_pol_route_input(struct net *net,
 558                                             struct fib6_table *table,
 559                                             struct flowi6 *fl6,
 560                                             const struct sk_buff *skb,
 561                                             int flags));
 562INDIRECT_CALLABLE_DECLARE(struct rt6_info *__ip6_route_redirect(struct net *net,
 563                                             struct fib6_table *table,
 564                                             struct flowi6 *fl6,
 565                                             const struct sk_buff *skb,
 566                                             int flags));
 567INDIRECT_CALLABLE_DECLARE(struct rt6_info *ip6_pol_route_lookup(struct net *net,
 568                                             struct fib6_table *table,
 569                                             struct flowi6 *fl6,
 570                                             const struct sk_buff *skb,
 571                                             int flags));
 572static inline struct rt6_info *pol_lookup_func(pol_lookup_t lookup,
 573                                                struct net *net,
 574                                                struct fib6_table *table,
 575                                                struct flowi6 *fl6,
 576                                                const struct sk_buff *skb,
 577                                                int flags)
 578{
 579        return INDIRECT_CALL_4(lookup,
 580                               ip6_pol_route_output,
 581                               ip6_pol_route_input,
 582                               ip6_pol_route_lookup,
 583                               __ip6_route_redirect,
 584                               net, table, fl6, skb, flags);
 585}
 586
 587#ifdef CONFIG_IPV6_MULTIPLE_TABLES
 588static inline bool fib6_has_custom_rules(const struct net *net)
 589{
 590        return net->ipv6.fib6_has_custom_rules;
 591}
 592
 593int fib6_rules_init(void);
 594void fib6_rules_cleanup(void);
 595bool fib6_rule_default(const struct fib_rule *rule);
 596int fib6_rules_dump(struct net *net, struct notifier_block *nb,
 597                    struct netlink_ext_ack *extack);
 598unsigned int fib6_rules_seq_read(struct net *net);
 599
 600static inline bool fib6_rules_early_flow_dissect(struct net *net,
 601                                                 struct sk_buff *skb,
 602                                                 struct flowi6 *fl6,
 603                                                 struct flow_keys *flkeys)
 604{
 605        unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP;
 606
 607        if (!net->ipv6.fib6_rules_require_fldissect)
 608                return false;
 609
 610        skb_flow_dissect_flow_keys(skb, flkeys, flag);
 611        fl6->fl6_sport = flkeys->ports.src;
 612        fl6->fl6_dport = flkeys->ports.dst;
 613        fl6->flowi6_proto = flkeys->basic.ip_proto;
 614
 615        return true;
 616}
 617#else
 618static inline bool fib6_has_custom_rules(const struct net *net)
 619{
 620        return false;
 621}
 622static inline int               fib6_rules_init(void)
 623{
 624        return 0;
 625}
 626static inline void              fib6_rules_cleanup(void)
 627{
 628        return ;
 629}
 630static inline bool fib6_rule_default(const struct fib_rule *rule)
 631{
 632        return true;
 633}
 634static inline int fib6_rules_dump(struct net *net, struct notifier_block *nb,
 635                                  struct netlink_ext_ack *extack)
 636{
 637        return 0;
 638}
 639static inline unsigned int fib6_rules_seq_read(struct net *net)
 640{
 641        return 0;
 642}
 643static inline bool fib6_rules_early_flow_dissect(struct net *net,
 644                                                 struct sk_buff *skb,
 645                                                 struct flowi6 *fl6,
 646                                                 struct flow_keys *flkeys)
 647{
 648        return false;
 649}
 650#endif
 651#endif
 652