1
  +   ˆl–Ü4ý( ©³( 	Å€fàB¦-ÿÁ„Ÿ}ï_†I|¥�+ÁÀ 2Æ    /* SPDX-License-Identifier: GPL-2.0 */
/*
 * Generic nexthop implementation
 *
 * Copyright (c) 2017-19 Cumulus Networks
 * Copyright (c) 2017-19 David Ahern <dsa@cumulusnetworks.com>
 */

#ifndef __LINUX_NEXTHOP_H
#define __LINUX_NEXTHOP_H

#include <linux/netdevice.h>
#include <linux/notifier.h>
#include <linux/route.h>
#include <linux/types.h>
#include <net/ip_fib.h>
#include <net/ip6_fib.h>
#include <net/netlink.h>

#include <linux/rh_kabi.h>

#define NEXTHOP_VALID_USER_FLAGS RTNH_F_ONLINK

struct nexthop;

struct nh_config {
	u32		nh_id;

	u8		nh_family;
	u8		nh_protocol;
	u8		nh_blackhole;
	u8		nh_fdb;
	u32		nh_flags;

	int		nh_ifindex;
	struct net_device *dev;

	union {
		__be32		ipv4;
		struct in6_addr	ipv6;
	} gw;

	struct nlattr	*nh_grp;
	u16		nh_grp_type;
	u16		nh_grp_res_num_buckets;
	unsigned long	nh_grp_res_idle_timer;
	unsigned long	nh_grp_res_unbalanced_timer;
	bool		nh_grp_res_has_num_buckets;
	bool		nh_grp_res_has_idle_timer;
	bool		nh_grp_res_has_unbalanced_timer;

	bool		nh_hw_stats;

	struct nlattr	*nh_encap;
	u16		nh_encap_type;

	u32		nlflags;
	struct nl_info	nlinfo;
};

struct nh_info {
	struct hlist_node	dev_hash;    /* entry on netns devhash */
	struct nexthop		*nh_parent;

	u8			family;
	bool			reject_nh;
	bool			fdb_nh;

	union {
		struct fib_nh_common	fib_nhc;
		struct fib_nh		fib_nh;
		struct fib6_nh		fib6_nh;
	};
};

struct nh_res_bucket {
	struct nh_grp_entry __rcu *nh_entry;
	atomic_long_t		used_time;
	unsigned long		migrated_time;
	bool			occupied;
	u8			nh_flags;
};

struct nh_res_table {
	struct net		*net;
	u32			nhg_id;
	struct delayed_work	upkeep_dw;

	/* List of NHGEs that have too few buckets ("uw" for underweight).
	 * Reclaimed buckets will be given to entries in this list.
	 */
	struct list_head	uw_nh_entries;
	unsigned long		unbalanced_since;

	u32			idle_timer;
	u32			unbalanced_timer;

	u16			num_nh_buckets;
	struct nh_res_bucket	nh_buckets[];
};

struct nh_grp_entry_stats {
	u64_stats_t packets;
	struct u64_stats_sync syncp;
};

struct nh_grp_entry {
	struct nexthop	*nh;
	struct nh_grp_entry_stats __percpu	*stats;
	u16		weight;

	union {
		struct {
			atomic_t	upper_bound;
		} hthr;
		struct {
			/* Member on uw_nh_entries. */
			struct list_head	uw_nh_entry;

			u16			count_buckets;
			u16			wants_buckets;
		} res;
	};

	struct list_head nh_list;
	struct nexthop	*nh_parent;  /* nexthop of group with this entry */
	u64		packets_hw;
};

struct nh_group {
	struct nh_group		*spare; /* spare group for removals */
	u16			num_nh;
	bool			is_multipath;
	bool			hash_threshold;
	bool			resilient;
	bool			fdb_nh;
	bool			has_v4;
	bool			hw_stats;

	RH_KABI_RESERVE(1)
	RH_KABI_RESERVE(2)

	struct nh_res_table __rcu *res_table;
	struct nh_grp_entry	nh_entries[];
};

struct nexthop {
	struct rb_node		rb_node;    /* entry on netns rbtree */
	struct list_head	fi_list;    /* v4 entries using nh */
	struct list_head	f6i_list;   /* v6 entries using nh */
	struct list_head        fdb_list;   /* fdb entries using this nh */
	struct list_head	grp_list;   /* nh group entries using this nh */
	struct net		*net;

	u32			id;

	u8			protocol;   /* app managing this nh */
	u8			nh_flags;
	bool			is_group;

	refcount_t		refcnt;
	struct rcu_head		rcu;

	union {
		struct nh_info	__rcu *nh_info;
		struct nh_group __rcu *nh_grp;
	};
};

enum nexthop_event_type {
	NEXTHOP_EVENT_DEL,
	NEXTHOP_EVENT_REPLACE,
	NEXTHOP_EVENT_RES_TABLE_PRE_REPLACE,
	NEXTHOP_EVENT_BUCKET_REPLACE,
	NEXTHOP_EVENT_HW_STATS_REPORT_DELTA,
};

enum nh_notifier_info_type {
	NH_NOTIFIER_INFO_TYPE_SINGLE,
	NH_NOTIFIER_INFO_TYPE_GRP,
	NH_NOTIFIER_INFO_TYPE_RES_TABLE,
	NH_NOTIFIER_INFO_TYPE_RES_BUCKET,
	NH_NOTIFIER_INFO_TYPE_GRP_HW_STATS,
};

struct nh_notifier_single_info {
	struct net_device *dev;
	u8 gw_family;
	union {
		__be32 ipv4;
		struct in6_addr ipv6;
	};
	u32 id;
	u8 is_reject:1,
	   is_fdb:1,
	   has_encap:1;
};

struct nh_notifier_grp_entry_info {
	u16 weight;
	struct nh_notifier_single_info nh;
};

struct nh_notifier_grp_info {
	u16 num_nh;
	bool is_fdb;
	bool hw_s