net/ipv6/ip6_gre.c

Source file repositories/reference/linux-study-clean/net/ipv6/ip6_gre.c

File Facts

System
Linux kernel
Corpus path
net/ipv6/ip6_gre.c
Extension
.c
Size
60144 bytes
Lines
2390
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: operation-table or driver-model contract
Status
pattern 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

static const struct net_device_ops ip6gre_netdev_ops = {
	.ndo_init		= ip6gre_tunnel_init,
	.ndo_uninit		= ip6gre_tunnel_uninit,
	.ndo_start_xmit		= ip6gre_tunnel_xmit,
	.ndo_siocdevprivate	= ip6gre_tunnel_siocdevprivate,
	.ndo_change_mtu		= ip6_tnl_change_mtu,
	.ndo_get_iflink		= ip6_tnl_get_iflink,
};

static void ip6gre_dev_free(struct net_device *dev)
{
	struct ip6_tnl *t = netdev_priv(dev);

	gro_cells_destroy(&t->gro_cells);
	dst_cache_destroy(&t->dst_cache);
}

static void ip6gre_tunnel_setup(struct net_device *dev)
{
	dev->netdev_ops = &ip6gre_netdev_ops;
	dev->needs_free_netdev = true;
	dev->priv_destructor = ip6gre_dev_free;

	dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
	dev->type = ARPHRD_IP6GRE;

	dev->flags |= IFF_NOARP;
	dev->addr_len = sizeof(struct in6_addr);
	netif_keep_dst(dev);
	/* This perm addr will be used as interface identifier by IPv6 */
	dev->addr_assign_type = NET_ADDR_RANDOM;
	eth_random_addr(dev->perm_addr);
}

#define GRE6_FEATURES (NETIF_F_SG |		\
		       NETIF_F_FRAGLIST |	\
		       NETIF_F_HIGHDMA |	\
		       NETIF_F_HW_CSUM)

static void ip6gre_tnl_init_features(struct net_device *dev)
{
	struct ip6_tnl *nt = netdev_priv(dev);

	dev->features		|= GRE6_FEATURES;
	dev->hw_features	|= GRE6_FEATURES;

	/* TCP offload with GRE SEQ is not supported, nor can we support 2
	 * levels of outer headers requiring an update.
	 */
	if (test_bit(IP_TUNNEL_SEQ_BIT, nt->parms.o_flags))
		return;
	if (test_bit(IP_TUNNEL_CSUM_BIT, nt->parms.o_flags) &&
	    nt->encap.type != TUNNEL_ENCAP_NONE)
		return;

	dev->features |= NETIF_F_GSO_SOFTWARE;
	dev->hw_features |= NETIF_F_GSO_SOFTWARE;

	dev->lltx = true;
}

static int ip6gre_tunnel_init_common(struct net_device *dev)
{
	struct ip6_tnl *tunnel;
	int ret;
	int t_hlen;

	tunnel = netdev_priv(dev);

	tunnel->dev = dev;
	strscpy(tunnel->parms.name, dev->name);

	ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
	if (ret)
		return ret;

	ret = gro_cells_init(&tunnel->gro_cells, dev);
	if (ret)
		goto cleanup_dst_cache_init;

	t_hlen = ip6gre_calc_hlen(tunnel);
	dev->mtu = ETH_DATA_LEN - t_hlen;
	if (dev->type == ARPHRD_ETHER)
		dev->mtu -= ETH_HLEN;
	if (!(tunnel->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
		dev->mtu -= 8;

	if (tunnel->parms.collect_md) {
		netif_keep_dst(dev);
	}

Annotation

Implementation Notes