source: lib/format_dag25.c @ 5e85c23

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 5e85c23 was 5e85c23, checked in by Shane Alcock <salcock@…>, 15 years ago

Split DAG format into it's own source files - one for DAG2.4 and another for DAG2.5.

  • Property mode set to 100644
File size: 11.7 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2004 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: format_dag25.c 1 2006-12-14 21:13:09Z spa1 $
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
49#ifdef WIN32
50#  include <io.h>
51#  include <share.h>
52#  define PATH_MAX _MAX_PATH
53#  define snprintf sprintf_s
54#else
55#  include <netdb.h>
56#  ifndef PATH_MAX
57#       define PATH_MAX 4096
58#  endif
59#  include <sys/ioctl.h>
60#endif
61
62#define DATA(x) ((struct dag_format_data_t *)x->format_data)
63#define FORMAT_DATA DATA(libtrace)
64#define DUCK FORMAT_DATA->duck
65static struct libtrace_format_t dag;
66
67struct dag_format_data_t {
68        struct {
69                uint32_t last_duck;
70                uint32_t duck_freq;
71                uint32_t last_pkt;
72                libtrace_t *dummy_duck;
73        } duck;
74
75        int fd;
76        unsigned int dagstream;
77};
78
79static int dag_init_input(libtrace_t *libtrace) {
80        struct stat buf;
81        libtrace->format_data = (struct dag_format_data_t *)
82                malloc(sizeof(struct dag_format_data_t));
83        if (stat(libtrace->uridata, &buf) == -1) {
84                trace_set_err(libtrace,errno,"stat(%s)",libtrace->uridata);
85                return -1;
86        }
87
88        /* For now, we don't offer the ability to select the stream */
89        FORMAT_DATA->dagstream = 0;
90
91        if (S_ISCHR(buf.st_mode)) {
92                if((FORMAT_DATA->fd = dag_open(libtrace->uridata)) < 0) {
93                        trace_set_err(libtrace,errno,"Cannot open DAG %s",
94                                        libtrace->uridata);
95                        return -1;
96                }
97        } else {
98                trace_set_err(libtrace,errno,"Not a valid dag device: %s",
99                                libtrace->uridata);
100                return -1;
101        }
102
103        DUCK.last_duck = 0;
104        DUCK.duck_freq = 0;
105        DUCK.last_pkt = 0;
106        DUCK.dummy_duck = NULL;
107
108        return 0;
109}
110       
111static int dag_config_input(libtrace_t *libtrace, trace_option_t option,
112                                void *data) {
113        switch(option) {
114                case TRACE_META_FREQ:
115                        DUCK.duck_freq = *(int *)data;
116                        return 0;
117                case TRACE_OPTION_SNAPLEN:
118                        /* Surely we can set this?? Fall through for now*/
119                        return -1;
120                case TRACE_OPTION_PROMISC:
121                        /* DAG already operates in a promisc fashion */
122                        return -1;
123                case TRACE_OPTION_FILTER:
124                        return -1;
125                default:
126                        trace_set_err(libtrace, TRACE_ERR_UNKNOWN_OPTION,
127                                        "Unknown or unsupported option: %i",
128                                        option);
129                        return -1;
130        }
131        assert (0);
132}
133
134static int dag_start_input(libtrace_t *libtrace) {
135        struct timeval zero, nopoll;
136        uint8_t *top, *bottom;
137        uint8_t diff = 0;
138        top = bottom = NULL;
139
140        zero.tv_sec = 0;
141        zero.tv_usec = 0;
142        nopoll = zero;
143
144
145       
146        if (dag_attach_stream(FORMAT_DATA->fd, 
147                                FORMAT_DATA->dagstream, 0, 0) < 0) {
148                trace_set_err(libtrace, errno, "Cannot attach DAG stream");
149                return -1;
150        }
151
152        if (dag_start_stream(FORMAT_DATA->fd, 
153                                FORMAT_DATA->dagstream) < 0) {
154                trace_set_err(libtrace, errno, "Cannot start DAG stream");
155                return -1;
156        }
157        /* We don't want the dag card to do any sleeping */
158        dag_set_stream_poll(FORMAT_DATA->fd, 
159                                FORMAT_DATA->dagstream, 0, &zero, 
160                                &nopoll);
161       
162        /* Should probably flush the memory hole now */
163        do {
164                top = dag_advance_stream(FORMAT_DATA->fd,
165                                        FORMAT_DATA->dagstream,
166                                        &bottom);
167                assert(top && bottom);
168                diff = top - bottom;
169        } while (diff != 0);
170
171        return 0;
172}
173
174static int dag_pause_input(libtrace_t *libtrace) {
175        if (dag_stop_stream(FORMAT_DATA->fd, 
176                                FORMAT_DATA->dagstream) < 0) {
177                trace_set_err(libtrace, errno, "Could not stop DAG stream");
178                return -1;
179        }
180        if (dag_detach_stream(FORMAT_DATA->fd, 
181                                FORMAT_DATA->dagstream) < 0) {
182                trace_set_err(libtrace, errno, "Could not detach DAG stream");
183                return -1;
184        }
185
186        return 0;
187}
188
189static int dag_fin_input(libtrace_t *libtrace) {
190        if (DUCK.dummy_duck)
191                trace_destroy_dead(DUCK.dummy_duck);
192        free(libtrace->format_data);
193        return 0; /* success */
194}
195
196static int dag_get_duckinfo(libtrace_t *libtrace,
197                                libtrace_packet_t *packet) {
198        daginf_t lt_dag_inf;
199
200        if (packet->buf_control == TRACE_CTRL_EXTERNAL ||
201                        !packet->buffer) {
202                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
203                packet->buf_control = TRACE_CTRL_PACKET;
204                if (!packet->buffer) {
205                        trace_set_err(libtrace, errno,
206                                        "Cannot allocate packet buffer");
207                        return -1;
208                }
209        }
210
211        packet->header = 0;
212        packet->payload = packet->buffer;
213
214        /* No need to check if we can get DUCK or not - we're modern
215         * enough */
216        if ((ioctl(FORMAT_DATA->fd, DAGIOCDUCK, (duckinf_t *)packet->payload)
217                                < 0)) {
218                trace_set_err(libtrace, errno, "Error using DAGIOCDUCK");
219                return -1;
220        }
221
222        packet->type = TRACE_RT_DUCK_2_5;
223        if (!DUCK.dummy_duck)
224                DUCK.dummy_duck = trace_create_dead("rt:localhost:3434");
225        packet->trace = DUCK.dummy_duck;
226        return sizeof(duckinf_t);
227}
228
229dag_record_t *dag_get_record(libtrace_t *libtrace) {
230        dag_record_t *erfptr = NULL;
231        uint16_t size;
232        erfptr = (dag_record_t *) dag_rx_stream_next_record(FORMAT_DATA->fd,
233                        FORMAT_DATA->dagstream);
234        if (!erfptr)
235                return NULL;
236        size = ntohs(erfptr->rlen);
237        assert( size >= dag_record_size );
238        return erfptr;
239}
240
241void dag_form_packet(dag_record_t *erfptr, libtrace_packet_t *packet) {
242        packet->buffer = erfptr;
243        packet->header = erfptr;
244        if (erfptr->flags.rxerror == 1) {
245                /* rxerror means the payload is corrupt - drop it
246                 * by tweaking rlen */
247                packet->payload = NULL;
248                erfptr->rlen = htons(erf_get_framing_length(packet));
249        } else {
250                packet->payload = (char*)packet->buffer
251                        + erf_get_framing_length(packet);
252        }
253
254}
255
256
257static int dag_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
258        int size = 0;
259        struct timeval tv;
260        dag_record_t *erfptr = NULL;
261
262        if (DUCK.last_pkt - DUCK.last_duck > DUCK.duck_freq &&
263                        DUCK.duck_freq != 0) {
264                size = dag_get_duckinfo(libtrace, packet);
265                DUCK.last_duck = DUCK.last_pkt;
266                if (size != 0) {
267                        return size;
268                }
269                /* No DUCK support, so don't waste our time anymore */
270                DUCK.duck_freq = 0;
271        }
272
273        if (packet->buf_control == TRACE_CTRL_PACKET) {
274                packet->buf_control = TRACE_CTRL_EXTERNAL;
275                free(packet->buffer);
276                packet->buffer = 0;
277        }
278
279        packet->type = TRACE_RT_DATA_ERF;
280
281        do {
282                erfptr = dag_get_record(libtrace);
283        } while (erfptr == NULL);
284
285        dag_form_packet(erfptr, packet);
286        tv = trace_get_timeval(packet);
287        DUCK.last_pkt = tv.tv_sec;
288        return packet->payload ? htons(erfptr->rlen) : 
289                                erf_get_framing_length(packet);
290}
291
292static libtrace_eventobj_t trace_event_dag(libtrace_t *trace,
293                                        libtrace_packet_t *packet) {
294        libtrace_eventobj_t event = {0,0,0.0,0};
295        dag_record_t *erfptr = NULL;
296       
297        erfptr = dag_get_record(trace);
298        if (erfptr == NULL) {
299                /* No packet available */
300                event.type = TRACE_EVENT_SLEEP;
301                event.seconds = 0.0001;
302                return event;
303        }
304        dag_form_packet(erfptr, packet);
305        event.size = trace_get_capture_length(packet) + trace_get_framing_length(packet);
306        if (trace->filter) {
307                if (trace_apply_filter(trace->filter, packet)) {
308                        event.type = TRACE_EVENT_PACKET;
309                } else {
310                        event.type = TRACE_EVENT_SLEEP;
311                        event.seconds = 0.000001;
312                        return event;
313                }
314        } else {
315                event.type = TRACE_EVENT_PACKET;
316        }
317
318        if (trace->snaplen > 0) {
319                trace_set_capture_length(packet, trace->snaplen);
320        }
321
322        return event;
323}
324
325
326static void dag_help(void) {
327        printf("dag format module: $Revision: 1110 $\n");
328        printf("Supported input URIs:\n");
329        printf("\tdag:/dev/dagn\n");
330        printf("\n");
331        printf("\te.g.: dag:/dev/dag0\n");
332        printf("\n");
333        printf("Supported output URIs:\n");
334        printf("\tnone\n");
335        printf("\n");
336}
337
338static struct libtrace_format_t dag = {
339        "dag",
340        "$Id: format_dag25.c 0 2006-12-14 21:13:09Z spa1 $",
341        TRACE_FORMAT_ERF,
342        dag_init_input,                 /* init_input */
343        dag_config_input,               /* config_input */
344        dag_start_input,                /* start_input */
345        dag_pause_input,                /* pause_input */
346        NULL,                           /* init_output */
347        NULL,                           /* config_output */
348        NULL,                           /* start_output */
349        dag_fin_input,                  /* fin_input */
350        NULL,                           /* fin_output */
351        dag_read_packet,                /* read_packet */
352        NULL,                           /* fin_packet */
353        NULL,                           /* write_packet */
354        erf_get_link_type,              /* get_link_type */
355        erf_get_direction,              /* get_direction */
356        erf_set_direction,              /* set_direction */
357        erf_get_erf_timestamp,          /* get_erf_timestamp */
358        NULL,                           /* get_timeval */
359        NULL,                           /* get_seconds */
360        NULL,                           /* seek_erf */
361        NULL,                           /* seek_timeval */
362        NULL,                           /* seek_seconds */
363        erf_get_capture_length,         /* get_capture_length */
364        erf_get_wire_length,            /* get_wire_length */
365        erf_get_framing_length,         /* get_framing_length */
366        erf_set_capture_length,         /* set_capture_length */
367        NULL,                           /* get_fd */
368        trace_event_dag,                /* trace_event */
369        dag_help,                       /* help */
370        NULL                            /* next pointer */
371};
372
373void dag_constructor(void) {
374        register_format(&dag);
375}
Note: See TracBrowser for help on using the repository browser.