source: lib/format_erf.c @ 30c0246

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 30c0246 was 30c0246, checked in by Shane Alcock <salcock@…>, 16 years ago

Removed debugging line from erf_set_capture_length
Ensured RT_DUCK and RT_STATUS set packet->payload and packet->header
correctly

  • Property mode set to 100644
File size: 25.0 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2004 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 "parse_cmd.h"
38
39#ifdef HAVE_INTTYPES_H
40#  include <inttypes.h>
41#else
42#  error "Can't find inttypes.h - this needs to be fixed"
43#endif
44
45#ifdef HAVE_STDDEF_H
46#  include <stddef.h>
47#else
48# error "Can't find stddef.h - do you define ptrdiff_t elsewhere?"
49#endif
50#include <sys/types.h>
51#include <sys/socket.h>
52#include <sys/un.h>
53#include <sys/mman.h>
54#include <sys/stat.h>
55#include <unistd.h>
56#include <assert.h>
57#include <errno.h>
58#include <netdb.h>
59#include <fcntl.h>
60#include <getopt.h>
61#include <stdio.h>
62#include <string.h>
63#include <stdlib.h>
64
65
66#define COLLECTOR_PORT 3435
67
68static struct libtrace_format_t erf;
69static struct libtrace_format_t rtclient;
70#if HAVE_DAG
71static struct libtrace_format_t dag;
72#endif
73
74#define DATA(x) ((struct erf_format_data_t *)x->format_data)
75#define DATAOUT(x) ((struct erf_format_data_out_t *)x->format_data)
76
77#define CONNINFO DATA(libtrace)->conn_info
78#define INPUT DATA(libtrace)->input
79#define OUTPUT DATAOUT(libtrace)->output
80#if HAVE_DAG
81#define DAG DATA(libtrace)->dag
82#endif
83#define OPTIONS DATAOUT(libtrace)->options
84struct erf_format_data_t {
85        union {
86                struct {
87                        char *hostname;
88                        short port;
89                } rt;
90        } conn_info;
91       
92        union {
93                int fd;
94                LIBTRACE_FILE file;
95        } input;
96
97        struct {
98                enum { INDEX_UNKNOWN=0, INDEX_NONE, INDEX_EXISTS } exists;
99                LIBTRACE_FILE index;
100                off_t index_len;
101        } seek;
102
103#if HAVE_DAG
104        struct {
105                void *buf; 
106                unsigned bottom;
107                unsigned top;
108                unsigned diff;
109                unsigned curr;
110                unsigned offset;
111        } dag;
112#endif
113};
114
115struct erf_format_data_out_t {
116        union {
117                struct {
118                        char *hostname;
119                        short port;
120                } rt;
121                char *path;
122        } conn_info;
123
124        union {
125                struct {
126                        int level;
127                        int fileflag;
128                } erf;
129               
130        } options;
131       
132        union {
133                int fd;
134                struct rtserver_t * rtserver;
135#if HAVE_ZLIB
136                gzFile *file;
137#else
138                int file;
139#endif
140        } output;
141};
142
143/** Structure holding status information for a packet */
144typedef struct libtrace_packet_status {
145        uint8_t type;
146        uint8_t reserved;
147        uint16_t message;
148} libtrace_packet_status_t;
149
150typedef struct erf_index_t {
151        uint64_t timestamp;
152        uint64_t offset; 
153} erf_index_t;
154
155#ifdef HAVE_DAG
156static int dag_init_input(struct libtrace_t *libtrace) {
157        libtrace->format_data = (struct erf_format_data_t *)
158                malloc(sizeof(struct erf_format_data_t));
159        return 0;
160}
161
162static int dag_start_input(struct libtrace_t *libtrace) {
163        struct stat buf;
164        if (stat(libtrace->uridata, &buf) == -1) {
165                trace_set_err(libtrace,errno,"stat(%s)",libtrace->uridata);
166                return -1;
167        } 
168        if (S_ISCHR(buf.st_mode)) {
169                /* DEVICE */
170                if((INPUT.fd = dag_open(libtrace->uridata)) < 0) {
171                        trace_set_err(libtrace,errno,"Cannot open DAG %s",
172                                        libtrace->uridata);
173                        return -1;
174                }
175                if((DAG.buf = (void *)dag_mmap(INPUT.fd)) == MAP_FAILED) {
176                        trace_set_err(libtrace,errno,"Cannot mmap DAG %s",
177                                        libtrace->uridata);
178                        return -1;
179                }
180                if(dag_start(INPUT.fd) < 0) {
181                        trace_set_err(libtrace,errno,"Cannot start DAG %s",
182                                        libtrace->uridata);
183                        return -1;
184                }
185        } else {
186                trace_set_err(libtrace,errno,"Not a valid dag device: %s",
187                                libtrace->uridata);
188                return -1;
189        }
190        return 0;
191}
192#endif
193
194/* Dag erf ether packets have a 2 byte padding before the packet
195 * so that the ip header is aligned on a 32 bit boundary.
196 */
197static int erf_get_padding(const struct libtrace_packet_t *packet)
198{
199        switch(trace_get_link_type(packet)) {
200                case TRACE_TYPE_ETH:    return 2;
201                default:                return 0;
202        }
203}
204
205static int erf_get_framing_length(const struct libtrace_packet_t *packet)
206{
207        return dag_record_size + erf_get_padding(packet);
208}
209
210
211static int erf_init_input(struct libtrace_t *libtrace) 
212{
213        libtrace->format_data = malloc(sizeof(struct erf_format_data_t));
214
215        return 0; /* success */
216}
217
218static int erf_start_input(libtrace_t *libtrace)
219{
220        if (INPUT.file)
221                return 0; /* success */
222
223        INPUT.file = trace_open_file(libtrace);
224
225        if (!INPUT.file)
226                return -1;
227
228        return 0; /* success */
229}
230
231/* Binary search through the index to find the closest point before
232 * the packet.  Consider in future having a btree index perhaps?
233 */
234static int erf_fast_seek_start(libtrace_t *libtrace,uint64_t erfts)
235{
236        size_t max_off = DATA(libtrace)->seek.index_len/sizeof(erf_index_t);
237        size_t min_off = 0;
238        off_t current;
239        erf_index_t record;
240        do {
241                current=(max_off+min_off)>>2;
242
243                LIBTRACE_SEEK(DATA(libtrace)->seek.index,
244                                current*sizeof(record),
245                                SEEK_SET);
246                LIBTRACE_READ(DATA(libtrace)->seek.index,
247                                &record,sizeof(record));
248                if (record.timestamp < erfts) {
249                        min_off=current;
250                }
251                if (record.timestamp > erfts) {
252                        max_off=current;
253                }
254                if (record.timestamp == erfts)
255                        break;
256        } while(min_off<max_off);
257
258        /* If we've passed it, seek backwards.  This loop shouldn't
259         * execute more than twice.
260         */
261        do {
262                LIBTRACE_SEEK(DATA(libtrace)->seek.index,
263                                current*sizeof(record),SEEK_SET);
264                LIBTRACE_READ(DATA(libtrace)->seek.index,
265                                &record,sizeof(record));
266                current--;
267        } while(record.timestamp>erfts);
268
269        /* We've found our location in the trace, now use it. */
270        LIBTRACE_SEEK(INPUT.file,record.offset,SEEK_SET);
271
272        return 0; /* success */
273}
274
275/* There is no index.  Seek through the entire trace from the start, nice
276 * and slowly.
277 */
278static int erf_slow_seek_start(libtrace_t *libtrace,uint64_t erfts)
279{
280        if (INPUT.file) {
281                LIBTRACE_CLOSE(INPUT.file);
282        }
283        INPUT.file = trace_open_file(libtrace);
284        if (!INPUT.file)
285                return -1;
286        return 0;
287}
288
289static int erf_seek_erf(libtrace_t *libtrace,uint64_t erfts)
290{
291        libtrace_packet_t *packet;
292        off_t off = 0;
293
294        if (DATA(libtrace)->seek.exists==INDEX_UNKNOWN) {
295                char buffer[PATH_MAX];
296                snprintf(buffer,sizeof(buffer),"%s.idx",libtrace->uridata);
297                DATA(libtrace)->seek.index=LIBTRACE_OPEN(buffer,"r");
298                if (DATA(libtrace)->seek.index) {
299                        DATA(libtrace)->seek.exists=INDEX_EXISTS;
300                }
301                else {
302                        DATA(libtrace)->seek.exists=INDEX_NONE;
303                }
304        }
305
306        /* If theres an index, use it to find the nearest packet that isn't
307         * after the time we're looking for.  If there is no index we need
308         * to seek slowly through the trace from the beginning.  Sigh.
309         */
310        switch(DATA(libtrace)->seek.exists) {
311                case INDEX_EXISTS:
312                        erf_fast_seek_start(libtrace,erfts);
313                        break;
314                case INDEX_NONE:
315                        erf_slow_seek_start(libtrace,erfts);
316                        break;
317                case INDEX_UNKNOWN:
318                        assert(0);
319                        break;
320        }
321
322        /* Now seek forward looking for the correct timestamp */
323        packet=trace_create_packet();
324        do {
325                trace_read_packet(libtrace,packet);
326                if (trace_get_erf_timestamp(packet)==erfts)
327                        break;
328                off=LIBTRACE_TELL(INPUT.file);
329        } while(trace_get_erf_timestamp(packet)<erfts);
330
331        LIBTRACE_SEEK(INPUT.file,off,SEEK_SET);
332
333        return 0;
334}
335
336static int rtclient_init_input(struct libtrace_t *libtrace) {
337        char *scan;
338        libtrace->format_data = malloc(sizeof(struct erf_format_data_t));
339
340
341        if (strlen(libtrace->uridata) == 0) {
342                CONNINFO.rt.hostname = 
343                        strdup("localhost");
344                CONNINFO.rt.port = 
345                        COLLECTOR_PORT;
346        } else {
347                if ((scan = strchr(libtrace->uridata,':')) == NULL) {
348                        CONNINFO.rt.hostname = 
349                                strdup(libtrace->uridata);
350                        CONNINFO.rt.port =
351                                COLLECTOR_PORT;
352                } else {
353                        CONNINFO.rt.hostname = 
354                                (char *)strndup(libtrace->uridata,
355                                                (scan - libtrace->uridata));
356                        CONNINFO.rt.port = 
357                                atoi(++scan);
358                }
359        }
360
361        return 0; /* success */
362}
363
364static int rtclient_start_input(libtrace_t *libtrace)
365{
366        struct hostent *he;
367        struct sockaddr_in remote;
368        if ((he=gethostbyname(CONNINFO.rt.hostname)) == NULL) { 
369                trace_set_err(libtrace,errno,"failed to resolve %s",
370                                CONNINFO.rt.hostname);
371                return -1;
372        } 
373        if ((INPUT.fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
374                trace_set_err(libtrace,errno,"socket(AF_INET,SOCK_STREAM)");
375                return -1;
376        }
377
378        remote.sin_family = AF_INET;   
379        remote.sin_port = htons(CONNINFO.rt.port);
380        remote.sin_addr = *((struct in_addr *)he->h_addr);
381        bzero(&(remote.sin_zero), 8);
382
383        if (connect(INPUT.fd, (struct sockaddr *)&remote,
384                                sizeof(struct sockaddr)) == -1) {
385                trace_set_err(libtrace,errno,"connect(%s)",
386                                CONNINFO.rt.hostname);
387                return -1;
388        }
389        return 0; /* success */
390}
391
392static int rtclient_pause_input(libtrace_t *libtrace)
393{
394        close(INPUT.fd);
395        return 0; /* success */
396}
397
398static int erf_init_output(struct libtrace_out_t *libtrace) {
399        libtrace->format_data = calloc(1,sizeof(struct erf_format_data_out_t));
400
401        OPTIONS.erf.level = 0;
402        OPTIONS.erf.fileflag = O_CREAT | O_LARGEFILE | O_WRONLY;
403        OUTPUT.file = 0;
404
405        return 0;
406}
407
408static int erf_config_output(struct libtrace_out_t *libtrace, trace_option_t option, void *value) {
409
410        switch (option) {
411                case TRACE_OPTION_OUTPUT_COMPRESS:
412                        OPTIONS.erf.level = *(int*)value;
413                        return 0;
414                case TRACE_OPTION_OUTPUT_FILEFLAGS:
415                        OPTIONS.erf.fileflag = *(int*)value;
416                        return 0;
417                default:
418                        /* Unknown option */
419                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
420                                        "Unknown option");
421                        return -1;
422        }
423}
424
425
426#ifdef HAVE_DAG
427static int dag_fin_input(struct libtrace_t *libtrace) {
428        dag_stop(INPUT.fd);
429        free(libtrace->format_data);
430}
431#endif
432
433static int rtclient_fin_input(struct libtrace_t *libtrace) {
434        free(CONNINFO.rt.hostname);
435        close(INPUT.fd);
436        free(libtrace->format_data);
437        return 0;
438}
439
440static int erf_fin_input(struct libtrace_t *libtrace) {
441        LIBTRACE_CLOSE(INPUT.file);
442        free(libtrace->format_data);
443        return 0;
444}
445
446static int erf_fin_output(struct libtrace_out_t *libtrace) {
447        LIBTRACE_CLOSE(OUTPUT.file);
448        free(libtrace->format_data);
449        return 0;
450}
451 
452#if HAVE_DAG
453static int dag_read(struct libtrace_t *libtrace, int block_flag) {
454        int numbytes;
455        static short lctr = 0;
456        struct dag_record_t *erfptr = 0;
457        int rlen;
458
459        if (DAG.diff != 0) 
460                return DAG.diff;
461
462        DAG.bottom = DAG.top;
463        DAG.top = dag_offset(
464                        INPUT.fd,
465                        &(DAG.bottom),
466                        block_flag);
467        DAG.diff = DAG.top -
468                DAG.bottom;
469
470        numbytes=DAG.diff;
471        DAG.offset = 0;
472        return numbytes;
473}
474#endif
475
476#if HAVE_DAG
477/* FIXME: dag_read_packet shouldn't update the pointers, dag_fin_packet
478 * should do that.
479 */
480static int dag_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
481        int numbytes;
482        int size;
483        dag_record_t *erfptr;
484        void *buffer = packet->buffer;
485        void *buffer2 = buffer;
486        int rlen;
487
488        if (packet->buf_control == TRACE_CTRL_PACKET) {
489                packet->buf_control = TRACE_CTRL_EXTERNAL;
490                free(packet->buffer);
491                packet->buffer = 0;
492        }
493       
494        packet->type = RT_DATA_ERF;
495       
496        if ((numbytes = dag_read(libtrace,0)) <= 0) 
497                return numbytes;
498
499        /*DAG always gives us whole packets */
500        erfptr = (dag_record_t *) ((void *)DAG.buf + 
501                        (DAG.bottom + DAG.offset));
502        size = ntohs(erfptr->rlen);
503
504        if ( size  > LIBTRACE_PACKET_BUFSIZE) {
505                assert( size < LIBTRACE_PACKET_BUFSIZE);
506        }
507       
508        packet->buffer = erfptr;
509        packet->header = erfptr;
510        if (((dag_record_t *)packet->buffer)->flags.rxerror == 1) {
511                packet->payload = NULL;
512        } else {
513                packet->payload = packet->buffer + erf_get_framing_length(packet);
514        }
515
516        DAG.offset += size;
517        DAG.diff -= size;
518
519        assert(DAG.diff >= 0);
520
521        return (size);
522}
523#endif
524
525static int erf_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
526        int numbytes;
527        int size;
528        void *buffer2 = packet->buffer;
529        int rlen;
530
531        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
532                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
533                packet->buf_control = TRACE_CTRL_PACKET;
534        }
535
536        packet->header = packet->buffer;
537        packet->type = RT_DATA_ERF;
538
539        if ((numbytes=LIBTRACE_READ(INPUT.file,
540                                        packet->buffer,
541                                        dag_record_size)) == -1) {
542                trace_set_err(libtrace,errno,"read(%s)",
543                                libtrace->uridata);
544                return -1;
545        }
546        if (numbytes == 0) {
547                return 0;
548        }
549
550        rlen = ntohs(((dag_record_t *)packet->buffer)->rlen);
551        buffer2 = (char*)packet->buffer + dag_record_size;
552        size = rlen - dag_record_size;
553        assert(size < LIBTRACE_PACKET_BUFSIZE);
554
555       
556        /* Unknown/corrupt */
557        assert(((dag_record_t *)packet->buffer)->type < 10);
558       
559        /* read in the rest of the packet */
560        if ((numbytes=LIBTRACE_READ(INPUT.file,
561                                        buffer2,
562                                        size)) != size) {
563                trace_set_err(libtrace,errno, "read(%s)", libtrace->uridata);
564                return -1;
565        }
566        if (((dag_record_t *)packet->buffer)->flags.rxerror == 1) {
567                packet->payload = NULL;
568        } else {
569                packet->payload = (char*)packet->buffer + erf_get_framing_length(packet);
570        }
571        return rlen;
572}
573
574static int rtclient_read(struct libtrace_t *libtrace, void *buffer, size_t len) {
575        int numbytes;
576
577        while(1) {
578#ifndef MSG_NOSIGNAL
579#  define MSG_NOSIGNAL 0
580#endif
581                if ((numbytes = recv(INPUT.fd,
582                                                buffer,
583                                                len,
584                                                MSG_NOSIGNAL)) == -1) {
585                        if (errno == EINTR) {
586                                /*ignore EINTR in case
587                                 *a caller is using signals
588                                 */
589                                continue;
590                        }
591                        trace_set_err(libtrace,errno,"recv(%s)",
592                                        libtrace->uridata);
593                        return -1;
594                }
595                break;
596
597        }
598        return numbytes;
599}
600
601static int rtclient_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
602        int numbytes = 0;
603        char buf[RP_BUFSIZE];
604        int read_required = 0;
605       
606        void *buffer = 0;
607
608        if (packet->buf_control == TRACE_CTRL_EXTERNAL || !packet->buffer) {
609                packet->buf_control = TRACE_CTRL_PACKET;
610                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
611        }
612
613        buffer = packet->buffer;
614        packet->header = packet->buffer;
615       
616        packet->type = RT_DATA_ERF;
617
618       
619        do {
620                struct libtrace_packet_status status;
621                int size;
622                if (tracefifo_out_available(libtrace->fifo) == 0 
623                                || read_required) {
624                        if ((numbytes = rtclient_read(
625                                        libtrace,buf,RP_BUFSIZE))<=0) {
626                                return numbytes;
627                        }
628                        tracefifo_write(libtrace->fifo,buf,numbytes);
629                        read_required = 0;
630                }
631                /* Read status byte */
632                if (tracefifo_out_read(libtrace->fifo,
633                                &status, sizeof(uint32_t)) == 0) {
634                        read_required = 1;
635                        continue;
636                }
637                tracefifo_out_update(libtrace->fifo,sizeof(uint32_t));
638                /* Read in packet size */
639                if (tracefifo_out_read(libtrace->fifo,
640                                &size, sizeof(uint32_t)) == 0) {
641                        tracefifo_out_reset(libtrace->fifo);
642                        read_required = 1;
643                        continue;
644                }
645                tracefifo_out_update(libtrace->fifo, sizeof(uint32_t));
646               
647                if (status.type == 2 /* RT_MSG */) {
648                        /* Need to skip this packet as it is a message packet */
649                        tracefifo_out_update(libtrace->fifo, size);
650                        tracefifo_ack_update(libtrace->fifo, size + 
651                                        sizeof(uint32_t) + 
652                                        sizeof(libtrace_packet_status_t));
653                        continue;
654                }
655               
656                /* read in the full packet */
657                if ((numbytes = tracefifo_out_read(libtrace->fifo, 
658                                                buffer, size)) == 0) {
659                        tracefifo_out_reset(libtrace->fifo);
660                        read_required = 1;
661                        continue;
662                }
663
664                /* got in our whole packet, so... */
665                tracefifo_out_update(libtrace->fifo,size);
666
667                tracefifo_ack_update(libtrace->fifo,size + 
668                                sizeof(uint32_t) + 
669                                sizeof(libtrace_packet_status_t));
670
671                if (((dag_record_t *)buffer)->flags.rxerror == 1) {
672                        packet->payload = NULL;
673                } else {
674                        packet->payload = (char*)packet->buffer + erf_get_framing_length(packet);
675                }
676                return numbytes;
677        } while(1);
678}
679
680static int erf_dump_packet(libtrace_out_t *libtrace,
681                dag_record_t *erfptr, int pad, void *buffer, size_t size) {
682        int numbytes = 0;
683        assert(size<=65536);
684        /* FIXME: Shouldn't this return != dag_record_size+pad on error? */
685        if ((numbytes = LIBTRACE_WRITE(OUTPUT.file, erfptr, dag_record_size + pad)) == 0) {
686                trace_set_err_out(libtrace,errno,
687                                "write(%s)",libtrace->uridata);
688                return -1;
689        }
690
691        if ((numbytes=LIBTRACE_WRITE(OUTPUT.file, buffer, size)) == 0) {
692                trace_set_err_out(libtrace,errno,
693                                "write(%s)",libtrace->uridata);
694                return -1;
695        }
696
697        return numbytes + pad + dag_record_size;
698}
699
700static int erf_start_output(libtrace_out_t *libtrace)
701{
702        OUTPUT.file = trace_open_file_out(libtrace,
703                        OPTIONS.erf.level,
704                        OPTIONS.erf.fileflag);
705        if (!OUTPUT.file) {
706                return -1;
707        }
708        return 0;
709}
710               
711static int erf_write_packet(libtrace_out_t *libtrace, 
712                const libtrace_packet_t *packet) 
713{
714        int numbytes = 0;
715        int pad = 0;
716        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
717        void *payload = packet->payload;
718
719        assert(OUTPUT.file);
720
721        pad = erf_get_padding(packet);
722
723        /* If we've had an rxerror, we have no payload to write - fix rlen to
724         * be the correct length */
725        if (payload == NULL) {
726                dag_hdr->rlen = htons(dag_record_size + pad);
727        } 
728       
729        if (libtrace->format == &erf 
730#if HAVE_DAG
731                        || libtrace->format == &dag
732#endif
733                        ) {
734                numbytes = erf_dump_packet(libtrace,
735                                (dag_record_t *)packet->buffer,
736                                pad,
737                                payload,
738                                trace_get_capture_length(packet)
739                                );
740        } else {
741                dag_record_t erfhdr;
742                int type;
743                /* convert format - build up a new erf header */
744                /* Timestamp */
745                erfhdr.ts = trace_get_erf_timestamp(packet);
746                type=libtrace_to_erf_type(trace_get_link_type(packet));
747                if (type==(char)-1) {
748                        trace_set_err_out(libtrace,TRACE_ERR_BAD_PACKET,
749                                        "No erf type for packet");
750                        return -1;
751                }
752                erfhdr.type = type;
753                /* Flags. Can't do this */
754                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
755                /* Packet length (rlen includes format overhead) */
756                erfhdr.rlen = trace_get_capture_length(packet) 
757                        + erf_get_framing_length(packet);
758                /* loss counter. Can't do this */
759                erfhdr.lctr = 0;
760                /* Wire length */
761                erfhdr.wlen = trace_get_wire_length(packet);
762
763                /* Write it out */
764                numbytes = erf_dump_packet(libtrace,
765                                &erfhdr,
766                                pad,
767                                payload,
768                                trace_get_capture_length(packet));
769        }
770        return numbytes;
771}
772
773static libtrace_linktype_t erf_get_link_type(const struct libtrace_packet_t *packet) {
774        dag_record_t *erfptr = 0;
775        erfptr = (dag_record_t *)packet->header;
776        return erf_type_to_libtrace(erfptr->type);
777}
778
779static int8_t erf_get_direction(const struct libtrace_packet_t *packet) {
780        dag_record_t *erfptr = 0;
781        erfptr = (dag_record_t *)packet->header;
782        return erfptr->flags.iface;
783}
784
785static int8_t erf_set_direction(const struct libtrace_packet_t *packet, int8_t direction) {
786        dag_record_t *erfptr = 0;
787        erfptr = (dag_record_t *)packet->header;
788        erfptr->flags.iface = direction;
789        return erfptr->flags.iface;
790}
791
792static uint64_t erf_get_erf_timestamp(const struct libtrace_packet_t *packet) {
793        dag_record_t *erfptr = 0;
794        erfptr = (dag_record_t *)packet->header;
795        return erfptr->ts;
796}
797
798static int erf_get_capture_length(const struct libtrace_packet_t *packet) {
799        dag_record_t *erfptr = 0;
800        erfptr = (dag_record_t *)packet->header;
801        return (ntohs(erfptr->rlen) - erf_get_framing_length(packet));
802}
803
804static int erf_get_wire_length(const struct libtrace_packet_t *packet) {
805        dag_record_t *erfptr = 0;
806        erfptr = (dag_record_t *)packet->header;
807        return ntohs(erfptr->wlen);
808}
809
810static size_t erf_set_capture_length(struct libtrace_packet_t *packet, size_t size) {
811        dag_record_t *erfptr = 0;
812        assert(packet);
813        if(size  > trace_get_capture_length(packet)) {
814                /* can't make a packet larger */
815                return trace_get_capture_length(packet);
816        }
817        erfptr = (dag_record_t *)packet->header;
818        erfptr->rlen = htons(size + erf_get_framing_length(packet));
819        return trace_get_capture_length(packet);
820}
821
822static int rtclient_get_fd(const libtrace_t *libtrace) {
823        return INPUT.fd;
824}
825
826#ifdef HAVE_DAG
827struct libtrace_eventobj_t trace_event_dag(struct libtrace_t *trace, struct libtrace_packet_t *packet) {
828        struct libtrace_eventobj_t event = {0,0,0.0,0};
829        int dag_fd;
830        int data;
831
832        if (trace->format->get_fd) {
833                dag_fd = trace->format->get_fd(trace);
834        } else {
835                dag_fd = 0;
836        }
837       
838        data = dag_read(trace, DAGF_NONBLOCK);
839
840        if (data > 0) {
841                event.size = trace_read_packet(trace,packet);
842                event.type = TRACE_EVENT_PACKET;
843                return event;
844        }
845        event.type = TRACE_EVENT_SLEEP;
846        event.seconds = 0.0001;
847        return event;
848}
849#endif
850
851#if HAVE_DAG
852static void dag_help() {
853        printf("dag format module: $Revision$\n");
854        printf("Supported input URIs:\n");
855        printf("\tdag:/dev/dagn\n");
856        printf("\n");
857        printf("\te.g.: dag:/dev/dag0\n");
858        printf("\n");
859        printf("Supported output URIs:\n");
860        printf("\tnone\n");
861        printf("\n");
862}
863#endif
864
865static void erf_help() {
866        printf("erf format module: $Revision$\n");
867        printf("Supported input URIs:\n");
868        printf("\terf:/path/to/file\t(uncompressed)\n");
869        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
870        printf("\terf:-\t(stdin, either compressed or not)\n");
871        printf("\terf:/path/to/socket\n");
872        printf("\n");
873        printf("\te.g.: erf:/tmp/trace\n");
874        printf("\n");
875        printf("Supported output URIs:\n");
876        printf("\terf:path/to/file\t(uncompressed)\n");
877        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
878        printf("\terf:-\t(stdout, either compressed or not)\n");
879        printf("\n");
880        printf("\te.g.: erf:/tmp/trace\n");
881        printf("\n");
882        printf("Supported output options:\n");
883        printf("\t-z\tSpecify the gzip compression, ranging from 0 (uncompressed) to 9 - defaults to 1\n");
884        printf("\n");
885
886       
887}
888
889static void rtclient_help() {
890        printf("rtclient format module: $Revision$\n");
891        printf("DEPRECATED - use rt module instead\n");
892        printf("Supported input URIs:\n");
893        printf("\trtclient:host:port\n");
894        printf("\n");
895        printf("\te.g.:rtclient:localhost:3435\n");
896        printf("\n");
897        printf("Supported output URIs:\n");
898        printf("\tnone\n");
899        printf("\n");
900}       
901
902static struct libtrace_format_t erf = {
903        "erf",
904        "$Id$",
905        TRACE_FORMAT_ERF,
906        erf_init_input,                 /* init_input */       
907        NULL,                           /* config_input */
908        erf_start_input,                /* start_input */
909        NULL,                           /* pause_input */
910        erf_init_output,                /* init_output */
911        erf_config_output,              /* config_output */
912        erf_start_output,               /* start_output */
913        erf_fin_input,                  /* fin_input */
914        erf_fin_output,                 /* fin_output */
915        erf_read_packet,                /* read_packet */
916        erf_write_packet,               /* write_packet */
917        erf_get_link_type,              /* get_link_type */
918        erf_get_direction,              /* get_direction */
919        erf_set_direction,              /* set_direction */
920        erf_get_erf_timestamp,          /* get_erf_timestamp */
921        NULL,                           /* get_timeval */
922        NULL,                           /* get_seconds */
923        erf_seek_erf,                   /* seek_erf */
924        NULL,                           /* seek_timeval */
925        NULL,                           /* seek_seconds */
926        erf_get_capture_length,         /* get_capture_length */
927        erf_get_wire_length,            /* get_wire_length */
928        erf_get_framing_length,         /* get_framing_length */
929        erf_set_capture_length,         /* set_capture_length */
930        NULL,                           /* get_fd */
931        trace_event_trace,              /* trace_event */
932        erf_help                        /* help */
933};
934
935#ifdef HAVE_DAG
936static struct libtrace_format_t dag = {
937        "dag",
938        "$Id$",
939        TRACE_FORMAT_ERF,
940        dag_init_input,                 /* init_input */       
941        NULL,                           /* config_input */
942        dag_start_input,                /* start_input */
943        NULL,                           /* pause_input */
944        NULL,                           /* init_output */
945        NULL,                           /* config_output */
946        NULL,                           /* start_output */
947        dag_fin_input,                  /* fin_input */
948        NULL,                           /* fin_output */
949        dag_read_packet,                /* read_packet */
950        NULL,                           /* write_packet */
951        erf_get_link_type,              /* get_link_type */
952        erf_get_direction,              /* get_direction */
953        erf_set_direction,              /* set_direction */
954        erf_get_erf_timestamp,          /* get_erf_timestamp */
955        NULL,                           /* get_timeval */
956        NULL,                           /* get_seconds */
957        NULL,                           /* seek_erf */
958        NULL,                           /* seek_timeval */
959        NULL,                           /* seek_seconds */
960        erf_get_capture_length,         /* get_capture_length */
961        erf_get_wire_length,            /* get_wire_length */
962        erf_get_framing_length,         /* get_framing_length */
963        erf_set_capture_length,         /* set_capture_length */
964        NULL,                           /* get_fd */
965        trace_event_dag,                /* trace_event */
966        dag_help                        /* help */
967};
968#endif
969
970static struct libtrace_format_t rtclient = {
971        "rtclient",
972        "$Id$",
973        TRACE_FORMAT_ERF,
974        rtclient_init_input,            /* init_input */       
975        NULL,                           /* config_input */
976        rtclient_start_input,           /* start_input */
977        rtclient_pause_input,           /* pause_input */
978        NULL,                           /* init_output */
979        NULL,                           /* config_output */
980        NULL,                           /* start_output */
981        rtclient_fin_input,             /* fin_input */
982        NULL,                           /* fin_output */
983        rtclient_read_packet,           /* read_packet */
984        NULL,                           /* write_packet */
985        erf_get_link_type,              /* get_link_type */
986        erf_get_direction,              /* get_direction */
987        erf_set_direction,              /* set_direction */
988        erf_get_erf_timestamp,          /* get_erf_timestamp */
989        NULL,                           /* get_timeval */
990        NULL,                           /* get_seconds */
991        NULL,                           /* seek_erf */
992        NULL,                           /* seek_timeval */
993        NULL,                           /* seek_seconds */
994        erf_get_capture_length,         /* get_capture_length */
995        erf_get_wire_length,            /* get_wire_length */
996        erf_get_framing_length,         /* get_framing_length */
997        erf_set_capture_length,         /* set_capture_length */
998        rtclient_get_fd,                /* get_fd */
999        trace_event_device,             /* trace_event */
1000        rtclient_help                   /* help */
1001};
1002
1003void __attribute__((constructor)) erf_constructor() {
1004        register_format(&rtclient);
1005        register_format(&erf);
1006#ifdef HAVE_DAG
1007        register_format(&dag);
1008#endif
1009}
Note: See TracBrowser for help on using the repository browser.