source: tools/tracereplay/tracereplay.c @ 82facc5

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 82facc5 was 19526f3, checked in by Shane Alcock <salcock@…>, 9 years ago
  • Fixed unused variable warnings in tracereplay
  • 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_packet_t *new_packet;
65        size_t wire_length;
66        void * pkt_buffer;
67        void * l2_header;
68        libtrace_ether_t * ether_header;
69        int i;
70
71        pkt_buffer = trace_get_packet_buffer(packet,&linktype,&remaining);
72        remaining = 0;
73        new_packet = trace_create_packet();
74
75        wire_length = trace_get_wire_length(packet);
76
77        /* if it's ehternet we don't want to add space for the FCS that will
78           be appended. */
79        if(linktype == TRACE_TYPE_ETH || linktype == TRACE_TYPE_80211) {
80                wire_length -= FCS_SIZE;
81        }
82
83        trace_construct_packet(new_packet,linktype,pkt_buffer,wire_length);
84
85
86        if(broadcast) {
87                l2_header = trace_get_layer2(new_packet,&linktype,&remaining);
88                if(linktype == TRACE_TYPE_ETH){
89                        ether_header = (libtrace_ether_t *) l2_header;
90                        for(i = 0; i < 6; i++) {
91                                ether_header -> ether_dhost[i] = 0xFF;
92                        }
93                }
94
95        }
96
97        replace_ip_checksum(new_packet);
98        replace_transport_checksum(new_packet);
99
100        return new_packet;
101
102}
103
104
105
106static uint32_t event_read_packet(libtrace_t *trace, libtrace_packet_t *packet) 
107{
108        libtrace_eventobj_t obj;
109        fd_set rfds;
110        struct timeval sleep_tv;
111
112        FD_ZERO(&rfds);
113
114        for (;;) {
115                obj = trace_event(trace, packet);
116
117                switch(obj.type) {
118
119                        /* Device has no packets at present - lets wait until
120                         * it does get something */
121                        case TRACE_EVENT_IOWAIT:
122                                FD_ZERO(&rfds);
123                                FD_SET(obj.fd, &rfds);
124                                select(obj.fd + 1, &rfds, NULL, NULL, 0);
125                                continue;
126
127                                /* Replaying a trace in tracetime and the next packet
128                                 * is not due yet */
129                        case TRACE_EVENT_SLEEP:
130                                /* select offers good precision for sleeping */
131                                sleep_tv.tv_sec = (int)obj.seconds;
132                                sleep_tv.tv_usec = (int) ((obj.seconds - sleep_tv.tv_sec) * 1000000.0);
133                                select(0, NULL, NULL, NULL, &sleep_tv);
134                                continue;
135
136                                /* We've got a packet! */
137                        case TRACE_EVENT_PACKET:
138                                /* Check for error first */
139                                if (obj.size == -1)
140                                        return -1;
141                                return 1;
142
143                                /* End of trace has been reached */
144                        case TRACE_EVENT_TERMINATE:
145                                return -1;
146
147                                /* An event we don't know about has occured */
148                        default:
149                                fprintf(stderr, "Unknown event type occured\n");
150                                return -1;
151                }
152        }
153}
154
155static void usage(char * argv) {
156        fprintf(stderr, "usage: %s [options] inputuri outputuri...\n", argv);
157        fprintf(stderr, " --filter bpfexpr\n");
158        fprintf(stderr, " -f bpfexpr\n");
159        fprintf(stderr, "\t\tApply a bpf filter expression\n");
160        fprintf(stderr, " -s snaplength\n");
161        fprintf(stderr, " --snaplength snaplength\n");
162        fprintf(stderr, "\t\tTruncate the packets read from inputuri to <snaplength>\n");
163        fprintf(stderr, " -b\n");
164        fprintf(stderr, " --broadcast\n");
165        fprintf(stderr, "\t\tSend ethernet frames to broadcast address\n");
166
167}
168
169int main(int argc, char *argv[]) {
170
171        libtrace_t *trace;
172        libtrace_out_t *output;
173        libtrace_packet_t *packet;
174        libtrace_filter_t *filter=NULL;
175        int psize = 0;
176        char *uri = 0;
177        libtrace_packet_t * new;
178        int snaplen = 0;
179
180
181        while(1) {
182                int option_index;
183                struct option long_options[] = {
184                        { "filter",     1, 0, 'f'},
185                        { "help",       0, 0, 'h'},
186                        { "snaplen",    1, 0, 's'},
187                        { "broadcast",  0, 0, 'b'},
188                        { NULL,         0, 0, 0}
189                };
190
191                int c = getopt_long(argc, argv, "bhs:f:",
192                                long_options, &option_index);
193
194                if(c == -1)
195                        break;
196
197                switch (c) {
198                        case 'f':
199                                filter = trace_create_filter(optarg);
200                                break;
201                        case 's':
202                                snaplen = atoi(optarg);
203                                break;
204
205                        case 'b':
206                                broadcast = 1;
207                                break;
208
209                        case 'h':
210
211                                usage(argv[0]);
212                                return 1;
213                        default:
214                                fprintf(stderr, "Unknown option: %c\n", c);
215                }
216        }
217
218        if(optind>=argc) {
219                fprintf(stderr, "Missing input uri\n");
220                usage(argv[0]);
221                return 1;
222        }
223        if(optind+1>=argc) {
224                fprintf(stderr, "Missing output uri\n");
225                usage(argv[0]);
226                return 1;
227        }
228
229        uri = strdup(argv[optind]);
230
231        /* Create the trace */
232        trace = trace_create(uri);
233        if (trace_is_err(trace)) {
234                trace_perror(trace, "trace_create");
235                return 1;
236        }
237
238        /*apply snaplength */
239        if(snaplen) {
240                if(trace_config(trace,TRACE_OPTION_SNAPLEN,&snaplen)) {
241                        trace_perror(trace,"error setting snaplength, proceeding anyway");
242                }
243        }
244
245        /* apply filter */
246        if(filter) {
247                if(trace_config(trace, TRACE_OPTION_FILTER, filter)) {
248                        trace_perror(trace, "ignoring: ");
249                }
250        }
251
252        /* Starting the trace */
253        if (trace_start(trace) != 0) {
254                trace_perror(trace, "trace_start");
255                return 1;
256        }
257
258        /* Creating output trace */
259        output = trace_create_output(argv[optind+1]);
260
261        if (trace_is_err_output(output)) {
262                trace_perror_output(output, "Opening output trace: ");
263                return 1;
264        }
265        if (trace_start_output(output)) {
266                trace_perror_output(output, "Starting output trace: ");
267                trace_destroy_output(output);
268                trace_destroy(trace);
269                return 1;
270        }
271
272        packet = trace_create_packet();
273
274        for (;;) {
275                if ((psize = event_read_packet(trace, packet)) <= 0) {
276                        break;
277                }
278
279                /* Got a packet - let's do something with it */
280                new = per_packet(packet);
281
282                if (trace_write_packet(output, new) < 0) {
283                        trace_perror_output(output, "Writing packet");
284                        trace_destroy(trace);
285                        trace_destroy_output(output);
286                        trace_destroy_packet(packet);
287                        return 1;
288                }
289                trace_destroy_packet(new);
290        }
291        if (trace_is_err(trace)) {
292                trace_perror(trace,"%s",uri);
293        }
294        free(uri);
295        trace_destroy(trace);
296        if(filter != NULL) {
297                trace_destroy_filter(filter);
298        }
299        trace_destroy_output(output);
300        trace_destroy_packet(packet);
301        return 0;
302
303}
304
Note: See TracBrowser for help on using the repository browser.