source: lib/format_dag24.c @ 91b72d3

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 91b72d3 was 91b72d3, checked in by Perry Lorier <perry@…>, 12 years ago

Try to autoguess the tracetype if the format uri specify is not present

  • Property mode set to 100644
File size: 14.4 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 void dag_probe_filename(const char *filename) 
86{
87        struct stat statbuf;
88        /* Can we stat the file? */
89        if (stat(filename, &statbuf) != 0) {
90                return 0;
91        }
92        /* Is it a character device? */
93        if (!S_ISCHR(statbuf.st_mode)) {
94                return 0;
95        }
96        /* Yeah, it's probably us. */
97        return 1;
98}
99
100static void dag_init_format_data(libtrace_t *libtrace) {
101        libtrace->format_data = (struct dag_format_data_t *)
102                malloc(sizeof(struct dag_format_data_t));
103
104        DUCK.last_duck = 0;
105        DUCK.duck_freq = 0;
106        DUCK.last_pkt = 0;
107        DUCK.dummy_duck = NULL;
108        FORMAT_DATA->drops = 0;
109        FORMAT_DATA->top = 0;
110        FORMAT_DATA->bottom = 0;
111        FORMAT_DATA->buf = NULL;
112        FORMAT_DATA->fd = -1;
113        FORMAT_DATA->offset = 0;
114        FORMAT_DATA->diff = 0;
115}
116
117static int dag_available(libtrace_t *libtrace) {
118
119        if (FORMAT_DATA->diff > 0)
120                return FORMAT_DATA->diff;
121
122        FORMAT_DATA->bottom = FORMAT_DATA->top;
123        FORMAT_DATA->top = dag_offset(
124                        FORMAT_DATA->fd,
125                        &(FORMAT_DATA->bottom),
126                        DAGF_NONBLOCK);
127        FORMAT_DATA->diff = FORMAT_DATA->top - FORMAT_DATA->bottom;
128        FORMAT_DATA->offset = 0;
129        return FORMAT_DATA->diff;
130}
131
132static int dag_init_input(libtrace_t *libtrace) {
133        struct stat buf;
134        char *dag_dev_name = NULL;
135        char *scan = NULL;
136
137        /* Since DAG 2.5 has been changed to support a slightly different URI
138         * format, it's probably a good idea to deal with URIs specified in
139         * such a fashion even if we just end up ignoring the stream number */
140        if ((scan = strchr(libtrace->uridata,',')) == NULL) {
141                dag_dev_name = strdup(libtrace->uridata);
142        } else {
143                dag_dev_name = (char *)strndup(libtrace->uridata,
144                                (size_t)(scan - libtrace->uridata));
145        }
146
147       
148        if (stat(dag_dev_name, &buf) == -1) {
149                trace_set_err(libtrace,errno,"stat(%s)",dag_dev_name);
150                free(dag_dev_name);
151                return -1;
152        }
153       
154        dag_init_format_data(libtrace);
155        if (S_ISCHR(buf.st_mode)) {
156                /* DEVICE */
157                if((FORMAT_DATA->fd = dag_open(dag_dev_name)) < 0) {
158                        trace_set_err(libtrace,errno,"Cannot open DAG %s",
159                                        dag_dev_name);
160                        free(dag_dev_name);
161                        return -1;
162                }
163                if((FORMAT_DATA->buf = (void *)dag_mmap(FORMAT_DATA->fd)) == MAP_FAILED) {
164                        trace_set_err(libtrace,errno,"Cannot mmap DAG %s",
165                                        dag_dev_name);
166                        free(dag_dev_name);
167                        return -1;
168                }
169        } else {
170                trace_set_err(libtrace,errno,"Not a valid dag device: %s",
171                                dag_dev_name);
172                free(dag_dev_name);
173                return -1;
174        }
175
176        free(dag_dev_name);
177
178        return 0;
179}
180
181static int dag_config_input(libtrace_t *libtrace, trace_option_t option,
182                                void *data) {
183        switch(option) {
184                case TRACE_OPTION_META_FREQ:
185                        DUCK.duck_freq = *(int *)data;
186                        return 0;
187                case TRACE_OPTION_SNAPLEN:
188                        /* Surely we can set this?? Fall through for now*/
189                        return -1;
190                case TRACE_OPTION_PROMISC:
191                        /* DAG already operates in a promisc fashion */
192                        return -1;
193                case TRACE_OPTION_FILTER:
194                        return -1;
195                case TRACE_OPTION_EVENT_REALTIME:
196                        return -1;
197        }
198        return -1;
199}
200
201static int dag_start_input(libtrace_t *libtrace) {     
202        if(dag_start(FORMAT_DATA->fd) < 0) {
203                trace_set_err(libtrace,errno,"Cannot start DAG %s",
204                                libtrace->uridata);
205                return -1;
206        }
207
208        /* Flush the memory hole */
209        while(dag_available(libtrace) != 0)
210                FORMAT_DATA->diff = 0;
211        FORMAT_DATA->drops = 0;
212        return 0;
213}
214
215static int dag_pause_input(libtrace_t *libtrace) {
216        dag_stop(FORMAT_DATA->fd);
217        return 0;
218}
219
220static int dag_fin_input(libtrace_t *libtrace) {
221        dag_close(FORMAT_DATA->fd);
222        if (DUCK.dummy_duck)
223                trace_destroy_dead(DUCK.dummy_duck);
224        free(libtrace->format_data);
225        return 0; /* success */
226}
227
228static int dag_get_duckinfo(libtrace_t *libtrace,
229                                libtrace_packet_t *packet) {
230        dag_inf lt_dag_inf;
231
232        if (packet->buf_control == TRACE_CTRL_EXTERNAL ||
233                        !packet->buffer) {
234                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
235                packet->buf_control = TRACE_CTRL_PACKET;
236                if (!packet->buffer) {
237                        trace_set_err(libtrace, errno,
238                                        "Cannot allocate packet buffer");
239                        return -1;
240                }
241        }
242
243        packet->header = 0;
244        packet->payload = packet->buffer;
245
246        if ((ioctl(FORMAT_DATA->fd, DAG_IOINF, &lt_dag_inf) < 0)) {
247                trace_set_err(libtrace, errno,
248                                "Error using DAG_IOINF");
249                return -1;
250        }
251        if (!IsDUCK(&lt_dag_inf)) {
252                printf("WARNING: %s does not have modern clock support - No DUCK information will be gathered\n", libtrace->uridata);
253                return 0;
254        }
255
256        if ((ioctl(FORMAT_DATA->fd, DAG_IOGETDUCK, (duck_inf *)packet->payload)
257                                < 0)) {
258                trace_set_err(libtrace, errno, "Error using DAG_IOGETDUCK");
259                return -1;
260        }
261
262        packet->type = TRACE_RT_DUCK_2_4;
263        if (!DUCK.dummy_duck)
264                DUCK.dummy_duck = trace_create_dead("duck:dummy");
265        packet->trace = DUCK.dummy_duck;
266        return sizeof(duck_inf);
267}
268
269
270static dag_record_t *dag_get_record(libtrace_t *libtrace) {
271        dag_record_t *erfptr = NULL;
272        uint16_t size;
273        erfptr = (dag_record_t *) ((char *)FORMAT_DATA->buf + 
274                        (FORMAT_DATA->bottom + FORMAT_DATA->offset));
275
276        if (!erfptr)
277                return NULL;
278        size = ntohs(erfptr->rlen);
279        assert( size >= dag_record_size );
280        FORMAT_DATA->offset += size;
281        FORMAT_DATA->diff -= size;
282        return erfptr;
283}
284
285static int dag_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
286                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
287
288        dag_record_t *erfptr;
289        if (packet->buffer != buffer &&
290                        packet->buf_control == TRACE_CTRL_PACKET) {
291                free(packet->buffer);
292        }
293
294        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
295                packet->buf_control = TRACE_CTRL_PACKET;
296        } else 
297                packet->buf_control = TRACE_CTRL_EXTERNAL;
298       
299        erfptr = (dag_record_t *)buffer;
300        packet->buffer = erfptr;
301        packet->header = erfptr;
302        packet->type = rt_type;
303
304        if (erfptr->flags.rxerror == 1) {
305                /* rxerror means the payload is corrupt - drop it
306                 * by tweaking rlen */
307                packet->payload = NULL;
308                erfptr->rlen = htons(erf_get_framing_length(packet));
309        } else {
310                packet->payload = (char*)packet->buffer
311                        + erf_get_framing_length(packet);
312        }
313
314        if (libtrace->format_data == NULL) {
315                dag_init_format_data(libtrace);
316        }
317
318        DATA(libtrace)->drops += ntohs(erfptr->lctr);
319
320        return 0;
321
322}
323
324static int dag_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
325        int numbytes;
326        int size = 0;
327        uint32_t flags = 0;
328        struct timeval tv;
329        dag_record_t *erfptr = NULL;
330
331        if (DUCK.last_pkt - DUCK.last_duck > DUCK.duck_freq &&
332                        DUCK.duck_freq != 0) {
333                size = dag_get_duckinfo(libtrace, packet);
334                DUCK.last_duck = DUCK.last_pkt;
335                if (size != 0) {
336                        return size;
337                }
338                /* No DUCK support, so don't waste our time anymore */
339                DUCK.duck_freq = 0;
340        }
341
342        flags |= TRACE_PREP_DO_NOT_OWN_BUFFER;
343       
344        if (packet->buf_control == TRACE_CTRL_PACKET) {
345                packet->buf_control = TRACE_CTRL_EXTERNAL;
346                free(packet->buffer);
347                packet->buffer = 0;
348        }
349
350
351        do {
352                numbytes = dag_available(libtrace);
353                if (numbytes < 0)
354                        return numbytes;
355                if (numbytes == 0)
356                        continue;
357                erfptr = dag_get_record(libtrace);
358        } while (erfptr == NULL);
359       
360       
361        if (dag_prepare_packet(libtrace, packet, erfptr, TRACE_RT_DATA_ERF, 
362                                flags))
363                return -1;
364        tv = trace_get_timeval(packet);
365        DUCK.last_pkt = tv.tv_sec;
366        return packet->payload ? htons(erfptr->rlen) : erf_get_framing_length(packet);
367}
368
369static libtrace_eventobj_t trace_event_dag(libtrace_t *trace,
370                                        libtrace_packet_t *packet) {
371        libtrace_eventobj_t event = {0,0,0.0,0};
372        int data;
373
374        data = dag_available(trace);
375        if (data > 0) {
376                event.size = dag_read_packet(trace,packet);
377                //DATA(trace)->dag.diff -= event.size;
378                if (trace->filter) {
379                        if (trace_apply_filter(trace->filter, packet)) {
380                                event.type = TRACE_EVENT_PACKET;
381                        } else {
382                                event.type = TRACE_EVENT_SLEEP;
383                                event.seconds = 0.000001;
384                                return event;
385                        }
386                } else {
387                        event.type = TRACE_EVENT_PACKET;
388                }
389                if (trace->snaplen > 0) {
390                        trace_set_capture_length(packet, trace->snaplen);
391                }
392
393                return event;
394        }
395        assert(data == 0);
396        event.type = TRACE_EVENT_SLEEP;
397        event.seconds = 0.0001;
398        return event;
399}
400
401static uint64_t dag_get_dropped_packets(libtrace_t *trace)
402{
403        if (!trace->format_data)
404                return (uint64_t)-1;
405        return DATA(trace)->drops;
406}
407
408static void dag_help(void) {
409        printf("dag format module: $Revision$\n");
410        printf("Supported input URIs:\n");
411        printf("\tdag:/dev/dagn\n");
412        printf("\n");
413        printf("\te.g.: dag:/dev/dag0\n");
414        printf("\n");
415        printf("Supported output URIs:\n");
416        printf("\tnone\n");
417        printf("\n");
418}
419
420static struct libtrace_format_t dag = {
421        "dag",
422        "$Id$",
423        TRACE_FORMAT_ERF,
424        dag_probe_filename,             /* probe filename */
425        NULL,                           /* probe magic */
426        dag_init_input,                 /* init_input */
427        dag_config_input,               /* config_input */
428        dag_start_input,                /* start_input */
429        dag_pause_input,                /* pause_input */
430        NULL,                           /* init_output */
431        NULL,                           /* config_output */
432        NULL,                           /* start_output */
433        dag_fin_input,                  /* fin_input */
434        NULL,                           /* fin_output */
435        dag_read_packet,                /* read_packet */
436        dag_prepare_packet,             /* prepare_packet */
437        NULL,                           /* fin_packet */
438        NULL,                           /* write_packet */
439        erf_get_link_type,              /* get_link_type */
440        erf_get_direction,              /* get_direction */
441        erf_set_direction,              /* set_direction */
442        erf_get_erf_timestamp,          /* get_erf_timestamp */
443        NULL,                           /* get_timeval */
444        NULL,                           /* get_seconds */
445        NULL,                           /* seek_erf */
446        NULL,                           /* seek_timeval */
447        NULL,                           /* seek_seconds */
448        erf_get_capture_length,         /* get_capture_length */
449        erf_get_wire_length,            /* get_wire_length */
450        erf_get_framing_length,         /* get_framing_length */
451        erf_set_capture_length,         /* set_capture_length */
452        NULL,                           /* get_received_packets */
453        NULL,                           /* get_filtered_packets */
454        dag_get_dropped_packets,        /* get_dropped_packets */
455        NULL,                           /* get_captured_packets */
456        NULL,                           /* get_fd */
457        trace_event_dag,                /* trace_event */
458        dag_help,                       /* help */
459        NULL                            /* next pointer */
460};
461
462void dag_constructor(void) {
463        register_format(&dag);
464}
Note: See TracBrowser for help on using the repository browser.