@@ -19,6 +19,8 @@ static struct {
1919	int  ringbuf_sz ; /* per-ringbuf, in bytes */ 
2020	bool  ringbuf_use_output ; /* use slower output API */ 
2121	int  perfbuf_sz ; /* per-CPU size, in pages */ 
22+ 	bool  overwrite ;
23+ 	bool  bench_producer ;
2224} args  =  {
2325	.back2back  =  false,
2426	.batch_cnt  =  500 ,
@@ -27,6 +29,8 @@ static struct {
2729	.ringbuf_sz  =  512  *  1024 ,
2830	.ringbuf_use_output  =  false,
2931	.perfbuf_sz  =  128 ,
32+ 	.overwrite  =  false,
33+ 	.bench_producer  =  false,
3034};
3135
3236enum  {
3539	ARG_RB_BATCH_CNT  =  2002 ,
3640	ARG_RB_SAMPLED  =  2003 ,
3741	ARG_RB_SAMPLE_RATE  =  2004 ,
42+ 	ARG_RB_OVERWRITE  =  2005 ,
43+ 	ARG_RB_BENCH_PRODUCER  =  2006 ,
3844};
3945
4046static  const  struct  argp_option  opts [] =  {
@@ -43,6 +49,8 @@ static const struct argp_option opts[] = {
4349	{ "rb-batch-cnt" , ARG_RB_BATCH_CNT , "CNT" , 0 , "Set BPF-side record batch count" },
4450	{ "rb-sampled" , ARG_RB_SAMPLED , NULL , 0 , "Notification sampling" },
4551	{ "rb-sample-rate" , ARG_RB_SAMPLE_RATE , "RATE" , 0 , "Notification sample rate" },
52+ 	{ "rb-overwrite" , ARG_RB_OVERWRITE , NULL , 0 , "Overwrite mode" },
53+ 	{ "rb-bench-producer" , ARG_RB_BENCH_PRODUCER , NULL , 0 , "Benchmark producer" },
4654	{},
4755};
4856
@@ -72,6 +80,12 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
7280			argp_usage (state );
7381		}
7482		break ;
83+ 	case  ARG_RB_OVERWRITE :
84+ 		args .overwrite  =  true;
85+ 		break ;
86+ 	case  ARG_RB_BENCH_PRODUCER :
87+ 		args .bench_producer  =  true;
88+ 		break ;
7589	default :
7690		return  ARGP_ERR_UNKNOWN ;
7791	}
@@ -95,8 +109,33 @@ static inline void bufs_trigger_batch(void)
95109
96110static  void  bufs_validate (void )
97111{
98- 	if  (env .consumer_cnt  !=  1 ) {
99- 		fprintf (stderr , "rb-libbpf benchmark needs one consumer!\n" );
112+ 	if  (args .bench_producer  &&  strcmp (env .bench_name , "rb-libbpf" )) {
113+ 		fprintf (stderr , "--rb-bench-producer only works with rb-libbpf!\n" );
114+ 		exit (1 );
115+ 	}
116+ 
117+ 	if  (args .overwrite  &&  !args .bench_producer ) {
118+ 		fprintf (stderr , "overwrite mode only works with --rb-bench-producer for now!\n" );
119+ 		exit (1 );
120+ 	}
121+ 
122+ 	if  (args .bench_producer  &&  env .consumer_cnt  !=  0 ) {
123+ 		fprintf (stderr , "no consumer is needed for --rb-bench-producer!\n" );
124+ 		exit (1 );
125+ 	}
126+ 
127+ 	if  (args .bench_producer  &&  args .back2back ) {
128+ 		fprintf (stderr , "back-to-back mode makes no sense for --rb-bench-producer!\n" );
129+ 		exit (1 );
130+ 	}
131+ 
132+ 	if  (args .bench_producer  &&  args .sampled ) {
133+ 		fprintf (stderr , "sampling mode makes no sense for --rb-bench-producer!\n" );
134+ 		exit (1 );
135+ 	}
136+ 
137+ 	if  (!args .bench_producer  &&  env .consumer_cnt  !=  1 ) {
138+ 		fprintf (stderr , "benchmarks without --rb-bench-producer require exactly one consumer!\n" );
100139		exit (1 );
101140	}
102141
@@ -128,12 +167,17 @@ static void ringbuf_libbpf_measure(struct bench_res *res)
128167{
129168	struct  ringbuf_libbpf_ctx  * ctx  =  & ringbuf_libbpf_ctx ;
130169
131- 	res -> hits  =  atomic_swap (& buf_hits .value , 0 );
170+ 	if  (args .bench_producer )
171+ 		res -> hits  =  atomic_swap (& ctx -> skel -> bss -> hits , 0 );
172+ 	else 
173+ 		res -> hits  =  atomic_swap (& buf_hits .value , 0 );
132174	res -> drops  =  atomic_swap (& ctx -> skel -> bss -> dropped , 0 );
133175}
134176
135177static  struct  ringbuf_bench  * ringbuf_setup_skeleton (void )
136178{
179+ 	__u32  flags ;
180+ 	struct  bpf_map  * ringbuf ;
137181	struct  ringbuf_bench  * skel ;
138182
139183	setup_libbpf ();
@@ -146,12 +190,19 @@ static struct ringbuf_bench *ringbuf_setup_skeleton(void)
146190
147191	skel -> rodata -> batch_cnt  =  args .batch_cnt ;
148192	skel -> rodata -> use_output  =  args .ringbuf_use_output  ? 1  : 0 ;
193+ 	skel -> rodata -> bench_producer  =  args .bench_producer ;
149194
150195	if  (args .sampled )
151196		/* record data + header take 16 bytes */ 
152197		skel -> rodata -> wakeup_data_size  =  args .sample_rate  *  16 ;
153198
154- 	bpf_map__set_max_entries (skel -> maps .ringbuf , args .ringbuf_sz );
199+ 	ringbuf  =  skel -> maps .ringbuf ;
200+ 	if  (args .overwrite ) {
201+ 		flags  =  bpf_map__map_flags (ringbuf ) | BPF_F_RB_OVERWRITE ;
202+ 		bpf_map__set_map_flags (ringbuf , flags );
203+ 	}
204+ 
205+ 	bpf_map__set_max_entries (ringbuf , args .ringbuf_sz );
155206
156207	if  (ringbuf_bench__load (skel )) {
157208		fprintf (stderr , "failed to load skeleton\n" );
@@ -171,10 +222,12 @@ static void ringbuf_libbpf_setup(void)
171222{
172223	struct  ringbuf_libbpf_ctx  * ctx  =  & ringbuf_libbpf_ctx ;
173224	struct  bpf_link  * link ;
225+ 	int  map_fd ;
174226
175227	ctx -> skel  =  ringbuf_setup_skeleton ();
176- 	ctx -> ringbuf  =  ring_buffer__new (bpf_map__fd (ctx -> skel -> maps .ringbuf ),
177- 					buf_process_sample , NULL , NULL );
228+ 
229+ 	map_fd  =  bpf_map__fd (ctx -> skel -> maps .ringbuf );
230+ 	ctx -> ringbuf  =  ring_buffer__new (map_fd , buf_process_sample , NULL , NULL );
178231	if  (!ctx -> ringbuf ) {
179232		fprintf (stderr , "failed to create ringbuf\n" );
180233		exit (1 );
0 commit comments