source: tools/tracereplay/tracereplay.c @ c8e8122

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

added a function to calculate checksums

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