source: lib/format_dag24.c @ 121b7e2

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 121b7e2 was 121b7e2, checked in by Shane Alcock <salcock@…>, 14 years ago
  • Updated format_dag25 to support multiple streams - the new uri format for dag is "dag:/dev/dagX,<stream number>"
  • As each dag card can only be opened by a single process, thread-safety is now incorporated to allow separate threads to read from each dag stream
  • format_dag24 also supports the new uri format, although the stream number is ignored because old dags only have the one stream
  • Updated dagformat.h to include a whole bunch of new erf types
  • Added explicit support for the DSM Coloured Ethernet record type which will be required to deal with streamed packets
  • Fixed erf_get_padding() code that was comparing the return value of trace_get_link_type against an erf type rather than a libtrace link type
  • Property mode set to 100644
File size: 13.1 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008 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        uint64_t drops;
83};
84
85static int dag_available(libtrace_t *libtrace) {
86
87        if (FORMAT_DATA->diff > 0)
88                return FORMAT_DATA->diff;
89
90        FORMAT_DATA->bottom = FORMAT_DATA->top;
91        FORMAT_DATA->top = dag_offset(
92                        FORMAT_DATA->fd,
93                        &(FORMAT_DATA->bottom),
94                        DAGF_NONBLOCK);
95        FORMAT_DATA->diff = FORMAT_DATA->top - FORMAT_DATA->bottom;
96        FORMAT_DATA->offset = 0;
97        return FORMAT_DATA->diff;
98}
99
100static int dag_init_input(libtrace_t *libtrace) {
101        struct stat buf;
102        char *dag_dev_name = NULL;
103        char *scan = NULL;
104
105        /* Since DAG 2.5 has been changed to support a slightly different URI
106         * format, it's probably a good idea to deal with URIs specified in
107         * such a fashion even if we just end up ignoring the stream number */
108        if ((scan = strchr(libtrace->uridata,',')) == NULL) {
109                dag_dev_name = strdup(libtrace->uridata);
110        } else {
111                dag_dev_name = (char *)strndup(libtrace->uridata,
112                                (size_t)(scan - libtrace->uridata));
113        }
114
115       
116        if (stat(dag_dev_name, &buf) == -1) {
117                trace_set_err(libtrace,errno,"stat(%s)",dag_dev_name);
118                free(dag_dev_name);
119                return -1;
120        }
121       
122        libtrace->format_data = (struct dag_format_data_t *)
123                malloc(sizeof(struct dag_format_data_t));
124        FORMAT_DATA->top = 0;
125        FORMAT_DATA->bottom = 0;
126        if (S_ISCHR(buf.st_mode)) {
127                /* DEVICE */
128                if((FORMAT_DATA->fd = dag_open(dag_dev_name)) < 0) {
129                        trace_set_err(libtrace,errno,"Cannot open DAG %s",
130                                        dag_dev_name);
131                        free(dag_dev_name);
132                        return -1;
133                }
134                if((FORMAT_DATA->buf = (void *)dag_mmap(FORMAT_DATA->fd)) == MAP_FAILED) {
135                        trace_set_err(libtrace,errno,"Cannot mmap DAG %s",
136                                        dag_dev_name);
137                        free(dag_dev_name);
138                        return -1;
139                }
140        } else {
141                trace_set_err(libtrace,errno,"Not a valid dag device: %s",
142                                dag_dev_name);
143                free(dag_dev_name);
144                return -1;
145        }
146
147        DUCK.last_duck = 0;
148        DUCK.duck_freq = 0;
149        DUCK.last_pkt = 0;
150        DUCK.dummy_duck = NULL;
151        FORMAT_DATA->drops = 0;
152        free(dag_dev_name);
153
154        return 0;
155}
156
157static int dag_config_input(libtrace_t *libtrace, trace_option_t option,
158                                void *data) {
159        switch(option) {
160                case TRACE_OPTION_META_FREQ:
161                        DUCK.duck_freq = *(int *)data;
162                        return 0;
163                case TRACE_OPTION_SNAPLEN:
164                        /* Surely we can set this?? Fall through for now*/
165                        return -1;
166                case TRACE_OPTION_PROMISC:
167                        /* DAG already operates in a promisc fashion */
168                        return -1;
169                case TRACE_OPTION_FILTER:
170                        return -1;
171                case TRACE_OPTION_EVENT_REALTIME:
172                        return -1;
173        }
174        return -1;
175}
176
177static int dag_start_input(libtrace_t *libtrace) {     
178        if(dag_start(FORMAT_DATA->fd) < 0) {
179                trace_set_err(libtrace,errno,"Cannot start DAG %s",
180                                libtrace->uridata);
181                return -1;
182        }
183
184        /* Flush the memory hole */
185        while(dag_available(libtrace) != 0)
186                FORMAT_DATA->diff = 0;
187        FORMAT_DATA->drops = 0;
188        return 0;
189}
190
191static int dag_pause_input(libtrace_t *libtrace) {
192        dag_stop(FORMAT_DATA->fd);
193        return 0;
194}
195
196static int dag_fin_input(libtrace_t *libtrace) {
197        dag_close(FORMAT_DATA->fd);
198        if (DUCK.dummy_duck)
199                trace_destroy_dead(DUCK.dummy_duck);
200        free(libtrace->format_data);
201        return 0; /* success */
202}
203
204static int dag_get_duckinfo(libtrace_t *libtrace,
205                                libtrace_packet_t *packet) {
206        dag_inf lt_dag_inf;
207
208        if (packet->buf_control == TRACE_CTRL_EXTERNAL ||
209                        !packet->buffer) {
210                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
211                packet->buf_control = TRACE_CTRL_PACKET;
212                if (!packet->buffer) {
213                        trace_set_err(libtrace, errno,
214                                        "Cannot allocate packet buffer");
215                        return -1;
216                }
217        }
218
219        packet->header = 0;
220        packet->payload = packet->buffer;
221
222        if ((ioctl(FORMAT_DATA->fd, DAG_IOINF, &lt_dag_inf) < 0)) {
223                trace_set_err(libtrace, errno,
224                                "Error using DAG_IOINF");
225                return -1;
226        }
227        if (!IsDUCK(&lt_dag_inf)) {
228                printf("WARNING: %s does not have modern clock support - No DUCK information will be gathered\n", libtrace->uridata);
229                return 0;
230        }
231
232        if ((ioctl(FORMAT_DATA->fd, DAG_IOGETDUCK, (duck_inf *)packet->payload)
233                                < 0)) {
234                trace_set_err(libtrace, errno, "Error using DAG_IOGETDUCK");
235                return -1;
236        }
237
238        packet->type = TRACE_RT_DUCK_2_4;
239        if (!DUCK.dummy_duck)
240                DUCK.dummy_duck = trace_create_dead("duck:dummy");
241        packet->trace = DUCK.dummy_duck;
242        return sizeof(duck_inf);
243}
244
245
246static dag_record_t *dag_get_record(libtrace_t *libtrace) {
247        dag_record_t *erfptr = NULL;
248        uint16_t size;
249        erfptr = (dag_record_t *) ((char *)FORMAT_DATA->buf + 
250                        (FORMAT_DATA->bottom + FORMAT_DATA->offset));
251
252        if (!erfptr)
253                return NULL;
254        size = ntohs(erfptr->rlen);
255        assert( size >= dag_record_size );
256        FORMAT_DATA->offset += size;
257        FORMAT_DATA->diff -= size;
258        return erfptr;
259}
260
261static void dag_form_packet(dag_record_t *erfptr, libtrace_packet_t *packet) {
262        packet->buffer = erfptr;
263        packet->header = erfptr;
264        packet->type = TRACE_RT_DATA_ERF;
265        if (erfptr->flags.rxerror == 1) {
266                /* rxerror means the payload is corrupt - drop it
267                 * by tweaking rlen */
268                packet->payload = NULL;
269                erfptr->rlen = htons(erf_get_framing_length(packet));
270        } else {
271                packet->payload = (char*)packet->buffer
272                        + erf_get_framing_length(packet);
273        }
274
275}
276
277static int dag_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
278        int numbytes;
279        int size = 0;
280        struct timeval tv;
281        dag_record_t *erfptr = NULL;
282
283        if (DUCK.last_pkt - DUCK.last_duck > DUCK.duck_freq &&
284                        DUCK.duck_freq != 0) {
285                size = dag_get_duckinfo(libtrace, packet);
286                DUCK.last_duck = DUCK.last_pkt;
287                if (size != 0) {
288                        return size;
289                }
290                /* No DUCK support, so don't waste our time anymore */
291                DUCK.duck_freq = 0;
292        }
293
294        if (packet->buf_control == TRACE_CTRL_PACKET) {
295                packet->buf_control = TRACE_CTRL_EXTERNAL;
296                free(packet->buffer);
297                packet->buffer = 0;
298        }
299
300
301        do {
302                numbytes = dag_available(libtrace);
303                if (numbytes < 0)
304                        return numbytes;
305                if (numbytes == 0)
306                        continue;
307                erfptr = dag_get_record(libtrace);
308        } while (erfptr == NULL);
309        dag_form_packet(erfptr, packet);
310        tv = trace_get_timeval(packet);
311        DUCK.last_pkt = tv.tv_sec;
312        DATA(libtrace)->drops += ntohs(erfptr->lctr);
313        return packet->payload ? htons(erfptr->rlen) : erf_get_framing_length(packet);
314}
315
316static libtrace_eventobj_t trace_event_dag(libtrace_t *trace,
317                                        libtrace_packet_t *packet) {
318        libtrace_eventobj_t event = {0,0,0.0,0};
319        int data;
320
321        data = dag_available(trace);
322        if (data > 0) {
323                event.size = dag_read_packet(trace,packet);
324                //DATA(trace)->dag.diff -= event.size;
325                if (trace->filter) {
326                        if (trace_apply_filter(trace->filter, packet)) {
327                                event.type = TRACE_EVENT_PACKET;
328                        } else {
329                                event.type = TRACE_EVENT_SLEEP;
330                                event.seconds = 0.000001;
331                                return event;
332                        }
333                } else {
334                        event.type = TRACE_EVENT_PACKET;
335                }
336                if (trace->snaplen > 0) {
337                        trace_set_capture_length(packet, trace->snaplen);
338                }
339
340                return event;
341        }
342        assert(data == 0);
343        event.type = TRACE_EVENT_SLEEP;
344        event.seconds = 0.0001;
345        return event;
346}
347
348static uint64_t dag_get_dropped_packets(libtrace_t *trace)
349{
350        return DATA(trace)->drops;
351}
352
353static void dag_help(void) {
354        printf("dag format module: $Revision$\n");
355        printf("Supported input URIs:\n");
356        printf("\tdag:/dev/dagn\n");
357        printf("\n");
358        printf("\te.g.: dag:/dev/dag0\n");
359        printf("\n");
360        printf("Supported output URIs:\n");
361        printf("\tnone\n");
362        printf("\n");
363}
364
365static struct libtrace_format_t dag = {
366        "dag",
367        "$Id$",
368        TRACE_FORMAT_ERF,
369        dag_init_input,                 /* init_input */
370        dag_config_input,               /* config_input */
371        dag_start_input,                /* start_input */
372        dag_pause_input,                /* pause_input */
373        NULL,                           /* init_output */
374        NULL,                           /* config_output */
375        NULL,                           /* start_output */
376        dag_fin_input,                  /* fin_input */
377        NULL,                           /* fin_output */
378        dag_read_packet,                /* read_packet */
379        NULL,                           /* fin_packet */
380        NULL,                           /* write_packet */
381        erf_get_link_type,              /* get_link_type */
382        erf_get_direction,              /* get_direction */
383        erf_set_direction,              /* set_direction */
384        erf_get_erf_timestamp,          /* get_erf_timestamp */
385        NULL,                           /* get_timeval */
386        NULL,                           /* get_seconds */
387        NULL,                           /* seek_erf */
388        NULL,                           /* seek_timeval */
389        NULL,                           /* seek_seconds */
390        erf_get_capture_length,         /* get_capture_length */
391        erf_get_wire_length,            /* get_wire_length */
392        erf_get_framing_length,         /* get_framing_length */
393        erf_set_capture_length,         /* set_capture_length */
394        NULL,                           /* get_received_packets */
395        NULL,                           /* get_filtered_packets */
396        dag_get_dropped_packets,        /* get_dropped_packets */
397        NULL,                           /* get_captured_packets */
398        NULL,                           /* get_fd */
399        trace_event_dag,                /* trace_event */
400        dag_help,                       /* help */
401        NULL                            /* next pointer */
402};
403
404void dag_constructor(void) {
405        register_format(&dag);
406}
Note: See TracBrowser for help on using the repository browser.