source: lib/format_pfring.c @ 06926f4

pfring
Last change on this file since 06926f4 was 06926f4, checked in by Shane Alcock <salcock@…>, 6 years ago

Just make sure pfring doesn't try to parse the packet

  • Property mode set to 100644
File size: 19.3 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007-2015 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Author: Shane Alcock
8 *
9 * All rights reserved.
10 *
11 * This code has been developed by the University of Waikato WAND
12 * research group. For further information please see http://www.wand.net.nz/
13 *
14 * libtrace is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * libtrace is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with libtrace; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27 *
28 */
29
30#define _GNU_SOURCE
31#include "config.h"
32#include "libtrace.h"
33#include "libtrace_int.h"
34#include "format_helper.h"
35#include "data-struct/linked_list.h"
36
37#include <stdlib.h>
38#include <assert.h>
39#include <unistd.h>
40#include <string.h>
41
42#if HAVE_LIBNUMA
43#include <numa.h>
44#endif
45
46#include <pthread.h>
47#ifdef __FreeBSD__
48#include <pthread_np.h>
49#endif
50
51#include <pfring.h>
52
53struct pfring_format_data_t {
54        libtrace_list_t *per_stream;   
55        int8_t promisc;
56        int snaplen;
57        int8_t ringenabled;
58        char *bpffilter;
59};
60
61struct pfring_per_stream_t {
62
63        pfring *pd;
64        int affinity;
65
66} ALIGN_STRUCT(CACHE_LINE_SIZE);
67
68#define ZERO_PFRING_STREAM {NULL, -1}
69
70#define DATA(x) ((struct pfring_format_data_t *)x->format_data)
71#define STREAM_DATA(x) ((struct pfring_per_stream_t *)x->data)
72
73#define FORMAT_DATA DATA(libtrace)
74#define FORMAT_DATA_HEAD FORMAT_DATA->per_stream->head
75#define FORMAT_DATA_FIRST ((struct pfring_per_stream_t *)FORMAT_DATA_HEAD->data)
76
77
78typedef union {
79        uint32_t ipv4;
80        uint8_t ipv6[16];
81} ip_addr_union;
82
83struct tunnelinfo {
84        uint32_t id;
85        uint8_t tunneledproto;
86        ip_addr_union tunnel_src;
87        ip_addr_union tunnel_dst;
88        uint16_t tunnel_srcport;
89        uint16_t tunnel_dstport;
90};
91
92struct pktoffset {
93        int16_t ethoffset;
94        int16_t vlanoffset;
95        int16_t l3offset;
96        int16_t l4offset;
97        int16_t payloadoffset;
98};
99
100struct parsing_info {
101        uint8_t dmac[ETH_ALEN];
102        uint8_t smac[ETH_ALEN];
103        uint16_t eth_type;
104        uint16_t vlan_id;
105        uint8_t ip_version;
106        uint8_t l3_proto;
107        uint8_t ip_tos;
108        ip_addr_union ip_src;
109        ip_addr_union ip_dst;
110        uint16_t l4_src_port;
111        uint16_t l4_dst_port;
112        struct {
113                uint8_t flags;
114                uint32_t seqno;
115                uint32_t ackno;
116        } tcp;
117        struct tunnelinfo tunnel;
118        uint16_t last_matched_plugin;
119        uint16_t last_matched_rule;
120        struct pktoffset offset;
121
122};
123
124struct libtrace_pfring_extend {
125
126        uint64_t ts_ns;
127        uint32_t flags;
128        uint8_t direction;
129        int32_t if_index;
130        uint32_t hash;
131        struct {
132                int bounce_iface;
133                void *reserved;
134        } tx;
135        uint16_t parsed_hdr_len;
136        struct parsing_info parsed;
137};
138
139struct local_pfring_header {
140        struct timeval ts;
141        uint32_t caplen;
142        uint32_t wlen;
143        struct libtrace_pfring_extend ext;     
144       
145};
146
147
148struct libtrace_pfring_header {
149        struct {
150                uint64_t tv_sec;
151                uint64_t tv_usec;
152        } ts;
153        uint32_t caplen;
154        uint32_t wlen;
155        struct libtrace_pfring_extend ext;     
156       
157};
158
159static inline int pfring_start_input_stream(libtrace_t *libtrace,
160                struct pfring_per_stream_t *stream) {
161
162        int rc;
163
164        if (FORMAT_DATA->bpffilter) {
165                rc = pfring_set_bpf_filter(stream->pd, FORMAT_DATA->bpffilter);
166                if (rc != 0) {
167                        trace_set_err(libtrace, TRACE_ERR_BAD_FILTER,
168                                "Failed to set BPF filter on pfring:");
169                        return -1;
170                }
171        }
172
173        if ((rc = pfring_set_socket_mode(stream->pd, recv_only_mode)) != 0) {
174                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
175                                "Failed to set recv only mode on pfring:");
176                return -1;
177        }
178
179        if (pfring_enable_ring(stream->pd) != 0) {
180                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, 
181                        "Failed to enable the pfring");
182                return -1;
183        }
184       
185        return 0;
186
187}
188
189static inline uint32_t pfring_flags(libtrace_t *libtrace) {
190        uint32_t flags = PF_RING_TIMESTAMP | PF_RING_LONG_HEADER;
191        flags |= PF_RING_HW_TIMESTAMP;
192        flags |= PF_RING_DO_NOT_PARSE;
193
194        if (FORMAT_DATA->promisc > 0) 
195                flags |= PF_RING_PROMISC;
196        return flags;
197}       
198
199static int pfring_start_input(libtrace_t *libtrace) {
200        struct pfring_per_stream_t *stream = FORMAT_DATA_FIRST;
201        int rc = 0;
202
203        if (libtrace->uridata == NULL) {
204                trace_set_err(libtrace, TRACE_ERR_BAD_FORMAT, 
205                                "Missing interface name from pfring: URI");
206                return -1;
207        }
208        if (FORMAT_DATA->ringenabled) {
209                trace_set_err(libtrace, TRACE_ERR_BAD_STATE,
210                        "Attempted to start a pfring: input that was already started!");
211                return -1;
212        }
213
214        stream->pd = pfring_open(libtrace->uridata, FORMAT_DATA->snaplen, 
215                pfring_flags(libtrace));
216        if (stream->pd == NULL) {
217                trace_set_err(libtrace, errno, "pfring_open failed: %s",
218                                strerror(errno));
219                return -1;
220        }
221
222        rc = pfring_start_input_stream(libtrace, FORMAT_DATA_FIRST);
223        if (rc < 0)
224                return rc;     
225        FORMAT_DATA->ringenabled = 1;
226        return rc;
227}
228
229static int pfring_pstart_input(libtrace_t *libtrace) {
230        pfring *ring[MAX_NUM_RX_CHANNELS];
231        uint8_t channels;
232        struct pfring_per_stream_t empty = ZERO_PFRING_STREAM;
233        int i, iserror = 0;
234       
235        if (libtrace->uridata == NULL) {
236                trace_set_err(libtrace, TRACE_ERR_BAD_FORMAT, 
237                                "Missing interface name from pfring: URI");
238                return -1;
239        }
240        if (FORMAT_DATA->ringenabled) {
241                trace_set_err(libtrace, TRACE_ERR_BAD_STATE,
242                        "Attempted to start a pfring: input that was already started!");
243                return -1;
244        }
245
246        channels = pfring_open_multichannel(libtrace->uridata, 
247                        FORMAT_DATA->snaplen, pfring_flags(libtrace), ring);
248        if (channels <= 0) {
249                trace_set_err(libtrace, errno, 
250                                "pfring_open_multichannel failed: %s",
251                                strerror(errno));
252                return -1;
253        }
254
255        printf("got %u channels\n", channels);
256
257        if (libtrace->perpkt_thread_count < channels) {
258                fprintf(stderr, "WARNING: pfring interface has %u channels, "
259                                "but this libtrace program has only enough "
260                                "threads to read the first %u channels.",
261                                channels, libtrace->perpkt_thread_count);
262        }
263
264        if (channels < libtrace->perpkt_thread_count)
265                libtrace->perpkt_thread_count = channels;
266       
267
268        for (i = 0; i < channels; i++) {
269                struct pfring_per_stream_t *stream;
270                if (libtrace_list_get_size(FORMAT_DATA->per_stream)<=(size_t)i)
271                        libtrace_list_push_back(FORMAT_DATA->per_stream, &empty);
272
273                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
274                stream->pd = ring[i];
275                if (pfring_start_input_stream(libtrace, stream) != 0) {
276                        iserror = 1;
277                        break;
278                }
279        }
280
281        if (iserror) {
282                /* Error state: free any streams we managed to create */
283                for (i = i - 1; i >= 0; i--) {
284                        struct pfring_per_stream_t *stream;
285                        stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
286
287                        pfring_disable_ring(stream->pd);       
288                        pfring_remove_bpf_filter(stream->pd);
289                        pfring_close(stream->pd);
290                }
291                return -1;
292        }
293        FORMAT_DATA->ringenabled = 1;
294        return 0;
295}
296
297
298static int pfring_init_input(libtrace_t *libtrace) {
299
300        struct pfring_per_stream_t stream_data = ZERO_PFRING_STREAM;
301
302        libtrace->format_data = (struct pfring_format_data_t *)
303                malloc(sizeof(struct pfring_format_data_t));
304        assert(libtrace->format_data != NULL);
305
306        FORMAT_DATA->promisc = -1;
307        FORMAT_DATA->snaplen = LIBTRACE_PACKET_BUFSIZE;
308        FORMAT_DATA->per_stream = libtrace_list_init(sizeof(stream_data));
309        FORMAT_DATA->ringenabled = 0;
310        FORMAT_DATA->bpffilter = NULL;
311
312        libtrace_list_push_back(FORMAT_DATA->per_stream, &stream_data);
313
314        return 0;
315}
316
317static int pfring_config_input(libtrace_t *libtrace, trace_option_t option,
318                void *data) {
319
320        switch (option) {
321                case TRACE_OPTION_SNAPLEN:
322                        FORMAT_DATA->snaplen = *(int *)data;
323                        return 0;
324                case TRACE_OPTION_PROMISC:
325                        FORMAT_DATA->promisc = *(int *)data;
326                        return 0;
327                case TRACE_OPTION_FILTER:
328                        FORMAT_DATA->bpffilter = strdup((char *)data);
329                        return 0;
330                case TRACE_OPTION_HASHER:
331                        /* We can do unidirectional hashing on hardware
332                         * by default, but symmetric hash requires the
333                         * extra ZC or DNA drivers. */
334                        switch (*((enum hasher_types *)data)) {
335                                case HASHER_UNIDIRECTIONAL:
336                                        return 0;
337                                case HASHER_BALANCE:
338                                case HASHER_CUSTOM:
339                                case HASHER_BIDIRECTIONAL:
340                                        return -1;
341                        }
342                        break;
343                case TRACE_OPTION_META_FREQ:
344                        break;
345                case TRACE_OPTION_EVENT_REALTIME:
346                        break;
347        }
348        return -1;
349}
350
351static int pfring_pause_input(libtrace_t *libtrace) {
352        size_t i;
353
354        for (i = 0; i < libtrace_list_get_size(FORMAT_DATA->per_stream); ++i) {
355                struct pfring_per_stream_t *stream;
356                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
357                pfring_disable_ring(stream->pd);       
358                pfring_remove_bpf_filter(stream->pd);
359                pfring_close(stream->pd);
360        }
361
362        FORMAT_DATA->ringenabled = 0;
363        return 0;
364
365}
366
367static int pfring_fin_input(libtrace_t *libtrace) {
368
369        if (libtrace->format_data) {
370                if (FORMAT_DATA->bpffilter)
371                        free(FORMAT_DATA->bpffilter);
372                if (FORMAT_DATA->per_stream) 
373                        libtrace_list_deinit(FORMAT_DATA->per_stream);
374                free(libtrace->format_data);
375        }
376        return 0;
377}
378
379
380static int pfring_get_capture_length(const libtrace_packet_t *packet) {
381        struct libtrace_pfring_header *phdr;
382        phdr = (struct libtrace_pfring_header *)packet->header;
383
384        if (packet->payload == NULL)
385                return 0;
386        if (ntohl(phdr->wlen) < ntohl(phdr->caplen))
387                return ntohl(phdr->wlen);
388        return ntohl(phdr->caplen);
389       
390}
391
392static int pfring_get_wire_length(const libtrace_packet_t *packet) {
393        struct libtrace_pfring_header *phdr;
394        phdr = (struct libtrace_pfring_header *)packet->header;
395        return ntohl(phdr->wlen);
396}
397
398static int pfring_get_framing_length(UNUSED const libtrace_packet_t *packet) {
399        return sizeof(struct libtrace_pfring_header);
400}
401
402static int pfring_prepare_packet(libtrace_t *libtrace UNUSED, 
403                libtrace_packet_t *packet, void *buffer, 
404                libtrace_rt_types_t rt_type, uint32_t flags) {
405
406
407        if (packet->buffer != buffer && packet->buf_control == 
408                        TRACE_CTRL_PACKET) {
409                free(packet->buffer);
410        }
411
412        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
413                packet->buf_control = TRACE_CTRL_PACKET;
414        } else {
415                packet->buf_control = TRACE_CTRL_EXTERNAL;
416        }
417
418        packet->type = rt_type;
419        packet->buffer = buffer;
420        packet->header = buffer;
421        packet->payload = (buffer + sizeof(struct libtrace_pfring_header));
422
423        return 0;
424}
425
426static int pfring_read_generic(libtrace_t *libtrace, libtrace_packet_t *packet,
427                struct pfring_per_stream_t *stream, uint8_t block, 
428                libtrace_message_queue_t *queue)
429{
430
431        struct libtrace_pfring_header *hdr;
432        struct local_pfring_header local;
433        int rc;
434
435        if (packet->buf_control == TRACE_CTRL_EXTERNAL || !packet->buffer) {
436                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
437                if (!packet->buffer) {
438                        trace_set_err(libtrace, errno, 
439                                "Cannot allocate memory for packet buffer");
440                        return -1;
441                }
442        }
443       
444        hdr = (struct libtrace_pfring_header *)packet->buffer;
445        while (block) {
446                if ((rc = pfring_recv(stream->pd, (u_char **)&packet->payload, 
447                        0, (struct pfring_pkthdr *)&local, 0)) == -1)
448                {
449                        trace_set_err(libtrace, errno, "Failed to read packet from pfring:");
450                        return -1;
451                }
452
453                if (rc == 0) {
454                        if (queue && libtrace_message_queue_count(queue) > 0)
455                                return READ_MESSAGE;
456                        continue;
457                }
458                break;
459        }
460
461        if (rc == 0)
462                return 0;
463
464        /* Convert the header fields to network byte order so we can
465         * export them over RT safely. Also deal with 32 vs 64 bit
466         * timevals! */
467        hdr->ts.tv_sec = bswap_host_to_le64((uint64_t)local.ts.tv_sec);
468        hdr->ts.tv_usec = bswap_host_to_le64((uint64_t)local.ts.tv_usec);
469        hdr->caplen = htonl(local.caplen);
470        hdr->wlen = htonl(local.wlen);
471        hdr->ts.tv_sec = htonl(local.ts.tv_sec);
472        hdr->ts.tv_usec = htonl(local.ts.tv_usec);
473        hdr->ext.ts_ns = bswap_host_to_le64(local.ext.ts_ns);
474        hdr->ext.flags = htonl(local.ext.flags);
475        hdr->ext.if_index = htonl(local.ext.if_index);
476        hdr->ext.hash = htonl(local.ext.hash);
477        hdr->ext.tx.bounce_iface = htonl(local.ext.tx.bounce_iface);
478        hdr->ext.parsed_hdr_len = htons(local.ext.parsed_hdr_len);
479        hdr->ext.direction = local.ext.direction;
480
481        /* I think we can ignore parsed as it will only be populated if
482         * we call pfring_parse_pkt (?)
483         */
484
485        packet->trace = libtrace;
486        packet->type = TRACE_RT_DATA_PFRING;
487        packet->header = packet->buffer;
488        packet->error = 1;
489
490        return pfring_get_capture_length(packet) + 
491                        pfring_get_framing_length(packet);
492
493}
494
495static int pfring_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet)
496{
497        return pfring_read_generic(libtrace, packet, FORMAT_DATA_FIRST, 1, NULL);
498}
499
500static libtrace_linktype_t pfring_get_link_type(const libtrace_packet_t *packet UNUSED)
501{
502        return TRACE_TYPE_ETH;
503}
504
505static libtrace_direction_t lt_pfring_set_direction(libtrace_packet_t *packet,
506                libtrace_direction_t dir) {
507
508        struct libtrace_pfring_header *phdr;
509
510        phdr = (struct libtrace_pfring_header *)packet->header;
511        phdr->ext.direction = dir;
512        return dir;     
513}
514
515static libtrace_direction_t pfring_get_direction(
516                const libtrace_packet_t *packet) {
517
518        struct libtrace_pfring_header *phdr;
519        phdr = (struct libtrace_pfring_header *)packet->header;
520        return phdr->ext.direction;
521}
522
523static uint64_t pfring_get_erf_timestamp(const libtrace_packet_t *packet) {
524        uint64_t ts;
525        struct libtrace_pfring_header *phdr;
526        phdr = (struct libtrace_pfring_header *)packet->header;
527
528        if (phdr->ext.ts_ns) {
529                uint64_t tns = bswap_le_to_host64(phdr->ext.ts_ns);
530
531                ts = ((tns / 1000000000) << 32);
532                ts += ((tns % 1000000000) << 32) / 1000000000;
533        } else {
534                ts = (((uint64_t)ntohl(phdr->ts.tv_sec)) << 32);
535                ts += (((uint64_t)(ntohl(phdr->ts.tv_usec)) << 32)/1000000);
536        }
537        return ts;
538               
539
540}
541static size_t pfring_set_capture_length(libtrace_packet_t *packet, size_t size)
542{
543        struct libtrace_pfring_header *phdr;
544        phdr = (struct libtrace_pfring_header *)packet->header;
545
546        if (size > trace_get_capture_length(packet)) {
547                /* Can't make a packet larger */
548                return trace_get_capture_length(packet);
549        }
550
551        packet->capture_length = -1;
552        phdr->caplen = htonl(size);
553        return trace_get_capture_length(packet);
554}
555
556static void pfring_get_statistics(libtrace_t *libtrace, libtrace_stat_t *stat) {
557
558        pfring_stat st;
559
560        size_t i;
561
562        for (i = 0; i < libtrace_list_get_size(FORMAT_DATA->per_stream); ++i) {
563                struct pfring_per_stream_t *stream;
564                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
565
566                if (pfring_stats(stream->pd, &st) != 0) {
567                        trace_set_err(libtrace, errno, "Failed to get statistics for pfring stream %u", (uint32_t)i);
568                        continue;
569                }
570
571                if (stat->dropped_valid) {
572                        stat->dropped += st.drop;
573                } else {
574                        stat->dropped = st.drop;
575                        stat->dropped_valid = 1;
576                }
577
578                if (stat->received_valid) {
579                        stat->received += st.recv;
580                } else {
581                        stat->received = st.recv;
582                        stat->received_valid = 1;
583                }
584        }
585
586}
587
588static libtrace_eventobj_t pfring_event(libtrace_t *libtrace, 
589                libtrace_packet_t *packet) {
590
591        libtrace_eventobj_t event = {0,0,0.0,0};
592        int rc;
593
594        rc = pfring_read_generic(libtrace, packet, FORMAT_DATA_FIRST, 0, NULL);
595       
596        if (rc > 0) {
597                event.size = rc;
598                event.type = TRACE_EVENT_PACKET;
599        } else if (rc == 0) {
600                if (libtrace_halt) {
601                        event.type = TRACE_EVENT_TERMINATE;
602                } else {
603                        event.type = TRACE_EVENT_SLEEP;
604                        event.seconds = 0.0001;
605                }
606        } else {
607                event.type = TRACE_EVENT_TERMINATE;
608        }
609        return event;
610}
611
612static int pfring_pread_packets(libtrace_t *libtrace,
613                libtrace_thread_t *t, 
614                libtrace_packet_t *packets[],
615                size_t nb_packets) {
616
617        size_t readpackets = 0;
618        int rc = 0;
619        struct pfring_per_stream_t *stream = (struct pfring_per_stream_t *)t->format_data;
620        uint8_t block = 1;
621
622        /* Block for the first packet, then read up to nb_packets if they
623         * are available. */
624        do {
625                rc = pfring_read_generic(libtrace, packets[readpackets], 
626                        stream, block, &t->messages);
627                if (rc == READ_MESSAGE) {
628                        if (readpackets == 0) {
629                                return rc;
630                        }
631                        break;
632                }
633                               
634                if (rc == READ_ERROR)
635                        return rc;
636
637                if (rc == 0)
638                        continue;
639               
640                block = 0;
641                readpackets ++;
642                if (readpackets >= nb_packets)
643                        break;
644
645        } while (rc != 0);
646
647        return readpackets;
648}
649
650static int pfring_pregister_thread(libtrace_t *libtrace, libtrace_thread_t *t,
651                bool reading) {
652
653        uint32_t cpus = trace_get_number_of_cores();
654
655        if (reading) {
656                struct pfring_per_stream_t *stream;
657                int tid = 0;
658                if (t->type == THREAD_PERPKT) {
659                        t->format_data = libtrace_list_get_index(FORMAT_DATA->per_stream, t->perpkt_num)->data;
660                        if (t->format_data == NULL) {
661                                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
662                                                "Too many threads registered");
663                                return -1;
664                        }
665                        tid = t->perpkt_num;
666                } else {
667                        t->format_data = FORMAT_DATA_FIRST;
668                }
669
670                stream = t->format_data;
671                if (cpus > 1) {
672                        cpu_set_t cpuset;
673                        uint32_t coreid;
674                        int s;
675
676                        coreid = (tid + 1) % cpus;
677                        CPU_ZERO(&cpuset);
678                        CPU_SET(coreid, &cpuset);
679                        if ((s = pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset)) != 0) {
680                                trace_set_err(libtrace, errno, "Warning "
681                                                "failed to set affinity for "
682                                                "pfring thread");
683                                return -1;
684                        }
685                        stream->affinity = coreid;
686                }
687        }
688
689        return 0;               
690
691}
692
693static struct libtrace_format_t pfringformat = {
694        "pfring",
695        "$Id$",
696        TRACE_FORMAT_PFRING,
697        NULL,                           /* probe filename */
698        NULL,                           /* probe magic */
699        pfring_init_input,                /* init_input */
700        pfring_config_input,              /* config_input */
701        pfring_start_input,               /* start_input */
702        pfring_pause_input,               /* pause_input */
703        NULL,                           /* init_output */
704        NULL,                           /* config_output */
705        NULL,                           /* start_output */
706        pfring_fin_input,                 /* fin_input */
707        NULL,                           /* fin_output */
708        pfring_read_packet,               /* read_packet */
709        pfring_prepare_packet,            /* prepare_packet */
710        NULL,                           /* fin_packet */
711        NULL,                             /* write_packet */
712        pfring_get_link_type,             /* get_link_type */
713        pfring_get_direction,             /* get_direction */
714        lt_pfring_set_direction,             /* set_direction */
715        pfring_get_erf_timestamp,         /* get_erf_timestamp */
716        NULL,               /* get_timeval */
717        NULL,                           /* get_seconds */
718        NULL,                           /* get_timespec */
719        NULL,                           /* seek_erf */
720        NULL,                           /* seek_timeval */
721        NULL,                           /* seek_seconds */
722        pfring_get_capture_length,        /* get_capture_length */
723        pfring_get_wire_length,           /* get_wire_length */
724        pfring_get_framing_length,        /* get_framing_length */
725        pfring_set_capture_length,        /* set_capture_length */
726        NULL,                           /* get_received_packets */
727        NULL,                           /* get_filtered_packets */
728        NULL,                           /* get_dropped_packets */
729        pfring_get_statistics,          /* get_statistics */
730        NULL,                           /* get_fd */
731        pfring_event,              /* trace_event */
732        NULL,                      /* help */
733        NULL,                   /* next pointer */
734        {true, MAX_NUM_RX_CHANNELS},         /* Live, with thread limit */
735        pfring_pstart_input,         /* pstart_input */
736        pfring_pread_packets,        /* pread_packets */
737        pfring_pause_input,        /* ppause */
738        pfring_fin_input,          /* p_fin */
739        pfring_pregister_thread,        /* register thread */ 
740        NULL,                           /* unregister thread */
741        NULL                            /* get thread stats */
742
743};
744
745void pfring_constructor(void) {
746        register_format(&pfringformat);
747}
Note: See TracBrowser for help on using the repository browser.