source: lib/format_erf.c @ 0317e3c

cachetimestampsdevelopdpdk-ndagetsilivendag_formatrc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformance
Last change on this file since 0317e3c was 0317e3c, checked in by Shane Alcock <salcock@…>, 3 years ago

Added perf boost to erf_get_padding() for ndag and rawerf formats.

The code will no longer call trace_get_link_type() for these
formats, as packet->header will always point to an ERF header
for both ndag and rawerf which we can use to find the link type
without extra function call overhead.

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