net/ipv4/route.c

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

File Facts

System
Linux kernel
Corpus path
net/ipv4/route.c
Extension
.c
Size
98008 bytes
Lines
3797
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

struct uncached_list {
	spinlock_t		lock;
	struct list_head	head;
};

static DEFINE_PER_CPU_ALIGNED(struct uncached_list, rt_uncached_list);

void rt_add_uncached_list(struct rtable *rt)
{
	struct uncached_list *ul = raw_cpu_ptr(&rt_uncached_list);

	rt->dst.rt_uncached_list = ul;

	spin_lock_bh(&ul->lock);
	list_add_tail(&rt->dst.rt_uncached, &ul->head);
	spin_unlock_bh(&ul->lock);
}

void rt_del_uncached_list(struct rtable *rt)
{
	struct uncached_list *ul = rt->dst.rt_uncached_list;

	if (ul) {
		spin_lock_bh(&ul->lock);
		list_del_init(&rt->dst.rt_uncached);
		spin_unlock_bh(&ul->lock);
	}
}

static void ipv4_dst_destroy(struct dst_entry *dst)
{
	ip_dst_metrics_put(dst);
	rt_del_uncached_list(dst_rtable(dst));
}

void rt_flush_dev(struct net_device *dev)
{
	struct rtable *rt, *safe;
	int cpu;

	for_each_possible_cpu(cpu) {
		struct uncached_list *ul = &per_cpu(rt_uncached_list, cpu);

		if (list_empty(&ul->head))
			continue;

		spin_lock_bh(&ul->lock);
		list_for_each_entry_safe(rt, safe, &ul->head, dst.rt_uncached) {
			if (rt->dst.dev != dev)
				continue;
			rt->dst.dev = blackhole_netdev;
			netdev_ref_replace(dev, blackhole_netdev,
					   &rt->dst.dev_tracker, GFP_ATOMIC);
			list_del_init(&rt->dst.rt_uncached);
		}
		spin_unlock_bh(&ul->lock);
	}
}

static bool rt_cache_valid(const struct rtable *rt)
{
	return	rt &&
		READ_ONCE(rt->dst.obsolete) == DST_OBSOLETE_FORCE_CHK &&
		!rt_is_expired(rt);
}

static void rt_set_nexthop(struct rtable *rt, __be32 daddr,
			   const struct fib_result *res,
			   struct fib_nh_exception *fnhe,
			   struct fib_info *fi, u16 type, u32 itag,
			   const bool do_cache)
{
	bool cached = false;

	if (fi) {
		struct fib_nh_common *nhc = FIB_RES_NHC(*res);

		if (nhc->nhc_gw_family && nhc->nhc_scope == RT_SCOPE_LINK) {
			rt->rt_uses_gateway = 1;
			rt->rt_gw_family = nhc->nhc_gw_family;
			/* only INET and INET6 are supported */
			if (likely(nhc->nhc_gw_family == AF_INET))
				rt->rt_gw4 = nhc->nhc_gw.ipv4;
			else
				rt->rt_gw6 = nhc->nhc_gw.ipv6;
		}

		ip_dst_init_metrics(&rt->dst, fi->fib_metrics);

#ifdef CONFIG_IP_ROUTE_CLASSID

Annotation

Implementation Notes