net/ipv4/ipmr_base.c

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

File Facts

System
Linux kernel
Corpus path
net/ipv4/ipmr_base.c
Extension
.c
Size
10692 bytes
Lines
451
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

if (vif_dev && c->mfc_un.res.ttls[ct] < 255) {

			nhp = nla_reserve_nohdr(skb, sizeof(*nhp));
			if (!nhp) {
				rcu_read_unlock();
				nla_nest_cancel(skb, mp_attr);
				return -EMSGSIZE;
			}

			nhp->rtnh_flags = 0;
			nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
			nhp->rtnh_ifindex = READ_ONCE(vif_dev->ifindex);
			nhp->rtnh_len = sizeof(*nhp);
		}
	}
	rcu_read_unlock();

	nla_nest_end(skb, mp_attr);

	lastuse = READ_ONCE(c->mfc_un.res.lastuse);
	lastuse = time_after_eq(jiffies, lastuse) ? jiffies - lastuse : 0;

	mfcs.mfcs_packets = atomic_long_read(&c->mfc_un.res.pkt);
	mfcs.mfcs_bytes = atomic_long_read(&c->mfc_un.res.bytes);
	mfcs.mfcs_wrong_if = atomic_long_read(&c->mfc_un.res.wrong_if);
	if (nla_put_64bit(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs, RTA_PAD) ||
	    nla_put_u64_64bit(skb, RTA_EXPIRES, jiffies_to_clock_t(lastuse),
			      RTA_PAD))
		return -EMSGSIZE;

	rtm->rtm_type = RTN_MULTICAST;
	return 1;
}

static bool mr_mfc_uses_dev(const struct mr_table *mrt,
			    const struct mr_mfc *c,
			    const struct net_device *dev)
{
	int ct;

	for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
		const struct net_device *vif_dev;
		const struct vif_device *vif;

		vif = &mrt->vif_table[ct];
		vif_dev = rcu_access_pointer(vif->dev);
		if (vif_dev && c->mfc_un.res.ttls[ct] < 255 &&
		    vif_dev == dev)
			return true;
	}
	return false;
}

int mr_table_dump(struct mr_table *mrt, struct sk_buff *skb,
		  struct netlink_callback *cb,
		  int (*fill)(struct mr_table *mrt, struct sk_buff *skb,
			      u32 portid, u32 seq, struct mr_mfc *c,
			      int cmd, int flags),
		  spinlock_t *lock, struct fib_dump_filter *filter)
{
	unsigned int e = 0, s_e = cb->args[1];
	unsigned int flags = NLM_F_MULTI;
	struct mr_mfc *mfc;
	int err;

	if (filter->filter_set)
		flags |= NLM_F_DUMP_FILTERED;

	list_for_each_entry_rcu(mfc, &mrt->mfc_cache_list, list,
				lockdep_rtnl_is_held()) {
		if (e < s_e)
			goto next_entry;
		if (filter->dev &&
		    !mr_mfc_uses_dev(mrt, mfc, filter->dev))
			goto next_entry;

		err = fill(mrt, skb, NETLINK_CB(cb->skb).portid,
			   cb->nlh->nlmsg_seq, mfc, RTM_NEWROUTE, flags);
		if (err < 0)
			goto out;
next_entry:
		e++;
	}

	spin_lock_bh(lock);
	list_for_each_entry(mfc, &mrt->mfc_unres_queue, list) {
		if (e < s_e)
			goto next_entry2;

		err = fill(mrt, skb, NETLINK_CB(cb->skb).portid,

Annotation

Implementation Notes