source: tools/tracereplay/tracereplay.c @ 43351e9

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

working on getting udp and tcp checksums going. Seem to have broken ip checksums again, works fine when I use trace_get_ip instead of trace_get_layer3 though.

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