diff options
Diffstat (limited to 'net/bpf')
| -rw-r--r-- | net/bpf/test_run.c | 30 | 
1 files changed, 25 insertions, 5 deletions
| diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index 68c3578343b4..f4078830ea50 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -11,12 +11,14 @@  #include <linux/filter.h>  #include <linux/sched/signal.h> -static __always_inline u32 bpf_test_run_one(struct bpf_prog *prog, void *ctx) +static __always_inline u32 bpf_test_run_one(struct bpf_prog *prog, void *ctx, +					    struct bpf_cgroup_storage *storage)  {  	u32 ret;  	preempt_disable();  	rcu_read_lock(); +	bpf_cgroup_storage_set(storage);  	ret = BPF_PROG_RUN(prog, ctx);  	rcu_read_unlock();  	preempt_enable(); @@ -26,14 +28,19 @@ static __always_inline u32 bpf_test_run_one(struct bpf_prog *prog, void *ctx)  static u32 bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat, u32 *time)  { +	struct bpf_cgroup_storage *storage = NULL;  	u64 time_start, time_spent = 0;  	u32 ret = 0, i; +	storage = bpf_cgroup_storage_alloc(prog); +	if (IS_ERR(storage)) +		return PTR_ERR(storage); +  	if (!repeat)  		repeat = 1;  	time_start = ktime_get_ns();  	for (i = 0; i < repeat; i++) { -		ret = bpf_test_run_one(prog, ctx); +		ret = bpf_test_run_one(prog, ctx, storage);  		if (need_resched()) {  			if (signal_pending(current))  				break; @@ -46,6 +53,8 @@ static u32 bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat, u32 *time)  	do_div(time_spent, repeat);  	*time = time_spent > U32_MAX ? U32_MAX : (u32)time_spent; +	bpf_cgroup_storage_free(storage); +  	return ret;  } @@ -96,6 +105,7 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,  	u32 size = kattr->test.data_size_in;  	u32 repeat = kattr->test.repeat;  	u32 retval, duration; +	int hh_len = ETH_HLEN;  	struct sk_buff *skb;  	void *data;  	int ret; @@ -131,12 +141,22 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,  	skb_reset_network_header(skb);  	if (is_l2) -		__skb_push(skb, ETH_HLEN); +		__skb_push(skb, hh_len);  	if (is_direct_pkt_access)  		bpf_compute_data_pointers(skb);  	retval = bpf_test_run(prog, skb, repeat, &duration); -	if (!is_l2) -		__skb_push(skb, ETH_HLEN); +	if (!is_l2) { +		if (skb_headroom(skb) < hh_len) { +			int nhead = HH_DATA_ALIGN(hh_len - skb_headroom(skb)); + +			if (pskb_expand_head(skb, nhead, 0, GFP_USER)) { +				kfree_skb(skb); +				return -ENOMEM; +			} +		} +		memset(__skb_push(skb, hh_len), 0, hh_len); +	} +  	size = skb->len;  	/* bpf program can never convert linear skb to non-linear */  	if (WARN_ON_ONCE(skb_is_nonlinear(skb))) |