source: lib/format_erf.c @ 7ff881a

cachetimestampsdevelopdpdk-ndagetsiliverc-4.0.3rc-4.0.4ringdecrementfixringperformance
Last change on this file since 7ff881a was 7ff881a, checked in by Shane Alcock <salcock@…>, 3 years ago

Add dpdkndag to the erf_get_padding() fast path.

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