1886 lines · 54.4 KB · C
RawDownload
/* SPDX-License-Identifier: GPL-2.0 *//* IP Virtual Server * data structure and functionality definitions */ #ifndef _NET_IP_VS_H#define _NET_IP_VS_H #include <linux/ip_vs.h>                /* definitions shared with userland */ #include <asm/types.h>                  /* for __uXX types */ #include <linux/list.h>                 /* for struct list_head */#include <linux/spinlock.h>             /* for struct rwlock_t */#include <linux/atomic.h>               /* for struct atomic_t */#include <linux/refcount.h>             /* for struct refcount_t */#include <linux/workqueue.h> #include <linux/compiler.h>#include <linux/timer.h>#include <linux/bug.h> #include <net/checksum.h>#include <linux/netfilter.h>		/* for union nf_inet_addr */#include <linux/ip.h>#include <linux/ipv6.h>			/* for struct ipv6hdr */#include <net/ipv6.h>#if IS_ENABLED(CONFIG_NF_CONNTRACK)#include <net/netfilter/nf_conntrack.h>#endif#include <net/net_namespace.h>		/* Netw namespace */#include <linux/sched/isolation.h> #define IP_VS_HDR_INVERSE	1#define IP_VS_HDR_ICMP		2 /* Generic access of ipvs struct */static inline struct netns_ipvs *net_ipvs(struct net* net){	return net->ipvs;} /* Connections' size value needed by ip_vs_ctl.c */extern int ip_vs_conn_tab_size; extern struct mutex __ip_vs_mutex; struct ip_vs_iphdr {	int hdr_flags;	/* ipvs flags */	__u32 off;	/* Where IP or IPv4 header starts */	__u32 len;	/* IPv4 simply where L4 starts			 * IPv6 where L4 Transport Header starts */	__u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/	__s16 protocol;	__s32 flags;	union nf_inet_addr saddr;	union nf_inet_addr daddr;}; static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,				      int len, void *buffer){	return skb_header_pointer(skb, offset, len, buffer);} /* This function handles filling *ip_vs_iphdr, both for IPv4 and IPv6. * IPv6 requires some extra work, as finding proper header position, * depend on the IPv6 extension headers. */static inline intip_vs_fill_iph_skb_off(int af, const struct sk_buff *skb, int offset,		       int hdr_flags, struct ip_vs_iphdr *iphdr){	iphdr->hdr_flags = hdr_flags;	iphdr->off = offset; #ifdef CONFIG_IP_VS_IPV6	if (af == AF_INET6) {		struct ipv6hdr _iph;		const struct ipv6hdr *iph = skb_header_pointer(			skb, offset, sizeof(_iph), &_iph);		if (!iph)			return 0; 		iphdr->saddr.in6 = iph->saddr;		iphdr->daddr.in6 = iph->daddr;		/* ipv6_find_hdr() updates len, flags */		iphdr->len	 = offset;		iphdr->flags	 = 0;		iphdr->protocol  = ipv6_find_hdr(skb, &iphdr->len, -1,						 &iphdr->fragoffs,						 &iphdr->flags);		if (iphdr->protocol < 0)			return 0;	} else#endif	{		struct iphdr _iph;		const struct iphdr *iph = skb_header_pointer(			skb, offset, sizeof(_iph), &_iph);		if (!iph)			return 0; 		iphdr->len	= offset + iph->ihl * 4;		iphdr->fragoffs	= 0;		iphdr->protocol	= iph->protocol;		iphdr->saddr.ip	= iph->saddr;		iphdr->daddr.ip	= iph->daddr;	} 	return 1;} static inline intip_vs_fill_iph_skb_icmp(int af, const struct sk_buff *skb, int offset,			bool inverse, struct ip_vs_iphdr *iphdr){	int hdr_flags = IP_VS_HDR_ICMP; 	if (inverse)		hdr_flags |= IP_VS_HDR_INVERSE; 	return ip_vs_fill_iph_skb_off(af, skb, offset, hdr_flags, iphdr);} static inline intip_vs_fill_iph_skb(int af, const struct sk_buff *skb, bool inverse,		   struct ip_vs_iphdr *iphdr){	int hdr_flags = 0; 	if (inverse)		hdr_flags |= IP_VS_HDR_INVERSE; 	return ip_vs_fill_iph_skb_off(af, skb, skb_network_offset(skb),				      hdr_flags, iphdr);} static inline boolip_vs_iph_inverse(const struct ip_vs_iphdr *iph){	return !!(iph->hdr_flags & IP_VS_HDR_INVERSE);} static inline boolip_vs_iph_icmp(const struct ip_vs_iphdr *iph){	return !!(iph->hdr_flags & IP_VS_HDR_ICMP);} static inline void ip_vs_addr_copy(int af, union nf_inet_addr *dst,				   const union nf_inet_addr *src){#ifdef CONFIG_IP_VS_IPV6	if (af == AF_INET6)		dst->in6 = src->in6;	else#endif	dst->ip = src->ip;} static inline void ip_vs_addr_set(int af, union nf_inet_addr *dst,				  const union nf_inet_addr *src){#ifdef CONFIG_IP_VS_IPV6	if (af == AF_INET6) {		dst->in6 = src->in6;		return;	}#endif	dst->ip = src->ip;	dst->all[1] = 0;	dst->all[2] = 0;	dst->all[3] = 0;} static inline int ip_vs_addr_equal(int af, const union nf_inet_addr *a,				   const union nf_inet_addr *b){#ifdef CONFIG_IP_VS_IPV6	if (af == AF_INET6)		return ipv6_addr_equal(&a->in6, &b->in6);#endif	return a->ip == b->ip;} #ifdef CONFIG_IP_VS_DEBUG#include <linux/net.h> int ip_vs_get_debug_level(void); static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len,					 const union nf_inet_addr *addr,					 int *idx){	int len;#ifdef CONFIG_IP_VS_IPV6	if (af == AF_INET6)		len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6c]",			       &addr->in6) + 1;	else#endif		len = snprintf(&buf[*idx], buf_len - *idx, "%pI4",			       &addr->ip) + 1; 	*idx += len;	BUG_ON(*idx > buf_len + 1);	return &buf[*idx - len];} #define IP_VS_DBG_BUF(level, msg, ...)					\	do {								\		char ip_vs_dbg_buf[160];				\		int ip_vs_dbg_idx = 0;					\		if (level <= ip_vs_get_debug_level())			\			printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__);	\	} while (0)#define IP_VS_ERR_BUF(msg...)						\	do {								\		char ip_vs_dbg_buf[160];				\		int ip_vs_dbg_idx = 0;					\		pr_err(msg);						\	} while (0) /* Only use from within IP_VS_DBG_BUF() or IP_VS_ERR_BUF macros */#define IP_VS_DBG_ADDR(af, addr)					\	ip_vs_dbg_addr(af, ip_vs_dbg_buf,				\		       sizeof(ip_vs_dbg_buf), addr,			\		       &ip_vs_dbg_idx) #define IP_VS_DBG(level, msg, ...)					\	do {								\		if (level <= ip_vs_get_debug_level())			\			printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__);	\	} while (0)#define IP_VS_DBG_RL(msg, ...)						\	do {								\		if (net_ratelimit())					\			printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__);	\	} while (0)#define IP_VS_DBG_PKT(level, af, pp, skb, ofs, msg)			\	do {								\		if (level <= ip_vs_get_debug_level())			\			pp->debug_packet(af, pp, skb, ofs, msg);	\	} while (0)#define IP_VS_DBG_RL_PKT(level, af, pp, skb, ofs, msg)			\	do {								\		if (level <= ip_vs_get_debug_level() &&			\		    net_ratelimit())					\			pp->debug_packet(af, pp, skb, ofs, msg);	\	} while (0)#else	/* NO DEBUGGING at ALL */#define IP_VS_DBG_BUF(level, msg...)  do {} while (0)#define IP_VS_ERR_BUF(msg...)  do {} while (0)#define IP_VS_DBG(level, msg...)  do {} while (0)#define IP_VS_DBG_RL(msg...)  do {} while (0)#define IP_VS_DBG_PKT(level, af, pp, skb, ofs, msg)	do {} while (0)#define IP_VS_DBG_RL_PKT(level, af, pp, skb, ofs, msg)	do {} while (0)#endif #define IP_VS_BUG() BUG()#define IP_VS_ERR_RL(msg, ...)						\	do {								\		if (net_ratelimit())					\			pr_err(msg, ##__VA_ARGS__);			\	} while (0) #ifdef CONFIG_IP_VS_DEBUG#define EnterFunction(level)						\	do {								\		if (level <= ip_vs_get_debug_level())			\			printk(KERN_DEBUG				\			       pr_fmt("Enter: %s, %s line %i\n"),	\			       __func__, __FILE__, __LINE__);		\	} while (0)#define LeaveFunction(level)						\	do {								\		if (level <= ip_vs_get_debug_level())			\			printk(KERN_DEBUG				\			       pr_fmt("Leave: %s, %s line %i\n"),	\			       __func__, __FILE__, __LINE__);		\	} while (0)#else#define EnterFunction(level)   do {} while (0)#define LeaveFunction(level)   do {} while (0)#endif /* The port number of FTP service (in network order). */#define FTPPORT  cpu_to_be16(21)#define FTPDATA  cpu_to_be16(20) /* TCP State Values */enum {	IP_VS_TCP_S_NONE = 0,	IP_VS_TCP_S_ESTABLISHED,	IP_VS_TCP_S_SYN_SENT,	IP_VS_TCP_S_SYN_RECV,	IP_VS_TCP_S_FIN_WAIT,	IP_VS_TCP_S_TIME_WAIT,	IP_VS_TCP_S_CLOSE,	IP_VS_TCP_S_CLOSE_WAIT,	IP_VS_TCP_S_LAST_ACK,	IP_VS_TCP_S_LISTEN,	IP_VS_TCP_S_SYNACK,	IP_VS_TCP_S_LAST}; /* UDP State Values */enum {	IP_VS_UDP_S_NORMAL,	IP_VS_UDP_S_LAST,}; /* ICMP State Values */enum {	IP_VS_ICMP_S_NORMAL,	IP_VS_ICMP_S_LAST,}; /* SCTP State Values */enum ip_vs_sctp_states {	IP_VS_SCTP_S_NONE,	IP_VS_SCTP_S_INIT1,	IP_VS_SCTP_S_INIT,	IP_VS_SCTP_S_COOKIE_SENT,	IP_VS_SCTP_S_COOKIE_REPLIED,	IP_VS_SCTP_S_COOKIE_WAIT,	IP_VS_SCTP_S_COOKIE,	IP_VS_SCTP_S_COOKIE_ECHOED,	IP_VS_SCTP_S_ESTABLISHED,	IP_VS_SCTP_S_SHUTDOWN_SENT,	IP_VS_SCTP_S_SHUTDOWN_RECEIVED,	IP_VS_SCTP_S_SHUTDOWN_ACK_SENT,	IP_VS_SCTP_S_REJECTED,	IP_VS_SCTP_S_CLOSED,	IP_VS_SCTP_S_LAST}; /* Connection templates use bits from state */#define IP_VS_CTPL_S_NONE		0x0000#define IP_VS_CTPL_S_ASSURED		0x0001#define IP_VS_CTPL_S_LAST		0x0002 /* Delta sequence info structure * Each ip_vs_conn has 2 (output AND input seq. changes). * Only used in the VS/NAT. */struct ip_vs_seq {	__u32			init_seq;	/* Add delta from this seq */	__u32			delta;		/* Delta in sequence numbers */	__u32			previous_delta;	/* Delta in sequence numbers						 * before last resized pkt */}; /* counters per cpu */struct ip_vs_counters {	u64_stats_t	conns;		/* connections scheduled */	u64_stats_t	inpkts;		/* incoming packets */	u64_stats_t	outpkts;	/* outgoing packets */	u64_stats_t	inbytes;	/* incoming bytes */	u64_stats_t	outbytes;	/* outgoing bytes */};/* Stats per cpu */struct ip_vs_cpu_stats {	struct ip_vs_counters   cnt;	struct u64_stats_sync   syncp;}; /* Default nice for estimator kthreads */#define IPVS_EST_NICE		0 /* IPVS statistics objects */struct ip_vs_estimator {	struct hlist_node	list; 	u64			last_inbytes;	u64			last_outbytes;	u64			last_conns;	u64			last_inpkts;	u64			last_outpkts; 	u64			cps;	u64			inpps;	u64			outpps;	u64			inbps;	u64			outbps; 	s32			ktid:16,	/* kthread ID, -1=temp list */				ktrow:8,	/* row/tick ID for kthread */				ktcid:8;	/* chain ID for kthread tick */}; /* * IPVS statistics object, 64-bit kernel version of struct ip_vs_stats_user */struct ip_vs_kstats {	u64			conns;		/* connections scheduled */	u64			inpkts;		/* incoming packets */	u64			outpkts;	/* outgoing packets */	u64			inbytes;	/* incoming bytes */	u64			outbytes;	/* outgoing bytes */ 	u64			cps;		/* current connection rate */	u64			inpps;		/* current in packet rate */	u64			outpps;		/* current out packet rate */	u64			inbps;		/* current in byte rate */	u64			outbps;		/* current out byte rate */}; struct ip_vs_stats {	struct ip_vs_kstats	kstats;		/* kernel statistics */	struct ip_vs_estimator	est;		/* estimator */	struct ip_vs_cpu_stats __percpu	*cpustats;	/* per cpu counters */	spinlock_t		lock;		/* spin lock */	struct ip_vs_kstats	kstats0;	/* reset values */}; struct ip_vs_stats_rcu {	struct ip_vs_stats	s;	struct rcu_head		rcu_head;}; int ip_vs_stats_init_alloc(struct ip_vs_stats *s);struct ip_vs_stats *ip_vs_stats_alloc(void);void ip_vs_stats_release(struct ip_vs_stats *stats);void ip_vs_stats_free(struct ip_vs_stats *stats); /* Process estimators in multiple timer ticks (20/50/100, see ktrow) */#define IPVS_EST_NTICKS		50/* Estimation uses a 2-second period containing ticks (in jiffies) */#define IPVS_EST_TICK		((2 * HZ) / IPVS_EST_NTICKS) /* Limit of CPU load per kthread (8 for 12.5%), ratio of CPU capacity (1/C). * Value of 4 and above ensures kthreads will take work without exceeding * the CPU capacity under different circumstances. */#define IPVS_EST_LOAD_DIVISOR	8 /* Kthreads should not have work that exceeds the CPU load above 50% */#define IPVS_EST_CPU_KTHREADS	(IPVS_EST_LOAD_DIVISOR / 2) /* Desired number of chains per timer tick (chain load factor in 100us units), * 48=4.8ms of 40ms tick (12% CPU usage): * 2 sec * 1000 ms in sec * 10 (100us in ms) / 8 (12.5%) / 50 */#define IPVS_EST_CHAIN_FACTOR	\	ALIGN_DOWN(2 * 1000 * 10 / IPVS_EST_LOAD_DIVISOR / IPVS_EST_NTICKS, 8) /* Compiled number of chains per tick * The defines should match cond_resched_rcu */#if defined(CONFIG_DEBUG_ATOMIC_SLEEP) || !defined(CONFIG_PREEMPT_RCU)#define IPVS_EST_TICK_CHAINS	IPVS_EST_CHAIN_FACTOR#else#define IPVS_EST_TICK_CHAINS	1#endif #if IPVS_EST_NTICKS > 127#error Too many timer ticks for ktrow#endif /* Multiple chains processed in same tick */struct ip_vs_est_tick_data {	struct hlist_head	chains[IPVS_EST_TICK_CHAINS];	DECLARE_BITMAP(present, IPVS_EST_TICK_CHAINS);	DECLARE_BITMAP(full, IPVS_EST_TICK_CHAINS);	int			chain_len[IPVS_EST_TICK_CHAINS];}; /* Context for estimation kthread */struct ip_vs_est_kt_data {	struct netns_ipvs	*ipvs;	struct task_struct	*task;		/* task if running */	struct ip_vs_est_tick_data __rcu *ticks[IPVS_EST_NTICKS];	DECLARE_BITMAP(avail, IPVS_EST_NTICKS);	/* tick has space for ests */	unsigned long		est_timer;	/* estimation timer (jiffies) */	struct ip_vs_stats	*calc_stats;	/* Used for calculation */	int			tick_len[IPVS_EST_NTICKS];	/* est count */	int			id;		/* ktid per netns */	int			chain_max;	/* max ests per tick chain */	int			tick_max;	/* max ests per tick */	int			est_count;	/* attached ests to kthread */	int			est_max_count;	/* max ests per kthread */	int			add_row;	/* row for new ests */	int			est_row;	/* estimated row */}; struct dst_entry;struct iphdr;struct ip_vs_conn;struct ip_vs_app;struct sk_buff;struct ip_vs_proto_data; struct ip_vs_protocol {	struct ip_vs_protocol	*next;	char			*name;	u16			protocol;	u16			num_states;	int			dont_defrag;

Lines 1–500 of 1886.