net/core/sock_map.c

Source file repositories/reference/linux-study-clean/net/core/sock_map.c

File Facts

System
Linux kernel
Corpus path
net/core/sock_map.c
Extension
.c
Size
48426 bytes
Lines
1971
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 bpf_stab {
	struct bpf_map map;
	struct sock **sks;
	struct sk_psock_progs progs;
	spinlock_t lock;
};

#define SOCK_CREATE_FLAG_MASK				\
	(BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY)

/* This mutex is used to
 *  - protect race between prog/link attach/detach and link prog update, and
 *  - protect race between releasing and accessing map in bpf_link.
 * A single global mutex lock is used since it is expected contention is low.
 */
static DEFINE_MUTEX(sockmap_mutex);

static int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
				struct bpf_prog *old, struct bpf_link *link,
				u32 which);
static struct sk_psock_progs *sock_map_progs(struct bpf_map *map);

static struct bpf_map *sock_map_alloc(union bpf_attr *attr)
{
	struct bpf_stab *stab;

	if (attr->max_entries == 0 ||
	    attr->key_size    != 4 ||
	    (attr->value_size != sizeof(u32) &&
	     attr->value_size != sizeof(u64)) ||
	    attr->map_flags & ~SOCK_CREATE_FLAG_MASK)
		return ERR_PTR(-EINVAL);

	stab = bpf_map_area_alloc(sizeof(*stab), NUMA_NO_NODE);
	if (!stab)
		return ERR_PTR(-ENOMEM);

	bpf_map_init_from_attr(&stab->map, attr);
	spin_lock_init(&stab->lock);

	stab->sks = bpf_map_area_alloc((u64) stab->map.max_entries *
				       sizeof(struct sock *),
				       stab->map.numa_node);
	if (!stab->sks) {
		bpf_map_area_free(stab);
		return ERR_PTR(-ENOMEM);
	}

	return &stab->map;
}

int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog)
{
	struct bpf_map *map;
	int ret;

	if (attr->attach_flags || attr->replace_bpf_fd)
		return -EINVAL;

	CLASS(fd, f)(attr->target_fd);
	map = __bpf_map_get(f);
	if (IS_ERR(map))
		return PTR_ERR(map);
	mutex_lock(&sockmap_mutex);
	ret = sock_map_prog_update(map, prog, NULL, NULL, attr->attach_type);
	mutex_unlock(&sockmap_mutex);
	return ret;
}

int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype)
{
	struct bpf_prog *prog;
	struct bpf_map *map;
	int ret;

	if (attr->attach_flags || attr->replace_bpf_fd)
		return -EINVAL;

	CLASS(fd, f)(attr->target_fd);
	map = __bpf_map_get(f);
	if (IS_ERR(map))
		return PTR_ERR(map);

	prog = bpf_prog_get(attr->attach_bpf_fd);
	if (IS_ERR(prog))
		return PTR_ERR(prog);

	if (prog->type != ptype) {
		ret = -EINVAL;
		goto put_prog;

Annotation

Implementation Notes