Add XDP_REDIRECT support for eBPF programs attached to cpumap entries Signed-off-by: Lorenzo Bianconi <lorenzo@xxxxxxxxxx> --- include/trace/events/xdp.h | 12 ++++++++---- kernel/bpf/cpumap.c | 21 +++++++++++++++++---- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/include/trace/events/xdp.h b/include/trace/events/xdp.h index 06ec557c6bf5..162ce06c6da0 100644 --- a/include/trace/events/xdp.h +++ b/include/trace/events/xdp.h @@ -177,9 +177,11 @@ DEFINE_EVENT(xdp_redirect_template, xdp_redirect_map_err, TRACE_EVENT(xdp_cpumap_kthread, TP_PROTO(int map_id, unsigned int processed, unsigned int drops, - int sched, unsigned int xdp_pass, unsigned int xdp_drop), + int sched, unsigned int xdp_pass, unsigned int xdp_drop, + unsigned int xdp_redirect), - TP_ARGS(map_id, processed, drops, sched, xdp_pass, xdp_drop), + TP_ARGS(map_id, processed, drops, sched, xdp_pass, xdp_drop, + xdp_redirect), TP_STRUCT__entry( __field(int, map_id) @@ -190,6 +192,7 @@ TRACE_EVENT(xdp_cpumap_kthread, __field(int, sched) __field(unsigned int, xdp_pass) __field(unsigned int, xdp_drop) + __field(unsigned int, xdp_redirect) ), TP_fast_assign( @@ -201,18 +204,19 @@ TRACE_EVENT(xdp_cpumap_kthread, __entry->sched = sched; __entry->xdp_pass = xdp_pass; __entry->xdp_drop = xdp_drop; + __entry->xdp_redirect = xdp_redirect; ), TP_printk("kthread" " cpu=%d map_id=%d action=%s" " processed=%u drops=%u" " sched=%d" - " xdp_pass=%u xdp_drop=%u", + " xdp_pass=%u xdp_drop=%u xdp_redirect=%u", __entry->cpu, __entry->map_id, __print_symbolic(__entry->act, __XDP_ACT_SYM_TAB), __entry->processed, __entry->drops, __entry->sched, - __entry->xdp_pass, __entry->xdp_drop) + __entry->xdp_pass, __entry->xdp_drop, __entry->xdp_redirect) ); TRACE_EVENT(xdp_cpumap_enqueue, diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c index 24ab0a6b9772..a45157627fbc 100644 --- a/kernel/bpf/cpumap.c +++ b/kernel/bpf/cpumap.c @@ -248,7 +248,7 @@ static int cpu_map_kthread_run(void *data) * kthread_stop signal until queue is empty. */ while (!kthread_should_stop() || !__ptr_ring_empty(rcpu->queue)) { - unsigned int xdp_pass = 0, xdp_drop = 0; + unsigned int xdp_pass = 0, xdp_drop = 0, xdp_redirect = 0; gfp_t gfp = __GFP_ZERO | GFP_ATOMIC; unsigned int drops = 0, sched = 0; void *xdp_frames[CPUMAP_BATCH]; @@ -279,7 +279,7 @@ static int cpu_map_kthread_run(void *data) n = ptr_ring_consume_batched(rcpu->queue, xdp_frames, CPUMAP_BATCH); - rcu_read_lock(); + rcu_read_lock_bh(); prog = READ_ONCE(rcpu->prog); for (i = 0; i < n; i++) { @@ -315,6 +315,16 @@ static int cpu_map_kthread_run(void *data) xdp_pass++; } break; + case XDP_REDIRECT: + err = xdp_do_redirect(xdpf->dev_rx, &xdp, + prog); + if (unlikely(err)) { + xdp_return_frame(xdpf); + drops++; + } else { + xdp_redirect++; + } + break; default: bpf_warn_invalid_xdp_action(act); /* fallthrough */ @@ -325,7 +335,10 @@ static int cpu_map_kthread_run(void *data) } } - rcu_read_unlock(); + if (xdp_redirect) + xdp_do_flush_map(); + + rcu_read_unlock_bh(); m = kmem_cache_alloc_bulk(skbuff_head_cache, gfp, nframes, skbs); @@ -354,7 +367,7 @@ static int cpu_map_kthread_run(void *data) } /* Feedback loop via tracepoint */ trace_xdp_cpumap_kthread(rcpu->map_id, n, drops, sched, - xdp_pass, xdp_drop); + xdp_pass, xdp_drop, xdp_redirect); local_bh_enable(); /* resched point, may call do_softirq() */ } -- 2.26.2