source: lib/format_duck.c @ e4f27d1

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since e4f27d1 was 5ab626a, checked in by Richard Sanger <rsangerarj@…>, 7 years ago

Deprecate trace_get_filtered/accepted/recevied/dropped() in favour of a single function

Adds the single trace_get_statistics function. This allows the structure to be filled
at a point in time, rather than making multiple calls to the library during which state
might have changed.

This has been designed such that the structure can be added to in the future without
breaking old code.

The old internal get_captured_packets was removed from the formats as it was never used.
Eventually we should completely remove get_filtered and received from the formats and replace
them with get_statistics.

In additon some extra fields have added, such as error and captured and the pre-existing
fields are better defined.

The linux formats have been updated to use this new API, which combined with reading
/proc/net/dev returns a full set of statistics.

  • Property mode set to 100644
File size: 10.3 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 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.