source: tools/tracereplay/tracereplay.c @ effd683

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

still b0rken, was a missing '+'

  • Property mode set to 100644
File size: 7.4 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
30
31
32/* This function assumes that the relevant fields have been zeroed out. RFC 1071*/
33static uint16_t checksum(void * buffer, uint16_t length) {
34  uint32_t sum = 0;
35  uint16_t * buff = (uint16_t *) buffer;
36  uint16_t count = length;
37
38  while(count > 1 ) {
39    sum += *buff++;
40    count = count -2;
41  }
42
43  if(count > 0) {
44    sum += *buff;
45  }
46 
47  while (sum>>16)
48    sum = (sum & 0xffff) + (sum >> 16);
49
50  return ~sum;
51}
52
53static void udp_tcp_checksum(libtrace_ip_t *ip, uint32_t length) {
54
55  uint32_t remaining = 0;
56
57  uint32_t sum = 0;
58 
59  uint16_t protocol = ip->ip_p;
60
61  uint16_t temp = 0;
62
63  uint16_t * check = NULL;
64  uint16_t tsum = 0;
65
66
67  sum += ~checksum(&ip->ip_src.s_addr,sizeof(uint32_t));
68  sum += ~checksum(&ip->ip_dst.s_addr,sizeof(uint32_t));
69
70  temp = htons(protocol);
71
72  sum += ~checksum(&temp,sizeof(uint16_t));
73
74  temp = htons(length);
75  sum += ~checksum(&temp,sizeof(uint16_t));
76
77
78  printf("IP payload length: %d\n",length);
79 
80  void * transportheader = trace_get_payload_from_ip(ip,NULL,NULL);
81
82
83  printf("proto: %d\n",ip->ip_p);
84
85  if(protocol == 17 ) {
86    libtrace_udp_t * udp_header = transportheader;
87    printf("udp  length: %d\n",ntohs(udp_header -> len));
88    check = &udp_header -> check;
89    *check = 0;
90    printf("l3 payload length: %d\n",length); 
91    tsum = checksum(transportheader, length);
92  }
93  else if(protocol == 6) {
94    libtrace_tcp_t * tcp_header = transportheader;
95    tcp_header -> check = 0;
96    check = &tcp_header -> check;
97
98    //use tcp header length and datagram length instead
99    tsum = checksum(transportheader,length);
100  }
101
102
103  printf("tsum: %04X\n", tsum);
104
105  sum += ~tsum;
106
107  while (sum>>16)
108    sum = (sum & 0xffff) + (sum >> 16);
109 
110  if(check != NULL) {
111    *check = (uint16_t)~sum;
112    printf("checksum: %04X\n",*check);
113  }
114 
115
116
117}
118
119
120static libtrace_packet_t * per_packet(libtrace_packet_t *packet) {
121  uint32_t remaining = 0; 
122  libtrace_linktype_t linktype = 0;
123  void * pkt_buffer = trace_get_packet_buffer(packet,&linktype,&remaining);
124  remaining = 0;
125  libtrace_ip_t * header = NULL;
126  uint16_t sum = 0;
127  libtrace_packet_t *new_packet = trace_create_packet();
128 
129  size_t wire_length = trace_get_wire_length(packet);
130
131  printf("wire length: %d\n",wire_length);
132
133  if(linktype == TRACE_TYPE_ETH || linktype == TRACE_TYPE_80211) {
134    wire_length -= FCS_SIZE;
135  }
136
137  printf("wire length after FCS: %d\n",wire_length);
138
139  trace_construct_packet(new_packet,linktype,pkt_buffer,wire_length);
140 
141
142  header = trace_get_ip(new_packet);
143  if(header != NULL) {
144    wire_length -= sizeof(uint32_t)*header->ip_hl;
145    header -> ip_sum = 0;
146    sum = checksum(header,header->ip_hl*sizeof(uint32_t));
147    header -> ip_sum = sum;
148    udp_tcp_checksum(header,ntohs(header->ip_len) - sizeof(uint32_t)*header->ip_hl);
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.