source: lib/format_erf.c @ 6b2d5ed

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 6b2d5ed was 6b2d5ed, checked in by Perry Lorier <perry@…>, 15 years ago

Move O_LARGEFILE from erf to helper

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