Skip to content

Commit 40e026a

Browse files
committed
(a) command line flag to repeat sending pcap, (b) command line flags to set sleep delay in nanoseconds every frequency packets, (c) command line option to group packets into bigger packets, (d) show sends stats per second
1 parent d6d6370 commit 40e026a

File tree

1 file changed

+61
-8
lines changed

1 file changed

+61
-8
lines changed

udpreplay.cpp

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ SOFTWARE.
2828
#include <netinet/udp.h>
2929
#include <pcap/pcap.h>
3030
#include <unistd.h>
31+
#include <sys/socket.h>
32+
#include <arpa/inet.h>
3133

3234
int main(int argc, char *argv[]) {
3335
static const char usage[] =
@@ -36,15 +38,23 @@ int main(int argc, char *argv[]) {
3638
" -i iface interface to send packets through\n"
3739
" -l enable loopback\n"
3840
" -s speed replay speed relative to pcap timestamps\n"
41+
" -d delay usec; e.g. 1,000 is 1 ms\n"
42+
" -f freq delay every <freq> packets sent\n"
43+
" -g group group <group> packets together, e.g. 1 or 6\n"
44+
" -r repeat at end of pcap file\n"
3945
" -t ttl packet ttl";
4046

4147
int ifindex = 0;
4248
int loopback = 0;
43-
double speed = 1;
49+
//double speed = 1;
4450
int ttl = -1;
51+
int delay = 100; // 0.1 ms
52+
int freq = 50; // delay every 50 packets
53+
int repeat = 0;
54+
int group = 1;
4555

4656
int opt;
47-
while ((opt = getopt(argc, argv, "i:ls:t:")) != -1) {
57+
while ((opt = getopt(argc, argv, "i:ls:t:rd:f:g:")) != -1) {
4858
switch (opt) {
4959
case 'i':
5060
ifindex = if_nametoindex(optarg);
@@ -56,8 +66,20 @@ int main(int argc, char *argv[]) {
5666
case 'l':
5767
loopback = 1;
5868
break;
59-
case 's':
60-
speed = std::stod(optarg);
69+
case 'r':
70+
repeat = 1;
71+
break;
72+
//case 's':
73+
// speed = std::stod(optarg);
74+
// break;
75+
case 'd':
76+
delay = std::stoi(optarg);
77+
break;
78+
case 'f':
79+
freq = std::stoi(optarg);
80+
break;
81+
case 'g':
82+
group = std::stoi(optarg);
6183
break;
6284
case 't':
6385
ttl = std::stoi(optarg);
@@ -104,6 +126,9 @@ int main(int argc, char *argv[]) {
104126
}
105127
}
106128

129+
time_t last_time = time(NULL);
130+
REPEAT:;
131+
107132
char errbuf[PCAP_ERRBUF_SIZE];
108133
pcap_t *handle = pcap_open_offline(argv[optind], errbuf);
109134
if (handle == nullptr) {
@@ -114,7 +139,17 @@ int main(int argc, char *argv[]) {
114139
pcap_pkthdr header;
115140
const u_char *p;
116141
timeval tv = {0, 0};
142+
unsigned long count = 0;
143+
unsigned long sent = 0;
144+
unsigned long last_count = 0;
145+
unsigned long last_sent = 0;
146+
#define JUMBO_MAX_BYTES (9001)
147+
char jumbo[JUMBO_MAX_BYTES];
148+
int jumbo_appends = 0;
149+
int jumbo_used = 0;
150+
printf("- starting sending loop\n");
117151
while ((p = pcap_next(handle, &header))) {
152+
p += 2; // see https://www.eecis.udel.edu/~sunshine/expcs/code/pcap_packet_read.c
118153
if (header.len != header.caplen) {
119154
continue;
120155
}
@@ -137,23 +172,41 @@ int main(int argc, char *argv[]) {
137172
}
138173
timeval diff;
139174
timersub(&header.ts, &tv, &diff);
140-
usleep((diff.tv_sec * 1000000 + diff.tv_usec) * speed);
175+
//do not use original timings usleep((diff.tv_sec * 1000000 + diff.tv_usec) * speed);
141176

142177
ssize_t len = ntohs(udp->len) - 8;
143178
const u_char *d = &p[sizeof(ether_header) + ip->ihl * 4 + sizeof(udphdr)];
144179

180+
if(jumbo_used + len > JUMBO_MAX_BYTES){ printf("ERROR: jumbo overflow detected!\n"); exit(0); }
181+
memcpy(&jumbo[jumbo_used], d, len);
182+
jumbo_appends ++;
183+
jumbo_used += len;
184+
if(jumbo_appends == group) { // 6 for MTU 9,001 byte packet
185+
145186
sockaddr_in addr;
146187
memset(&addr, 0, sizeof(addr));
147188
addr.sin_family = AF_INET;
148189
addr.sin_port = udp->dest;
149-
addr.sin_addr = {ip->daddr};
150-
auto n = sendto(fd, d, len, 0, reinterpret_cast<sockaddr *>(&addr),
190+
//addr.sin_addr = {ip->daddr};
191+
addr.sin_addr.s_addr = inet_addr("10.130.18.8"); // force send packets to this IP!
192+
auto n = sendto(fd, &jumbo[0], jumbo_used, 0, reinterpret_cast<sockaddr *>(&addr),
151193
sizeof(addr));
152-
if (n != len) {
194+
if (n != jumbo_used) {
153195
std::cerr << "sendto: " << strerror(errno) << std::endl;
154196
return 1;
155197
}
198+
sent += jumbo_used;
199+
if ((++ count % 100) == 0) { time_t this_time = time(NULL); if(this_time != last_time) { last_time = this_time; printf("- sent %lu bytes in %lu packets\n", sent - last_sent, count - last_count); last_sent = sent; last_count = count; }}
200+
if ((count % freq) == 0) { usleep(delay); } // delay=100 means sleep for 0.1 ms
201+
//if (count == 152) { exit(0); }
202+
203+
jumbo_appends = 0;
204+
jumbo_used = 0;
205+
}
156206
}
207+
printf("- sent %lu bytes in %lu packets total\n", sent, count);
208+
209+
if (repeat) { pcap_close(handle); goto REPEAT; }
157210

158211
return 0;
159212
}

0 commit comments

Comments
 (0)