cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bpf.c (15848B)


      1/*
      2 * Copyright (C) 2017 Netronome Systems, Inc.
      3 *
      4 * This software is licensed under the GNU General License Version 2,
      5 * June 1991 as shown in the file COPYING in the top-level directory of this
      6 * source tree.
      7 *
      8 * THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
      9 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
     10 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     11 * FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
     12 * OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
     13 * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
     14 */
     15
     16#include <linux/bpf.h>
     17#include <linux/bpf_verifier.h>
     18#include <linux/debugfs.h>
     19#include <linux/kernel.h>
     20#include <linux/mutex.h>
     21#include <linux/rtnetlink.h>
     22#include <net/pkt_cls.h>
     23
     24#include "netdevsim.h"
     25
     26#define pr_vlog(env, fmt, ...)	\
     27	bpf_verifier_log_write(env, "[netdevsim] " fmt, ##__VA_ARGS__)
     28
     29struct nsim_bpf_bound_prog {
     30	struct nsim_dev *nsim_dev;
     31	struct bpf_prog *prog;
     32	struct dentry *ddir;
     33	const char *state;
     34	bool is_loaded;
     35	struct list_head l;
     36};
     37
     38#define NSIM_BPF_MAX_KEYS		2
     39
     40struct nsim_bpf_bound_map {
     41	struct netdevsim *ns;
     42	struct bpf_offloaded_map *map;
     43	struct mutex mutex;
     44	struct nsim_map_entry {
     45		void *key;
     46		void *value;
     47	} entry[NSIM_BPF_MAX_KEYS];
     48	struct list_head l;
     49};
     50
     51static int nsim_bpf_string_show(struct seq_file *file, void *data)
     52{
     53	const char **str = file->private;
     54
     55	if (*str)
     56		seq_printf(file, "%s\n", *str);
     57
     58	return 0;
     59}
     60DEFINE_SHOW_ATTRIBUTE(nsim_bpf_string);
     61
     62static int
     63nsim_bpf_verify_insn(struct bpf_verifier_env *env, int insn_idx, int prev_insn)
     64{
     65	struct nsim_bpf_bound_prog *state;
     66	int ret = 0;
     67
     68	state = env->prog->aux->offload->dev_priv;
     69	if (state->nsim_dev->bpf_bind_verifier_delay && !insn_idx)
     70		msleep(state->nsim_dev->bpf_bind_verifier_delay);
     71
     72	if (insn_idx == env->prog->len - 1) {
     73		pr_vlog(env, "Hello from netdevsim!\n");
     74
     75		if (!state->nsim_dev->bpf_bind_verifier_accept)
     76			ret = -EOPNOTSUPP;
     77	}
     78
     79	return ret;
     80}
     81
     82static int nsim_bpf_finalize(struct bpf_verifier_env *env)
     83{
     84	return 0;
     85}
     86
     87static bool nsim_xdp_offload_active(struct netdevsim *ns)
     88{
     89	return ns->xdp_hw.prog;
     90}
     91
     92static void nsim_prog_set_loaded(struct bpf_prog *prog, bool loaded)
     93{
     94	struct nsim_bpf_bound_prog *state;
     95
     96	if (!prog || !prog->aux->offload)
     97		return;
     98
     99	state = prog->aux->offload->dev_priv;
    100	state->is_loaded = loaded;
    101}
    102
    103static int
    104nsim_bpf_offload(struct netdevsim *ns, struct bpf_prog *prog, bool oldprog)
    105{
    106	nsim_prog_set_loaded(ns->bpf_offloaded, false);
    107
    108	WARN(!!ns->bpf_offloaded != oldprog,
    109	     "bad offload state, expected offload %sto be active",
    110	     oldprog ? "" : "not ");
    111	ns->bpf_offloaded = prog;
    112	ns->bpf_offloaded_id = prog ? prog->aux->id : 0;
    113	nsim_prog_set_loaded(prog, true);
    114
    115	return 0;
    116}
    117
    118int nsim_bpf_setup_tc_block_cb(enum tc_setup_type type,
    119			       void *type_data, void *cb_priv)
    120{
    121	struct tc_cls_bpf_offload *cls_bpf = type_data;
    122	struct bpf_prog *prog = cls_bpf->prog;
    123	struct netdevsim *ns = cb_priv;
    124	struct bpf_prog *oldprog;
    125
    126	if (type != TC_SETUP_CLSBPF) {
    127		NSIM_EA(cls_bpf->common.extack,
    128			"only offload of BPF classifiers supported");
    129		return -EOPNOTSUPP;
    130	}
    131
    132	if (!tc_cls_can_offload_and_chain0(ns->netdev, &cls_bpf->common))
    133		return -EOPNOTSUPP;
    134
    135	if (cls_bpf->common.protocol != htons(ETH_P_ALL)) {
    136		NSIM_EA(cls_bpf->common.extack,
    137			"only ETH_P_ALL supported as filter protocol");
    138		return -EOPNOTSUPP;
    139	}
    140
    141	if (!ns->bpf_tc_accept) {
    142		NSIM_EA(cls_bpf->common.extack,
    143			"netdevsim configured to reject BPF TC offload");
    144		return -EOPNOTSUPP;
    145	}
    146	/* Note: progs without skip_sw will probably not be dev bound */
    147	if (prog && !prog->aux->offload && !ns->bpf_tc_non_bound_accept) {
    148		NSIM_EA(cls_bpf->common.extack,
    149			"netdevsim configured to reject unbound programs");
    150		return -EOPNOTSUPP;
    151	}
    152
    153	if (cls_bpf->command != TC_CLSBPF_OFFLOAD)
    154		return -EOPNOTSUPP;
    155
    156	oldprog = cls_bpf->oldprog;
    157
    158	/* Don't remove if oldprog doesn't match driver's state */
    159	if (ns->bpf_offloaded != oldprog) {
    160		oldprog = NULL;
    161		if (!cls_bpf->prog)
    162			return 0;
    163		if (ns->bpf_offloaded) {
    164			NSIM_EA(cls_bpf->common.extack,
    165				"driver and netdev offload states mismatch");
    166			return -EBUSY;
    167		}
    168	}
    169
    170	return nsim_bpf_offload(ns, cls_bpf->prog, oldprog);
    171}
    172
    173int nsim_bpf_disable_tc(struct netdevsim *ns)
    174{
    175	if (ns->bpf_offloaded && !nsim_xdp_offload_active(ns))
    176		return -EBUSY;
    177	return 0;
    178}
    179
    180static int nsim_xdp_offload_prog(struct netdevsim *ns, struct netdev_bpf *bpf)
    181{
    182	if (!nsim_xdp_offload_active(ns) && !bpf->prog)
    183		return 0;
    184	if (!nsim_xdp_offload_active(ns) && bpf->prog && ns->bpf_offloaded) {
    185		NSIM_EA(bpf->extack, "TC program is already loaded");
    186		return -EBUSY;
    187	}
    188
    189	return nsim_bpf_offload(ns, bpf->prog, nsim_xdp_offload_active(ns));
    190}
    191
    192static int
    193nsim_xdp_set_prog(struct netdevsim *ns, struct netdev_bpf *bpf,
    194		  struct xdp_attachment_info *xdp)
    195{
    196	int err;
    197
    198	if (bpf->command == XDP_SETUP_PROG && !ns->bpf_xdpdrv_accept) {
    199		NSIM_EA(bpf->extack, "driver XDP disabled in DebugFS");
    200		return -EOPNOTSUPP;
    201	}
    202	if (bpf->command == XDP_SETUP_PROG_HW && !ns->bpf_xdpoffload_accept) {
    203		NSIM_EA(bpf->extack, "XDP offload disabled in DebugFS");
    204		return -EOPNOTSUPP;
    205	}
    206
    207	if (bpf->command == XDP_SETUP_PROG_HW) {
    208		err = nsim_xdp_offload_prog(ns, bpf);
    209		if (err)
    210			return err;
    211	}
    212
    213	xdp_attachment_setup(xdp, bpf);
    214
    215	return 0;
    216}
    217
    218static int nsim_bpf_create_prog(struct nsim_dev *nsim_dev,
    219				struct bpf_prog *prog)
    220{
    221	struct nsim_bpf_bound_prog *state;
    222	char name[16];
    223	int ret;
    224
    225	state = kzalloc(sizeof(*state), GFP_KERNEL);
    226	if (!state)
    227		return -ENOMEM;
    228
    229	state->nsim_dev = nsim_dev;
    230	state->prog = prog;
    231	state->state = "verify";
    232
    233	/* Program id is not populated yet when we create the state. */
    234	sprintf(name, "%u", nsim_dev->prog_id_gen++);
    235	state->ddir = debugfs_create_dir(name, nsim_dev->ddir_bpf_bound_progs);
    236	if (IS_ERR(state->ddir)) {
    237		ret = PTR_ERR(state->ddir);
    238		kfree(state);
    239		return ret;
    240	}
    241
    242	debugfs_create_u32("id", 0400, state->ddir, &prog->aux->id);
    243	debugfs_create_file("state", 0400, state->ddir,
    244			    &state->state, &nsim_bpf_string_fops);
    245	debugfs_create_bool("loaded", 0400, state->ddir, &state->is_loaded);
    246
    247	list_add_tail(&state->l, &nsim_dev->bpf_bound_progs);
    248
    249	prog->aux->offload->dev_priv = state;
    250
    251	return 0;
    252}
    253
    254static int nsim_bpf_verifier_prep(struct bpf_prog *prog)
    255{
    256	struct nsim_dev *nsim_dev =
    257			bpf_offload_dev_priv(prog->aux->offload->offdev);
    258
    259	if (!nsim_dev->bpf_bind_accept)
    260		return -EOPNOTSUPP;
    261
    262	return nsim_bpf_create_prog(nsim_dev, prog);
    263}
    264
    265static int nsim_bpf_translate(struct bpf_prog *prog)
    266{
    267	struct nsim_bpf_bound_prog *state = prog->aux->offload->dev_priv;
    268
    269	state->state = "xlated";
    270	return 0;
    271}
    272
    273static void nsim_bpf_destroy_prog(struct bpf_prog *prog)
    274{
    275	struct nsim_bpf_bound_prog *state;
    276
    277	state = prog->aux->offload->dev_priv;
    278	WARN(state->is_loaded,
    279	     "offload state destroyed while program still bound");
    280	debugfs_remove_recursive(state->ddir);
    281	list_del(&state->l);
    282	kfree(state);
    283}
    284
    285static const struct bpf_prog_offload_ops nsim_bpf_dev_ops = {
    286	.insn_hook	= nsim_bpf_verify_insn,
    287	.finalize	= nsim_bpf_finalize,
    288	.prepare	= nsim_bpf_verifier_prep,
    289	.translate	= nsim_bpf_translate,
    290	.destroy	= nsim_bpf_destroy_prog,
    291};
    292
    293static int nsim_setup_prog_checks(struct netdevsim *ns, struct netdev_bpf *bpf)
    294{
    295	if (bpf->prog && bpf->prog->aux->offload) {
    296		NSIM_EA(bpf->extack, "attempt to load offloaded prog to drv");
    297		return -EINVAL;
    298	}
    299	if (ns->netdev->mtu > NSIM_XDP_MAX_MTU) {
    300		NSIM_EA(bpf->extack, "MTU too large w/ XDP enabled");
    301		return -EINVAL;
    302	}
    303	return 0;
    304}
    305
    306static int
    307nsim_setup_prog_hw_checks(struct netdevsim *ns, struct netdev_bpf *bpf)
    308{
    309	struct nsim_bpf_bound_prog *state;
    310
    311	if (!bpf->prog)
    312		return 0;
    313
    314	if (!bpf->prog->aux->offload) {
    315		NSIM_EA(bpf->extack, "xdpoffload of non-bound program");
    316		return -EINVAL;
    317	}
    318	if (!bpf_offload_dev_match(bpf->prog, ns->netdev)) {
    319		NSIM_EA(bpf->extack, "program bound to different dev");
    320		return -EINVAL;
    321	}
    322
    323	state = bpf->prog->aux->offload->dev_priv;
    324	if (WARN_ON(strcmp(state->state, "xlated"))) {
    325		NSIM_EA(bpf->extack, "offloading program in bad state");
    326		return -EINVAL;
    327	}
    328	return 0;
    329}
    330
    331static bool
    332nsim_map_key_match(struct bpf_map *map, struct nsim_map_entry *e, void *key)
    333{
    334	return e->key && !memcmp(key, e->key, map->key_size);
    335}
    336
    337static int nsim_map_key_find(struct bpf_offloaded_map *offmap, void *key)
    338{
    339	struct nsim_bpf_bound_map *nmap = offmap->dev_priv;
    340	unsigned int i;
    341
    342	for (i = 0; i < ARRAY_SIZE(nmap->entry); i++)
    343		if (nsim_map_key_match(&offmap->map, &nmap->entry[i], key))
    344			return i;
    345
    346	return -ENOENT;
    347}
    348
    349static int
    350nsim_map_alloc_elem(struct bpf_offloaded_map *offmap, unsigned int idx)
    351{
    352	struct nsim_bpf_bound_map *nmap = offmap->dev_priv;
    353
    354	nmap->entry[idx].key = kmalloc(offmap->map.key_size, GFP_USER);
    355	if (!nmap->entry[idx].key)
    356		return -ENOMEM;
    357	nmap->entry[idx].value = kmalloc(offmap->map.value_size, GFP_USER);
    358	if (!nmap->entry[idx].value) {
    359		kfree(nmap->entry[idx].key);
    360		nmap->entry[idx].key = NULL;
    361		return -ENOMEM;
    362	}
    363
    364	return 0;
    365}
    366
    367static int
    368nsim_map_get_next_key(struct bpf_offloaded_map *offmap,
    369		      void *key, void *next_key)
    370{
    371	struct nsim_bpf_bound_map *nmap = offmap->dev_priv;
    372	int idx = -ENOENT;
    373
    374	mutex_lock(&nmap->mutex);
    375
    376	if (key)
    377		idx = nsim_map_key_find(offmap, key);
    378	if (idx == -ENOENT)
    379		idx = 0;
    380	else
    381		idx++;
    382
    383	for (; idx < ARRAY_SIZE(nmap->entry); idx++) {
    384		if (nmap->entry[idx].key) {
    385			memcpy(next_key, nmap->entry[idx].key,
    386			       offmap->map.key_size);
    387			break;
    388		}
    389	}
    390
    391	mutex_unlock(&nmap->mutex);
    392
    393	if (idx == ARRAY_SIZE(nmap->entry))
    394		return -ENOENT;
    395	return 0;
    396}
    397
    398static int
    399nsim_map_lookup_elem(struct bpf_offloaded_map *offmap, void *key, void *value)
    400{
    401	struct nsim_bpf_bound_map *nmap = offmap->dev_priv;
    402	int idx;
    403
    404	mutex_lock(&nmap->mutex);
    405
    406	idx = nsim_map_key_find(offmap, key);
    407	if (idx >= 0)
    408		memcpy(value, nmap->entry[idx].value, offmap->map.value_size);
    409
    410	mutex_unlock(&nmap->mutex);
    411
    412	return idx < 0 ? idx : 0;
    413}
    414
    415static int
    416nsim_map_update_elem(struct bpf_offloaded_map *offmap,
    417		     void *key, void *value, u64 flags)
    418{
    419	struct nsim_bpf_bound_map *nmap = offmap->dev_priv;
    420	int idx, err = 0;
    421
    422	mutex_lock(&nmap->mutex);
    423
    424	idx = nsim_map_key_find(offmap, key);
    425	if (idx < 0 && flags == BPF_EXIST) {
    426		err = idx;
    427		goto exit_unlock;
    428	}
    429	if (idx >= 0 && flags == BPF_NOEXIST) {
    430		err = -EEXIST;
    431		goto exit_unlock;
    432	}
    433
    434	if (idx < 0) {
    435		for (idx = 0; idx < ARRAY_SIZE(nmap->entry); idx++)
    436			if (!nmap->entry[idx].key)
    437				break;
    438		if (idx == ARRAY_SIZE(nmap->entry)) {
    439			err = -E2BIG;
    440			goto exit_unlock;
    441		}
    442
    443		err = nsim_map_alloc_elem(offmap, idx);
    444		if (err)
    445			goto exit_unlock;
    446	}
    447
    448	memcpy(nmap->entry[idx].key, key, offmap->map.key_size);
    449	memcpy(nmap->entry[idx].value, value, offmap->map.value_size);
    450exit_unlock:
    451	mutex_unlock(&nmap->mutex);
    452
    453	return err;
    454}
    455
    456static int nsim_map_delete_elem(struct bpf_offloaded_map *offmap, void *key)
    457{
    458	struct nsim_bpf_bound_map *nmap = offmap->dev_priv;
    459	int idx;
    460
    461	if (offmap->map.map_type == BPF_MAP_TYPE_ARRAY)
    462		return -EINVAL;
    463
    464	mutex_lock(&nmap->mutex);
    465
    466	idx = nsim_map_key_find(offmap, key);
    467	if (idx >= 0) {
    468		kfree(nmap->entry[idx].key);
    469		kfree(nmap->entry[idx].value);
    470		memset(&nmap->entry[idx], 0, sizeof(nmap->entry[idx]));
    471	}
    472
    473	mutex_unlock(&nmap->mutex);
    474
    475	return idx < 0 ? idx : 0;
    476}
    477
    478static const struct bpf_map_dev_ops nsim_bpf_map_ops = {
    479	.map_get_next_key	= nsim_map_get_next_key,
    480	.map_lookup_elem	= nsim_map_lookup_elem,
    481	.map_update_elem	= nsim_map_update_elem,
    482	.map_delete_elem	= nsim_map_delete_elem,
    483};
    484
    485static int
    486nsim_bpf_map_alloc(struct netdevsim *ns, struct bpf_offloaded_map *offmap)
    487{
    488	struct nsim_bpf_bound_map *nmap;
    489	int i, err;
    490
    491	if (WARN_ON(offmap->map.map_type != BPF_MAP_TYPE_ARRAY &&
    492		    offmap->map.map_type != BPF_MAP_TYPE_HASH))
    493		return -EINVAL;
    494	if (offmap->map.max_entries > NSIM_BPF_MAX_KEYS)
    495		return -ENOMEM;
    496	if (offmap->map.map_flags)
    497		return -EINVAL;
    498
    499	nmap = kzalloc(sizeof(*nmap), GFP_USER);
    500	if (!nmap)
    501		return -ENOMEM;
    502
    503	offmap->dev_priv = nmap;
    504	nmap->ns = ns;
    505	nmap->map = offmap;
    506	mutex_init(&nmap->mutex);
    507
    508	if (offmap->map.map_type == BPF_MAP_TYPE_ARRAY) {
    509		for (i = 0; i < ARRAY_SIZE(nmap->entry); i++) {
    510			u32 *key;
    511
    512			err = nsim_map_alloc_elem(offmap, i);
    513			if (err)
    514				goto err_free;
    515			key = nmap->entry[i].key;
    516			*key = i;
    517			memset(nmap->entry[i].value, 0, offmap->map.value_size);
    518		}
    519	}
    520
    521	offmap->dev_ops = &nsim_bpf_map_ops;
    522	list_add_tail(&nmap->l, &ns->nsim_dev->bpf_bound_maps);
    523
    524	return 0;
    525
    526err_free:
    527	while (--i >= 0) {
    528		kfree(nmap->entry[i].key);
    529		kfree(nmap->entry[i].value);
    530	}
    531	kfree(nmap);
    532	return err;
    533}
    534
    535static void nsim_bpf_map_free(struct bpf_offloaded_map *offmap)
    536{
    537	struct nsim_bpf_bound_map *nmap = offmap->dev_priv;
    538	unsigned int i;
    539
    540	for (i = 0; i < ARRAY_SIZE(nmap->entry); i++) {
    541		kfree(nmap->entry[i].key);
    542		kfree(nmap->entry[i].value);
    543	}
    544	list_del_init(&nmap->l);
    545	mutex_destroy(&nmap->mutex);
    546	kfree(nmap);
    547}
    548
    549int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf)
    550{
    551	struct netdevsim *ns = netdev_priv(dev);
    552	int err;
    553
    554	ASSERT_RTNL();
    555
    556	switch (bpf->command) {
    557	case XDP_SETUP_PROG:
    558		err = nsim_setup_prog_checks(ns, bpf);
    559		if (err)
    560			return err;
    561
    562		return nsim_xdp_set_prog(ns, bpf, &ns->xdp);
    563	case XDP_SETUP_PROG_HW:
    564		err = nsim_setup_prog_hw_checks(ns, bpf);
    565		if (err)
    566			return err;
    567
    568		return nsim_xdp_set_prog(ns, bpf, &ns->xdp_hw);
    569	case BPF_OFFLOAD_MAP_ALLOC:
    570		if (!ns->bpf_map_accept)
    571			return -EOPNOTSUPP;
    572
    573		return nsim_bpf_map_alloc(ns, bpf->offmap);
    574	case BPF_OFFLOAD_MAP_FREE:
    575		nsim_bpf_map_free(bpf->offmap);
    576		return 0;
    577	default:
    578		return -EINVAL;
    579	}
    580}
    581
    582int nsim_bpf_dev_init(struct nsim_dev *nsim_dev)
    583{
    584	int err;
    585
    586	INIT_LIST_HEAD(&nsim_dev->bpf_bound_progs);
    587	INIT_LIST_HEAD(&nsim_dev->bpf_bound_maps);
    588
    589	nsim_dev->ddir_bpf_bound_progs = debugfs_create_dir("bpf_bound_progs",
    590							    nsim_dev->ddir);
    591	if (IS_ERR(nsim_dev->ddir_bpf_bound_progs))
    592		return PTR_ERR(nsim_dev->ddir_bpf_bound_progs);
    593
    594	nsim_dev->bpf_dev = bpf_offload_dev_create(&nsim_bpf_dev_ops, nsim_dev);
    595	err = PTR_ERR_OR_ZERO(nsim_dev->bpf_dev);
    596	if (err)
    597		return err;
    598
    599	nsim_dev->bpf_bind_accept = true;
    600	debugfs_create_bool("bpf_bind_accept", 0600, nsim_dev->ddir,
    601			    &nsim_dev->bpf_bind_accept);
    602	debugfs_create_u32("bpf_bind_verifier_delay", 0600, nsim_dev->ddir,
    603			   &nsim_dev->bpf_bind_verifier_delay);
    604	nsim_dev->bpf_bind_verifier_accept = true;
    605	debugfs_create_bool("bpf_bind_verifier_accept", 0600, nsim_dev->ddir,
    606			    &nsim_dev->bpf_bind_verifier_accept);
    607	return 0;
    608}
    609
    610void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev)
    611{
    612	WARN_ON(!list_empty(&nsim_dev->bpf_bound_progs));
    613	WARN_ON(!list_empty(&nsim_dev->bpf_bound_maps));
    614	bpf_offload_dev_destroy(nsim_dev->bpf_dev);
    615}
    616
    617int nsim_bpf_init(struct netdevsim *ns)
    618{
    619	struct dentry *ddir = ns->nsim_dev_port->ddir;
    620	int err;
    621
    622	err = bpf_offload_dev_netdev_register(ns->nsim_dev->bpf_dev,
    623					      ns->netdev);
    624	if (err)
    625		return err;
    626
    627	debugfs_create_u32("bpf_offloaded_id", 0400, ddir,
    628			   &ns->bpf_offloaded_id);
    629
    630	ns->bpf_tc_accept = true;
    631	debugfs_create_bool("bpf_tc_accept", 0600, ddir,
    632			    &ns->bpf_tc_accept);
    633	debugfs_create_bool("bpf_tc_non_bound_accept", 0600, ddir,
    634			    &ns->bpf_tc_non_bound_accept);
    635	ns->bpf_xdpdrv_accept = true;
    636	debugfs_create_bool("bpf_xdpdrv_accept", 0600, ddir,
    637			    &ns->bpf_xdpdrv_accept);
    638	ns->bpf_xdpoffload_accept = true;
    639	debugfs_create_bool("bpf_xdpoffload_accept", 0600, ddir,
    640			    &ns->bpf_xdpoffload_accept);
    641
    642	ns->bpf_map_accept = true;
    643	debugfs_create_bool("bpf_map_accept", 0600, ddir,
    644			    &ns->bpf_map_accept);
    645
    646	return 0;
    647}
    648
    649void nsim_bpf_uninit(struct netdevsim *ns)
    650{
    651	WARN_ON(ns->xdp.prog);
    652	WARN_ON(ns->xdp_hw.prog);
    653	WARN_ON(ns->bpf_offloaded);
    654	bpf_offload_dev_netdev_unregister(ns->nsim_dev->bpf_dev, ns->netdev);
    655}