diff options
Diffstat (limited to 'drivers/net/netdevsim/bpf.c')
| -rw-r--r-- | drivers/net/netdevsim/bpf.c | 91 | 
1 files changed, 50 insertions, 41 deletions
| diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c index 75c25306d234..81444208b216 100644 --- a/drivers/net/netdevsim/bpf.c +++ b/drivers/net/netdevsim/bpf.c @@ -92,7 +92,7 @@ static const struct bpf_prog_offload_ops nsim_bpf_analyzer_ops = {  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 +195,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 +219,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 +238,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 +250,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 +279,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 +294,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 +497,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 +552,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 +582,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 +611,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 +629,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); +	}  } |