include/net/ip_vs.h

Source file repositories/reference/linux-study-clean/include/net/ip_vs.h

File Facts

System
Linux kernel
Corpus path
include/net/ip_vs.h
Extension
.h
Size
66547 bytes
Lines
2224
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

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 int
ip_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 int
ip_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 int
ip_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);
}

Annotation

Implementation Notes