source: lib/format_dag25.c @ f2fae49

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

Add new "loss" framework

  • Property mode set to 100644
File size: 13.1 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007 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
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        int stream_attached;
78        uint8_t *bottom;
79        uint8_t *top;
80        uint32_t processed;
81};
82
83static int dag_init_input(libtrace_t *libtrace) {
84        struct stat buf;
85        libtrace->format_data = (struct dag_format_data_t *)
86                malloc(sizeof(struct dag_format_data_t));
87        if (stat(libtrace->uridata, &buf) == -1) {
88                trace_set_err(libtrace,errno,"stat(%s)",libtrace->uridata);
89                return -1;
90        }
91
92        /* For now, we don't offer the ability to select the stream */
93        FORMAT_DATA->dagstream = 0;
94
95        if (S_ISCHR(buf.st_mode)) {
96                if((FORMAT_DATA->fd = dag_open(libtrace->uridata)) < 0) {
97                        trace_set_err(libtrace,errno,"Cannot open DAG %s",
98                                        libtrace->uridata);
99                        return -1;
100                }
101        } else {
102                trace_set_err(libtrace,errno,"Not a valid dag device: %s",
103                                libtrace->uridata);
104                return -1;
105        }
106
107        DUCK.last_duck = 0;
108        DUCK.duck_freq = 0;
109        DUCK.last_pkt = 0;
110        DUCK.dummy_duck = NULL;
111        FORMAT_DATA->stream_attached = 0;
112       
113        return 0;
114}
115       
116static int dag_config_input(libtrace_t *libtrace, trace_option_t option,
117                                void *data) {
118        char conf_str[4096];
119        switch(option) {
120                case TRACE_OPTION_META_FREQ:
121                        DUCK.duck_freq = *(int *)data;
122                        return 0;
123                case TRACE_OPTION_SNAPLEN:
124                        snprintf(conf_str, 4096, "varlen slen=%i", *(int *)data);
125                        if (dag_configure(FORMAT_DATA->fd, conf_str) != 0) {
126                                trace_set_err(libtrace, errno, "Failed to configure snaplen on DAG card: %s", libtrace->uridata);
127                                return -1;
128                        }
129                        return 0;
130                case TRACE_OPTION_PROMISC:
131                        /* DAG already operates in a promisc fashion */
132                        return -1;
133                case TRACE_OPTION_FILTER:
134                        return -1;
135                case TRACE_OPTION_EVENT_REALTIME:
136                        return -1;
137        }
138        return -1;
139}
140
141static int dag_start_input(libtrace_t *libtrace) {
142        struct timeval zero, nopoll;
143        uint8_t *top, *bottom;
144        uint8_t diff = 0;
145        top = bottom = NULL;
146
147        zero.tv_sec = 0;
148        zero.tv_usec = 0;
149        nopoll = zero;
150
151
152       
153        if (dag_attach_stream(FORMAT_DATA->fd, 
154                                FORMAT_DATA->dagstream, 0, 0) < 0) {
155                trace_set_err(libtrace, errno, "Cannot attach DAG stream");
156                return -1;
157        }
158
159        if (dag_start_stream(FORMAT_DATA->fd, 
160                                FORMAT_DATA->dagstream) < 0) {
161                trace_set_err(libtrace, errno, "Cannot start DAG stream");
162                return -1;
163        }
164        FORMAT_DATA->stream_attached = 1;
165        /* We don't want the dag card to do any sleeping */
166        dag_set_stream_poll(FORMAT_DATA->fd, 
167                                FORMAT_DATA->dagstream, 0, &zero, 
168                                &nopoll);
169       
170        /* Should probably flush the memory hole now */
171       
172        do {
173                top = dag_advance_stream(FORMAT_DATA->fd,
174                                        FORMAT_DATA->dagstream,
175                                        &bottom);
176                assert(top && bottom);
177                diff = top - bottom;
178                bottom -= diff;
179        } while (diff != 0);
180        FORMAT_DATA->top = NULL;
181        FORMAT_DATA->bottom = NULL;
182        FORMAT_DATA->processed = 0;
183       
184        return 0;
185}
186
187static int dag_pause_input(libtrace_t *libtrace) {
188        if (dag_stop_stream(FORMAT_DATA->fd, 
189                                FORMAT_DATA->dagstream) < 0) {
190                trace_set_err(libtrace, errno, "Could not stop DAG stream");
191                return -1;
192        }
193        if (dag_detach_stream(FORMAT_DATA->fd, 
194                                FORMAT_DATA->dagstream) < 0) {
195                trace_set_err(libtrace, errno, "Could not detach DAG stream");
196                return -1;
197        }
198        FORMAT_DATA->stream_attached = 0;
199        return 0;
200}
201
202static int dag_fin_input(libtrace_t *libtrace) {
203        if (FORMAT_DATA->stream_attached)
204                dag_pause_input(libtrace);
205        dag_close(FORMAT_DATA->fd);
206        if (DUCK.dummy_duck)
207                trace_destroy_dead(DUCK.dummy_duck);
208        free(libtrace->format_data);
209        return 0; /* success */
210}
211
212static int dag_get_duckinfo(libtrace_t *libtrace,
213                                libtrace_packet_t *packet) {
214        if (packet->buf_control == TRACE_CTRL_EXTERNAL ||
215                        !packet->buffer) {
216                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
217                packet->buf_control = TRACE_CTRL_PACKET;
218                if (!packet->buffer) {
219                        trace_set_err(libtrace, errno,
220                                        "Cannot allocate packet buffer");
221                        return -1;
222                }
223        }
224
225        packet->header = 0;
226        packet->payload = packet->buffer;
227
228        /* No need to check if we can get DUCK or not - we're modern
229         * enough */
230        if ((ioctl(FORMAT_DATA->fd, DAGIOCDUCK, (duckinf_t *)packet->payload)
231                                < 0)) {
232                trace_set_err(libtrace, errno, "Error using DAGIOCDUCK");
233                return -1;
234        }
235
236        packet->type = TRACE_RT_DUCK_2_5;
237        if (!DUCK.dummy_duck)
238                DUCK.dummy_duck = trace_create_dead("rt:localhost:3434");
239        packet->trace = DUCK.dummy_duck;
240        return sizeof(duckinf_t);
241}
242
243static int dag_available(libtrace_t *libtrace) {
244        uint32_t diff = FORMAT_DATA->top - FORMAT_DATA->bottom;
245        /* If we've processed more than 4MB of data since we last called
246         * dag_advance_stream, then we should call it again to allow the
247         * space occupied by that 4MB to be released */
248        if (diff >= dag_record_size && FORMAT_DATA->processed < 4 * 1024 * 1024)
249                return diff;
250        FORMAT_DATA->top = dag_advance_stream(FORMAT_DATA->fd, 
251                        FORMAT_DATA->dagstream, 
252                        &(FORMAT_DATA->bottom));
253        if (FORMAT_DATA->top == NULL) {
254                trace_set_err(libtrace, errno, "dag_advance_stream failed!");
255                return -1;
256        }
257        FORMAT_DATA->processed = 0;
258        diff = FORMAT_DATA->top - FORMAT_DATA->bottom;
259        return diff;
260}
261
262static dag_record_t *dag_get_record(libtrace_t *libtrace) {
263        dag_record_t *erfptr = NULL;
264        uint16_t size;
265        erfptr = (dag_record_t *)FORMAT_DATA->bottom;
266        if (!erfptr)
267                return NULL;
268        size = ntohs(erfptr->rlen);
269        assert( size >= dag_record_size );
270        /* Make certain we have the full packet available */
271        if (size > (FORMAT_DATA->top - FORMAT_DATA->bottom))
272                return NULL;
273        FORMAT_DATA->bottom += size;
274        FORMAT_DATA->processed += size;
275        return erfptr;
276}
277
278static void dag_form_packet(dag_record_t *erfptr, libtrace_packet_t *packet) {
279        packet->buffer = erfptr;
280        packet->header = erfptr;
281        packet->type = TRACE_RT_DATA_ERF;
282        if (erfptr->flags.rxerror == 1) {
283                /* rxerror means the payload is corrupt - drop it
284                 * by tweaking rlen */
285                packet->payload = NULL;
286                erfptr->rlen = htons(erf_get_framing_length(packet));
287        } else {
288                packet->payload = (char*)packet->buffer
289                        + erf_get_framing_length(packet);
290        }
291
292}
293
294
295static int dag_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
296        int size = 0;
297        struct timeval tv;
298        dag_record_t *erfptr = NULL;
299        int numbytes = 0;
300       
301        if (DUCK.last_pkt - DUCK.last_duck > DUCK.duck_freq &&
302                        DUCK.duck_freq != 0) {
303                size = dag_get_duckinfo(libtrace, packet);
304                DUCK.last_duck = DUCK.last_pkt;
305                if (size != 0) {
306                        return size;
307                }
308                /* No DUCK support, so don't waste our time anymore */
309                DUCK.duck_freq = 0;
310        }
311
312        if (packet->buf_control == TRACE_CTRL_PACKET) {
313                packet->buf_control = TRACE_CTRL_EXTERNAL;
314                free(packet->buffer);
315                packet->buffer = 0;
316        }
317
318        do {
319                numbytes = dag_available(libtrace);
320                if (numbytes < 0)
321                        return numbytes;
322                if (numbytes < dag_record_size)
323                        /* Block until we see a packet */
324                        continue;
325                erfptr = dag_get_record(libtrace);
326        } while (erfptr == NULL);
327
328        dag_form_packet(erfptr, packet);
329        tv = trace_get_timeval(packet);
330        DUCK.last_pkt = tv.tv_sec;
331        return packet->payload ? htons(erfptr->rlen) : 
332                                erf_get_framing_length(packet);
333}
334
335static libtrace_eventobj_t trace_event_dag(libtrace_t *trace,
336                                        libtrace_packet_t *packet) {
337        libtrace_eventobj_t event = {0,0,0.0,0};
338        dag_record_t *erfptr = NULL;
339       
340        erfptr = dag_get_record(trace);
341        if (erfptr == NULL) {
342                /* No packet available */
343                event.type = TRACE_EVENT_SLEEP;
344                event.seconds = 0.0001;
345                return event;
346        }
347        dag_form_packet(erfptr, packet);
348        event.size = trace_get_capture_length(packet) + trace_get_framing_length(packet);
349        if (trace->filter) {
350                if (trace_apply_filter(trace->filter, packet)) {
351                        event.type = TRACE_EVENT_PACKET;
352                } else {
353                        event.type = TRACE_EVENT_SLEEP;
354                        event.seconds = 0.000001;
355                        return event;
356                }
357        } else {
358                event.type = TRACE_EVENT_PACKET;
359        }
360
361        if (trace->snaplen > 0) {
362                trace_set_capture_length(packet, trace->snaplen);
363        }
364
365        return event;
366}
367
368
369static void dag_help(void) {
370        printf("dag format module: $Revision$\n");
371        printf("Supported input URIs:\n");
372        printf("\tdag:/dev/dagn\n");
373        printf("\n");
374        printf("\te.g.: dag:/dev/dag0\n");
375        printf("\n");
376        printf("Supported output URIs:\n");
377        printf("\tnone\n");
378        printf("\n");
379}
380
381static struct libtrace_format_t dag = {
382        "dag",
383        "$Id$",
384        TRACE_FORMAT_ERF,
385        dag_init_input,                 /* init_input */
386        dag_config_input,               /* config_input */
387        dag_start_input,                /* start_input */
388        dag_pause_input,                /* pause_input */
389        NULL,                           /* init_output */
390        NULL,                           /* config_output */
391        NULL,                           /* start_output */
392        dag_fin_input,                  /* fin_input */
393        NULL,                           /* fin_output */
394        dag_read_packet,                /* read_packet */
395        NULL,                           /* fin_packet */
396        NULL,                           /* write_packet */
397        erf_get_link_type,              /* get_link_type */
398        erf_get_direction,              /* get_direction */
399        erf_set_direction,              /* set_direction */
400        erf_get_erf_timestamp,          /* get_erf_timestamp */
401        NULL,                           /* get_timeval */
402        NULL,                           /* get_seconds */
403        NULL,                           /* seek_erf */
404        NULL,                           /* seek_timeval */
405        NULL,                           /* seek_seconds */
406        erf_get_capture_length,         /* get_capture_length */
407        erf_get_wire_length,            /* get_wire_length */
408        erf_get_framing_length,         /* get_framing_length */
409        erf_set_capture_length,         /* set_capture_length */
410        NULL,                           /* get_received_packets */
411        NULL,                           /* get_filtered_packets */
412        NULL,                           /* get_dropped_packets */
413        NULL,                           /* get_captured_packets */
414        NULL,                           /* get_fd */
415        trace_event_dag,                /* trace_event */
416        dag_help,                       /* help */
417        NULL                            /* next pointer */
418};
419
420void dag_constructor(void) {
421        register_format(&dag);
422}
Note: See TracBrowser for help on using the repository browser.