net/sctp/input.c

Source file repositories/reference/linux-study-clean/net/sctp/input.c

File Facts

System
Linux kernel
Corpus path
net/sctp/input.c
Extension
.c
Size
37514 bytes
Lines
1371
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 sctp_hash_cmp_arg {
	const union sctp_addr	*paddr;
	const struct net	*net;
	__be16			lport;
};

static inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg,
				const void *ptr)
{
	struct sctp_transport *t = (struct sctp_transport *)ptr;
	const struct sctp_hash_cmp_arg *x = arg->key;
	int err = 1;

	if (!sctp_cmp_addr_exact(&t->ipaddr, x->paddr))
		return err;
	if (!sctp_transport_hold(t))
		return err;

	if (!net_eq(t->asoc->base.net, x->net))
		goto out;
	if (x->lport != htons(t->asoc->base.bind_addr.port))
		goto out;

	err = 0;
out:
	sctp_transport_put(t);
	return err;
}

static inline __u32 sctp_hash_obj(const void *data, u32 len, u32 seed)
{
	const struct sctp_transport *t = data;

	return sctp_hashfn(t->asoc->base.net,
			   htons(t->asoc->base.bind_addr.port),
			   &t->ipaddr, seed);
}

static inline __u32 sctp_hash_key(const void *data, u32 len, u32 seed)
{
	const struct sctp_hash_cmp_arg *x = data;

	return sctp_hashfn(x->net, x->lport, x->paddr, seed);
}

static const struct rhashtable_params sctp_hash_params = {
	.head_offset		= offsetof(struct sctp_transport, node),
	.hashfn			= sctp_hash_key,
	.obj_hashfn		= sctp_hash_obj,
	.obj_cmpfn		= sctp_hash_cmp,
	.automatic_shrinking	= true,
};

int sctp_transport_hashtable_init(void)
{
	return rhltable_init(&sctp_transport_hashtable, &sctp_hash_params);
}

void sctp_transport_hashtable_destroy(void)
{
	rhltable_destroy(&sctp_transport_hashtable);
}

int sctp_hash_transport(struct sctp_transport *t)
{
	struct sctp_transport *transport;
	struct rhlist_head *tmp, *list;
	struct sctp_hash_cmp_arg arg;
	int err;

	if (t->asoc->temp)
		return 0;

	arg.net   = t->asoc->base.net;
	arg.paddr = &t->ipaddr;
	arg.lport = htons(t->asoc->base.bind_addr.port);

	rcu_read_lock();
	list = rhltable_lookup(&sctp_transport_hashtable, &arg,
			       sctp_hash_params);

	rhl_for_each_entry_rcu(transport, tmp, list, node)
		if (transport->asoc->ep == t->asoc->ep) {
			rcu_read_unlock();
			return -EEXIST;
		}
	rcu_read_unlock();

	err = rhltable_insert_key(&sctp_transport_hashtable, &arg,
				  &t->node, sctp_hash_params);

Annotation

Implementation Notes