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