source: lib/format_dag24.c @ f0fb38f

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