source: lib/format_dag25.c @ f0b87a7

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since f0b87a7 was f0b87a7, checked in by Daniel Lawson <dlawson@…>, 13 years ago

DAG write support. Work was referenced from the Endace DAG Programming Guide (EDM04-19)

Added dag_init_output(), dag_start_output(), dag_fin_output() and dag_write_packet() format functions.

Added datastructures: struct dag_format_data_out_t
Added other supporting internal functions: dag_init_format_out_data(), dag_open_output_device(), dag_pause_output()

dag_pause_output() may not make sense semantically, however the function essentially duplicates dag_pause_input(), but with the output device.

To use, specify an outputuri in the form dag:/dev/dag0 or dag:/dev/dag0,1
Note that while this supports using transmit streams other than 1, as of this commit there are no DAG cards that have mulitple transmit streams. Attempting to use a stream that does not work will result in an error inside libdag being passed back out to libtrace.

  • Property mode set to 100644
File size: 22.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/* XXX: Windows doesn't have pthreads, but this code doesn't compile under
49 * Windows anyway so we'll worry about this more later :] */
50#include <pthread.h>
51
52
53#ifdef WIN32
54#  include <io.h>
55#  include <share.h>
56#  define PATH_MAX _MAX_PATH
57#  define snprintf sprintf_s
58#else
59#  include <netdb.h>
60#  ifndef PATH_MAX
61#       define PATH_MAX 4096
62#  endif
63#  include <sys/ioctl.h>
64#endif
65
66
67#define DATA(x) ((struct dag_format_data_t *)x->format_data)
68#define FORMAT_DATA DATA(libtrace)
69#define DATA_OUT(x) ((struct dag_format_data_out_t *)x->format_data)
70#define FORMAT_DATA_OUT DATA_OUT(libtrace)
71
72#define DUCK FORMAT_DATA->duck
73static struct libtrace_format_t dag;
74
75struct dag_dev_t {
76        //pthread_mutex_t dag_mutex;
77        char * dev_name;
78        int fd;
79        uint16_t ref_count;
80        struct dag_dev_t *prev;
81        struct dag_dev_t *next;
82};
83
84struct dag_format_data_out_t {
85        struct dag_dev_t *device;
86        unsigned int dagstream;
87        int stream_attached;
88        uint8_t *bottom;
89        uint8_t *top;
90        uint32_t processed;
91        uint64_t drops;
92};
93
94struct dag_format_data_t {
95        struct {
96                uint32_t last_duck;
97                uint32_t duck_freq;
98                uint32_t last_pkt;
99                libtrace_t *dummy_duck;
100        } duck;
101
102        struct dag_dev_t *device;
103        unsigned int dagstream;
104        int stream_attached;
105        uint8_t *bottom;
106        uint8_t *top;
107        uint32_t processed;
108        uint64_t drops;
109};
110
111pthread_mutex_t open_dag_mutex;
112struct dag_dev_t *open_dags = NULL;
113
114static void dag_probe_filename(const char *filename)
115{
116        struct stat statbuf;
117        /* Can we stat the file? */
118        if (stat(filename, &statbuf) != 0) {
119                return 0;
120        }
121        /* Is it a character device? */
122        if (!S_ISCHR(statbuf.st_mode)) {
123                return 0;
124        }
125        /* Yeah, it's probably us. */
126        return 1;
127}
128
129static void dag_init_format_out_data(libtrace_out_t *libtrace) {
130        libtrace->format_data = (struct dag_format_data_out_t *) malloc(sizeof(struct dag_format_data_out_t));
131        // no DUCK on output
132        FORMAT_DATA_OUT->stream_attached = 0;
133        FORMAT_DATA_OUT->drops = 0;
134        FORMAT_DATA_OUT->device = NULL;
135        FORMAT_DATA_OUT->dagstream = 0;
136        FORMAT_DATA_OUT->processed = 0;
137        FORMAT_DATA_OUT->bottom = NULL;
138        FORMAT_DATA_OUT->top = NULL;
139
140}
141
142static void dag_init_format_data(libtrace_t *libtrace) {
143        libtrace->format_data = (struct dag_format_data_t *)
144                malloc(sizeof(struct dag_format_data_t));
145        DUCK.last_duck = 0;
146        DUCK.duck_freq = 0;
147        DUCK.last_pkt = 0;
148        DUCK.dummy_duck = NULL;
149        FORMAT_DATA->stream_attached = 0;
150        FORMAT_DATA->drops = 0;
151        FORMAT_DATA->device = NULL;
152        FORMAT_DATA->dagstream = 0;
153        FORMAT_DATA->processed = 0;
154        FORMAT_DATA->bottom = NULL;
155        FORMAT_DATA->top = NULL;
156}
157
158/* NOTE: This function assumes the open_dag_mutex is held by the caller */
159static struct dag_dev_t *dag_find_open_device(char *dev_name) {
160        struct dag_dev_t *dag_dev;
161
162        dag_dev = open_dags;
163
164        /* XXX: Not exactly zippy, but how often are we going to be dealing
165         * with multiple dag cards? */
166        while (dag_dev != NULL) {
167                if (strcmp(dag_dev->dev_name, dev_name) == 0) {
168                        dag_dev->ref_count ++;
169                        return dag_dev;
170
171                }
172                dag_dev = dag_dev->next;
173        }
174        return NULL;
175
176
177}
178
179/* NOTE: This function assumes the open_dag_mutex is held by the caller */
180static void dag_close_device(struct dag_dev_t *dev) {
181        /* Need to remove from the device list */
182
183        assert(dev->ref_count == 0);
184
185        if (dev->prev == NULL) {
186                open_dags = dev->next;
187                if (dev->next)
188                        dev->next->prev = NULL;
189        } else {
190                dev->prev->next = dev->next;
191                if (dev->next)
192                        dev->next->prev = dev->prev;
193        }
194
195        dag_close(dev->fd);
196        if (dev->dev_name)
197        free(dev->dev_name);
198        free(dev);
199}
200
201static struct dag_dev_t *dag_open_output_device(libtrace_out_t *libtrace, char *dev_name) {
202        struct stat buf;
203        int fd;
204        struct dag_dev_t *new_dev;
205
206        if (stat(dev_name, &buf) == -1) {
207                trace_set_err_out(libtrace,errno,"stat(%s)",dev_name);
208                return NULL;
209}
210
211        if (S_ISCHR(buf.st_mode)) {
212                if((fd = dag_open(dev_name)) < 0) {
213                        trace_set_err_out(libtrace,errno,"Cannot open DAG %s",
214                                        dev_name);
215                        return NULL;
216                }
217        } else {
218                trace_set_err_out(libtrace,errno,"Not a valid dag device: %s",
219                                dev_name);
220                return NULL;
221        }
222
223        new_dev = (struct dag_dev_t *)malloc(sizeof(struct dag_dev_t));
224        new_dev->fd = fd;
225        new_dev->dev_name = dev_name;
226        new_dev->ref_count = 1;
227
228        new_dev->prev = NULL;
229        new_dev->next = open_dags;
230        if (open_dags)
231                open_dags->prev = new_dev;
232
233        open_dags = new_dev;
234
235        return new_dev;
236}
237
238/* NOTE: This function assumes the open_dag_mutex is held by the caller */
239static struct dag_dev_t *dag_open_device(libtrace_t *libtrace, char *dev_name) {
240        struct stat buf;
241        int fd;
242        struct dag_dev_t *new_dev;
243
244        if (stat(dev_name, &buf) == -1) {
245                trace_set_err(libtrace,errno,"stat(%s)",dev_name);
246                return NULL;
247        }
248
249        if (S_ISCHR(buf.st_mode)) {
250                if((fd = dag_open(dev_name)) < 0) {
251                        trace_set_err(libtrace,errno,"Cannot open DAG %s",
252                                        dev_name);
253                        return NULL;
254                }
255        } else {
256                trace_set_err(libtrace,errno,"Not a valid dag device: %s",
257                                dev_name);
258                return NULL;
259        }
260
261        new_dev = (struct dag_dev_t *)malloc(sizeof(struct dag_dev_t));
262        new_dev->fd = fd;
263        new_dev->dev_name = dev_name;
264        new_dev->ref_count = 1;
265
266        new_dev->prev = NULL;
267        new_dev->next = open_dags;
268        if (open_dags)
269                open_dags->prev = new_dev;
270
271        open_dags = new_dev;
272
273        return new_dev;
274}
275
276static int dag_init_output(libtrace_out_t *libtrace) {
277        char *dag_dev_name = NULL;
278        char *scan = NULL;
279        struct dag_dev_t *dag_device = NULL;
280        int stream = 1;
281
282        dag_init_format_out_data(libtrace);
283        pthread_mutex_lock(&open_dag_mutex);
284        if ((scan = strchr(libtrace->uridata,',')) == NULL) {
285                dag_dev_name = strdup(libtrace->uridata);
286        } else {
287                dag_dev_name = (char *)strndup(libtrace->uridata,
288                                (size_t)(scan - libtrace->uridata));
289                stream = atoi(++scan);
290        }
291        FORMAT_DATA->dagstream = stream;
292
293        dag_device = dag_find_open_device(dag_dev_name);
294
295        if (dag_device == NULL) {
296                /* Device not yet opened - open it ourselves */
297                dag_device = dag_open_output_device(libtrace, dag_dev_name);
298        } else {
299                free(dag_dev_name);
300                dag_dev_name = NULL;
301        }
302
303        if (dag_device == NULL) {
304                if (dag_dev_name)
305                        free(dag_dev_name);
306                return -1;
307        }
308
309        FORMAT_DATA->device = dag_device;
310        pthread_mutex_unlock(&open_dag_mutex);
311        return 0;
312}
313
314static int dag_init_input(libtrace_t *libtrace) {
315        char *dag_dev_name = NULL;
316        char *scan = NULL;
317        int stream = 0;
318        struct dag_dev_t *dag_device = NULL;
319
320        dag_init_format_data(libtrace);
321        pthread_mutex_lock(&open_dag_mutex);
322        if ((scan = strchr(libtrace->uridata,',')) == NULL) {
323                dag_dev_name = strdup(libtrace->uridata);
324        } else {
325                dag_dev_name = (char *)strndup(libtrace->uridata,
326                                (size_t)(scan - libtrace->uridata));
327                stream = atoi(++scan);
328        }
329
330        FORMAT_DATA->dagstream = stream;
331
332        dag_device = dag_find_open_device(dag_dev_name);
333
334        if (dag_device == NULL) {
335                /* Device not yet opened - open it ourselves */
336                dag_device = dag_open_device(libtrace, dag_dev_name);
337        } else {
338                free(dag_dev_name);
339                dag_dev_name = NULL;
340        }
341
342        if (dag_device == NULL) {
343                if (dag_dev_name)
344                        free(dag_dev_name);
345                dag_dev_name = NULL;
346                return -1;
347        }
348
349        FORMAT_DATA->device = dag_device;
350
351        pthread_mutex_unlock(&open_dag_mutex);
352        return 0;
353}
354
355static int dag_config_input(libtrace_t *libtrace, trace_option_t option,
356                                void *data) {
357        char conf_str[4096];
358        switch(option) {
359                case TRACE_OPTION_META_FREQ:
360                        DUCK.duck_freq = *(int *)data;
361                        return 0;
362                case TRACE_OPTION_SNAPLEN:
363                        snprintf(conf_str, 4096, "varlen slen=%i", *(int *)data);
364                        if (dag_configure(FORMAT_DATA->device->fd,
365                                                conf_str) != 0) {
366                                trace_set_err(libtrace, errno, "Failed to configure snaplen on DAG card: %s", libtrace->uridata);
367                                return -1;
368                        }
369                        return 0;
370                case TRACE_OPTION_PROMISC:
371                        /* DAG already operates in a promisc fashion */
372                        return -1;
373                case TRACE_OPTION_FILTER:
374                        return -1;
375                case TRACE_OPTION_EVENT_REALTIME:
376                        return -1;
377        }
378        return -1;
379}
380static int dag_start_output(libtrace_out_t *libtrace) {
381        struct timeval zero, nopoll;
382        uint8_t *top, *bottom;
383        uint8_t diff = 0;
384        top = bottom = NULL;
385
386        zero.tv_sec = 0;
387        zero.tv_usec = 0;
388        nopoll = zero;
389
390        if (dag_attach_stream(FORMAT_DATA->device->fd,
391                        FORMAT_DATA->dagstream, 0, 1048576) < 0) {
392                trace_set_err_out(libtrace, errno, "Cannot attach DAG stream");
393                return -1;
394        }
395
396        if (dag_start_stream(FORMAT_DATA->device->fd,
397                        FORMAT_DATA->dagstream) < 0) {
398                trace_set_err_out(libtrace, errno, "Cannot start DAG stream");
399                return -1;
400        }
401        FORMAT_DATA->stream_attached = 1;
402
403        /* We don't want the dag card to do any sleeping */
404        dag_set_stream_poll(FORMAT_DATA->device->fd,
405                        FORMAT_DATA->dagstream, 0, &zero,
406                        &nopoll);
407
408        return 0;
409}
410
411static int dag_start_input(libtrace_t *libtrace) {
412        struct timeval zero, nopoll;
413        uint8_t *top, *bottom;
414        uint8_t diff = 0;
415        top = bottom = NULL;
416
417        zero.tv_sec = 0;
418        zero.tv_usec = 0;
419        nopoll = zero;
420
421
422
423        if (dag_attach_stream(FORMAT_DATA->device->fd,
424                                FORMAT_DATA->dagstream, 0, 0) < 0) {
425                trace_set_err(libtrace, errno, "Cannot attach DAG stream");
426                return -1;
427        }
428
429        if (dag_start_stream(FORMAT_DATA->device->fd,
430                                FORMAT_DATA->dagstream) < 0) {
431                trace_set_err(libtrace, errno, "Cannot start DAG stream");
432                return -1;
433        }
434        FORMAT_DATA->stream_attached = 1;
435        /* We don't want the dag card to do any sleeping */
436        dag_set_stream_poll(FORMAT_DATA->device->fd,
437                                FORMAT_DATA->dagstream, 0, &zero,
438                                &nopoll);
439
440        /* Should probably flush the memory hole now */
441
442        do {
443                top = dag_advance_stream(FORMAT_DATA->device->fd,
444                                        FORMAT_DATA->dagstream,
445                                        &bottom);
446                assert(top && bottom);
447                diff = top - bottom;
448                bottom -= diff;
449        } while (diff != 0);
450        FORMAT_DATA->top = NULL;
451        FORMAT_DATA->bottom = NULL;
452        FORMAT_DATA->processed = 0;
453        FORMAT_DATA->drops = 0;
454
455        return 0;
456}
457
458static int dag_pause_output(libtrace_out_t *libtrace) {
459        if (dag_stop_stream(FORMAT_DATA->device->fd,
460                        FORMAT_DATA->dagstream) < 0) {
461                trace_set_err_out(libtrace, errno, "Could not stop DAG stream");
462                return -1;
463        }
464        if (dag_detach_stream(FORMAT_DATA->device->fd,
465                        FORMAT_DATA->dagstream) < 0) {
466                trace_set_err_out(libtrace, errno, "Could not detach DAG stream");
467                return -1;
468        }
469        FORMAT_DATA->stream_attached = 0;
470        return 0;
471}
472
473static int dag_pause_input(libtrace_t *libtrace) {
474        if (dag_stop_stream(FORMAT_DATA->device->fd,
475                                FORMAT_DATA->dagstream) < 0) {
476                trace_set_err(libtrace, errno, "Could not stop DAG stream");
477                return -1;
478        }
479        if (dag_detach_stream(FORMAT_DATA->device->fd,
480                                FORMAT_DATA->dagstream) < 0) {
481                trace_set_err(libtrace, errno, "Could not detach DAG stream");
482                return -1;
483        }
484        FORMAT_DATA->stream_attached = 0;
485        return 0;
486}
487
488static int dag_fin_input(libtrace_t *libtrace) {
489        pthread_mutex_lock(&open_dag_mutex);
490        if (FORMAT_DATA->stream_attached)
491                dag_pause_input(libtrace);
492        FORMAT_DATA->device->ref_count --;
493
494        if (FORMAT_DATA->device->ref_count == 0)
495                dag_close_device(FORMAT_DATA->device);
496        if (DUCK.dummy_duck)
497                trace_destroy_dead(DUCK.dummy_duck);
498        free(libtrace->format_data);
499        pthread_mutex_unlock(&open_dag_mutex);
500        return 0; /* success */
501}
502
503static int dag_fin_output(libtrace_out_t *libtrace) {
504        pthread_mutex_lock(&open_dag_mutex);
505        if (FORMAT_DATA->stream_attached)
506                dag_pause_output(libtrace);
507        FORMAT_DATA->device->ref_count --;
508
509        if (FORMAT_DATA->device->ref_count == 0)
510                dag_close_device(FORMAT_DATA->device);
511        free(libtrace->format_data);
512        pthread_mutex_unlock(&open_dag_mutex);
513        return 0; /* success */
514}
515
516static int dag_get_duckinfo(libtrace_t *libtrace,
517                                libtrace_packet_t *packet) {
518        if (packet->buf_control == TRACE_CTRL_EXTERNAL ||
519                        !packet->buffer) {
520                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
521                packet->buf_control = TRACE_CTRL_PACKET;
522                if (!packet->buffer) {
523                        trace_set_err(libtrace, errno,
524                                        "Cannot allocate packet buffer");
525                        return -1;
526                }
527        }
528
529        packet->header = 0;
530        packet->payload = packet->buffer;
531
532        /* No need to check if we can get DUCK or not - we're modern
533         * enough */
534        if ((ioctl(FORMAT_DATA->device->fd, DAGIOCDUCK,
535                                        (duckinf_t *)packet->payload) < 0)) {
536                trace_set_err(libtrace, errno, "Error using DAGIOCDUCK");
537                return -1;
538        }
539
540        packet->type = TRACE_RT_DUCK_2_5;
541        if (!DUCK.dummy_duck)
542                DUCK.dummy_duck = trace_create_dead("rt:localhost:3434");
543        packet->trace = DUCK.dummy_duck;
544        return sizeof(duckinf_t);
545}
546
547static int dag_available(libtrace_t *libtrace) {
548        uint32_t diff = FORMAT_DATA->top - FORMAT_DATA->bottom;
549        /* If we've processed more than 4MB of data since we last called
550         * dag_advance_stream, then we should call it again to allow the
551         * space occupied by that 4MB to be released */
552        if (diff >= dag_record_size && FORMAT_DATA->processed < 4 * 1024 * 1024)
553                return diff;
554        FORMAT_DATA->top = dag_advance_stream(FORMAT_DATA->device->fd,
555                        FORMAT_DATA->dagstream,
556                        &(FORMAT_DATA->bottom));
557        if (FORMAT_DATA->top == NULL) {
558                trace_set_err(libtrace, errno, "dag_advance_stream failed!");
559                return -1;
560        }
561        FORMAT_DATA->processed = 0;
562        diff = FORMAT_DATA->top - FORMAT_DATA->bottom;
563        return diff;
564}
565
566static dag_record_t *dag_get_record(libtrace_t *libtrace) {
567        dag_record_t *erfptr = NULL;
568        uint16_t size;
569        erfptr = (dag_record_t *)FORMAT_DATA->bottom;
570        if (!erfptr)
571                return NULL;
572        size = ntohs(erfptr->rlen);
573        assert( size >= dag_record_size );
574        /* Make certain we have the full packet available */
575        if (size > (FORMAT_DATA->top - FORMAT_DATA->bottom))
576                return NULL;
577        FORMAT_DATA->bottom += size;
578        FORMAT_DATA->processed += size;
579        return erfptr;
580}
581
582static int dag_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
583                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
584
585        dag_record_t *erfptr;
586
587        if (packet->buffer != buffer &&
588                        packet->buf_control == TRACE_CTRL_PACKET) {
589                free(packet->buffer);
590        }
591
592        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
593                packet->buf_control = TRACE_CTRL_PACKET;
594        } else
595                packet->buf_control = TRACE_CTRL_EXTERNAL;
596
597        erfptr = (dag_record_t *)buffer;
598        packet->buffer = erfptr;
599        packet->header = erfptr;
600        packet->type = rt_type;
601
602        if (erfptr->flags.rxerror == 1) {
603                /* rxerror means the payload is corrupt - drop it
604                 * by tweaking rlen */
605                packet->payload = NULL;
606                erfptr->rlen = htons(erf_get_framing_length(packet));
607        } else {
608                packet->payload = (char*)packet->buffer
609                        + erf_get_framing_length(packet);
610        }
611
612        if (libtrace->format_data == NULL) {
613                dag_init_format_data(libtrace);
614        }
615
616        /* No loss counter for DSM coloured records - have to use
617         * some other API */
618        if (erfptr->type == TYPE_DSM_COLOR_ETH) {
619
620        } else {
621                DATA(libtrace)->drops += ntohs(erfptr->lctr);
622        }
623
624        return 0;
625}
626
627
628static int dag_write_packet(libtrace_out_t *libtrace, libtrace_packet_t *packet) {
629        int err;
630        void *record;
631        int size = trace_get_capture_length(packet);
632        size = size + (8 - (size % 8));
633
634        err = dag_tx_stream_copy_bytes(FORMAT_DATA->device->fd, FORMAT_DATA->dagstream,
635                        packet->buffer, size);
636
637        if (err == NULL)
638                trace_set_err(libtrace, errno, "dag_tx_stream_copy_bytes failed!");
639
640        return 0;
641}
642
643static int dag_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
644        int size = 0;
645        struct timeval tv;
646        dag_record_t *erfptr = NULL;
647        int numbytes = 0;
648        uint32_t flags = 0;
649
650        if (DUCK.last_pkt - DUCK.last_duck > DUCK.duck_freq &&
651                        DUCK.duck_freq != 0) {
652                size = dag_get_duckinfo(libtrace, packet);
653                DUCK.last_duck = DUCK.last_pkt;
654                if (size != 0) {
655                        return size;
656                }
657                /* No DUCK support, so don't waste our time anymore */
658                DUCK.duck_freq = 0;
659        }
660
661        flags |= TRACE_PREP_DO_NOT_OWN_BUFFER;
662
663        if (packet->buf_control == TRACE_CTRL_PACKET) {
664                free(packet->buffer);
665                packet->buffer = 0;
666        }
667
668        do {
669                numbytes = dag_available(libtrace);
670                if (numbytes < 0)
671                        return numbytes;
672                if (numbytes < dag_record_size)
673                        /* Block until we see a packet */
674                        continue;
675                erfptr = dag_get_record(libtrace);
676        } while (erfptr == NULL);
677
678        //dag_form_packet(erfptr, packet);
679        if (dag_prepare_packet(libtrace, packet, erfptr, TRACE_RT_DATA_ERF,
680                                flags))
681                return -1;
682        tv = trace_get_timeval(packet);
683        DUCK.last_pkt = tv.tv_sec;
684
685        return packet->payload ? htons(erfptr->rlen) :
686                                erf_get_framing_length(packet);
687}
688
689static libtrace_eventobj_t trace_event_dag(libtrace_t *trace,
690                                        libtrace_packet_t *packet) {
691        libtrace_eventobj_t event = {0,0,0.0,0};
692        dag_record_t *erfptr = NULL;
693        int numbytes;
694        uint32_t flags = 0;
695
696        /* Need to call dag_available so that the top pointer will get
697         * updated, otherwise we'll never see any data! */
698        numbytes = dag_available(trace);
699
700        /* May as well not bother calling dag_get_record if dag_available
701         * suggests that there's no data */
702        if (numbytes != 0)
703                erfptr = dag_get_record(trace);
704        if (erfptr == NULL) {
705                /* No packet available */
706                event.type = TRACE_EVENT_SLEEP;
707                event.seconds = 0.0001;
708                return event;
709        }
710        //dag_form_packet(erfptr, packet);
711        if (dag_prepare_packet(trace, packet, erfptr, TRACE_RT_DATA_ERF,
712                                flags)) {
713                event.type = TRACE_EVENT_TERMINATE;
714                return event;
715        }
716
717
718        event.size = trace_get_capture_length(packet) + trace_get_framing_length(packet);
719        if (trace->filter) {
720                if (trace_apply_filter(trace->filter, packet)) {
721                        event.type = TRACE_EVENT_PACKET;
722                } else {
723                        event.type = TRACE_EVENT_SLEEP;
724                        event.seconds = 0.000001;
725                        return event;
726                }
727        } else {
728                event.type = TRACE_EVENT_PACKET;
729        }
730
731        if (trace->snaplen > 0) {
732                trace_set_capture_length(packet, trace->snaplen);
733        }
734
735        return event;
736}
737
738static uint64_t dag_get_dropped_packets(libtrace_t *trace) {
739        if (trace->format_data == NULL)
740                return (uint64_t)-1;
741        return DATA(trace)->drops;
742}
743
744static void dag_help(void) {
745        printf("dag format module: $Revision$\n");
746        printf("Supported input URIs:\n");
747        printf("\tdag:/dev/dagn\n");
748        printf("\n");
749        printf("\te.g.: dag:/dev/dag0\n");
750        printf("\n");
751        printf("Supported output URIs:\n");
752        printf("\tnone\n");
753        printf("\n");
754}
755
756static struct libtrace_format_t dag = {
757        "dag",
758        "$Id$",
759        TRACE_FORMAT_ERF,
760        dag_probe_filename,             /* probe filename */
761        NULL,                           /* probe magic */
762        dag_init_input,                 /* init_input */
763        dag_config_input,               /* config_input */
764        dag_start_input,                /* start_input */
765        dag_pause_input,                /* pause_input */
766        dag_init_output,                /* init_output */ /* done */
767        NULL,                           /* config_output */
768        dag_start_output,               /* start_output */ /* done */
769        dag_fin_input,                  /* fin_input */
770        dag_fin_output,                 /* fin_output */ /* done */
771        dag_read_packet,                /* read_packet */
772        dag_prepare_packet,             /* prepare_packet */
773        NULL,                           /* fin_packet */
774        dag_write_packet,               /* write_packet */ /* todo */
775        erf_get_link_type,              /* get_link_type */
776        erf_get_direction,              /* get_direction */
777        erf_set_direction,              /* set_direction */
778        erf_get_erf_timestamp,          /* get_erf_timestamp */
779        NULL,                           /* get_timeval */
780        NULL,                           /* get_seconds */
781        NULL,                           /* seek_erf */
782        NULL,                           /* seek_timeval */
783        NULL,                           /* seek_seconds */
784        erf_get_capture_length,         /* get_capture_length */
785        erf_get_wire_length,            /* get_wire_length */
786        erf_get_framing_length,         /* get_framing_length */
787        erf_set_capture_length,         /* set_capture_length */
788        NULL,                           /* get_received_packets */
789        NULL,                           /* get_filtered_packets */
790        dag_get_dropped_packets,        /* get_dropped_packets */
791        NULL,                           /* get_captured_packets */
792        NULL,                           /* get_fd */
793        trace_event_dag,                /* trace_event */
794        dag_help,                       /* help */
795        NULL                            /* next pointer */
796};
797
798void dag_constructor(void) {
799        register_format(&dag);
800}
Note: See TracBrowser for help on using the repository browser.