source: tools/tracereplay/tracereplay.c @ c5fe79a

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since c5fe79a was c5fe79a, checked in by Andreas Löf <andreas.lof@…>, 12 years ago

fixing bugs

  • Property mode set to 100644
File size: 7.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
9  Authors: Andreas Loef and Yuwei Wang
10
11
12 */
13
14
15
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <assert.h>
20#include <sys/types.h>
21#include <unistd.h>
22#include <string.h>
23#include <libtrace.h>
24#include <getopt.h>
25#include <arpa/inet.h>
26
27#define FCS_SIZE 4
28
29/* This function assumes that the relevant fields have been zeroed out. RFC 1071*/
30static uint16_t checksum(void * buffer, uint16_t length) {
31  uint32_t sum = 0;
32  uint16_t * buff = (uint16_t *) buffer;
33  uint16_t count = length;
34
35  while(count > 1 ) {
36    sum += *buff++;
37    count = count -2;
38  }
39
40  if(count > 0) {
41    sum += *buff;
42  }
43 
44  while (sum>>16)
45    sum = (sum & 0xffff) + (sum >> 16);
46  return ~sum;
47}
48
49static void udp_tcp_checksum(libtrace_ip_t *ip, uint32_t* remaining) {
50
51
52
53  uint32_t sum = 0;
54  uint32_t pseudoheader[3] = {0,0,0};
55  uint8_t * other8 = NULL;
56  uint16_t * other16 = NULL;
57 
58  uint8_t proto = 0;
59
60  printf("IP payload length: %d\n",*remaining);
61 
62  /*
63    Remaining gets the wrong value here.
64
65   */
66  void * transportheader = trace_get_payload_from_ip(ip,&proto,remaining);
67
68  printf("l3 payload length: %d\n",*remaining); 
69
70  uint16_t * check = NULL;
71  uint16_t tsum = 0;
72
73  pseudoheader[0] = (uint32_t) (ip -> ip_src).s_addr;
74  pseudoheader[1] = (uint32_t)(ip -> ip_dst).s_addr;
75 
76  other8 = (uint8_t *) &pseudoheader[2];
77
78  *other8 = 0x00;
79  other8++;
80  *other8 = ip -> ip_p;
81  other8++;
82 
83  other16 = (uint16_t *) other8;
84
85  if(proto == 17 ) {
86    printf("udp  length: %d\n",sizeof(libtrace_udp_t));
87    libtrace_udp_t * udp_header = transportheader;
88    udp_header -> check = 0;
89    check = &udp_header -> check;
90    *other16 = *remaining + sizeof(libtrace_udp_t);
91    tsum = checksum(transportheader,*remaining + sizeof(libtrace_udp_t));
92  }
93  else if(proto == 6) {
94   
95    libtrace_tcp_t * tcp_header = transportheader;
96    tcp_header -> check = 0;
97    check = &tcp_header -> check;
98    *other16 = *remaining + sizeof(libtrace_tcp_t);
99    //use tcp header length and datagram length instead
100    tsum = checksum(transportheader,*remaining+sizeof(libtrace_tcp_t));
101  }
102
103  *other16 = *remaining;
104
105  sum = (~checksum(pseudoheader,3*sizeof(uint32_t)) + ~tsum);
106
107  while (sum>>16)
108    sum = (sum & 0xffff) + (sum >> 16);
109 
110  if(check != NULL) {
111    *check = (uint16_t)~sum;
112  }
113 
114
115}
116
117
118static libtrace_packet_t * per_packet(libtrace_packet_t *packet) {
119  uint32_t remaining = 0; 
120  libtrace_linktype_t linktype = 0;
121  void * pkt_buffer = trace_get_packet_buffer(packet,&linktype,&remaining);
122  remaining = 0;
123  libtrace_ip_t * header = NULL;
124  uint16_t sum = 0;
125  libtrace_packet_t *new_packet = trace_create_packet();
126 
127  size_t wire_length = trace_get_wire_length(packet);
128
129  printf("wire length: %d\n",wire_length);
130
131  if(linktype == TRACE_TYPE_ETH || linktype == TRACE_TYPE_80211) {
132    wire_length -= FCS_SIZE;
133  }
134
135  printf("wire length after FCS: %d\n",wire_length);
136
137  trace_construct_packet(new_packet,linktype,pkt_buffer,wire_length);
138 
139
140  header = trace_get_ip(new_packet);
141  if(header != NULL) {
142    wire_length -= sizeof(libtrace_ip_t);
143    header -> ip_sum = 0;
144    sum = checksum(header,header->ip_hl*sizeof(uint32_t));
145    header -> ip_sum = sum;
146    udp_tcp_checksum(header,&wire_length);
147  }
148
149
150
151  return new_packet;
152 
153}
154
155
156
157static uint32_t event_read_packet(libtrace_t *trace, libtrace_packet_t *packet) 
158{
159        libtrace_eventobj_t obj;
160        fd_set rfds;
161        struct timeval sleep_tv;
162       
163        FD_ZERO(&rfds);
164       
165        for (;;) {
166                obj = trace_event(trace, packet);
167
168                switch(obj.type) {
169                       
170                        /* Device has no packets at present - lets wait until
171                         * it does get something */
172                        case TRACE_EVENT_IOWAIT:
173                                FD_ZERO(&rfds);
174                                FD_SET(obj.fd, &rfds);
175                                select(obj.fd + 1, &rfds, NULL, NULL, 0);
176                                continue;
177                               
178                        /* Replaying a trace in tracetime and the next packet
179                         * is not due yet */
180                        case TRACE_EVENT_SLEEP:
181                                /* select offers good precision for sleeping */
182                                sleep_tv.tv_sec = (int)obj.seconds;
183                                sleep_tv.tv_usec = (int) ((obj.seconds - sleep_tv.tv_sec) * 1000000.0);
184                                select(0, NULL, NULL, NULL, &sleep_tv);
185                                continue;
186                               
187                        /* We've got a packet! */
188                        case TRACE_EVENT_PACKET:
189                                /* Check for error first */
190                                if (obj.size == -1)
191                                        return -1;
192                                return 1;
193                               
194                        /* End of trace has been reached */
195                        case TRACE_EVENT_TERMINATE:
196                                return -1;
197                               
198                        /* An event we don't know about has occured */
199                        default:
200                                fprintf(stderr, "Unknown event type occured\n");
201                                return -1;
202                }
203        }
204}
205
206static void usage(char * argv) {
207        fprintf(stderr, "usage: %s [options] libtraceuri outputuri...\n", argv);
208        fprintf(stderr, " --filter bpfexpr\n");
209        fprintf(stderr, " -f bpfexpr\n");
210        fprintf(stderr, "\t\tApply a bpf filter expression\n");
211}
212
213/* int main(int argc, char *argv[]) {  */
214 
215/*   /\* uint16_t buffer[] = {0x45,0x00,0x00,0x30, */
216/*                     0x3b,0xa9,0x40,0x00, */
217/*                     0x6e,0x06,0x44,0x5b, */
218/*                     0x25,0xdb,0xef,0x28, */
219/*                     0x7d,0xb6,0x6a,0xb1 */
220/*                     };*\/  */
221
222/*   uint8_t buffer[] = {0x00,0x01, */
223/*                    0xf2,0x03, */
224/*                    0xf4,0xf5, */
225/*                    0xf6,0xf7 */
226/*   }; */
227
228/*   uint16_t checksum = ip_checksum(buffer,8); */
229
230/*   printf("checksum: %04X\n",checksum); */
231 
232/* } */
233
234
235int main(int argc, char *argv[]) {
236       
237        libtrace_t *trace;
238        libtrace_out_t *output;
239        libtrace_packet_t *packet;
240        libtrace_filter_t *filter=NULL;
241        int psize = 0;
242        char *uri = 0;
243
244        while(1) {
245                int option_index;
246                struct option long_options[] = {
247                        { "filter",     1, 0, 'f'},
248                        { "help",       0, 0, 'h'},
249                        { NULL,         0, 0, 0}
250                };
251
252                int c = getopt_long(argc, argv, "f:",
253                                long_options, &option_index);
254
255                if(c == -1)
256                        break;
257
258                switch (c) {
259                        case 'f':
260                                filter = trace_create_filter(optarg);
261                                break;
262                        case 'h':
263                                usage(argv[0]);
264                                return 1;
265                        default:
266                                fprintf(stderr, "Unknown option: %c\n", c);
267                }
268        }
269
270        if(optind>=argc) {
271                fprintf(stderr, "Missing input uri\n");
272                usage(argv[0]);
273                return 1;
274        }
275        if(optind+1>=argc) {
276                fprintf(stderr, "Missing output uri\n");
277                usage(argv[0]);
278                return 1;
279        }
280
281        uri = strdup(argv[optind]);
282
283        /* Create the trace */
284        trace = trace_create(uri);
285        if (trace_is_err(trace)) {
286                trace_perror(trace, "trace_create");
287                return 1;
288        }
289
290        /* apply filter */
291        if(filter) {
292                if(trace_config(trace, TRACE_OPTION_FILTER, filter)) {
293                        trace_perror(trace, "ignoring: ");
294                }
295        }
296
297        /* Starting the trace */
298        if (trace_start(trace) != 0) {
299                trace_perror(trace, "trace_start");
300                return 1;
301        }
302
303        /* Creating output trace */
304        output = trace_create_output(argv[optind+1]);
305       
306        if (trace_is_err_output(output)) {
307                trace_perror_output(output, "Opening output trace: ");
308                return 1;
309        }
310        if (trace_start_output(output)) {
311                trace_perror_output(output, "Starting output trace: ");
312                trace_destroy_output(output);
313                trace_destroy(trace);
314                return 1;
315        }
316
317        packet = trace_create_packet();
318
319        for (;;) {
320                if ((psize = event_read_packet(trace, packet)) <= 0) {
321                        break;
322                }
323
324                /* Got a packet - let's do something with it */
325                libtrace_packet_t * new = per_packet(packet);
326
327                //libtrace_ip_t * header;
328                //              header = trace_get_ip(new);
329
330                //printf("before write: %04X\n",header->ip_sum);
331               
332                if (trace_write_packet(output, new) < 0) {
333                        trace_perror_output(output, "Writing packet");
334                        trace_destroy(trace);
335                        trace_destroy_output(output);
336                        trace_destroy_packet(packet);
337                        return 1;
338                }
339                trace_destroy_packet(new);
340        }
341        free(uri);
342        trace_destroy(trace);
343        if(filter != NULL) {
344          trace_destroy_filter(filter);
345        }
346        trace_destroy_output(output);
347        trace_destroy_packet(packet);
348        return 0;
349
350}
351
Note: See TracBrowser for help on using the repository browser.