@@ -111,6 +111,7 @@ static bool opt_app_stats;
111
111
static const char * opt_irq_str = "" ;
112
112
static u32 irq_no ;
113
113
static int irqs_at_init = -1 ;
114
+ static u32 sequence ;
114
115
static int opt_poll ;
115
116
static int opt_interval = 1 ;
116
117
static int opt_retries = 3 ;
@@ -129,6 +130,7 @@ static clockid_t opt_clock = CLOCK_MONOTONIC;
129
130
static unsigned long opt_tx_cycle_ns ;
130
131
static int opt_schpolicy = SCHED_OTHER ;
131
132
static int opt_schprio = SCHED_PRI__DEFAULT ;
133
+ static bool opt_tstamp ;
132
134
133
135
struct vlan_ethhdr {
134
136
unsigned char h_dest [6 ];
@@ -138,6 +140,14 @@ struct vlan_ethhdr {
138
140
__be16 h_vlan_encapsulated_proto ;
139
141
};
140
142
143
+ #define PKTGEN_MAGIC 0xbe9be955
144
+ struct pktgen_hdr {
145
+ __be32 pgh_magic ;
146
+ __be32 seq_num ;
147
+ __be32 tv_sec ;
148
+ __be32 tv_usec ;
149
+ };
150
+
141
151
struct xsk_ring_stats {
142
152
unsigned long rx_npkts ;
143
153
unsigned long tx_npkts ;
@@ -836,18 +846,25 @@ static inline u16 udp_csum(u32 saddr, u32 daddr, u32 len,
836
846
837
847
#define ETH_HDR_SIZE (opt_vlan_tag ? sizeof(struct vlan_ethhdr) : \
838
848
sizeof(struct ethhdr))
849
+ #define PKTGEN_HDR_SIZE (opt_tstamp ? sizeof(struct pktgen_hdr) : 0)
839
850
#define PKT_HDR_SIZE (ETH_HDR_SIZE + sizeof(struct iphdr) + \
840
- sizeof(struct udphdr))
851
+ sizeof(struct udphdr) + PKTGEN_HDR_SIZE)
852
+ #define PKTGEN_HDR_OFFSET (ETH_HDR_SIZE + sizeof(struct iphdr) + \
853
+ sizeof(struct udphdr))
854
+ #define PKTGEN_SIZE_MIN (PKTGEN_HDR_OFFSET + sizeof(struct pktgen_hdr) + \
855
+ ETH_FCS_SIZE)
841
856
842
857
#define PKT_SIZE (opt_pkt_size - ETH_FCS_SIZE)
843
858
#define IP_PKT_SIZE (PKT_SIZE - ETH_HDR_SIZE)
844
859
#define UDP_PKT_SIZE (IP_PKT_SIZE - sizeof(struct iphdr))
845
- #define UDP_PKT_DATA_SIZE (UDP_PKT_SIZE - sizeof(struct udphdr))
860
+ #define UDP_PKT_DATA_SIZE (UDP_PKT_SIZE - \
861
+ (sizeof(struct udphdr) + PKTGEN_HDR_SIZE))
846
862
847
863
static u8 pkt_data [XSK_UMEM__DEFAULT_FRAME_SIZE ];
848
864
849
865
static void gen_eth_hdr_data (void )
850
866
{
867
+ struct pktgen_hdr * pktgen_hdr ;
851
868
struct udphdr * udp_hdr ;
852
869
struct iphdr * ip_hdr ;
853
870
@@ -860,7 +877,10 @@ static void gen_eth_hdr_data(void)
860
877
sizeof (struct iphdr ));
861
878
ip_hdr = (struct iphdr * )(pkt_data +
862
879
sizeof (struct vlan_ethhdr ));
863
-
880
+ pktgen_hdr = (struct pktgen_hdr * )(pkt_data +
881
+ sizeof (struct vlan_ethhdr ) +
882
+ sizeof (struct iphdr ) +
883
+ sizeof (struct udphdr ));
864
884
/* ethernet & VLAN header */
865
885
memcpy (veth_hdr -> h_dest , & opt_txdmac , ETH_ALEN );
866
886
memcpy (veth_hdr -> h_source , & opt_txsmac , ETH_ALEN );
@@ -877,7 +897,10 @@ static void gen_eth_hdr_data(void)
877
897
sizeof (struct iphdr ));
878
898
ip_hdr = (struct iphdr * )(pkt_data +
879
899
sizeof (struct ethhdr ));
880
-
900
+ pktgen_hdr = (struct pktgen_hdr * )(pkt_data +
901
+ sizeof (struct ethhdr ) +
902
+ sizeof (struct iphdr ) +
903
+ sizeof (struct udphdr ));
881
904
/* ethernet header */
882
905
memcpy (eth_hdr -> h_dest , & opt_txdmac , ETH_ALEN );
883
906
memcpy (eth_hdr -> h_source , & opt_txsmac , ETH_ALEN );
@@ -906,6 +929,9 @@ static void gen_eth_hdr_data(void)
906
929
udp_hdr -> dest = htons (0x1000 );
907
930
udp_hdr -> len = htons (UDP_PKT_SIZE );
908
931
932
+ if (opt_tstamp )
933
+ pktgen_hdr -> pgh_magic = htonl (PKTGEN_MAGIC );
934
+
909
935
/* UDP data */
910
936
memset32_htonl (pkt_data + PKT_HDR_SIZE , opt_pkt_fill_pattern ,
911
937
UDP_PKT_DATA_SIZE );
@@ -1049,6 +1075,7 @@ static struct option long_options[] = {
1049
1075
{"tx-dmac" , required_argument , 0 , 'G' },
1050
1076
{"tx-smac" , required_argument , 0 , 'H' },
1051
1077
{"tx-cycle" , required_argument , 0 , 'T' },
1078
+ {"tstamp" , no_argument , 0 , 'y' },
1052
1079
{"policy" , required_argument , 0 , 'W' },
1053
1080
{"schpri" , required_argument , 0 , 'U' },
1054
1081
{"extra-stats" , no_argument , 0 , 'x' },
@@ -1099,6 +1126,7 @@ static void usage(const char *prog)
1099
1126
" -G, --tx-dmac=<MAC> Dest MAC addr of TX frame in aa:bb:cc:dd:ee:ff format (For -V|--tx-vlan)\n"
1100
1127
" -H, --tx-smac=<MAC> Src MAC addr of TX frame in aa:bb:cc:dd:ee:ff format (For -V|--tx-vlan)\n"
1101
1128
" -T, --tx-cycle=n Tx cycle time in micro-seconds (For -t|--txonly).\n"
1129
+ " -y, --tstamp Add time-stamp to packet (For -t|--txonly).\n"
1102
1130
" -W, --policy=POLICY Schedule policy. Default: SCHED_OTHER\n"
1103
1131
" -U, --schpri=n Schedule priority. Default: %d\n"
1104
1132
" -x, --extra-stats Display extra statistics.\n"
@@ -1125,7 +1153,7 @@ static void parse_command_line(int argc, char **argv)
1125
1153
1126
1154
for (;;) {
1127
1155
c = getopt_long (argc , argv ,
1128
- "Frtli:q:pSNn:w:O:czf:muMd:b:C:s:P:VJ:K:G:H:T:W :U:xQaI:BR" ,
1156
+ "Frtli:q:pSNn:w:O:czf:muMd:b:C:s:P:VJ:K:G:H:T:yW :U:xQaI:BR" ,
1129
1157
long_options , & option_index );
1130
1158
if (c == -1 )
1131
1159
break ;
@@ -1246,6 +1274,9 @@ static void parse_command_line(int argc, char **argv)
1246
1274
opt_tx_cycle_ns = atoi (optarg );
1247
1275
opt_tx_cycle_ns *= NSEC_PER_USEC ;
1248
1276
break ;
1277
+ case 'y' :
1278
+ opt_tstamp = 1 ;
1279
+ break ;
1249
1280
case 'W' :
1250
1281
if (get_schpolicy (& opt_schpolicy , optarg )) {
1251
1282
fprintf (stderr ,
@@ -1462,9 +1493,10 @@ static void rx_drop_all(void)
1462
1493
}
1463
1494
}
1464
1495
1465
- static int tx_only (struct xsk_socket_info * xsk , u32 * frame_nb , int batch_size )
1496
+ static int tx_only (struct xsk_socket_info * xsk , u32 * frame_nb ,
1497
+ int batch_size , unsigned long tx_ns )
1466
1498
{
1467
- u32 idx ;
1499
+ u32 idx , tv_sec , tv_usec ;
1468
1500
unsigned int i ;
1469
1501
1470
1502
while (xsk_ring_prod__reserve (& xsk -> tx , batch_size , & idx ) <
@@ -1474,11 +1506,31 @@ static int tx_only(struct xsk_socket_info *xsk, u32 *frame_nb, int batch_size)
1474
1506
return 0 ;
1475
1507
}
1476
1508
1509
+ if (opt_tstamp ) {
1510
+ tv_sec = (u32 )(tx_ns / NSEC_PER_SEC );
1511
+ tv_usec = (u32 )((tx_ns % NSEC_PER_SEC ) / 1000 );
1512
+ }
1513
+
1477
1514
for (i = 0 ; i < batch_size ; i ++ ) {
1478
1515
struct xdp_desc * tx_desc = xsk_ring_prod__tx_desc (& xsk -> tx ,
1479
1516
idx + i );
1480
1517
tx_desc -> addr = (* frame_nb + i ) * opt_xsk_frame_size ;
1481
1518
tx_desc -> len = PKT_SIZE ;
1519
+
1520
+ if (opt_tstamp ) {
1521
+ struct pktgen_hdr * pktgen_hdr ;
1522
+ u64 addr = tx_desc -> addr ;
1523
+ char * pkt ;
1524
+
1525
+ pkt = xsk_umem__get_data (xsk -> umem -> buffer , addr );
1526
+ pktgen_hdr = (struct pktgen_hdr * )(pkt + PKTGEN_HDR_OFFSET );
1527
+
1528
+ pktgen_hdr -> seq_num = htonl (sequence ++ );
1529
+ pktgen_hdr -> tv_sec = htonl (tv_sec );
1530
+ pktgen_hdr -> tv_usec = htonl (tv_usec );
1531
+
1532
+ hex_dump (pkt , PKT_SIZE , addr );
1533
+ }
1482
1534
}
1483
1535
1484
1536
xsk_ring_prod__submit (& xsk -> tx , batch_size );
@@ -1552,6 +1604,7 @@ static void tx_only_all(void)
1552
1604
1553
1605
while ((opt_pkt_count && pkt_cnt < opt_pkt_count ) || !opt_pkt_count ) {
1554
1606
int batch_size = get_batch_size (pkt_cnt );
1607
+ unsigned long tx_ns = 0 ;
1555
1608
struct timespec next ;
1556
1609
int tx_cnt = 0 ;
1557
1610
long diff ;
@@ -1581,7 +1634,8 @@ static void tx_only_all(void)
1581
1634
}
1582
1635
1583
1636
/* Measure periodic Tx scheduling variance */
1584
- diff = get_nsecs () - next_tx_ns ;
1637
+ tx_ns = get_nsecs ();
1638
+ diff = tx_ns - next_tx_ns ;
1585
1639
if (diff < tx_cycle_diff_min )
1586
1640
tx_cycle_diff_min = diff ;
1587
1641
@@ -1590,10 +1644,12 @@ static void tx_only_all(void)
1590
1644
1591
1645
tx_cycle_diff_ave += (double )diff ;
1592
1646
tx_cycle_cnt ++ ;
1647
+ } else if (opt_tstamp ) {
1648
+ tx_ns = get_nsecs ();
1593
1649
}
1594
1650
1595
1651
for (i = 0 ; i < num_socks ; i ++ )
1596
- tx_cnt += tx_only (xsks [i ], & frame_nb [i ], batch_size );
1652
+ tx_cnt += tx_only (xsks [i ], & frame_nb [i ], batch_size , tx_ns );
1597
1653
1598
1654
pkt_cnt += tx_cnt ;
1599
1655
@@ -1895,6 +1951,9 @@ int main(int argc, char **argv)
1895
1951
apply_setsockopt (xsks [i ]);
1896
1952
1897
1953
if (opt_bench == BENCH_TXONLY ) {
1954
+ if (opt_tstamp && opt_pkt_size < PKTGEN_SIZE_MIN )
1955
+ opt_pkt_size = PKTGEN_SIZE_MIN ;
1956
+
1898
1957
gen_eth_hdr_data ();
1899
1958
1900
1959
for (i = 0 ; i < NUM_FRAMES ; i ++ )
0 commit comments