kernel/bpf/tcx.c

Source file repositories/reference/linux-study-clean/kernel/bpf/tcx.c

File Facts

System
Linux kernel
Corpus path
kernel/bpf/tcx.c
Extension
.c
Size
8050 bytes
Lines
347
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (IS_ERR(replace_prog)) {
			ret = PTR_ERR(replace_prog);
			replace_prog = NULL;
			goto out;
		}
	}
	entry = tcx_entry_fetch_or_create(dev, ingress, &created);
	if (!entry) {
		ret = -ENOMEM;
		goto out;
	}
	ret = bpf_mprog_attach(entry, &entry_new, prog, NULL, replace_prog,
			       attr->attach_flags, attr->relative_fd,
			       attr->expected_revision);
	if (!ret) {
		if (entry != entry_new) {
			tcx_entry_update(dev, entry_new, ingress);
			tcx_entry_sync();
			tcx_skeys_inc(ingress);
		}
		bpf_mprog_commit(entry);
	} else if (created) {
		tcx_entry_free(entry);
	}
out:
	if (replace_prog)
		bpf_prog_put(replace_prog);
	rtnl_unlock();
	return ret;
}

int tcx_prog_detach(const union bpf_attr *attr, struct bpf_prog *prog)
{
	bool ingress = attr->attach_type == BPF_TCX_INGRESS;
	struct net *net = current->nsproxy->net_ns;
	struct bpf_mprog_entry *entry, *entry_new;
	struct net_device *dev;
	int ret;

	rtnl_lock();
	dev = __dev_get_by_index(net, attr->target_ifindex);
	if (!dev) {
		ret = -ENODEV;
		goto out;
	}
	entry = tcx_entry_fetch(dev, ingress);
	if (!entry) {
		ret = -ENOENT;
		goto out;
	}
	ret = bpf_mprog_detach(entry, &entry_new, prog, NULL, attr->attach_flags,
			       attr->relative_fd, attr->expected_revision);
	if (!ret) {
		if (!tcx_entry_is_active(entry_new))
			entry_new = NULL;
		tcx_entry_update(dev, entry_new, ingress);
		tcx_entry_sync();
		tcx_skeys_dec(ingress);
		bpf_mprog_commit(entry);
		if (!entry_new)
			tcx_entry_free(entry);
	}
out:
	rtnl_unlock();
	return ret;
}

void tcx_uninstall(struct net_device *dev, bool ingress)
{
	struct bpf_mprog_entry *entry, *entry_new = NULL;
	struct bpf_tuple tuple = {};
	struct bpf_mprog_fp *fp;
	struct bpf_mprog_cp *cp;
	bool active;

	entry = tcx_entry_fetch(dev, ingress);
	if (!entry)
		return;
	active = tcx_entry(entry)->miniq_active;
	if (active)
		bpf_mprog_clear_all(entry, &entry_new);
	tcx_entry_update(dev, entry_new, ingress);
	tcx_entry_sync();
	bpf_mprog_foreach_tuple(entry, fp, cp, tuple) {
		if (tuple.link)
			tcx_link(tuple.link)->dev = NULL;
		else
			bpf_prog_put(tuple.prog);
		tcx_skeys_dec(ingress);
	}

Annotation

Implementation Notes