source: lib/format_duck.c @ 21c0d70

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 21c0d70 was d8b05b7, checked in by Shane Alcock <salcock@…>, 6 years ago

Make sure our copyright covers recent years

Consistency across all of our source files is also nice.

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