diff options
Diffstat (limited to 'drivers/net/netdevsim/bpf.c')
| -rw-r--r-- | drivers/net/netdevsim/bpf.c | 99 | 
1 files changed, 57 insertions, 42 deletions
diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c index 75c25306d234..cb3518474f0e 100644 --- a/drivers/net/netdevsim/bpf.c +++ b/drivers/net/netdevsim/bpf.c @@ -86,13 +86,19 @@ nsim_bpf_verify_insn(struct bpf_verifier_env *env, int insn_idx, int prev_insn)  	return 0;  } +static int nsim_bpf_finalize(struct bpf_verifier_env *env) +{ +	return 0; +} +  static const struct bpf_prog_offload_ops nsim_bpf_analyzer_ops = { -	.insn_hook = nsim_bpf_verify_insn, +	.insn_hook	= nsim_bpf_verify_insn, +	.finalize	= nsim_bpf_finalize,  };  static bool nsim_xdp_offload_active(struct netdevsim *ns)  { -	return ns->xdp_prog_mode == XDP_ATTACHED_HW; +	return ns->xdp_hw.prog;  }  static void nsim_prog_set_loaded(struct bpf_prog *prog, bool loaded) @@ -195,14 +201,14 @@ static int nsim_xdp_offload_prog(struct netdevsim *ns, struct netdev_bpf *bpf)  	return nsim_bpf_offload(ns, bpf->prog, nsim_xdp_offload_active(ns));  } -static int nsim_xdp_set_prog(struct netdevsim *ns, struct netdev_bpf *bpf) +static int +nsim_xdp_set_prog(struct netdevsim *ns, struct netdev_bpf *bpf, +		  struct xdp_attachment_info *xdp)  {  	int err; -	if (ns->xdp_prog && (bpf->flags ^ ns->xdp_flags) & XDP_FLAGS_MODES) { -		NSIM_EA(bpf->extack, "program loaded with different flags"); +	if (!xdp_attachment_flags_ok(xdp, bpf))  		return -EBUSY; -	}  	if (bpf->command == XDP_SETUP_PROG && !ns->bpf_xdpdrv_accept) {  		NSIM_EA(bpf->extack, "driver XDP disabled in DebugFS"); @@ -219,18 +225,7 @@ static int nsim_xdp_set_prog(struct netdevsim *ns, struct netdev_bpf *bpf)  			return err;  	} -	if (ns->xdp_prog) -		bpf_prog_put(ns->xdp_prog); - -	ns->xdp_prog = bpf->prog; -	ns->xdp_flags = bpf->flags; - -	if (!bpf->prog) -		ns->xdp_prog_mode = XDP_ATTACHED_NONE; -	else if (bpf->command == XDP_SETUP_PROG) -		ns->xdp_prog_mode = XDP_ATTACHED_DRV; -	else -		ns->xdp_prog_mode = XDP_ATTACHED_HW; +	xdp_attachment_setup(xdp, bpf);  	return 0;  } @@ -249,8 +244,8 @@ static int nsim_bpf_create_prog(struct netdevsim *ns, struct bpf_prog *prog)  	state->state = "verify";  	/* Program id is not populated yet when we create the state. */ -	sprintf(name, "%u", ns->prog_id_gen++); -	state->ddir = debugfs_create_dir(name, ns->ddir_bpf_bound_progs); +	sprintf(name, "%u", ns->sdev->prog_id_gen++); +	state->ddir = debugfs_create_dir(name, ns->sdev->ddir_bpf_bound_progs);  	if (IS_ERR_OR_NULL(state->ddir)) {  		kfree(state);  		return -ENOMEM; @@ -261,7 +256,7 @@ static int nsim_bpf_create_prog(struct netdevsim *ns, struct bpf_prog *prog)  			    &state->state, &nsim_bpf_string_fops);  	debugfs_create_bool("loaded", 0400, state->ddir, &state->is_loaded); -	list_add_tail(&state->l, &ns->bpf_bound_progs); +	list_add_tail(&state->l, &ns->sdev->bpf_bound_progs);  	prog->aux->offload->dev_priv = state; @@ -290,10 +285,6 @@ static int nsim_setup_prog_checks(struct netdevsim *ns, struct netdev_bpf *bpf)  		NSIM_EA(bpf->extack, "MTU too large w/ XDP enabled");  		return -EINVAL;  	} -	if (nsim_xdp_offload_active(ns)) { -		NSIM_EA(bpf->extack, "xdp offload active, can't load drv prog"); -		return -EBUSY; -	}  	return 0;  } @@ -309,7 +300,7 @@ nsim_setup_prog_hw_checks(struct netdevsim *ns, struct netdev_bpf *bpf)  		NSIM_EA(bpf->extack, "xdpoffload of non-bound program");  		return -EINVAL;  	} -	if (bpf->prog->aux->offload->netdev != ns->netdev) { +	if (!bpf_offload_dev_match(bpf->prog, ns->netdev)) {  		NSIM_EA(bpf->extack, "program bound to different dev");  		return -EINVAL;  	} @@ -512,7 +503,7 @@ nsim_bpf_map_alloc(struct netdevsim *ns, struct bpf_offloaded_map *offmap)  	}  	offmap->dev_ops = &nsim_bpf_map_ops; -	list_add_tail(&nmap->l, &ns->bpf_bound_maps); +	list_add_tail(&nmap->l, &ns->sdev->bpf_bound_maps);  	return 0; @@ -567,22 +558,21 @@ int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf)  		nsim_bpf_destroy_prog(bpf->offload.prog);  		return 0;  	case XDP_QUERY_PROG: -		bpf->prog_attached = ns->xdp_prog_mode; -		bpf->prog_id = ns->xdp_prog ? ns->xdp_prog->aux->id : 0; -		bpf->prog_flags = ns->xdp_prog ? ns->xdp_flags : 0; -		return 0; +		return xdp_attachment_query(&ns->xdp, bpf); +	case XDP_QUERY_PROG_HW: +		return xdp_attachment_query(&ns->xdp_hw, bpf);  	case XDP_SETUP_PROG:  		err = nsim_setup_prog_checks(ns, bpf);  		if (err)  			return err; -		return nsim_xdp_set_prog(ns, bpf); +		return nsim_xdp_set_prog(ns, bpf, &ns->xdp);  	case XDP_SETUP_PROG_HW:  		err = nsim_setup_prog_hw_checks(ns, bpf);  		if (err)  			return err; -		return nsim_xdp_set_prog(ns, bpf); +		return nsim_xdp_set_prog(ns, bpf, &ns->xdp_hw);  	case BPF_OFFLOAD_MAP_ALLOC:  		if (!ns->bpf_map_accept)  			return -EOPNOTSUPP; @@ -598,8 +588,26 @@ int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf)  int nsim_bpf_init(struct netdevsim *ns)  { -	INIT_LIST_HEAD(&ns->bpf_bound_progs); -	INIT_LIST_HEAD(&ns->bpf_bound_maps); +	int err; + +	if (ns->sdev->refcnt == 1) { +		INIT_LIST_HEAD(&ns->sdev->bpf_bound_progs); +		INIT_LIST_HEAD(&ns->sdev->bpf_bound_maps); + +		ns->sdev->ddir_bpf_bound_progs = +			debugfs_create_dir("bpf_bound_progs", ns->sdev->ddir); +		if (IS_ERR_OR_NULL(ns->sdev->ddir_bpf_bound_progs)) +			return -ENOMEM; + +		ns->sdev->bpf_dev = bpf_offload_dev_create(); +		err = PTR_ERR_OR_ZERO(ns->sdev->bpf_dev); +		if (err) +			return err; +	} + +	err = bpf_offload_dev_netdev_register(ns->sdev->bpf_dev, ns->netdev); +	if (err) +		goto err_destroy_bdev;  	debugfs_create_u32("bpf_offloaded_id", 0400, ns->ddir,  			   &ns->bpf_offloaded_id); @@ -609,10 +617,6 @@ int nsim_bpf_init(struct netdevsim *ns)  			    &ns->bpf_bind_accept);  	debugfs_create_u32("bpf_bind_verifier_delay", 0600, ns->ddir,  			   &ns->bpf_bind_verifier_delay); -	ns->ddir_bpf_bound_progs = -		debugfs_create_dir("bpf_bound_progs", ns->ddir); -	if (IS_ERR_OR_NULL(ns->ddir_bpf_bound_progs)) -		return -ENOMEM;  	ns->bpf_tc_accept = true;  	debugfs_create_bool("bpf_tc_accept", 0600, ns->ddir, @@ -631,12 +635,23 @@ int nsim_bpf_init(struct netdevsim *ns)  			    &ns->bpf_map_accept);  	return 0; + +err_destroy_bdev: +	if (ns->sdev->refcnt == 1) +		bpf_offload_dev_destroy(ns->sdev->bpf_dev); +	return err;  }  void nsim_bpf_uninit(struct netdevsim *ns)  { -	WARN_ON(!list_empty(&ns->bpf_bound_progs)); -	WARN_ON(!list_empty(&ns->bpf_bound_maps)); -	WARN_ON(ns->xdp_prog); +	WARN_ON(ns->xdp.prog); +	WARN_ON(ns->xdp_hw.prog);  	WARN_ON(ns->bpf_offloaded); +	bpf_offload_dev_netdev_unregister(ns->sdev->bpf_dev, ns->netdev); + +	if (ns->sdev->refcnt == 1) { +		WARN_ON(!list_empty(&ns->sdev->bpf_bound_progs)); +		WARN_ON(!list_empty(&ns->sdev->bpf_bound_maps)); +		bpf_offload_dev_destroy(ns->sdev->bpf_dev); +	}  }  |