source: lib/format_duck.c @ f0fb38f

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since f0fb38f was f0fb38f, checked in by Shane Alcock <salcock@…>, 14 years ago
  • Added prepare_packet functions to all formats, primarily to support translating RT packets into the appropriate format. These functions are all used internally as well, as most formats still need to "prepare" packets that have been read by setting pointers, updating loss counters etc.
  • Also added a trace_prepare_packet function, but this is not made available externally at this stage
  • Added init_format_data functions to some formats to initialise format data structures in cases where the init_trace function does more than just that
  • Refactored rt packet reading code to use the new trace_prepare_packet functionality - also did a lot of tidying of the code
  • Added missing RT type for BPF format
  • Property mode set to 100644
File size: 9.3 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008 The University of Waikato, Hamilton, New Zealand.
5 * Authors: Daniel Lawson
6 *          Perry Lorier
7 *         
8 * All rights reserved.
9 *
10 * This code has been developed by the University of Waikato WAND
11 * research group. For further information please see http://www.wand.net.nz/
12 *
13 * libtrace is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * libtrace is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with libtrace; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 *
27 * $Id$
28 *
29 */
30
31#include "libtrace.h"
32#include "libtrace_int.h"
33#include "format_helper.h"
34#include "config.h"
35#include <stdlib.h>
36#include "libtraceio.h"
37#include "rt_protocol.h"
38
39#include <errno.h>
40#include <assert.h>
41#include <stdio.h>
42#include <fcntl.h>
43
44#define DATA(x) ((struct duck_format_data_t *)x->format_data)
45#define DATAOUT(x) ((struct duck_format_data_out_t *)x->format_data)
46
47#define INPUT DATA(libtrace)
48#define OUTPUT DATAOUT(libtrace)
49
50struct duck_format_data_t {
51        char *path;
52        libtrace_io_t *file;
53        int dag_version;
54};
55
56struct duck_format_data_out_t {
57        char *path;
58        int level;
59        int fileflag;
60        libtrace_io_t *file;
61        int dag_version;       
62};
63
64static int duck_init_input(libtrace_t *libtrace) {
65        libtrace->format_data = malloc(sizeof(struct duck_format_data_t));
66
67        INPUT->file = 0;
68        INPUT->dag_version = 0;
69        return 0;
70}
71
72static int duck_init_output(libtrace_out_t *libtrace) {
73        libtrace->format_data = malloc(sizeof(struct duck_format_data_out_t));
74       
75        OUTPUT->level = 0;
76        OUTPUT->fileflag = O_CREAT | O_WRONLY;
77        OUTPUT->file = 0;
78        OUTPUT->dag_version = 0;
79        return 0;
80}
81
82static int duck_config_output(libtrace_out_t *libtrace, 
83                                trace_option_output_t option,
84                                void *data) {
85        switch (option) {
86                case TRACE_OPTION_OUTPUT_COMPRESS:
87                        OUTPUT->level = *(int *)data;
88                        return 0;
89                case TRACE_OPTION_OUTPUT_FILEFLAGS:
90                        OUTPUT->fileflag = *(int *)data;
91                        return 0;
92                default:
93                        trace_set_err_out(libtrace, TRACE_ERR_UNKNOWN_OPTION,
94                                        "Unknown option");
95                        return -1;
96        }
97        assert(0);
98}
99
100static int duck_start_input(libtrace_t *libtrace) {
101       
102        if (INPUT->file)
103                /* File already open */
104                return 0;
105       
106        INPUT->file = trace_open_file(libtrace);
107        if (!INPUT->file)
108                return -1;
109
110        return 0;
111}
112
113static int duck_start_output(libtrace_out_t *libtrace) {
114        OUTPUT->file = trace_open_file_out(libtrace, OUTPUT->level,
115                                                OUTPUT->fileflag);
116        if (!OUTPUT->file) {
117                return -1;
118        }
119        return 0;
120}
121
122static int duck_fin_input(libtrace_t *libtrace) {
123        libtrace_io_close(INPUT->file);
124        free(libtrace->format_data);
125
126        return 0;
127}
128
129static int duck_fin_output(libtrace_out_t *libtrace) {
130        libtrace_io_close(OUTPUT->file);
131        free(libtrace->format_data);
132        return 0;
133}
134
135static int duck_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
136                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
137
138        if (packet->buffer != buffer &&
139                        packet->buf_control == TRACE_CTRL_PACKET) {
140                free(packet->buffer);
141        }
142
143        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
144                packet->buf_control = TRACE_CTRL_PACKET;
145        } else
146                packet->buf_control = TRACE_CTRL_EXTERNAL;
147
148
149        packet->buffer = buffer;
150        packet->header = NULL;
151        packet->payload = buffer;
152        packet->type = rt_type;
153
154        if (libtrace->format_data == NULL) {
155                if (duck_init_input(libtrace))
156                        return -1;
157        }
158
159        return 0;
160}
161
162static int duck_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
163
164        int numbytes = 0;
165        uint32_t version = 0;
166        unsigned int duck_size;
167        uint32_t flags = 0;
168       
169        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
170                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
171                if (!packet->buffer) {
172                        trace_set_err(libtrace, errno,
173                                        "Cannot allocate memory");
174                        return -1;
175                }
176        }
177
178        flags |= TRACE_PREP_OWN_BUFFER;
179       
180        if (INPUT->dag_version == 0) {
181                /* Read in the duck version from the start of the trace */
182                if ((numbytes = libtrace_io_read(INPUT->file, &version, 
183                                        sizeof(version))) != sizeof(uint32_t)) {
184                        trace_set_err(libtrace, errno, 
185                                        "Reading DUCK version failed");
186                        return -1;
187                }
188                if (numbytes == 0) {
189                        return 0;
190                }
191                INPUT->dag_version = bswap_le_to_host32(version);
192        }
193       
194
195        if (INPUT->dag_version == TRACE_RT_DUCK_2_4) {
196                duck_size = sizeof(duck2_4_t);
197                packet->type = TRACE_RT_DUCK_2_4;
198        } else if (INPUT->dag_version == TRACE_RT_DUCK_2_5) {
199                duck_size = sizeof(duck2_5_t);
200                packet->type = TRACE_RT_DUCK_2_5;
201        } else {
202                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
203                                "Unrecognised DUCK version %i", 
204                                INPUT->dag_version);
205                return -1;
206        }
207
208        if ((numbytes = libtrace_io_read(INPUT->file, packet->buffer,
209                                        (size_t)duck_size)) != (int)duck_size) {
210                if (numbytes == -1) {
211                        trace_set_err(libtrace, errno, "Reading DUCK failed");
212                        return -1;
213                }
214                else if (numbytes == 0) {
215                        return 0;
216                }
217                else {
218                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Truncated DUCK packet");
219                }
220        }
221
222        if (duck_prepare_packet(libtrace, packet, packet->buffer, packet->type,
223                                flags)) 
224                return -1;
225       
226        return numbytes;
227}
228
229static int duck_write_packet(libtrace_out_t *libtrace, 
230                libtrace_packet_t *packet) 
231{
232
233        int numbytes = 0;
234        if (packet->type != TRACE_RT_DUCK_2_4
235                        && packet->type != TRACE_RT_DUCK_2_5) {
236                trace_set_err_out(libtrace, TRACE_ERR_BAD_PACKET,
237                                "Only DUCK packets may be written to a DUCK file");
238                return -1;
239        }
240       
241        assert(OUTPUT->file);
242
243        if (OUTPUT->dag_version == 0) {
244        /* Writing the DUCK version will help with reading it back in later! */
245                if ((numbytes = libtrace_io_write(OUTPUT->file, &packet->type,
246                                sizeof(packet->type))) != sizeof(uint32_t)){
247                        trace_set_err_out(libtrace, errno, 
248                                        "Writing DUCK version failed");
249                        return -1;
250                }
251                OUTPUT->dag_version = packet->type;
252        }
253       
254        if ((numbytes = libtrace_io_write(OUTPUT->file, packet->payload, 
255                                        trace_get_capture_length(packet))) !=
256                                (int)trace_get_capture_length(packet)) {
257                trace_set_err_out(libtrace, errno, "Writing DUCK failed");
258                return -1;
259        }
260        return numbytes;
261}
262
263static int duck_get_capture_length(const libtrace_packet_t *packet) {
264        switch(packet->type) {
265                case TRACE_RT_DUCK_2_4:
266                        return sizeof(duck2_4_t);
267                case TRACE_RT_DUCK_2_5:
268                        return sizeof(duck2_5_t);
269                default:
270                        trace_set_err(packet->trace,TRACE_ERR_BAD_PACKET,
271                                        "Not a duck packet");
272                        return -1;
273        }
274        return 0;
275}
276
277static int duck_get_framing_length(const libtrace_packet_t *packet UNUSED) 
278{
279        return 0;
280}
281
282static int duck_get_wire_length(const libtrace_packet_t *packet UNUSED) 
283{
284        return 0;
285}
286
287static libtrace_linktype_t duck_get_link_type(
288                                const libtrace_packet_t *packet UNUSED) 
289{
290        return TRACE_TYPE_DUCK;
291}
292
293static void duck_help(void) {
294        printf("Endace DUCK format module\n");
295        printf("Supported input uris:\n");
296        printf("\tduck:/path/to/input/file\n");
297        printf("Supported output uris:\n");
298        printf("\tduck:/path/to/output/file\n");
299        printf("\n");
300        return;
301}
302static struct libtrace_format_t duck = {
303        "duck",
304        "$Id$",
305        TRACE_FORMAT_DUCK,
306        duck_init_input,                /* init_input */
307        NULL,                           /* config_input */
308        duck_start_input,               /* start_input */
309        NULL,                           /* pause_input */
310        duck_init_output,               /* init_output */
311        duck_config_output,             /* config_output */
312        duck_start_output,              /* start_output */
313        duck_fin_input,                 /* fin_input */
314        duck_fin_output,                /* fin_output */
315        duck_read_packet,               /* read_packet */
316        duck_prepare_packet,            /* prepare_packet */
317        NULL,                           /* fin_packet */
318        duck_write_packet,              /* write_packet */
319        duck_get_link_type,             /* get_link_type */
320        NULL,                           /* get_direction */
321        NULL,                           /* set_direction */
322        NULL,                           /* get_erf_timestamp */
323        NULL,                           /* get_timeval */
324        NULL,                           /* get_seconds */
325        NULL,                           /* seek_erf */
326        NULL,                           /* seek_timeval */
327        NULL,                           /* seek_seconds */
328        duck_get_capture_length,        /* get_capture_length */
329        duck_get_wire_length,           /* get_wire_length */
330        duck_get_framing_length,        /* get_framing_length */
331        NULL,                           /* set_capture_length */
332        NULL,                           /* get_received_packets */
333        NULL,                           /* get_filtered_packets */
334        NULL,                           /* get_dropped_packets */
335        NULL,                           /* get_captured_packets */
336        NULL,                           /* get_fd */
337        NULL,                           /* trace_event */
338        duck_help,                      /* help */
339        NULL                            /* next pointer */
340};
341
342void duck_constructor(void) {
343        register_format(&duck);
344}       
Note: See TracBrowser for help on using the repository browser.