source: lib/format_erf.c @ 7050c10

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 7050c10 was 7050c10, checked in by Daniel Lawson <dlawson@…>, 15 years ago

updated new backend - libtrace_erf, libtrace_pcap all work

  • Property mode set to 100644
File size: 13.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
31#include "libtrace.h"
32#include "format.h"
33
34#ifdef HAVE_INTTYPES_H
35#  include <inttypes.h>
36#else
37#  error "Can't find inttypes.h - this needs to be fixed"
38#endif
39
40#ifdef HAVE_STDDEF_H
41#  include <stddef.h>
42#else
43# error "Can't find stddef.h - do you define ptrdiff_t elsewhere?"
44#endif
45#include <sys/types.h>
46#include <sys/socket.h>
47#include <sys/un.h>
48#include <sys/mman.h>
49#include <sys/stat.h>
50#include <unistd.h>
51#include <assert.h>
52#include <errno.h>
53#include <netdb.h>
54
55/* Catch undefined O_LARGEFILE on *BSD etc */
56#ifndef O_LARGEFILE
57#  define O_LARGEFILE 0
58#endif
59static int dag_init_input(struct libtrace_t *libtrace) {
60#ifdef HAVE_DAG
61        struct stat buf;
62        if (stat(libtrace->conn_info.path,&buf) == -1) {
63                perror("stat");
64                return 0;
65        } 
66        if (S_ISCHR(buf.st_mode)) {
67                // DEVICE
68                if((libtrace->input.fd = 
69                                dag_open(libtrace->conn_info.path)) < 0) {
70                        fprintf(stderr,"Cannot open DAG %s: %m\n", 
71                                        libtrace->conn_info.path,errno);
72                        exit(0);
73                }
74                if((libtrace->dag.buf = (void *)
75                                dag_mmap(libtrace->input.fd)) == MAP_FAILED) {
76                        fprintf(stderr,"Cannot mmap DAG %s: %m\n", 
77                                        libtrace->conn_info.path,errno);
78                        exit(0);
79                }
80                if(dag_start(libtrace->input.fd) < 0) {
81                        fprintf(stderr,"Cannot start DAG %s: %m\n", 
82                                        libtrace->conn_info.path,errno);
83                        exit(0);
84                }
85        } else {
86                fprintf(stderr,"%s isn't a valid char device, exiting\n",
87                                libtrace->conn_info.path);
88                return 0;
89        }
90#endif
91}
92
93static int erf_init_input(struct libtrace_t *libtrace) {
94        struct stat buf;
95        struct hostent *he;
96        struct sockaddr_in remote;
97        struct sockaddr_un unix_sock;
98        if (!strncmp(libtrace->conn_info.path,"-",1)) {
99                // STDIN
100#if HAVE_ZLIB
101                libtrace->input.file = gzdopen(STDIN, "r");
102#else   
103                libtrace->input.file = stdin;
104#endif
105
106        } else {
107                if (stat(libtrace->conn_info.path,&buf) == -1 ) {
108                        perror("stat");
109                        return 0;
110                }
111                if (S_ISSOCK(buf.st_mode)) {
112                        // SOCKET
113                        if ((libtrace->input.fd = socket(
114                                        AF_UNIX, SOCK_STREAM, 0)) == -1) {
115                                perror("socket");
116                                return 0;
117                        }
118                        unix_sock.sun_family = AF_UNIX;
119                        bzero(unix_sock.sun_path,108);
120                        snprintf(unix_sock.sun_path,
121                                        108,"%s"
122                                        ,libtrace->conn_info.path);
123
124                        if (connect(libtrace->input.fd, 
125                                        (struct sockaddr *)&unix_sock,
126                                        sizeof(struct sockaddr)) == -1) {
127                                perror("connect (unix)");
128                                return 0;
129                        }
130                } else { 
131                        // TRACE
132#if HAVE_ZLIB
133                        // using gzdopen means we can set O_LARGEFILE
134                        // ourselves. However, this way is messy and
135                        // we lose any error checking on "open"
136                        libtrace->input.file = 
137                                gzdopen(open(
138                                        libtrace->conn_info.path,
139                                        O_LARGEFILE), "r");
140#else
141                        libtrace->input.file = 
142                                fdopen(open(
143                                        libtrace->conn_info.path,
144                                        O_LARGEFILE), "r");
145#endif
146
147                }
148        }
149}
150
151static int rtclient_init_input(struct libtrace_t *libtrace) {
152        char *scan;
153        char *uridata = libtrace->conn_info.path;
154        struct hostent *he;
155        struct sockaddr_in remote;
156
157        if (strlen(uridata) == 0) {
158                libtrace->conn_info.rt.hostname = 
159                        strdup("localhost");
160                libtrace->conn_info.rt.port = 
161                        COLLECTOR_PORT;
162        } else {
163                if ((scan = strchr(uridata,':')) == NULL) {
164                        libtrace->conn_info.rt.hostname = 
165                                strdup(uridata);
166                        libtrace->conn_info.rt.port =
167                                COLLECTOR_PORT;
168                } else {
169                        libtrace->conn_info.rt.hostname = 
170                                (char *)strndup(uridata,
171                                                (scan - uridata));
172                        libtrace->conn_info.rt.port = 
173                                atoi(++scan);
174                }
175        }
176       
177        if ((he=gethostbyname(libtrace->conn_info.rt.hostname)) == NULL) { 
178                perror("gethostbyname");
179                return 0;
180        } 
181        if ((libtrace->input.fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
182                perror("socket");
183                return 0;
184        }
185
186        remote.sin_family = AF_INET;   
187        remote.sin_port = htons(libtrace->conn_info.rt.port);
188        remote.sin_addr = *((struct in_addr *)he->h_addr);
189        bzero(&(remote.sin_zero), 8);
190
191        if (connect(libtrace->input.fd, (struct sockaddr *)&remote,
192                                sizeof(struct sockaddr)) == -1) {
193                perror("connect (inet)");
194                return 0;
195        }
196}
197
198static int dag_fin_input(struct libtrace_t *libtrace) {
199#ifdef HAVE_DAG
200        dag_stop(libtrace->input.fd);
201#endif
202}
203
204static int erf_fin_input(struct libtrace_t *libtrace) {
205#if HAVE_ZLIB
206        gzclose(libtrace->input.file);
207#else   
208        fclose(libtrace->input.file);   
209#endif
210}
211
212static int rtclient_fin_input(struct libtrace_t *libtrace) {
213        close(libtrace->input.fd);
214}
215
216static int dag_read(struct libtrace_t *libtrace, void *buffer, size_t len) {
217#if HAVE_DAG
218        int numbytes;
219        static short lctr = 0;
220        struct dag_record_t *erfptr = 0;
221        int rlen;
222
223        if (buffer == 0)
224                buffer = malloc(len);
225       
226        libtrace->dag.bottom = libtrace->dag.top;
227        libtrace->dag.top = dag_offset(
228                        libtrace->input.fd,
229                        &(libtrace->dag.bottom),
230                        0);
231        libtrace->dag.diff = libtrace->dag.top -
232                libtrace->dag.bottom;
233
234        numbytes=libtrace->dag.diff;
235        libtrace->dag.offset = 0;
236        return numbytes;
237#else
238        return -1;
239#endif
240}
241
242static int dag_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
243#if HAVE_DAG
244        int numbytes;
245        int size;
246        char buf[RP_BUFSIZE];
247        dag_record_t *erfptr;
248        void *buffer = packet->buffer;
249        void *buffer2 = buffer;
250        int rlen;
251       
252        if (libtrace->dag.diff == 0) {
253                if ((numbytes = dag_read(libtrace,buf,RP_BUFSIZE)) <= 0) 
254                        return numbytes;
255        }
256
257        //DAG always gives us whole packets
258        erfptr = (dag_record_t *) ((void *)libtrace->dag.buf + 
259                        (libtrace->dag.bottom + libtrace->dag.offset));
260        size = ntohs(erfptr->rlen);
261
262        if ( size  > LIBTRACE_PACKET_BUFSIZE) {
263                printf("%d\n",size);
264                assert( size < LIBTRACE_PACKET_BUFSIZE);
265        }
266
267        // have to copy it out of the memory hole at this stage:
268        memcpy(packet->buffer, erfptr, size);
269
270        packet->size = size;
271        libtrace->dag.offset += size;
272        libtrace->dag.diff -= size;
273
274        assert(libtrace->dag.diff >= 0);
275
276        return (size);
277#else
278        return -1;
279#endif
280}
281
282static int erf_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
283        int numbytes;
284        int size;
285        char buf[RP_BUFSIZE];
286        dag_record_t *erfptr;
287        void *buffer = packet->buffer;
288        void *buffer2 = buffer;
289        int rlen;
290       
291        if ((numbytes=gzread(libtrace->input.file,
292                                        buffer,
293                                        dag_record_size)) == -1) {
294                perror("gzread");
295                return -1;
296        }
297        if (numbytes == 0) {
298                return 0;
299        }
300        rlen = ntohs(((dag_record_t *)buffer)->rlen);
301        size = rlen - dag_record_size;
302        assert(size < LIBTRACE_PACKET_BUFSIZE);
303        buffer2 = buffer + dag_record_size;
304       
305        // read in the rest of the packet
306        if ((numbytes=gzread(libtrace->input.file,
307                                        buffer2,
308                                        size)) == -1) {
309                perror("gzread");
310                return -1;
311        }
312        packet->size = rlen;
313        return rlen;
314}
315
316static int rtclient_read(struct libtrace_t *libtrace, void *buffer, size_t len) {
317        int numbytes;
318        static short lctr = 0;
319        struct dag_record_t *erfptr = 0;
320        int rlen;
321
322        if (buffer == 0)
323                buffer = malloc(len);
324        while(1) {
325#ifndef MSG_NOSIGNAL
326#  define MSG_NOSIGNAL 0
327#endif
328                if ((numbytes = recv(libtrace->input.fd,
329                                                buffer,
330                                                len,
331                                                MSG_NOSIGNAL)) == -1) {
332                        if (errno == EINTR) {
333                                //ignore EINTR in case
334                                // a caller is using signals
335                                continue;
336                        }
337                        perror("recv");
338                        return -1;
339                }
340                break;
341
342        }
343        return numbytes;
344}
345
346static int rtclient_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
347        int numbytes;
348        int size;
349        char buf[RP_BUFSIZE];
350        dag_record_t *erfptr;
351        int read_required = 0;
352       
353        void *buffer = 0;
354        buffer = packet->buffer;
355
356        do {
357                if (fifo_out_available(libtrace->fifo) == 0 || read_required) {
358                        if ((numbytes = rtclient_read(
359                                                libtrace,buf,RP_BUFSIZE))<=0) {
360                                return numbytes;
361                        }
362                        assert(libtrace->fifo);
363                        fifo_write(libtrace->fifo,buf,numbytes);
364                        read_required = 0;
365                }
366                // Read status byte
367                if (fifo_out_read(libtrace->fifo,
368                                &packet->status, sizeof(int)) == 0) {
369                        read_required = 1;
370                        continue;
371                }
372                fifo_out_update(libtrace->fifo,sizeof(int));
373
374                // read in the ERF header
375                if ((numbytes = fifo_out_read(libtrace->fifo, buffer,
376                                                sizeof(dag_record_t))) == 0) {
377                        fifo_out_reset(libtrace->fifo);
378                        read_required = 1;
379                        continue;
380                }
381                size = ntohs(((dag_record_t *)buffer)->rlen);
382
383                // read in the full packet
384                if ((numbytes = fifo_out_read(libtrace->fifo, 
385                                                buffer, size)) == 0) {
386                        fifo_out_reset(libtrace->fifo);
387                        read_required = 1;
388                        continue;
389                }
390
391                // got in our whole packet, so...
392                fifo_out_update(libtrace->fifo,size);
393
394                fifo_ack_update(libtrace->fifo,size + sizeof(int));
395
396                packet->size = numbytes;
397                return numbytes;
398        } while(1);
399}
400
401static void *erf_get_link(const struct libtrace_packet_t *packet) {
402        dag_record_t *erfptr = 0;
403        erfptr = (dag_record_t *)packet->buffer;
404        const void *ethptr = 0;
405
406        if (erfptr->flags.rxerror == 1) {
407                return NULL;
408        }
409        ethptr = ((uint8_t *)packet->buffer +
410                        dag_record_size + 2);
411        return ethptr;
412}
413
414static libtrace_linktype_t erf_get_link_type(const struct libtrace_packet_t *packet) {
415        dag_record_t *erfptr = 0;
416        erfptr = (dag_record_t *)packet->buffer;
417        switch (erfptr->type) {
418                case TYPE_ETH: return TRACE_TYPE_ETH;
419                case TYPE_ATM: return TRACE_TYPE_ATM;
420                default: assert(0);
421        }
422        return erfptr->type;
423}
424
425static int8_t erf_get_direction(const struct libtrace_packet_t *packet) {
426        dag_record_t *erfptr = 0;
427        erfptr = (dag_record_t *)packet->buffer;
428        return erfptr->flags.iface;
429}
430
431static int8_t erf_set_direction(const struct libtrace_packet_t *packet, int8_t direction) {
432        dag_record_t *erfptr = 0;
433        erfptr = (dag_record_t *)packet->buffer;
434        erfptr->flags.iface = direction;
435        return erfptr->flags.iface;
436}
437
438static uint64_t erf_get_erf_timestamp(const struct libtrace_packet_t *packet) {
439        dag_record_t *erfptr = 0;
440        erfptr = (dag_record_t *)packet->buffer;
441        return erfptr->ts;
442}
443
444static int erf_get_capture_length(const struct libtrace_packet_t *packet) {
445        dag_record_t *erfptr = 0;
446        erfptr = (dag_record_t *)packet->buffer;
447        return ntohs(erfptr->rlen);
448}
449
450static int erf_get_wire_length(const struct libtrace_packet_t *packet) {
451        dag_record_t *erfptr = 0;
452        erfptr = (dag_record_t *)packet->buffer;
453        return ntohs(erfptr->wlen);
454}
455
456static size_t erf_set_capture_length(struct libtrace_packet_t *packet, const size_t size) {
457        dag_record_t *erfptr = 0;
458        assert(packet);
459        if(size > packet->size) {
460                // can't make a packet larger
461                return packet->size;
462        }
463        erfptr = (dag_record_t *)packet->buffer;
464        erfptr->rlen = ntohs(size + sizeof(dag_record_t));
465        packet->size = size + sizeof(dag_record_t);
466        return packet->size;
467}
468
469static struct format_t erf = {
470        "erf",
471        "$Id$",
472        erf_init_input,                 /* init_input */       
473        NULL,                           /* init_output */
474        erf_fin_input,                  /* fin_input */
475        NULL,                           /* fin_output */
476        NULL,                           /* read */
477        erf_read_packet,                /* read_packet */
478        NULL,                           /* write_packet */
479        erf_get_link,                   /* get_link */
480        erf_get_link_type,              /* get_link_type */
481        erf_get_direction,              /* get_direction */
482        erf_set_direction,              /* set_direction */
483        erf_get_erf_timestamp,          /* get_erf_timestamp */
484        NULL,                           /* get_timeval */
485        NULL,                           /* get_seconds */
486        erf_get_capture_length,         /* get_capture_length */
487        erf_get_wire_length,            /* get_wire_length */
488        erf_set_capture_length          /* set_capture_length */
489};
490
491static struct format_t dag = {
492        "dag",
493        "$Id$",
494        dag_init_input,                 /* init_input */       
495        NULL,                           /* init_output */
496        dag_fin_input,                  /* fin_input */
497        NULL,                           /* fin_output */
498        dag_read,                       /* read */
499        dag_read_packet,                /* read_packet */
500        NULL,                           /* write_packet */
501        erf_get_link,                   /* get_link */
502        erf_get_link_type,              /* get_link_type */
503        erf_get_direction,              /* get_direction */
504        erf_set_direction,              /* set_direction */
505        erf_get_erf_timestamp,          /* get_erf_timestamp */
506        NULL,                           /* get_timeval */
507        NULL,                           /* get_seconds */
508        erf_get_capture_length,         /* get_capture_length */
509        erf_get_wire_length,            /* get_wire_length */
510        erf_set_capture_length          /* set_capture_length */
511};
512
513static struct format_t rtclient = {
514        "rtclient",
515        "$Id$",
516        rtclient_init_input,            /* init_input */       
517        NULL,                           /* init_output */
518        rtclient_fin_input,             /* fin_input */
519        NULL,                           /* fin_output */
520        rtclient_read,                  /* read */
521        rtclient_read_packet,           /* read_packet */
522        NULL,                           /* write_packet */
523        erf_get_link,                   /* get_link */
524        erf_get_link_type,              /* get_link_type */
525        erf_get_direction,              /* get_direction */
526        erf_set_direction,              /* set_direction */
527        erf_get_erf_timestamp,          /* get_erf_timestamp */
528        NULL,                           /* get_timeval */
529        NULL,                           /* get_seconds */
530        erf_get_capture_length,         /* get_capture_length */
531        erf_get_wire_length,            /* get_wire_length */
532        erf_set_capture_length          /* set_capture_length */
533};
534
535void __attribute__((constructor)) erf_constructor() {
536        register_format(&erf);
537        register_format(&dag);
538        register_format(&rtclient);
539}
Note: See TracBrowser for help on using the repository browser.