source: lib/format_dag24.c @ a81d2fc

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since a81d2fc was 5798dc6, checked in by Shane Alcock <salcock@…>, 14 years ago
  • Changed DAG 2.5 code to force it to call dag_advance_stream if it has read 4MB without doing so. This is to ensure that the processed records get freed regularly.
  • Changed a couple of internal functions in format_dag24 to be static, which fixes some warnings
  • Changed the wording of the configure message that checks for DAG2.4 after failing to find DAG 2.5 or later to make it obvious that we aren't trying to do the same thing twice (and getting inconsistent results!)
  • Property mode set to 100644
File size: 12.2 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007 The University of Waikato, Hamilton, New Zealand.
5 * Authors: Daniel Lawson
6 *          Perry Lorier
7 *          Shane Alcock
8 *
9 * All rights reserved.
10 *
11 * This code has been developed by the University of Waikato WAND
12 * research group. For further information please see http://www.wand.net.nz/
13 *
14 * libtrace is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * libtrace is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with libtrace; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27 *
28 * $Id$
29 *
30 */
31#define _GNU_SOURCE
32
33#include "config.h"
34#include "common.h"
35#include "libtrace.h"
36#include "libtrace_int.h"
37#include "format_helper.h"
38#include "format_erf.h"
39
40#include <assert.h>
41#include <errno.h>
42#include <fcntl.h>
43#include <stdio.h>
44#include <string.h>
45#include <stdlib.h>
46
47#include <sys/mman.h>
48#ifdef WIN32
49#  include <io.h>
50#  include <share.h>
51#  define PATH_MAX _MAX_PATH
52#  define snprintf sprintf_s
53#else
54#  include <netdb.h>
55#  ifndef PATH_MAX
56#       define PATH_MAX 4096
57#  endif
58#  include <sys/ioctl.h>
59#endif
60
61
62static struct libtrace_format_t dag;
63
64#define DATA(x) ((struct dag_format_data_t *)x->format_data)
65#define DUCK DATA(libtrace)->duck
66#define FORMAT_DATA DATA(libtrace)
67
68struct dag_format_data_t {
69        struct {
70                uint32_t last_duck;
71                uint32_t duck_freq;
72                uint32_t last_pkt;
73                libtrace_t *dummy_duck;
74        } duck; 
75       
76        int fd;
77        void *buf;
78        uint32_t diff;
79        uint32_t offset;
80        uint32_t bottom;
81        uint32_t top;
82};
83
84static int dag_available(libtrace_t *libtrace) {
85
86        if (FORMAT_DATA->diff > 0)
87                return FORMAT_DATA->diff;
88
89        FORMAT_DATA->bottom = FORMAT_DATA->top;
90        FORMAT_DATA->top = dag_offset(
91                        FORMAT_DATA->fd,
92                        &(FORMAT_DATA->bottom),
93                        DAGF_NONBLOCK);
94        FORMAT_DATA->diff = FORMAT_DATA->top - FORMAT_DATA->bottom;
95        FORMAT_DATA->offset = 0;
96        return FORMAT_DATA->diff;
97}
98
99static int dag_init_input(libtrace_t *libtrace) {
100        struct stat buf;
101        libtrace->format_data = (struct dag_format_data_t *)
102                malloc(sizeof(struct dag_format_data_t));
103        if (stat(libtrace->uridata, &buf) == -1) {
104                trace_set_err(libtrace,errno,"stat(%s)",libtrace->uridata);
105                return -1;
106        }
107
108        FORMAT_DATA->top = 0;
109        FORMAT_DATA->bottom = 0;
110        if (S_ISCHR(buf.st_mode)) {
111                /* DEVICE */
112                if((FORMAT_DATA->fd = dag_open(libtrace->uridata)) < 0) {
113                        trace_set_err(libtrace,errno,"Cannot open DAG %s",
114                                        libtrace->uridata);
115                        return -1;
116                }
117                if((FORMAT_DATA->buf = (void *)dag_mmap(FORMAT_DATA->fd)) == MAP_FAILED) {
118                        trace_set_err(libtrace,errno,"Cannot mmap DAG %s",
119                                        libtrace->uridata);
120                        return -1;
121                }
122        } else {
123                trace_set_err(libtrace,errno,"Not a valid dag device: %s",
124                                libtrace->uridata);
125                return -1;
126        }
127
128        DUCK.last_duck = 0;
129        DUCK.duck_freq = 0;
130        DUCK.last_pkt = 0;
131        DUCK.dummy_duck = NULL;
132
133        return 0;
134}
135
136static int dag_config_input(libtrace_t *libtrace, trace_option_t option,
137                                void *data) {
138        switch(option) {
139                case TRACE_OPTION_META_FREQ:
140                        DUCK.duck_freq = *(int *)data;
141                        return 0;
142                case TRACE_OPTION_SNAPLEN:
143                        /* Surely we can set this?? Fall through for now*/
144                        return -1;
145                case TRACE_OPTION_PROMISC:
146                        /* DAG already operates in a promisc fashion */
147                        return -1;
148                case TRACE_OPTION_FILTER:
149                        return -1;
150                case TRACE_OPTION_EVENT_REALTIME:
151                        return -1;
152        }
153        return -1;
154}
155
156static int dag_start_input(libtrace_t *libtrace) {     
157        if(dag_start(FORMAT_DATA->fd) < 0) {
158                trace_set_err(libtrace,errno,"Cannot start DAG %s",
159                                libtrace->uridata);
160                return -1;
161        }
162
163        /* Flush the memory hole */
164        while(dag_available(libtrace) != 0)
165                FORMAT_DATA->diff = 0;
166        return 0;
167}
168
169static int dag_pause_input(libtrace_t *libtrace) {
170        dag_stop(FORMAT_DATA->fd);
171        return 0;
172}
173
174static int dag_fin_input(libtrace_t *libtrace) {
175        dag_close(FORMAT_DATA->fd);
176        if (DUCK.dummy_duck)
177                trace_destroy_dead(DUCK.dummy_duck);
178        free(libtrace->format_data);
179        return 0; /* success */
180}
181
182static int dag_get_duckinfo(libtrace_t *libtrace,
183                                libtrace_packet_t *packet) {
184        dag_inf lt_dag_inf;
185
186        if (packet->buf_control == TRACE_CTRL_EXTERNAL ||
187                        !packet->buffer) {
188                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
189                packet->buf_control = TRACE_CTRL_PACKET;
190                if (!packet->buffer) {
191                        trace_set_err(libtrace, errno,
192                                        "Cannot allocate packet buffer");
193                        return -1;
194                }
195        }
196
197        packet->header = 0;
198        packet->payload = packet->buffer;
199
200        if ((ioctl(FORMAT_DATA->fd, DAG_IOINF, &lt_dag_inf) < 0)) {
201                trace_set_err(libtrace, errno,
202                                "Error using DAG_IOINF");
203                return -1;
204        }
205        if (!IsDUCK(&lt_dag_inf)) {
206                printf("WARNING: %s does not have modern clock support - No DUCK information will be gathered\n", libtrace->uridata);
207                return 0;
208        }
209
210        if ((ioctl(FORMAT_DATA->fd, DAG_IOGETDUCK, (duck_inf *)packet->payload)
211                                < 0)) {
212                trace_set_err(libtrace, errno, "Error using DAG_IOGETDUCK");
213                return -1;
214        }
215
216        packet->type = TRACE_RT_DUCK_2_4;
217        if (!DUCK.dummy_duck)
218                DUCK.dummy_duck = trace_create_dead("duck:dummy");
219        packet->trace = DUCK.dummy_duck;
220        return sizeof(duck_inf);
221}
222
223
224static dag_record_t *dag_get_record(libtrace_t *libtrace) {
225        dag_record_t *erfptr = NULL;
226        uint16_t size;
227        erfptr = (dag_record_t *) ((char *)FORMAT_DATA->buf + 
228                        (FORMAT_DATA->bottom + FORMAT_DATA->offset));
229
230        if (!erfptr)
231                return NULL;
232        size = ntohs(erfptr->rlen);
233        assert( size >= dag_record_size );
234        FORMAT_DATA->offset += size;
235        FORMAT_DATA->diff -= size;
236        return erfptr;
237}
238
239static void dag_form_packet(dag_record_t *erfptr, libtrace_packet_t *packet) {
240        packet->buffer = erfptr;
241        packet->header = erfptr;
242        packet->type = TRACE_RT_DATA_ERF;
243        if (erfptr->flags.rxerror == 1) {
244                /* rxerror means the payload is corrupt - drop it
245                 * by tweaking rlen */
246                packet->payload = NULL;
247                erfptr->rlen = htons(erf_get_framing_length(packet));
248        } else {
249                packet->payload = (char*)packet->buffer
250                        + erf_get_framing_length(packet);
251        }
252
253}
254
255static int dag_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
256        int numbytes;
257        int size = 0;
258        struct timeval tv;
259        dag_record_t *erfptr = NULL;
260
261        if (DUCK.last_pkt - DUCK.last_duck > DUCK.duck_freq &&
262                        DUCK.duck_freq != 0) {
263                size = dag_get_duckinfo(libtrace, packet);
264                DUCK.last_duck = DUCK.last_pkt;
265                if (size != 0) {
266                        return size;
267                }
268                /* No DUCK support, so don't waste our time anymore */
269                DUCK.duck_freq = 0;
270        }
271
272        if (packet->buf_control == TRACE_CTRL_PACKET) {
273                packet->buf_control = TRACE_CTRL_EXTERNAL;
274                free(packet->buffer);
275                packet->buffer = 0;
276        }
277
278
279        do {
280                numbytes = dag_available(libtrace);
281                if (numbytes < 0)
282                        return numbytes;
283                if (numbytes == 0)
284                        continue;
285                erfptr = dag_get_record(libtrace);
286        } while (erfptr == NULL);
287        dag_form_packet(erfptr, packet);
288        tv = trace_get_timeval(packet);
289        DUCK.last_pkt = tv.tv_sec;
290        return packet->payload ? htons(erfptr->rlen) : erf_get_framing_length(packet);
291}
292
293static libtrace_eventobj_t trace_event_dag(libtrace_t *trace,
294                                        libtrace_packet_t *packet) {
295        libtrace_eventobj_t event = {0,0,0.0,0};
296        int data;
297
298        data = dag_available(trace);
299        if (data > 0) {
300                event.size = dag_read_packet(trace,packet);
301                //DATA(trace)->dag.diff -= event.size;
302                if (trace->filter) {
303                        if (trace_apply_filter(trace->filter, packet)) {
304                                event.type = TRACE_EVENT_PACKET;
305                        } else {
306                                event.type = TRACE_EVENT_SLEEP;
307                                event.seconds = 0.000001;
308                                return event;
309                        }
310                } else {
311                        event.type = TRACE_EVENT_PACKET;
312                }
313                if (trace->snaplen > 0) {
314                        trace_set_capture_length(packet, trace->snaplen);
315                }
316
317                return event;
318        }
319        assert(data == 0);
320        event.type = TRACE_EVENT_SLEEP;
321        event.seconds = 0.0001;
322        return event;
323}
324
325static void dag_help(void) {
326        printf("dag format module: $Revision$\n");
327        printf("Supported input URIs:\n");
328        printf("\tdag:/dev/dagn\n");
329        printf("\n");
330        printf("\te.g.: dag:/dev/dag0\n");
331        printf("\n");
332        printf("Supported output URIs:\n");
333        printf("\tnone\n");
334        printf("\n");
335}
336
337static struct libtrace_format_t dag = {
338        "dag",
339        "$Id$",
340        TRACE_FORMAT_ERF,
341        dag_init_input,                 /* init_input */
342        dag_config_input,               /* config_input */
343        dag_start_input,                /* start_input */
344        dag_pause_input,                /* pause_input */
345        NULL,                           /* init_output */
346        NULL,                           /* config_output */
347        NULL,                           /* start_output */
348        dag_fin_input,                  /* fin_input */
349        NULL,                           /* fin_output */
350        dag_read_packet,                /* read_packet */
351        NULL,                           /* fin_packet */
352        NULL,                           /* write_packet */
353        erf_get_link_type,              /* get_link_type */
354        erf_get_direction,              /* get_direction */
355        erf_set_direction,              /* set_direction */
356        erf_get_erf_timestamp,          /* get_erf_timestamp */
357        NULL,                           /* get_timeval */
358        NULL,                           /* get_seconds */
359        NULL,                           /* seek_erf */
360        NULL,                           /* seek_timeval */
361        NULL,                           /* seek_seconds */
362        erf_get_capture_length,         /* get_capture_length */
363        erf_get_wire_length,            /* get_wire_length */
364        erf_get_framing_length,         /* get_framing_length */
365        erf_set_capture_length,         /* set_capture_length */
366        NULL,                           /* get_fd */
367        trace_event_dag,                /* trace_event */
368        dag_help,                       /* help */
369        NULL                            /* next pointer */
370};
371
372void dag_constructor(void) {
373        register_format(&dag);
374}
Note: See TracBrowser for help on using the repository browser.