net/netfilter/ipvs/ip_vs_ctl.c

Source file repositories/reference/linux-study-clean/net/netfilter/ipvs/ip_vs_ctl.c

File Facts

System
Linux kernel
Corpus path
net/netfilter/ipvs/ip_vs_ctl.c
Extension
.c
Size
137701 bytes
Lines
5324
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

struct ip_vs_iter {
	struct seq_net_private p;  /* Do not move this, netns depends upon it*/
	struct ip_vs_rht *t;
	u32 bucket;
};

/*
 *	Write the contents of the VS rule table to a PROCfs file.
 *	(It is kept just for backward compatibility)
 */
static inline const char *ip_vs_fwd_name(unsigned int flags)
{
	switch (flags & IP_VS_CONN_F_FWD_MASK) {
	case IP_VS_CONN_F_LOCALNODE:
		return "Local";
	case IP_VS_CONN_F_TUNNEL:
		return "Tunnel";
	case IP_VS_CONN_F_DROUTE:
		return "Route";
	default:
		return "Masq";
	}
}

/* Do not expect consistent view during add, del and move(table resize).
 * We may miss entries and even show duplicates.
 */
static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos)
{
	struct ip_vs_iter *iter = seq->private;
	struct ip_vs_rht *t = iter->t;
	struct ip_vs_service *svc;
	struct hlist_bl_node *e;
	int idx;

	if (!t)
		return NULL;
	for (idx = 0; idx < t->size; idx++) {
		hlist_bl_for_each_entry_rcu(svc, e, &t->buckets[idx], s_list) {
			if (!ip_vs_rht_same_table(t, READ_ONCE(svc->hash_key)))
				break;
			if (pos-- == 0) {
				iter->bucket = idx;
				return svc;
			}
		}
	}
	return NULL;
}

static void *ip_vs_info_seq_start(struct seq_file *seq, loff_t *pos)
	__acquires(RCU)
{
	struct ip_vs_iter *iter = seq->private;
	struct net *net = seq_file_net(seq);
	struct netns_ipvs *ipvs = net_ipvs(net);

	rcu_read_lock();
	iter->t = rcu_dereference(ipvs->svc_table);
	return *pos ? ip_vs_info_array(seq, *pos - 1) : SEQ_START_TOKEN;
}


static void *ip_vs_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	struct ip_vs_service *svc;
	struct ip_vs_iter *iter;
	struct hlist_bl_node *e;
	struct ip_vs_rht *t;

	++*pos;
	if (v == SEQ_START_TOKEN)
		return ip_vs_info_array(seq,0);

	svc = v;
	iter = seq->private;
	t = iter->t;
	if (!t)
		return NULL;

	hlist_bl_for_each_entry_continue_rcu(svc, e, s_list) {
		/* Our cursor was moved to new table ? */
		if (!ip_vs_rht_same_table(t, READ_ONCE(svc->hash_key)))
			break;
		return svc;
	}

	while (++iter->bucket < t->size) {
		hlist_bl_for_each_entry_rcu(svc, e, &t->buckets[iter->bucket],
					    s_list) {

Annotation

Implementation Notes