source: tools/tracereplay/tracereplay.c @ 58e2f74

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

cleaned up code.

Works now.

Might be necessary to change the destination MAC addresses as well.

  • 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
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 sum = 0;
56  uint16_t protocol = ip->ip_p;
57  uint16_t temp = 0;
58  uint16_t * check = NULL;
59  uint16_t tsum = 0;
60
61
62  sum += (uint16_t) ~checksum(&ip->ip_src.s_addr,sizeof(uint32_t));
63  sum += (uint16_t) ~checksum(&ip->ip_dst.s_addr,sizeof(uint32_t));
64
65
66  /*this will be in host order whereas everything else is in network order*/
67  temp = htons(protocol);
68  sum += (uint16_t) ~checksum(&temp,sizeof(uint16_t));
69
70  /*this will be in host order whereas everything else is in network order*/
71  temp = htons(length);
72  sum += (uint16_t) ~checksum(&temp,sizeof(uint16_t));
73
74  void * transportheader = trace_get_payload_from_ip(ip,NULL,NULL);
75
76  if(protocol == 17 ) {
77    libtrace_udp_t * udp_header = transportheader;
78    check = &udp_header -> check;
79    *check = 0;
80    tsum = checksum(transportheader, length);
81  }
82  else if(protocol == 6) {
83    libtrace_tcp_t * tcp_header = transportheader;
84    tcp_header -> check = 0;
85    check = &tcp_header -> check;
86    *check = 0;
87    tsum = checksum(transportheader,length);
88  }
89
90  sum += (uint16_t) ~tsum;
91
92  while (sum>>16)
93    sum = (sum & 0xffff) + (sum >> 16);
94
95  if(check != NULL) {
96    *check = (uint16_t)~sum;
97  }
98 
99
100
101}
102
103
104static libtrace_packet_t * per_packet(libtrace_packet_t *packet) {
105  uint32_t remaining = 0; 
106  libtrace_linktype_t linktype = 0;
107  void * pkt_buffer = trace_get_packet_buffer(packet,&linktype,&remaining);
108  remaining = 0;
109  libtrace_ip_t * header = NULL;
110  uint16_t sum = 0;
111  libtrace_packet_t *new_packet = trace_create_packet();
112 
113  size_t wire_length = trace_get_wire_length(packet);
114
115  if(linktype == TRACE_TYPE_ETH || linktype == TRACE_TYPE_80211) {
116    wire_length -= FCS_SIZE;
117  }
118
119  trace_construct_packet(new_packet,linktype,pkt_buffer,wire_length);
120 
121
122  header = trace_get_ip(new_packet);
123  if(header != NULL) {
124    wire_length -= sizeof(uint32_t)*header->ip_hl;
125    header -> ip_sum = 0;
126    sum = checksum(header,header->ip_hl*sizeof(uint32_t));
127    header -> ip_sum = sum;
128    udp_tcp_checksum(header,ntohs(header->ip_len)-sizeof(uint32_t)*header->ip_hl);
129  }
130
131  return new_packet;
132 
133}
134
135
136
137static uint32_t event_read_packet(libtrace_t *trace, libtrace_packet_t *packet) 
138{
139        libtrace_eventobj_t obj;
140        fd_set rfds;
141        struct timeval sleep_tv;
142       
143        FD_ZERO(&rfds);
144       
145        for (;;) {
146                obj = trace_event(trace, packet);
147
148                switch(obj.type) {
149                       
150                        /* Device has no packets at present - lets wait until
151                         * it does get something */
152                        case TRACE_EVENT_IOWAIT:
153                                FD_ZERO(&rfds);
154                                FD_SET(obj.fd, &rfds);
155                                select(obj.fd + 1, &rfds, NULL, NULL, 0);
156                                continue;
157                               
158                        /* Replaying a trace in tracetime and the next packet
159                         * is not due yet */
160                        case TRACE_EVENT_SLEEP:
161                                /* select offers good precision for sleeping */
162                                sleep_tv.tv_sec = (int)obj.seconds;
163                                sleep_tv.tv_usec = (int) ((obj.seconds - sleep_tv.tv_sec) * 1000000.0);
164                                select(0, NULL, NULL, NULL, &sleep_tv);
165                                continue;
166                               
167                        /* We've got a packet! */
168                        case TRACE_EVENT_PACKET:
169                                /* Check for error first */
170                                if (obj.size == -1)
171                                        return -1;
172                                return 1;
173                               
174                        /* End of trace has been reached */
175                        case TRACE_EVENT_TERMINATE:
176                                return -1;
177                               
178                        /* An event we don't know about has occured */
179                        default:
180                                fprintf(stderr, "Unknown event type occured\n");
181                                return -1;
182                }
183        }
184}
185
186static void usage(char * argv) {
187        fprintf(stderr, "usage: %s [options] libtraceuri outputuri...\n", argv);
188        fprintf(stderr, " --filter bpfexpr\n");
189        fprintf(stderr, " -f bpfexpr\n");
190        fprintf(stderr, "\t\tApply a bpf filter expression\n");
191}
192
193int main(int argc, char *argv[]) {
194       
195        libtrace_t *trace;
196        libtrace_out_t *output;
197        libtrace_packet_t *packet;
198        libtrace_filter_t *filter=NULL;
199        int psize = 0;
200        char *uri = 0;
201
202        while(1) {
203                int option_index;
204                struct option long_options[] = {
205                        { "filter",     1, 0, 'f'},
206                        { "help",       0, 0, 'h'},
207                        { NULL,         0, 0, 0}
208                };
209
210                int c = getopt_long(argc, argv, "f:",
211                                long_options, &option_index);
212
213                if(c == -1)
214                        break;
215
216                switch (c) {
217                        case 'f':
218                                filter = trace_create_filter(optarg);
219                                break;
220                        case 'h':
221                                usage(argv[0]);
222                                return 1;
223                        default:
224                                fprintf(stderr, "Unknown option: %c\n", c);
225                }
226        }
227
228        if(optind>=argc) {
229                fprintf(stderr, "Missing input uri\n");
230                usage(argv[0]);
231                return 1;
232        }
233        if(optind+1>=argc) {
234                fprintf(stderr, "Missing output uri\n");
235                usage(argv[0]);
236                return 1;
237        }
238
239        uri = strdup(argv[optind]);
240
241        /* Create the trace */
242        trace = trace_create(uri);
243        if (trace_is_err(trace)) {
244                trace_perror(trace, "trace_create");
245                return 1;
246        }
247
248        /* apply filter */
249        if(filter) {
250                if(trace_config(trace, TRACE_OPTION_FILTER, filter)) {
251                        trace_perror(trace, "ignoring: ");
252                }
253        }
254
255        /* Starting the trace */
256        if (trace_start(trace) != 0) {
257                trace_perror(trace, "trace_start");
258                return 1;
259        }
260
261        /* Creating output trace */
262        output = trace_create_output(argv[optind+1]);
263       
264        if (trace_is_err_output(output)) {
265                trace_perror_output(output, "Opening output trace: ");
266                return 1;
267        }
268        if (trace_start_output(output)) {
269                trace_perror_output(output, "Starting output trace: ");
270                trace_destroy_output(output);
271                trace_destroy(trace);
272                return 1;
273        }
274
275        packet = trace_create_packet();
276
277        for (;;) {
278                if ((psize = event_read_packet(trace, packet)) <= 0) {
279                        break;
280                }
281
282                /* Got a packet - let's do something with it */
283                libtrace_packet_t * new = per_packet(packet);
284
285                if (trace_write_packet(output, new) < 0) {
286                        trace_perror_output(output, "Writing packet");
287                        trace_destroy(trace);
288                        trace_destroy_output(output);
289                        trace_destroy_packet(packet);
290                        return 1;
291                }
292                trace_destroy_packet(new);
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.