MAJOR=4
MINOR=0
DEVNAME=tty0
     ˆÄÃ„�}ÏÂÆÅ ?D    /* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 *	Linux INET6 implementation 
 *
 *	Authors:
 *	Pedro Roque		<roque@di.fc.ul.pt>	
 */

#ifndef _IP6_FIB_H
#define _IP6_FIB_H

#include <linux/ipv6_route.h>
#include <linux/rtnetlink.h>
#include <linux/spinlock.h>
#include <linux/notifier.h>
#include <net/dst.h>
#include <net/flow.h>
#include <net/ip_fib.h>
#include <net/netlink.h>
#include <net/inetpeer.h>
#include <net/fib_notifier.h>
#include <linux/indirect_call_wrapper.h>
#include <uapi/linux/bpf.h>

#include <linux/rh_kabi.h>

#ifdef CONFIG_IPV6_MULTIPLE_TABLES
#define FIB6_TABLE_HASHSZ 256
#else
#define FIB6_TABLE_HASHSZ 1
#endif

#define RT6_DEBUG 2

#if RT6_DEBUG >= 3
#define RT6_TRACE(x...) pr_debug(x)
#else
#define RT6_TRACE(x...) do { ; } while (0)
#endif

struct rt6_info;
struct fib6_info;

struct fib6_config {
	u32		fc_table;
	u32		fc_metric;
	int		fc_dst_len;
	int		fc_src_len;
	int		fc_ifindex;
	u32		fc_flags;
	u32		fc_protocol;
	u16		fc_type;        /* only 8 bits are used */
	u16		fc_delete_all_nh : 1,
			fc_ignore_dev_down:1,
			__unused : 14;
	u32		fc_nh_id;

	struct in6_addr	fc_dst;
	struct in6_addr	fc_src;
	struct in6_addr	fc_prefsrc;
	struct in6_addr	fc_gateway;

	unsigned long	fc_expires;
	struct nlattr	*fc_mx;
	int		fc_mx_len;
	int		fc_mp_len;
	struct nlattr	*fc_mp;

	struct nl_info	fc_nlinfo;
	struct nlattr	*fc_encap;
	u16		fc_encap_type;
	bool		fc_is_fdb;
};

struct fib6_node {
	struct fib6_node __rcu	*parent;
	struct fib6_node __rcu	*left;
	struct fib6_node __rcu	*right;
#ifdef CONFIG_IPV6_SUBTREES
	struct fib6_node __rcu	*subtree;
#endif
	struct fib6_info __rcu	*leaf;

	__u16			fn_bit;		/* bit key */
	__u16			fn_flags;
	int			fn_sernum;
	struct fib6_info __rcu	*rr_ptr;
	struct rcu_head		rcu;
};

struct fib6_gc_args {
	int			timeout;
	int			more;
};

#ifndef CONFIG_IPV6_SUBTREES
#define FIB6_SUBTREE(fn)	NULL

static inline bool fib6_routes_require_src(const struct net *net)
{
	return false;
}

static inline void fib6_routes_require_src_inc(struct net *net) {}
static inline void fib6_routes_require_src_dec(struct net *net) {}

#else

static inline bool fib6_routes_require_src(const struct net *net)
{
	return net->ipv6.fib6_routes_require_src > 0;
}

static inline void fib6_routes_require_src_inc(struct net *net)
{
	net->ipv6.fib6_routes_require_src++;
}

static inline void fib6_routes_require_src_dec(struct net *net)
{
	net->ipv6.fib6_routes_require_src--;
}

#define FIB6_SUBTREE(fn)	(rcu_dereference_protected((fn)->subtree, 1))
#endif

/*
 *	routing information
 *
 */

struct rt6key {
	struct in6_addr	addr;
	int		plen;
};

struct fib6_table;

struct rt6_exception_bucket {
	struct hlist_head	chain;
	int			depth;
};

struct rt6_exception {
	struct hlist_node	hlist;
	struct rt6_info		*rt6i;
	unsigned long		stamp;
	struct rcu_head		rcu;
};

#define FIB6_EXCEPTION_BUCKET_SIZE_SHIFT 10
#define FIB6_EXCEPTION_BUCKET_SIZE (1 << FIB6_EXCEPTION_BUCKET_SIZE_SHIFT)
#define FIB6_MAX_DEPTH 5

struct fib6_nh {
	struct fib_nh_common	nh_common;

#ifdef CONFIG_IPV6_ROUTER_PREF
	unsigned long		last_probe;
#endif

	struct rt6_info * __percpu *rt6i_pcpu;
	struct rt6_exception_bucket __rcu *rt6i_exception_bucket;
};

struct fib6_info {
	struct fib6_table		*fib6_table;
	struct fib6_info __rcu		*fib6_next;
	struct fib6_node __rcu		*fib6_node;

	/* Multipath routes:
	 * siblings is a list of fib6_info that have the same metric/weight,
	 * destination, but not the same gateway. nsiblings is just a cache
	 * to speed up lookup.
	 */
	union {
		struct list_head	fib6_siblings;
		struct list_head	nh_list;
	};
	unsigned int			fib6_nsiblings;

	refcount_t			fib6_ref;
	unsigned long			expires;
	struct dst_metrics		*fib6_metrics;
#define fib6_pmtu		fib6_metrics->metrics[RTAX_MTU-1]

	struct rt6key			fib6_dst;
	u32				fib6_flags;
	struct rt6key			fib6_src;
	struct rt6key			fib6_prefsrc;

	u32				fib6_metric;
	u8				fib6_protocol;
	u8				fib6_type;

	u8				offload;
	u8				trap;
	u8				offload_failed;

	u8				should_flush:1,
					dst_nocount:1,
					dst_nopolicy:1,
					f