@@ -311,20 +311,33 @@ static inline void __v2_tx_user_ready(struct tpacket2_hdr *hdr)
311
311
__sync_synchronize ();
312
312
}
313
313
314
- static inline int __v1_v2_tx_kernel_ready (void * base , int version )
314
+ static inline int __v3_tx_kernel_ready (struct tpacket3_hdr * hdr )
315
+ {
316
+ return !(hdr -> tp_status & (TP_STATUS_SEND_REQUEST | TP_STATUS_SENDING ));
317
+ }
318
+
319
+ static inline void __v3_tx_user_ready (struct tpacket3_hdr * hdr )
320
+ {
321
+ hdr -> tp_status = TP_STATUS_SEND_REQUEST ;
322
+ __sync_synchronize ();
323
+ }
324
+
325
+ static inline int __tx_kernel_ready (void * base , int version )
315
326
{
316
327
switch (version ) {
317
328
case TPACKET_V1 :
318
329
return __v1_tx_kernel_ready (base );
319
330
case TPACKET_V2 :
320
331
return __v2_tx_kernel_ready (base );
332
+ case TPACKET_V3 :
333
+ return __v3_tx_kernel_ready (base );
321
334
default :
322
335
bug_on (1 );
323
336
return 0 ;
324
337
}
325
338
}
326
339
327
- static inline void __v1_v2_tx_user_ready (void * base , int version )
340
+ static inline void __tx_user_ready (void * base , int version )
328
341
{
329
342
switch (version ) {
330
343
case TPACKET_V1 :
@@ -333,6 +346,9 @@ static inline void __v1_v2_tx_user_ready(void *base, int version)
333
346
case TPACKET_V2 :
334
347
__v2_tx_user_ready (base );
335
348
break ;
349
+ case TPACKET_V3 :
350
+ __v3_tx_user_ready (base );
351
+ break ;
336
352
}
337
353
}
338
354
@@ -348,7 +364,22 @@ static void __v1_v2_set_packet_loss_discard(int sock)
348
364
}
349
365
}
350
366
351
- static void walk_v1_v2_tx (int sock , struct ring * ring )
367
+ static inline void * get_next_frame (struct ring * ring , int n )
368
+ {
369
+ uint8_t * f0 = ring -> rd [0 ].iov_base ;
370
+
371
+ switch (ring -> version ) {
372
+ case TPACKET_V1 :
373
+ case TPACKET_V2 :
374
+ return ring -> rd [n ].iov_base ;
375
+ case TPACKET_V3 :
376
+ return f0 + (n * ring -> req3 .tp_frame_size );
377
+ default :
378
+ bug_on (1 );
379
+ }
380
+ }
381
+
382
+ static void walk_tx (int sock , struct ring * ring )
352
383
{
353
384
struct pollfd pfd ;
354
385
int rcv_sock , ret ;
@@ -360,9 +391,19 @@ static void walk_v1_v2_tx(int sock, struct ring *ring)
360
391
.sll_family = PF_PACKET ,
361
392
.sll_halen = ETH_ALEN ,
362
393
};
394
+ int nframes ;
395
+
396
+ /* TPACKET_V{1,2} sets up the ring->rd* related variables based
397
+ * on frames (e.g., rd_num is tp_frame_nr) whereas V3 sets these
398
+ * up based on blocks (e.g, rd_num is tp_block_nr)
399
+ */
400
+ if (ring -> version <= TPACKET_V2 )
401
+ nframes = ring -> rd_num ;
402
+ else
403
+ nframes = ring -> req3 .tp_frame_nr ;
363
404
364
405
bug_on (ring -> type != PACKET_TX_RING );
365
- bug_on (ring -> rd_num < NUM_PACKETS );
406
+ bug_on (nframes < NUM_PACKETS );
366
407
367
408
rcv_sock = socket (PF_PACKET , SOCK_RAW , htons (ETH_P_ALL ));
368
409
if (rcv_sock == -1 ) {
@@ -388,10 +429,11 @@ static void walk_v1_v2_tx(int sock, struct ring *ring)
388
429
create_payload (packet , & packet_len );
389
430
390
431
while (total_packets > 0 ) {
391
- while (__v1_v2_tx_kernel_ready (ring -> rd [frame_num ].iov_base ,
392
- ring -> version ) &&
432
+ void * next = get_next_frame (ring , frame_num );
433
+
434
+ while (__tx_kernel_ready (next , ring -> version ) &&
393
435
total_packets > 0 ) {
394
- ppd .raw = ring -> rd [ frame_num ]. iov_base ;
436
+ ppd .raw = next ;
395
437
396
438
switch (ring -> version ) {
397
439
case TPACKET_V1 :
@@ -413,14 +455,27 @@ static void walk_v1_v2_tx(int sock, struct ring *ring)
413
455
packet_len );
414
456
total_bytes += ppd .v2 -> tp_h .tp_snaplen ;
415
457
break ;
458
+ case TPACKET_V3 : {
459
+ struct tpacket3_hdr * tx = next ;
460
+
461
+ tx -> tp_snaplen = packet_len ;
462
+ tx -> tp_len = packet_len ;
463
+ tx -> tp_next_offset = 0 ;
464
+
465
+ memcpy ((uint8_t * )tx + TPACKET3_HDRLEN -
466
+ sizeof (struct sockaddr_ll ), packet ,
467
+ packet_len );
468
+ total_bytes += tx -> tp_snaplen ;
469
+ break ;
470
+ }
416
471
}
417
472
418
473
status_bar_update ();
419
474
total_packets -- ;
420
475
421
- __v1_v2_tx_user_ready ( ppd . raw , ring -> version );
476
+ __tx_user_ready ( next , ring -> version );
422
477
423
- frame_num = (frame_num + 1 ) % ring -> rd_num ;
478
+ frame_num = (frame_num + 1 ) % nframes ;
424
479
}
425
480
426
481
poll (& pfd , 1 , 1 );
@@ -460,7 +515,7 @@ static void walk_v1_v2(int sock, struct ring *ring)
460
515
if (ring -> type == PACKET_RX_RING )
461
516
walk_v1_v2_rx (sock , ring );
462
517
else
463
- walk_v1_v2_tx (sock , ring );
518
+ walk_tx (sock , ring );
464
519
}
465
520
466
521
static uint64_t __v3_prev_block_seq_num = 0 ;
@@ -583,7 +638,7 @@ static void walk_v3(int sock, struct ring *ring)
583
638
if (ring -> type == PACKET_RX_RING )
584
639
walk_v3_rx (sock , ring );
585
640
else
586
- bug_on ( 1 );
641
+ walk_tx ( sock , ring );
587
642
}
588
643
589
644
static void __v1_v2_fill (struct ring * ring , unsigned int blocks )
@@ -602,12 +657,13 @@ static void __v1_v2_fill(struct ring *ring, unsigned int blocks)
602
657
ring -> flen = ring -> req .tp_frame_size ;
603
658
}
604
659
605
- static void __v3_fill (struct ring * ring , unsigned int blocks )
660
+ static void __v3_fill (struct ring * ring , unsigned int blocks , int type )
606
661
{
607
- ring -> req3 .tp_retire_blk_tov = 64 ;
608
- ring -> req3 .tp_sizeof_priv = 0 ;
609
- ring -> req3 .tp_feature_req_word = TP_FT_REQ_FILL_RXHASH ;
610
-
662
+ if (type == PACKET_RX_RING ) {
663
+ ring -> req3 .tp_retire_blk_tov = 64 ;
664
+ ring -> req3 .tp_sizeof_priv = 0 ;
665
+ ring -> req3 .tp_feature_req_word = TP_FT_REQ_FILL_RXHASH ;
666
+ }
611
667
ring -> req3 .tp_block_size = getpagesize () << 2 ;
612
668
ring -> req3 .tp_frame_size = TPACKET_ALIGNMENT << 7 ;
613
669
ring -> req3 .tp_block_nr = blocks ;
@@ -641,7 +697,7 @@ static void setup_ring(int sock, struct ring *ring, int version, int type)
641
697
break ;
642
698
643
699
case TPACKET_V3 :
644
- __v3_fill (ring , blocks );
700
+ __v3_fill (ring , blocks , type );
645
701
ret = setsockopt (sock , SOL_PACKET , type , & ring -> req3 ,
646
702
sizeof (ring -> req3 ));
647
703
break ;
@@ -796,6 +852,7 @@ int main(void)
796
852
ret |= test_tpacket (TPACKET_V2 , PACKET_TX_RING );
797
853
798
854
ret |= test_tpacket (TPACKET_V3 , PACKET_RX_RING );
855
+ ret |= test_tpacket (TPACKET_V3 , PACKET_TX_RING );
799
856
800
857
if (ret )
801
858
return 1 ;
0 commit comments