source: tools/tracereplay/tracereplay.c @ 47a5c5e

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

created toplevel comments

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