net/ipv4/ip_tunnel.c

Source file repositories/reference/linux-study-clean/net/ipv4/ip_tunnel.c

File Facts

System
Linux kernel
Corpus path
net/ipv4/ip_tunnel.c
Extension
.c
Size
32816 bytes
Lines
1343
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration 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

if (!IS_ERR(rt)) {
			tdev = rt->dst.dev;
			ip_rt_put(rt);
		}
		if (dev->type != ARPHRD_ETHER)
			dev->flags |= IFF_POINTOPOINT;

		dst_cache_reset(&tunnel->dst_cache);
	}

	if (!tdev && tunnel->parms.link)
		tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);

	if (tdev) {
		hlen = tdev->hard_header_len + tdev->needed_headroom;
		mtu = min(tdev->mtu, IP_MAX_MTU);
	}

	dev->needed_headroom = t_hlen + hlen;
	mtu -= t_hlen + (dev->type == ARPHRD_ETHER ? dev->hard_header_len : 0);

	if (mtu < IPV4_MIN_MTU)
		mtu = IPV4_MIN_MTU;

	return mtu;
}

static struct ip_tunnel *ip_tunnel_create(struct net *net,
					  struct ip_tunnel_net *itn,
					  struct ip_tunnel_parm_kern *parms)
{
	struct ip_tunnel *nt;
	struct net_device *dev;
	int t_hlen;
	int mtu;
	int err;

	dev = __ip_tunnel_create(net, itn->rtnl_link_ops, parms);
	if (IS_ERR(dev))
		return ERR_CAST(dev);

	mtu = ip_tunnel_bind_dev(dev);
	err = dev_set_mtu(dev, mtu);
	if (err)
		goto err_dev_set_mtu;

	nt = netdev_priv(dev);
	t_hlen = nt->hlen + sizeof(struct iphdr);
	dev->min_mtu = ETH_MIN_MTU;
	dev->max_mtu = IP_MAX_MTU - t_hlen;
	if (dev->type == ARPHRD_ETHER)
		dev->max_mtu -= dev->hard_header_len;

	ip_tunnel_add(itn, nt);
	return nt;

err_dev_set_mtu:
	unregister_netdevice(dev);
	return ERR_PTR(err);
}

void ip_tunnel_md_udp_encap(struct sk_buff *skb, struct ip_tunnel_info *info)
{
	const struct iphdr *iph = ip_hdr(skb);
	const struct udphdr *udph;

	if (iph->protocol != IPPROTO_UDP)
		return;

	udph = (struct udphdr *)((__u8 *)iph + (iph->ihl << 2));
	info->encap.sport = udph->source;
	info->encap.dport = udph->dest;
}
EXPORT_SYMBOL(ip_tunnel_md_udp_encap);

int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
		  const struct tnl_ptk_info *tpi, struct metadata_dst *tun_dst,
		  bool log_ecn_error)
{
	const struct iphdr *iph = ip_hdr(skb);
	int nh, err;

#ifdef CONFIG_NET_IPGRE_BROADCAST
	if (ipv4_is_multicast(iph->daddr)) {
		DEV_STATS_INC(tunnel->dev, multicast);
		skb->pkt_type = PACKET_BROADCAST;
	}
#endif

	if (test_bit(IP_TUNNEL_CSUM_BIT, tunnel->parms.i_flags) !=

Annotation

Implementation Notes