source: tools/tracereplay/tracereplay.c @ 5ea8d25

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 5ea8d25 was 68b7f29, checked in by Shane Alcock <salcock@…>, 8 years ago
  • Updated tracereplay to use the new libtrace checksumming functions - tracereplay was kinda broken anyway in that it wouldn't do anything with the TCP/UDP checksums because of a broken call to trace_get_payload_from_ip (bad remaining value).
  • As an added benefit, tracereplay show now correctly update the checksums for IPv6 and ICMPv4 packets
  • Property mode set to 100644
File size: 6.5 KB
Line 
1
2/*
3
4   Tracereplay is a simple utility that takes a trace and replays it to a
5   specified interface.
6   It pads packets with zeroes to reach the original length of the packet
7   and recalculates checksums in ip/tcp/udp headers.
8
9Authors: Andreas Loef and Yuwei Wang
10
11
12 */
13
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <assert.h>
18#include <sys/types.h>
19#include <unistd.h>
20#include <string.h>
21#include <libtrace.h>
22#include <getopt.h>
23#include <arpa/inet.h>
24
25#define FCS_SIZE 4
26
27int broadcast = 0;
28
29static void replace_ip_checksum(libtrace_packet_t *packet) {
30
31        uint16_t *ip_csm_ptr = NULL;
32        uint16_t calc_csum;
33
34        ip_csm_ptr = trace_checksum_layer3(packet, &calc_csum);
35
36        if (ip_csm_ptr == NULL)
37                return;
38        *ip_csm_ptr = htons(calc_csum);
39
40}
41
42static void replace_transport_checksum(libtrace_packet_t *packet) {
43
44        uint16_t *csm_ptr = NULL;
45        uint16_t calc_csum;
46       
47        csm_ptr = trace_checksum_transport(packet, &calc_csum);
48
49        if (csm_ptr == NULL)
50                return;
51        *csm_ptr = htons(calc_csum);
52
53}
54
55/*
56   Create a copy of the packet that can be written to the output URI.
57   if the packet is IPv4 the checksum will be recalculated to account for
58   cryptopan. Same for TCP and UDP. No other protocols are supported at the
59   moment.
60 */
61static libtrace_packet_t * per_packet(libtrace_packet_t *packet) {
62        uint32_t remaining = 0; 
63        libtrace_linktype_t linktype = 0;
64        libtrace_ip_t * header = NULL;
65        uint16_t sum = 0;
66        libtrace_packet_t *new_packet;
67        size_t wire_length;
68        void * pkt_buffer;
69        void * l2_header;
70        libtrace_ether_t * ether_header;
71        int i;
72
73        pkt_buffer = trace_get_packet_buffer(packet,&linktype,&remaining);
74        remaining = 0;
75        new_packet = trace_create_packet();
76
77        wire_length = trace_get_wire_length(packet);
78
79        /* if it's ehternet we don't want to add space for the FCS that will
80           be appended. */
81        if(linktype == TRACE_TYPE_ETH || linktype == TRACE_TYPE_80211) {
82                wire_length -= FCS_SIZE;
83        }
84
85        trace_construct_packet(new_packet,linktype,pkt_buffer,wire_length);
86
87
88        if(broadcast) {
89                l2_header = trace_get_layer2(new_packet,&linktype,&remaining);
90                if(linktype == TRACE_TYPE_ETH){
91                        ether_header = (libtrace_ether_t *) l2_header;
92                        for(i = 0; i < 6; i++) {
93                                ether_header -> ether_dhost[i] = 0xFF;
94                        }
95                }
96
97        }
98
99        replace_ip_checksum(new_packet);
100        replace_transport_checksum(new_packet);
101
102        return new_packet;
103
104}
105
106
107
108static uint32_t event_read_packet(libtrace_t *trace, libtrace_packet_t *packet) 
109{
110        libtrace_eventobj_t obj;
111        fd_set rfds;
112        struct timeval sleep_tv;
113
114        FD_ZERO(&rfds);
115
116        for (;;) {
117                obj = trace_event(trace, packet);
118
119                switch(obj.type) {
120
121                        /* Device has no packets at present - lets wait until
122                         * it does get something */
123                        case TRACE_EVENT_IOWAIT:
124                                FD_ZERO(&rfds);
125                                FD_SET(obj.fd, &rfds);
126                                select(obj.fd + 1, &rfds, NULL, NULL, 0);
127                                continue;
128
129                                /* Replaying a trace in tracetime and the next packet
130                                 * is not due yet */
131                        case TRACE_EVENT_SLEEP:
132                                /* select offers good precision for sleeping */
133                                sleep_tv.tv_sec = (int)obj.seconds;
134                                sleep_tv.tv_usec = (int) ((obj.seconds - sleep_tv.tv_sec) * 1000000.0);
135                                select(0, NULL, NULL, NULL, &sleep_tv);
136                                continue;
137
138                                /* We've got a packet! */
139                        case TRACE_EVENT_PACKET:
140                                /* Check for error first */
141                                if (obj.size == -1)
142                                        return -1;
143                                return 1;
144
145                                /* End of trace has been reached */
146                        case TRACE_EVENT_TERMINATE:
147                                return -1;
148
149                                /* An event we don't know about has occured */
150                        default:
151                                fprintf(stderr, "Unknown event type occured\n");
152                                return -1;
153                }
154        }
155}
156
157static void usage(char * argv) {
158        fprintf(stderr, "usage: %s [options] inputuri outputuri...\n", argv);
159        fprintf(stderr, " --filter bpfexpr\n");
160        fprintf(stderr, " -f bpfexpr\n");
161        fprintf(stderr, "\t\tApply a bpf filter expression\n");
162        fprintf(stderr, " -s snaplength\n");
163        fprintf(stderr, " --snaplength snaplength\n");
164        fprintf(stderr, "\t\tTruncate the packets read from inputuri to <snaplength>\n");
165        fprintf(stderr, " -b\n");
166        fprintf(stderr, " --broadcast\n");
167        fprintf(stderr, "\t\tSend ethernet frames to broadcast address\n");
168
169}
170
171int main(int argc, char *argv[]) {
172
173        libtrace_t *trace;
174        libtrace_out_t *output;
175        libtrace_packet_t *packet;
176        libtrace_filter_t *filter=NULL;
177        int psize = 0;
178        char *uri = 0;
179        libtrace_packet_t * new;
180        int snaplen = 0;
181
182
183        while(1) {
184                int option_index;
185                struct option long_options[] = {
186                        { "filter",     1, 0, 'f'},
187                        { "help",       0, 0, 'h'},
188                        { "snaplen",    1, 0, 's'},
189                        { "broadcast",  0, 0, 'b'},
190                        { NULL,         0, 0, 0}
191                };
192
193                int c = getopt_long(argc, argv, "bhs:f:",
194                                long_options, &option_index);
195
196                if(c == -1)
197                        break;
198
199                switch (c) {
200                        case 'f':
201                                filter = trace_create_filter(optarg);
202                                break;
203                        case 's':
204                                snaplen = atoi(optarg);
205                                break;
206
207                        case 'b':
208                                broadcast = 1;
209                                break;
210
211                        case 'h':
212
213                                usage(argv[0]);
214                                return 1;
215                        default:
216                                fprintf(stderr, "Unknown option: %c\n", c);
217                }
218        }
219
220        if(optind>=argc) {
221                fprintf(stderr, "Missing input uri\n");
222                usage(argv[0]);
223                return 1;
224        }
225        if(optind+1>=argc) {
226                fprintf(stderr, "Missing output uri\n");
227                usage(argv[0]);
228                return 1;
229        }
230
231        uri = strdup(argv[optind]);
232
233        /* Create the trace */
234        trace = trace_create(uri);
235        if (trace_is_err(trace)) {
236                trace_perror(trace, "trace_create");
237                return 1;
238        }
239
240        /*apply snaplength */
241        if(snaplen) {
242                if(trace_config(trace,TRACE_OPTION_SNAPLEN,&snaplen)) {
243                        trace_perror(trace,"error setting snaplength, proceeding anyway");
244                }
245        }
246
247        /* apply filter */
248        if(filter) {
249                if(trace_config(trace, TRACE_OPTION_FILTER, filter)) {
250                        trace_perror(trace, "ignoring: ");
251                }
252        }
253
254        /* Starting the trace */
255        if (trace_start(trace) != 0) {
256                trace_perror(trace, "trace_start");
257                return 1;
258        }
259
260        /* Creating output trace */
261        output = trace_create_output(argv[optind+1]);
262
263        if (trace_is_err_output(output)) {
264                trace_perror_output(output, "Opening output trace: ");
265                return 1;
266        }
267        if (trace_start_output(output)) {
268                trace_perror_output(output, "Starting output trace: ");
269                trace_destroy_output(output);
270                trace_destroy(trace);
271                return 1;
272        }
273
274        packet = trace_create_packet();
275
276        for (;;) {
277                if ((psize = event_read_packet(trace, packet)) <= 0) {
278                        break;
279                }
280
281                /* Got a packet - let's do something with it */
282                new = per_packet(packet);
283
284                if (trace_write_packet(output, new) < 0) {
285                        trace_perror_output(output, "Writing packet");
286                        trace_destroy(trace);
287                        trace_destroy_output(output);
288                        trace_destroy_packet(packet);
289                        return 1;
290                }
291                trace_destroy_packet(new);
292        }
293        if (trace_is_err(trace)) {
294                trace_perror(trace,"%s",uri);
295        }
296        free(uri);
297        trace_destroy(trace);
298        if(filter != NULL) {
299                trace_destroy_filter(filter);
300        }
301        trace_destroy_output(output);
302        trace_destroy_packet(packet);
303        return 0;
304
305}
306
Note: See TracBrowser for help on using the repository browser.