net/ipv4/igmp.c

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

File Facts

System
Linux kernel
Corpus path
net/ipv4/igmp.c
Extension
.c
Size
78243 bytes
Lines
3220
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 igmp_mc_iter_state {
	struct seq_net_private p;
	struct net_device *dev;
	struct in_device *in_dev;
};

#define	igmp_mc_seq_private(seq)	((struct igmp_mc_iter_state *)(seq)->private)

static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq)
{
	struct net *net = seq_file_net(seq);
	struct ip_mc_list *im = NULL;
	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);

	state->in_dev = NULL;
	for_each_netdev_rcu(net, state->dev) {
		struct in_device *in_dev;

		in_dev = __in_dev_get_rcu(state->dev);
		if (!in_dev)
			continue;
		im = rcu_dereference(in_dev->mc_list);
		if (im) {
			state->in_dev = in_dev;
			break;
		}
	}
	return im;
}

static struct ip_mc_list *igmp_mc_get_next(struct seq_file *seq, struct ip_mc_list *im)
{
	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);

	im = rcu_dereference(im->next_rcu);
	while (!im) {
		state->dev = next_net_device_rcu(state->dev);
		if (!state->dev) {
			state->in_dev = NULL;
			break;
		}
		state->in_dev = __in_dev_get_rcu(state->dev);
		if (!state->in_dev)
			continue;
		im = rcu_dereference(state->in_dev->mc_list);
	}
	return im;
}

static struct ip_mc_list *igmp_mc_get_idx(struct seq_file *seq, loff_t pos)
{
	struct ip_mc_list *im = igmp_mc_get_first(seq);
	if (im)
		while (pos && (im = igmp_mc_get_next(seq, im)) != NULL)
			--pos;
	return pos ? NULL : im;
}

static void *igmp_mc_seq_start(struct seq_file *seq, loff_t *pos)
	__acquires(rcu)
{
	rcu_read_lock();
	return *pos ? igmp_mc_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
}

static void *igmp_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	struct ip_mc_list *im;
	if (v == SEQ_START_TOKEN)
		im = igmp_mc_get_first(seq);
	else
		im = igmp_mc_get_next(seq, v);
	++*pos;
	return im;
}

static void igmp_mc_seq_stop(struct seq_file *seq, void *v)
	__releases(rcu)
{
	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);

	state->in_dev = NULL;
	state->dev = NULL;
	rcu_read_unlock();
}

static int igmp_mc_seq_show(struct seq_file *seq, void *v)
{
	if (v == SEQ_START_TOKEN)
		seq_puts(seq,

Annotation

Implementation Notes