source: tools/tracereplay/tracereplay.c @ c988da9

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

rewrote the checksum function

  • Property mode set to 100644
File size: 5.1 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 crc 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  //printf("length: %d\n",length);
32  uint32_t sum = 0;
33  uint16_t * buff = (uint16_t *) buffer;
34  uint16_t i;
35  uint16_t result;
36
37  for (i=0;i<length;i=i+2) {
38    sum += ~ntohs(buff[i]);
39  }
40 
41  result = sum;
42  result += sum >> 16;
43
44  return ~sum;
45}
46
47
48static libtrace_packet_t * per_packet(libtrace_packet_t *packet) {
49 
50  uint32_t remaining;
51  libtrace_linktype_t linktype;
52  void * pkt_buffer = trace_get_packet_buffer(packet,&linktype,&remaining);
53  libtrace_packet_t *new_packet = trace_create_packet();
54
55  size_t wire_length = trace_get_wire_length(packet);
56
57  libtrace_ip_t * header;
58
59  if(linktype == TRACE_TYPE_ETH || linktype == TRACE_TYPE_80211) {
60    wire_length -= FCS_SIZE;
61  }
62
63  trace_construct_packet(new_packet,linktype,pkt_buffer,wire_length);
64 
65
66  header = trace_get_ip(new_packet);
67  if(header != NULL) {
68    header -> ip_sum = 0;
69    header -> ip_sum = htons(checksum(header,header->ip_hl*4));
70  }
71
72  return new_packet;
73 
74}
75
76
77
78static uint32_t event_read_packet(libtrace_t *trace, libtrace_packet_t *packet) 
79{
80        libtrace_eventobj_t obj;
81        fd_set rfds;
82        struct timeval sleep_tv;
83       
84        FD_ZERO(&rfds);
85       
86        for (;;) {
87                obj = trace_event(trace, packet);
88
89                switch(obj.type) {
90                       
91                        /* Device has no packets at present - lets wait until
92                         * it does get something */
93                        case TRACE_EVENT_IOWAIT:
94                                FD_ZERO(&rfds);
95                                FD_SET(obj.fd, &rfds);
96                                select(obj.fd + 1, &rfds, NULL, NULL, 0);
97                                continue;
98                               
99                        /* Replaying a trace in tracetime and the next packet
100                         * is not due yet */
101                        case TRACE_EVENT_SLEEP:
102                                /* select offers good precision for sleeping */
103                                sleep_tv.tv_sec = (int)obj.seconds;
104                                sleep_tv.tv_usec = (int) ((obj.seconds - sleep_tv.tv_sec) * 1000000.0);
105                                select(0, NULL, NULL, NULL, &sleep_tv);
106                                continue;
107                               
108                        /* We've got a packet! */
109                        case TRACE_EVENT_PACKET:
110                                /* Check for error first */
111                                if (obj.size == -1)
112                                        return -1;
113                                return 1;
114                               
115                        /* End of trace has been reached */
116                        case TRACE_EVENT_TERMINATE:
117                                return -1;
118                               
119                        /* An event we don't know about has occured */
120                        default:
121                                fprintf(stderr, "Unknown event type occured\n");
122                                return -1;
123                }
124        }
125}
126
127static void usage(char * argv) {
128        fprintf(stderr, "usage: %s [options] libtraceuri outputuri...\n", argv);
129        fprintf(stderr, " --filter bpfexpr\n");
130        fprintf(stderr, " -f bpfexpr\n");
131        fprintf(stderr, "\t\tApply a bpf filter expression\n");
132}
133
134int main(int argc, char *argv[]) {
135       
136        libtrace_t *trace;
137        libtrace_out_t *output;
138        libtrace_packet_t *packet;
139        libtrace_filter_t *filter=NULL;
140        int psize = 0;
141        char *uri = 0;
142
143        while(1) {
144                int option_index;
145                struct option long_options[] = {
146                        { "filter",     1, 0, 'f'},
147                        { "help",       0, 0, 'h'},
148                        { NULL,         0, 0, 0}
149                };
150
151                int c = getopt_long(argc, argv, "f:",
152                                long_options, &option_index);
153
154                if(c == -1)
155                        break;
156
157                switch (c) {
158                        case 'f':
159                                filter = trace_create_filter(optarg);
160                                break;
161                        case 'h':
162                                usage(argv[0]);
163                                return 1;
164                        default:
165                                fprintf(stderr, "Unknown option: %c\n", c);
166                }
167        }
168
169        if(optind>=argc) {
170                fprintf(stderr, "Missing input uri\n");
171                usage(argv[0]);
172                return 1;
173        }
174        if(optind+1>=argc) {
175                fprintf(stderr, "Missing output uri\n");
176                usage(argv[0]);
177                return 1;
178        }
179
180        uri = strdup(argv[optind]);
181
182        /* Create the trace */
183        trace = trace_create(uri);
184        if (trace_is_err(trace)) {
185                trace_perror(trace, "trace_create");
186                return 1;
187        }
188
189        /* apply filter */
190        if(filter) {
191                if(trace_config(trace, TRACE_OPTION_FILTER, filter)) {
192                        trace_perror(trace, "ignoring: ");
193                }
194        }
195
196        /* Starting the trace */
197        if (trace_start(trace) != 0) {
198                trace_perror(trace, "trace_start");
199                return 1;
200        }
201
202        /* Creating output trace */
203        output = trace_create_output(argv[optind+1]);
204       
205        if (trace_is_err_output(output)) {
206                trace_perror_output(output, "Opening output trace: ");
207                return 1;
208        }
209        if (trace_start_output(output)) {
210                trace_perror_output(output, "Starting output trace: ");
211                trace_destroy_output(output);
212                trace_destroy(trace);
213                return 1;
214        }
215
216        packet = trace_create_packet();
217
218        for (;;) {
219                if ((psize = event_read_packet(trace, packet)) <= 0) {
220                        break;
221                }
222
223                /* Got a packet - let's do something with it */
224                libtrace_packet_t * new = per_packet(packet);
225
226                if (trace_write_packet(output, new) < 0) {
227                        trace_perror_output(output, "Writing packet");
228                        trace_destroy(trace);
229                        trace_destroy_output(output);
230                        trace_destroy_packet(packet);
231                        return 1;
232                }
233                trace_destroy_packet(new);
234        }
235        free(uri);
236        trace_destroy(trace);
237        if(filter != NULL) {
238          trace_destroy_filter(filter);
239        }
240        trace_destroy_output(output);
241        trace_destroy_packet(packet);
242        return 0;
243
244}
Note: See TracBrowser for help on using the repository browser.