source: lib/format_tsh.c @ 5ab626a

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 5ab626a was 5ab626a, checked in by Richard Sanger <rsangerarj@…>, 6 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: 8.9 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
35#include "config.h"
36#include "common.h"
37#include "libtrace.h"
38#include "libtrace_int.h"
39#include "format_helper.h"
40
41#include <assert.h>
42#include <errno.h>
43#include <fcntl.h>
44#include <stdio.h>
45#include <string.h>
46#include <stdlib.h>
47
48/* This format module deals with reading traces that are in the TSH format.
49 *
50 * We do not support writing TSH traces, because it's a pretty rubbish format.
51 */
52
53static struct libtrace_format_t tshformat;
54
55typedef struct tsh_pkt_header_t {
56        uint32_t seconds;
57        uint32_t usecs;
58} tsh_pkt_header_t;
59
60static int tsh_get_framing_length(const libtrace_packet_t *packet UNUSED)
61{
62        return sizeof(tsh_pkt_header_t);
63}
64
65
66static int tsh_init_input(libtrace_t *libtrace) 
67{
68        libtrace->format_data = NULL; /* No format data */
69       
70        return 0; /* success */
71}
72
73static int tsh_start_input(libtrace_t *libtrace)
74{
75        if (libtrace->io)
76                return 0; /* success */
77
78        libtrace->io = trace_open_file(libtrace);
79
80        if (!libtrace->io)
81                return -1;
82
83        return 0; /* success */
84}
85
86static int tsh_fin_input(libtrace_t *libtrace) {
87        if (libtrace->io)
88                wandio_destroy(libtrace->io);
89        return 0;
90}
91
92static int tsh_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
93                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
94        if (packet->buffer != buffer &&
95                        packet->buf_control == TRACE_CTRL_PACKET) {
96                free(packet->buffer);
97        }
98
99        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
100                packet->buf_control = TRACE_CTRL_PACKET;
101        } else
102                packet->buf_control = TRACE_CTRL_EXTERNAL;
103
104
105        packet->buffer = buffer;
106        packet->header = buffer;
107        packet->type = rt_type;
108        packet->payload = (char *)packet->buffer + sizeof(tsh_pkt_header_t);
109
110        if (libtrace->format_data == NULL) {
111                if (tsh_init_input(libtrace))
112                        return -1;
113        }
114
115        return 0;
116}
117
118static int tsh_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
119        int numbytes;
120        void *buffer2 = packet->buffer;
121        uint32_t flags = 0;
122
123        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
124                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
125                if (!packet->buffer) {
126                        trace_set_err(libtrace, errno, 
127                                        "Cannot allocate memory");
128                        return -1;
129                }
130        }
131
132        flags |= TRACE_PREP_OWN_BUFFER;
133        packet->type = TRACE_RT_DATA_TSH;
134
135        buffer2 = packet->buffer;
136
137        /* Read the TSH header */
138        if ((numbytes=wandio_read(libtrace->io,
139                                        buffer2,
140                                        (size_t)sizeof(tsh_pkt_header_t))) == -1) {
141                trace_set_err(libtrace,errno,"read(%s)",
142                                libtrace->uridata);
143                return -1;
144        }
145        /* EOF */
146        if (numbytes == 0) {
147                return 0;
148        }
149
150        if (numbytes < (int)sizeof(tsh_pkt_header_t)) {
151                trace_set_err(libtrace, errno, "Incomplete TSH header");
152                return -1;
153        }
154
155        buffer2 = (char*)buffer2 + numbytes;
156
157        /* Read the IP header */
158        if ((numbytes=wandio_read(libtrace->io,
159                                buffer2,
160                                (size_t)sizeof(libtrace_ip_t)+16))  /* 16 bytes of transport header */
161                        != sizeof(libtrace_ip_t)+16) {
162                trace_set_err(libtrace,errno,"read(%s)",
163                                libtrace->uridata);
164                return -1;
165        }
166
167#if 0
168        /* IP Options aren't captured in the trace, so leave room
169         * for them, and put the transport header where it "should" be
170         */
171        buffer2 = (char*)buffer2 + ((libtrace_ip_t*)buffer2)->ip_hl*4;
172
173        /* Read the transport header */
174        if ((numbytes=wandio_read(libtrace->io,
175                                buffer2,
176                                16)) != 16) {
177                trace_set_err(libtrace,errno,"read(%s)",
178                                libtrace->uridata);
179                return -1;
180        }
181#endif
182       
183        if (tsh_prepare_packet(libtrace, packet, packet->buffer, packet->type, 
184                                flags)) {
185                return -1;
186        }
187
188
189        return 80;
190}
191
192static libtrace_linktype_t tsh_get_link_type(const libtrace_packet_t *packet UNUSED) {
193        return TRACE_TYPE_NONE;
194}
195
196static libtrace_direction_t tsh_get_direction(const libtrace_packet_t *packet) {
197        return ntohl(((tsh_pkt_header_t*)(packet->header))->usecs & htonl(0xFF000000)) >> 24;
198}
199
200static struct timeval tsh_get_timeval(const libtrace_packet_t *packet)
201{
202        struct timeval tv;
203        tv.tv_sec=ntohl(((tsh_pkt_header_t*)(packet->header))->seconds);
204        tv.tv_usec=ntohl(((tsh_pkt_header_t*)(packet->header))->usecs & htonl(0x00FFFFFF));
205
206        return tv;
207}
208
209static int tsh_get_capture_length(const libtrace_packet_t *packet UNUSED) {
210        /* 16 bytes transport + 24 bytes IP, and we're missing the
211         * IP options, but we'll pretend we have them
212         */
213#if 0
214        return 16+((libtrace_ip_t*)packet->payload)->ip_hl*4;
215#else
216        return 16+sizeof(libtrace_ip_t);
217#endif
218}
219
220static int tsh_get_wire_length(const libtrace_packet_t *packet) {
221        return ntohs(((libtrace_ip_t*)packet->payload)->ip_len);
222}
223
224static void tsh_help(void) {
225        printf("tsh format module: $Revision: 1611 $\n");
226        printf("Supported input URIs:\n");
227        printf("\ttsh:/path/to/file\t(uncompressed)\n");
228        printf("\ttsh:/path/to/file.gz\t(gzip-compressed)\n");
229        printf("\ttsh:-\t(stdin, either compressed or not)\n");
230        printf("\ttsh:/path/to/socket\n");
231        printf("\n");
232        printf("\te.g.: erf:/tmp/trace\n");
233        printf("\n");
234}
235
236static struct libtrace_format_t tshformat = {
237        "tsh",
238        "$Id$",
239        TRACE_FORMAT_TSH,
240        NULL,                           /* probe filename */
241        NULL,                           /* probe magic */
242        tsh_init_input,                 /* init_input */       
243        NULL,                           /* config_input */
244        tsh_start_input,                /* start_input */
245        NULL,                           /* pause_input */
246        NULL,                           /* init_output */
247        NULL,                           /* config_output */
248        NULL,                           /* start_output */
249        tsh_fin_input,                  /* fin_input */
250        NULL,                           /* fin_output */
251        tsh_read_packet,                /* read_packet */
252        tsh_prepare_packet,             /* prepare_packet */
253        NULL,                           /* fin_packet */
254        NULL,                           /* write_packet */
255        tsh_get_link_type,              /* get_link_type */
256        tsh_get_direction,              /* get_direction */
257        NULL,                           /* set_direction */
258        NULL,                           /* get_erf_timestamp */
259        tsh_get_timeval,                /* get_timeval */
260        NULL,                           /* get_timespec */
261        NULL,                           /* get_seconds */
262        NULL,                           /* seek_erf */
263        NULL,                           /* seek_timeval */
264        NULL,                           /* seek_seconds */
265        tsh_get_capture_length,         /* get_capture_length */
266        tsh_get_wire_length,            /* get_wire_length */
267        tsh_get_framing_length,         /* get_framing_length */
268        NULL,                           /* set_capture_length */
269        NULL,                           /* get_received_packets */
270        NULL,                           /* get_filtered_packets */
271        NULL,                           /* get_dropped_packets */
272        NULL,                           /* get_statistics */
273        NULL,                           /* get_fd */
274        trace_event_trace,              /* trace_event */
275        tsh_help,                       /* help */
276        NULL,                   /* next pointer */
277        NON_PARALLEL(false)
278};
279
280/* the tsh header format is the same as tsh, except that the bits that will
281 * always be "0" in the fr+ format are used for an "interface" identifier,
282 * thus on tr+ traces, this will always be 0.  So, we use the exact same
283 * decoder for both traces.
284 */
285static struct libtrace_format_t frplusformat = {
286        "fr+",
287        "$Id$",
288        TRACE_FORMAT_TSH,
289        NULL,                           /* probe filename */
290        NULL,                           /* probe magic */
291        tsh_init_input,                 /* init_input */       
292        NULL,                           /* config_input */
293        tsh_start_input,                /* start_input */
294        NULL,                           /* pause_input */
295        NULL,                           /* init_output */
296        NULL,                           /* config_output */
297        NULL,                           /* start_output */
298        tsh_fin_input,                  /* fin_input */
299        NULL,                           /* fin_output */
300        tsh_read_packet,                /* read_packet */
301        tsh_prepare_packet,             /* prepare_packet */
302        NULL,                           /* fin_packet */
303        NULL,                           /* write_packet */
304        tsh_get_link_type,              /* get_link_type */
305        tsh_get_direction,              /* get_direction */
306        NULL,                           /* set_direction */
307        NULL,                           /* get_erf_timestamp */
308        tsh_get_timeval,                /* get_timeval */
309        NULL,                           /* get_timespec */
310        NULL,                           /* get_seconds */
311        NULL,                           /* seek_erf */
312        NULL,                           /* seek_timeval */
313        NULL,                           /* seek_seconds */
314        tsh_get_capture_length,         /* get_capture_length */
315        tsh_get_wire_length,            /* get_wire_length */
316        tsh_get_framing_length,         /* get_framing_length */
317        NULL,                           /* set_capture_length */
318        NULL,                           /* get_received_packets */
319        NULL,                           /* get_filtered_packets */
320        NULL,                           /* get_dropped_packets */
321        NULL,                           /* get_statistics */
322        NULL,                           /* get_fd */
323        trace_event_trace,              /* trace_event */
324        tsh_help,                       /* help */
325        NULL,                   /* next pointer */
326        NON_PARALLEL(false)
327};
328
329void tsh_constructor(void) {
330        register_format(&tshformat);
331        register_format(&frplusformat);
332}
Note: See TracBrowser for help on using the repository browser.