source: lib/format_erf.c @ 17a3dff

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 17a3dff was 29bbef0, checked in by Richard Sanger <rsangerarj@…>, 7 years ago

My work from over summer, with a few things tidied up and updated to include recent commits/patches to bring this up to date. Still very much work in progress.

  • Property mode set to 100644
File size: 22.8 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 * $Id$
31 *
32 */
33
34
35#define _GNU_SOURCE
36
37#include "config.h"
38#include "common.h"
39#include "libtrace.h"
40#include "libtrace_int.h"
41#include "format_helper.h"
42#include "format_erf.h"
43#include "wandio.h"
44
45#include <assert.h>
46#include <errno.h>
47#include <fcntl.h>
48#include <stdio.h>
49#include <string.h>
50#include <stdlib.h>
51
52#ifdef WIN32
53#  include <io.h>
54#  include <share.h>
55#  define PATH_MAX _MAX_PATH
56#else
57#  include <netdb.h>
58#  ifndef PATH_MAX
59#       define PATH_MAX 4096
60#  endif
61#  include <sys/ioctl.h>
62#endif
63
64/* This format module deals with reading and writing ERF traces. ERF is the
65 * trace format developed by Endace for use by DAG hardware capture cards.
66 *
67 * ERF is not a live capture format.
68 *
69 */
70
71
72static struct libtrace_format_t erfformat;
73
74#define DATA(x) ((struct erf_format_data_t *)x->format_data)
75#define DATAOUT(x) ((struct erf_format_data_out_t *)x->format_data)
76
77#define IN_OPTIONS DATA(libtrace)->options
78#define OUTPUT DATAOUT(libtrace)
79#define OUT_OPTIONS DATAOUT(libtrace)->options
80
81/* "Global" data that is stored for each ERF input trace */
82struct erf_format_data_t {
83       
84        /* Index used for seeking within a trace */
85        struct {
86                /* The index itself */
87                io_t *index;
88                /* The offset of the index */
89                off_t index_len;
90                /* Indicates the existence of an index */
91                enum { INDEX_UNKNOWN=0, INDEX_NONE, INDEX_EXISTS } exists;
92        } seek;
93
94        /* Number of packets that were dropped during the capture */
95        uint64_t drops;
96
97        /* Config options for the input trace */
98        struct {
99                /* Flag indicating whether the event API should replicate the
100                 * time gaps between each packet or return a PACKET event for
101                 * each packet */
102                int real_time;
103        } options;
104};
105
106/* "Global" data that is stored for each ERF output trace */
107struct erf_format_data_out_t {
108
109        /* Config options for the output trace */
110        struct {
111                /* Compression level for the output file */
112                int level;
113                /* Compression type */
114                int compress_type;
115                /* File flags used to open the file, e.g. O_CREATE */
116                int fileflag;
117        } options;
118
119        /* The output file itself */
120        iow_t *file;
121       
122};
123
124typedef struct erf_index_t {
125        uint64_t timestamp;
126        uint64_t offset; 
127} erf_index_t;
128
129
130/* Ethernet packets have a 2 byte padding before the packet
131 * so that the IP header is aligned on a 32 bit boundary.
132 */
133static int erf_get_padding(const libtrace_packet_t *packet)
134{
135        if (packet->trace->format->type==TRACE_FORMAT_ERF) {
136                dag_record_t *erfptr = (dag_record_t *)packet->header;
137                switch(erfptr->type) {
138                        case TYPE_ETH:         
139                        case TYPE_DSM_COLOR_ETH:
140                                return 2;
141                        default:                return 0;
142                }
143        }
144        else {
145                switch(trace_get_link_type(packet)) {
146                        case TRACE_TYPE_ETH:    return 2;
147                        default:                return 0;
148                }
149        }
150}
151
152int erf_get_framing_length(const libtrace_packet_t *packet)
153{
154        return dag_record_size + erf_get_padding(packet);
155}
156
157/* Attempts to determine whether a given trace file is using the ERF format
158 *
159 * Returns 1 if the trace is probably ERF, 0 otherwise
160 */
161static int erf_probe_magic(io_t *io)
162{
163        char buffer[4096];
164        int len;
165        dag_record_t *erf;
166        len = wandio_peek(io, buffer, sizeof(buffer));
167        if (len < (int)dag_record_size) {
168                return 0; /* False */
169        }
170        erf = (dag_record_t *) buffer;
171        /* If the record is too short */
172        if (ntohs(erf->rlen) < dag_record_size) {
173                return 0;
174        }
175        /* There aren't any erf traces before 1995-01-01 */
176        if (bswap_le_to_host64(erf->ts) < 0x2f0539b000000000ULL) {
177                return 0;
178        }
179        /* And not pcap! */
180        if (bswap_le_to_host64(erf->ts) >>32 == 0xa1b2c3d4) {
181                return 0;
182        }
183        /* And not the other pcap! */
184        if (bswap_le_to_host64(erf->ts) >>32 == 0xd4c3b2a1) {
185                return 0;
186        }
187        /* Is this a proper typed packet */
188        if (erf->type > TYPE_AAL2) {
189                return 0;
190        }
191        /* We should put some more tests in here. */
192        /* Yeah, this is probably ERF */
193        return 1;
194}
195
196static int erf_init_input(libtrace_t *libtrace) 
197{
198        libtrace->format_data = malloc(sizeof(struct erf_format_data_t));
199       
200        IN_OPTIONS.real_time = 0;
201        DATA(libtrace)->drops = 0;
202       
203        return 0; /* success */
204}
205
206static int erf_config_input(libtrace_t *libtrace, trace_option_t option,
207                void *value) {
208
209        switch (option) {
210                case TRACE_OPTION_EVENT_REALTIME:
211                        IN_OPTIONS.real_time = *(int *)value;
212                        return 0;
213                case TRACE_OPTION_SNAPLEN:
214                case TRACE_OPTION_PROMISC:
215                case TRACE_OPTION_FILTER:
216                case TRACE_OPTION_META_FREQ:
217                        trace_set_err(libtrace, TRACE_ERR_OPTION_UNAVAIL,
218                                        "Unsupported option");
219                        return -1;
220                default:
221                        /* Unknown option */
222                        trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
223                                        "Unknown option");
224                        return -1;
225        }
226}
227
228static int erf_start_input(libtrace_t *libtrace) 
229{
230        if (libtrace->io)
231                return 0; /* Success -- already done. */
232
233        libtrace->io = trace_open_file(libtrace);
234
235        if (!libtrace->io)
236                return -1;
237
238        DATA(libtrace)->drops = 0;
239        return 0; /* success */
240}
241
242/* Raw ERF is a special case -- we want to force libwandio to treat the file
243 * as uncompressed so we can't just use trace_open_file() */
244static int rawerf_start_input(libtrace_t *libtrace)
245{
246        if (libtrace->io)
247                return 0; 
248
249        libtrace->io = wandio_create_uncompressed(libtrace->uridata);
250
251        if (!libtrace->io) {
252                if (errno != 0) {
253                        trace_set_err(libtrace, errno, "Unable to open raw ERF file %s", libtrace->uridata);
254                }
255                return -1;
256        }
257
258        DATA(libtrace)->drops = 0;
259
260        return 0; /* success */
261}
262
263/* Binary search through the index to find the closest point before
264 * the packet.  Consider in future having a btree index perhaps?
265 */
266static int erf_fast_seek_start(libtrace_t *libtrace,uint64_t erfts)
267{
268        size_t max_off = DATA(libtrace)->seek.index_len/sizeof(erf_index_t);
269        size_t min_off = 0;
270        off_t current;
271        erf_index_t record;
272        do {
273                current=(max_off+min_off)>>2;
274
275                wandio_seek(DATA(libtrace)->seek.index,
276                                (int64_t)(current*sizeof(record)),
277                                SEEK_SET);
278                wandio_read(DATA(libtrace)->seek.index,
279                                &record,sizeof(record));
280                if (record.timestamp < erfts) {
281                        min_off=current;
282                }
283                if (record.timestamp > erfts) {
284                        max_off=current;
285                }
286                if (record.timestamp == erfts)
287                        break;
288        } while(min_off<max_off);
289
290        /* If we've passed it, seek backwards.  This loop shouldn't
291         * execute more than twice.
292         */
293        do {
294                wandio_seek(DATA(libtrace)->seek.index,
295                                (int64_t)(current*sizeof(record)),SEEK_SET);
296                wandio_read(DATA(libtrace)->seek.index,
297                                &record,sizeof(record));
298                current--;
299        } while(record.timestamp>erfts);
300
301        /* We've found our location in the trace, now use it. */
302        wandio_seek(libtrace->io,(int64_t) record.offset,SEEK_SET);
303
304        return 0; /* success */
305}
306
307/* There is no index.  Seek through the entire trace from the start, nice
308 * and slowly.
309 */
310static int erf_slow_seek_start(libtrace_t *libtrace,uint64_t erfts UNUSED)
311{
312        if (libtrace->io) {
313                wandio_destroy(libtrace->io);
314        }
315        libtrace->io = trace_open_file(libtrace);
316        if (!libtrace->io)
317                return -1;
318        return 0;
319}
320
321/* Seek within an ERF trace based on an ERF timestamp */
322static int erf_seek_erf(libtrace_t *libtrace,uint64_t erfts)
323{
324        libtrace_packet_t *packet;
325        off_t off = 0;
326
327        if (DATA(libtrace)->seek.exists==INDEX_UNKNOWN) {
328                char buffer[PATH_MAX];
329                snprintf(buffer,sizeof(buffer),"%s.idx",libtrace->uridata);
330                DATA(libtrace)->seek.index=wandio_create(buffer);
331                if (DATA(libtrace)->seek.index) {
332                        DATA(libtrace)->seek.exists=INDEX_EXISTS;
333                }
334                else {
335                        DATA(libtrace)->seek.exists=INDEX_NONE;
336                }
337        }
338
339        /* If theres an index, use it to find the nearest packet that isn't
340         * after the time we're looking for.  If there is no index we need
341         * to seek slowly through the trace from the beginning.  Sigh.
342         */
343        switch(DATA(libtrace)->seek.exists) {
344                case INDEX_EXISTS:
345                        erf_fast_seek_start(libtrace,erfts);
346                        break;
347                case INDEX_NONE:
348                        erf_slow_seek_start(libtrace,erfts);
349                        break;
350                case INDEX_UNKNOWN:
351                        assert(0);
352                        break;
353        }
354
355        /* Now seek forward looking for the correct timestamp */
356        packet=trace_create_packet();
357        do {
358                trace_read_packet(libtrace,packet);
359                if (trace_get_erf_timestamp(packet)==erfts)
360                        break;
361                off=wandio_tell(libtrace->io);
362        } while(trace_get_erf_timestamp(packet)<erfts);
363
364        wandio_seek(libtrace->io,off,SEEK_SET);
365
366        return 0;
367}
368
369static int erf_init_output(libtrace_out_t *libtrace) {
370        libtrace->format_data = malloc(sizeof(struct erf_format_data_out_t));
371
372        OUT_OPTIONS.level = 0;
373        OUT_OPTIONS.compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
374        OUT_OPTIONS.fileflag = O_CREAT | O_WRONLY;
375        OUTPUT->file = 0;
376
377        return 0;
378}
379
380static int erf_config_output(libtrace_out_t *libtrace, 
381                trace_option_output_t option, void *value) {
382
383        switch (option) {
384                case TRACE_OPTION_OUTPUT_COMPRESS:
385                        OUT_OPTIONS.level = *(int*)value;
386                        return 0;
387                case TRACE_OPTION_OUTPUT_COMPRESSTYPE:
388                        OUT_OPTIONS.compress_type = *(int*)value;
389                        return 0;
390                case TRACE_OPTION_OUTPUT_FILEFLAGS:
391                        OUT_OPTIONS.fileflag = *(int*)value;
392                        return 0;
393                default:
394                        /* Unknown option */
395                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
396                                        "Unknown option");
397                        return -1;
398        }
399}
400
401
402
403static int erf_fin_input(libtrace_t *libtrace) {
404        if (libtrace->io)
405                wandio_destroy(libtrace->io);
406        free(libtrace->format_data);
407        return 0;
408}
409
410static int erf_fin_output(libtrace_out_t *libtrace) {
411        if (OUTPUT->file)
412                wandio_wdestroy(OUTPUT->file);
413        free(libtrace->format_data);
414        return 0;
415}
416 
417static int erf_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
418                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
419       
420        dag_record_t *erfptr;
421       
422        if (packet->buffer != buffer && 
423                packet->buf_control == TRACE_CTRL_PACKET) {
424                free(packet->buffer);
425        }
426
427        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
428                packet->buf_control = TRACE_CTRL_PACKET;
429        } else
430                packet->buf_control = TRACE_CTRL_EXTERNAL;
431       
432       
433        packet->type = rt_type;
434        packet->buffer = buffer;
435        packet->header = buffer;
436        erfptr = (dag_record_t *)packet->buffer;
437        if (erfptr->flags.rxerror == 1) {
438                packet->payload = NULL;
439        } else {
440                packet->payload = (char*)packet->buffer + erf_get_framing_length(packet);
441        }
442       
443        if (libtrace->format_data == NULL) {
444                /* Allocates the format_data structure */
445                if (erf_init_input(libtrace)) 
446                        return -1;
447        }
448
449        /* Check for loss */
450        if (erfptr->type == TYPE_DSM_COLOR_ETH) {
451                /* No idea how we get this yet */
452
453        } else if (erfptr->lctr) {
454                DATA(libtrace)->drops += ntohs(erfptr->lctr);
455        }
456
457        return 0;
458}
459
460static int erf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
461        int numbytes;
462        unsigned int size;
463        void *buffer2 = packet->buffer;
464        unsigned int rlen;
465        uint32_t flags = 0;
466       
467       
468        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
469                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
470                if (!packet->buffer) {
471                        trace_set_err(libtrace, errno, 
472                                        "Cannot allocate memory");
473                        return -1;
474                }
475        }
476
477        flags |= TRACE_PREP_OWN_BUFFER; 
478       
479        if ((numbytes=wandio_read(libtrace->io,
480                                        packet->buffer,
481                                        (size_t)dag_record_size)) == -1) {
482                trace_set_err(libtrace,errno,"read(%s)",
483                                libtrace->uridata);
484                return -1;
485        }
486        /* EOF */
487        if (numbytes == 0) {
488                return 0;
489        }
490
491        rlen = ntohs(((dag_record_t *)packet->buffer)->rlen);
492        buffer2 = (char*)packet->buffer + dag_record_size;
493        size = rlen - dag_record_size;
494
495        if (size >= LIBTRACE_PACKET_BUFSIZE) {
496                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
497                                "Packet size %u larger than supported by libtrace - packet is probably corrupt", 
498                                size);
499                return -1;
500        }
501
502        /* Unknown/corrupt */
503        if (((dag_record_t *)packet->buffer)->type >= TYPE_RAW_LINK) {
504                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
505                                "Corrupt or Unknown ERF type");
506                return -1;
507        }
508       
509        /* read in the rest of the packet */
510        if ((numbytes=wandio_read(libtrace->io,
511                                        buffer2,
512                                        (size_t)size)) != (int)size) {
513                if (numbytes==-1) {
514                        trace_set_err(libtrace,errno, "read(%s)", 
515                                        libtrace->uridata);
516                        return -1;
517                }
518                trace_set_err(libtrace,EIO,
519                                "Truncated packet (wanted %d, got %d)", 
520                                size, numbytes);
521                /* Failed to read the full packet?  must be EOF */
522                return -1;
523        }
524       
525        if (erf_prepare_packet(libtrace, packet, packet->buffer, 
526                                TRACE_RT_DATA_ERF, flags))
527                return -1;
528       
529        return rlen;
530}
531
532static int erf_dump_packet(libtrace_out_t *libtrace,
533                dag_record_t *erfptr, unsigned int pad, void *buffer) {
534        int numbytes = 0;
535        int size;
536
537        if ((numbytes = 
538                wandio_wwrite(OUTPUT->file, 
539                                erfptr,
540                                (size_t)(dag_record_size + pad))) 
541                        != (int)(dag_record_size+pad)) {
542                trace_set_err_out(libtrace,errno,
543                                "write(%s)",libtrace->uridata);
544                return -1;
545        }
546
547        size=ntohs(erfptr->rlen)-(dag_record_size+pad);
548        numbytes=wandio_wwrite(OUTPUT->file, buffer, (size_t)size);
549        if (numbytes != size) {
550                trace_set_err_out(libtrace,errno,
551                                "write(%s)",libtrace->uridata);
552                return -1;
553        }
554        return numbytes + pad + dag_record_size;
555}
556
557static int erf_start_output(libtrace_out_t *libtrace)
558{
559        OUTPUT->file = trace_open_file_out(libtrace,
560                        OUT_OPTIONS.compress_type,
561                        OUT_OPTIONS.level,
562                        OUT_OPTIONS.fileflag);
563
564        if (!OUTPUT->file) {
565                return -1;
566        }
567        return 0;
568}
569
570static bool find_compatible_linktype(libtrace_out_t *libtrace,
571                                libtrace_packet_t *packet)
572{
573        /* Keep trying to simplify the packet until we can find
574         * something we can do with it */
575        do {
576                char type=libtrace_to_erf_type(trace_get_link_type(packet));
577
578                /* Success */
579                if (type != (char)-1)
580                        return true;
581
582                if (!demote_packet(packet)) {
583                        trace_set_err_out(libtrace,
584                                        TRACE_ERR_NO_CONVERSION,
585                                        "No erf type for packet (%i)",
586                                        trace_get_link_type(packet));
587                        return false;
588                }
589
590        } while(1);
591
592        return true;
593}
594               
595static int erf_write_packet(libtrace_out_t *libtrace, 
596                libtrace_packet_t *packet) 
597{
598        int numbytes = 0;
599        unsigned int pad = 0;
600        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
601        void *payload = packet->payload;
602
603        assert(OUTPUT->file);
604
605        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
606                return 0;
607
608        if (!packet->header) {
609                return -1;
610        }
611       
612        pad = erf_get_padding(packet);
613
614        /* If we've had an rxerror, we have no payload to write - fix
615         * rlen to be the correct length
616         */
617        /* I Think this is bogus, we should somehow figure out
618         * a way to write out the payload even if it is gibberish -- Perry */
619        if (payload == NULL) {
620                dag_hdr->rlen = htons(dag_record_size + pad);
621               
622        } 
623       
624        if (packet->type == TRACE_RT_DATA_ERF) {
625                        numbytes = erf_dump_packet(libtrace,
626                                (dag_record_t *)packet->header,
627                                pad,
628                                payload
629                                );
630        } else {
631                dag_record_t erfhdr;
632                int rlen;
633                /* convert format - build up a new erf header */
634                /* Timestamp */
635                erfhdr.ts = bswap_host_to_le64(trace_get_erf_timestamp(packet));
636
637                /* Flags. Can't do this */
638                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
639                if (trace_get_direction(packet)!=TRACE_DIR_UNKNOWN)
640                        erfhdr.flags.iface = trace_get_direction(packet);
641
642                if (!find_compatible_linktype(libtrace,packet))
643                        return -1;
644
645                payload=packet->payload;
646                pad = erf_get_padding(packet);
647
648                erfhdr.type = libtrace_to_erf_type(trace_get_link_type(packet));
649
650                /* Packet length (rlen includes format overhead) */
651                assert(trace_get_capture_length(packet)>0 
652                                && trace_get_capture_length(packet)<=65536);
653                assert(erf_get_framing_length(packet)>0 
654                                && trace_get_framing_length(packet)<=65536);
655
656                rlen = trace_get_capture_length(packet) + 
657                                erf_get_framing_length(packet);
658                assert(rlen > 0 && rlen <= 65536);
659                erfhdr.rlen = htons(rlen);
660                /* loss counter. Can't do this */
661                erfhdr.lctr = 0;
662                /* Wire length, does not include padding! */
663                erfhdr.wlen = htons(trace_get_wire_length(packet));
664
665                /* Write it out */
666                numbytes = erf_dump_packet(libtrace,
667                                &erfhdr,
668                                pad,
669                                payload);
670        }
671        return numbytes;
672}
673
674libtrace_linktype_t erf_get_link_type(const libtrace_packet_t *packet) {
675        dag_record_t *erfptr = 0;
676        erfptr = (dag_record_t *)packet->header;
677        if (erfptr->type != TYPE_LEGACY)
678                return erf_type_to_libtrace(erfptr->type);
679        else {
680                /* Sigh, lets start wildly guessing */
681                if (((char*)packet->payload)[4]==0x45)
682                        return TRACE_TYPE_PPP;
683                return ~0;
684        }
685}
686
687libtrace_direction_t erf_get_direction(const libtrace_packet_t *packet) {
688        dag_record_t *erfptr = 0;
689        erfptr = (dag_record_t *)packet->header;
690        return erfptr->flags.iface;
691}
692
693libtrace_direction_t erf_set_direction(libtrace_packet_t *packet, libtrace_direction_t direction) {
694        dag_record_t *erfptr = 0;
695        erfptr = (dag_record_t *)packet->header;
696        erfptr->flags.iface = direction;
697        return erfptr->flags.iface;
698}
699
700uint64_t erf_get_erf_timestamp(const libtrace_packet_t *packet) {
701        dag_record_t *erfptr = 0;
702        erfptr = (dag_record_t *)packet->header;
703        return bswap_le_to_host64(erfptr->ts);
704}
705
706int erf_get_capture_length(const libtrace_packet_t *packet) {
707        dag_record_t *erfptr = 0;
708        int caplen;
709        if (packet->payload == NULL)
710                return 0; 
711       
712        erfptr = (dag_record_t *)packet->header;
713        caplen = ntohs(erfptr->rlen) - erf_get_framing_length(packet);
714        if (ntohs(erfptr->wlen) < caplen)
715                return ntohs(erfptr->wlen);
716
717        return (ntohs(erfptr->rlen) - erf_get_framing_length(packet));
718}
719
720int erf_get_wire_length(const libtrace_packet_t *packet) {
721        dag_record_t *erfptr = 0;
722        erfptr = (dag_record_t *)packet->header;
723        return ntohs(erfptr->wlen);
724}
725
726size_t erf_set_capture_length(libtrace_packet_t *packet, size_t size) {
727        dag_record_t *erfptr = 0;
728        assert(packet);
729        if(size  > trace_get_capture_length(packet)) {
730                /* Can't make a packet larger */
731                return trace_get_capture_length(packet);
732        }
733        /* Reset cached capture length - otherwise we will both return the
734         * wrong value here and subsequent get_capture_length() calls will
735         * return the wrong value. */
736        packet->capture_length = -1;
737        erfptr = (dag_record_t *)packet->header;
738        erfptr->rlen = htons(size + erf_get_framing_length(packet));
739        return trace_get_capture_length(packet);
740}
741
742static struct libtrace_eventobj_t erf_event(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
743        struct libtrace_eventobj_t event = {0,0,0.0,0};
744       
745        /* If we are being told to replay packets as fast as possible, then
746         * we just need to read and return the next packet in the trace */
747        if (IN_OPTIONS.real_time) {
748                event.size = erf_read_packet(libtrace, packet);
749                if (event.size < 1)
750                        event.type = TRACE_EVENT_TERMINATE;
751                else
752                        event.type = TRACE_EVENT_PACKET;
753                return event;
754               
755        } else {
756                /* Otherwise, use the generic event function */
757                return trace_event_trace(libtrace, packet);
758        }
759       
760}
761
762static uint64_t erf_get_dropped_packets(libtrace_t *trace)
763{
764        if (trace->format_data == NULL)
765                return (uint64_t)-1;
766        return DATA(trace)->drops;
767}
768
769static void erf_help(void) {
770        printf("erf format module: $Revision: 1752 $\n");
771        printf("Supported input URIs:\n");
772        printf("\terf:/path/to/file\t(uncompressed)\n");
773        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
774        printf("\terf:-\t(stdin, either compressed or not)\n");
775        printf("\terf:/path/to/socket\n");
776        printf("\n");
777        printf("\te.g.: erf:/tmp/trace\n");
778        printf("\n");
779        printf("Supported output URIs:\n");
780        printf("\terf:path/to/file\t(uncompressed)\n");
781        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
782        printf("\terf:-\t(stdout, either compressed or not)\n");
783        printf("\n");
784        printf("\te.g.: erf:/tmp/trace\n");
785        printf("\n");
786
787       
788}
789
790static struct libtrace_format_t erfformat = {
791        "erf",
792        "$Id$",
793        TRACE_FORMAT_ERF,
794        NULL,                           /* probe filename */
795        erf_probe_magic,                /* probe magic */
796        erf_init_input,                 /* init_input */       
797        erf_config_input,               /* config_input */
798        erf_start_input,                /* start_input */
799        NULL,                           /* pause_input */
800        erf_init_output,                /* init_output */
801        erf_config_output,              /* config_output */
802        erf_start_output,               /* start_output */
803        erf_fin_input,                  /* fin_input */
804        erf_fin_output,                 /* fin_output */
805        erf_read_packet,                /* read_packet */
806        erf_prepare_packet,             /* prepare_packet */
807        NULL,                           /* fin_packet */
808        erf_write_packet,               /* write_packet */
809        erf_get_link_type,              /* get_link_type */
810        erf_get_direction,              /* get_direction */
811        erf_set_direction,              /* set_direction */
812        erf_get_erf_timestamp,          /* get_erf_timestamp */
813        NULL,                           /* get_timeval */
814        NULL,                           /* get_timespec */
815        NULL,                           /* get_seconds */
816        erf_seek_erf,                   /* seek_erf */
817        NULL,                           /* seek_timeval */
818        NULL,                           /* seek_seconds */
819        erf_get_capture_length,         /* get_capture_length */
820        erf_get_wire_length,            /* get_wire_length */
821        erf_get_framing_length,         /* get_framing_length */
822        erf_set_capture_length,         /* set_capture_length */
823        NULL,                           /* get_received_packets */
824        NULL,                           /* get_filtered_packets */
825        erf_get_dropped_packets,        /* get_dropped_packets */
826        NULL,                           /* get_captured_packets */
827        NULL,                           /* get_fd */
828        erf_event,                      /* trace_event */
829        erf_help,                       /* help */
830        NULL, /* pstart_input */
831        NULL, /* pread_packet */
832        NULL, /* ppause_input */
833        NULL, /* pfin_input */
834        NULL, /* pconfig_input */
835        NULL                            /* next pointer */
836};
837
838static struct libtrace_format_t rawerfformat = {
839        "rawerf",
840        "$Id$",
841        TRACE_FORMAT_RAWERF,
842        NULL,                           /* probe filename */
843        NULL,           /* probe magic */
844        erf_init_input,                 /* init_input */       
845        erf_config_input,               /* config_input */
846        rawerf_start_input,             /* start_input */
847        NULL,                           /* pause_input */
848        erf_init_output,                /* init_output */
849        erf_config_output,              /* config_output */
850        erf_start_output,               /* start_output */
851        erf_fin_input,                  /* fin_input */
852        erf_fin_output,                 /* fin_output */
853        erf_read_packet,                /* read_packet */
854        erf_prepare_packet,             /* prepare_packet */
855        NULL,                           /* fin_packet */
856        erf_write_packet,               /* write_packet */
857        erf_get_link_type,              /* get_link_type */
858        erf_get_direction,              /* get_direction */
859        erf_set_direction,              /* set_direction */
860        erf_get_erf_timestamp,          /* get_erf_timestamp */
861        NULL,                           /* get_timeval */
862        NULL,                           /* get_timespec */
863        NULL,                           /* get_seconds */
864        erf_seek_erf,                   /* seek_erf */
865        NULL,                           /* seek_timeval */
866        NULL,                           /* seek_seconds */
867        erf_get_capture_length,         /* get_capture_length */
868        erf_get_wire_length,            /* get_wire_length */
869        erf_get_framing_length,         /* get_framing_length */
870        erf_set_capture_length,         /* set_capture_length */
871        NULL,                           /* get_received_packets */
872        NULL,                           /* get_filtered_packets */
873        erf_get_dropped_packets,        /* get_dropped_packets */
874        NULL,                           /* get_captured_packets */
875        NULL,                           /* get_fd */
876        erf_event,                      /* trace_event */
877        erf_help,                       /* help */
878        NULL, /* pstart_input */
879        NULL, /* pread_packet */
880        NULL, /* ppause_input */
881        NULL, /* pfin_input */
882        NULL, /* pconfig_input */
883        NULL                            /* next pointer */
884};
885
886
887
888void erf_constructor(void) {
889        register_format(&erfformat);
890        register_format(&rawerfformat);
891}
Note: See TracBrowser for help on using the repository browser.