source: lib/format_pfring.c @ 274770a

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

Added parallel API support for pf_ring

Also added a general purpose "count our CPUs" function to
format_helper (thanks Perry for linking me some example code
on how to do this!).

  • 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
193        if (FORMAT_DATA->promisc > 0) 
194                flags |= PF_RING_PROMISC;
195        return flags;
196}       
197
198static int pfring_start_input(libtrace_t *libtrace) {
199        struct pfring_per_stream_t *stream = FORMAT_DATA_FIRST;
200        int rc = 0;
201
202        if (libtrace->uridata == NULL) {
203                trace_set_err(libtrace, TRACE_ERR_BAD_FORMAT, 
204                                "Missing interface name from pfring: URI");
205                return -1;
206        }
207        if (FORMAT_DATA->ringenabled) {
208                trace_set_err(libtrace, TRACE_ERR_BAD_STATE,
209                        "Attempted to start a pfring: input that was already started!");
210                return -1;
211        }
212
213        stream->pd = pfring_open(libtrace->uridata, FORMAT_DATA->snaplen, 
214                pfring_flags(libtrace));
215        if (stream->pd == NULL) {
216                trace_set_err(libtrace, errno, "pfring_open failed: %s",
217                                strerror(errno));
218                return -1;
219        }
220
221        rc = pfring_start_input_stream(libtrace, FORMAT_DATA_FIRST);
222        if (rc < 0)
223                return rc;     
224        FORMAT_DATA->ringenabled = 1;
225        return rc;
226}
227
228static int pfring_pstart_input(libtrace_t *libtrace) {
229        pfring *ring[MAX_NUM_RX_CHANNELS];
230        uint8_t channels;
231        struct pfring_per_stream_t empty = ZERO_PFRING_STREAM;
232        int i, iserror = 0;
233       
234        if (libtrace->uridata == NULL) {
235                trace_set_err(libtrace, TRACE_ERR_BAD_FORMAT, 
236                                "Missing interface name from pfring: URI");
237                return -1;
238        }
239        if (FORMAT_DATA->ringenabled) {
240                trace_set_err(libtrace, TRACE_ERR_BAD_STATE,
241                        "Attempted to start a pfring: input that was already started!");
242                return -1;
243        }
244
245        channels = pfring_open_multichannel(libtrace->uridata, 
246                        FORMAT_DATA->snaplen, pfring_flags(libtrace), ring);
247        if (channels <= 0) {
248                trace_set_err(libtrace, errno, 
249                                "pfring_open_multichannel failed: %s",
250                                strerror(errno));
251                return -1;
252        }
253
254        printf("got %u channels\n", channels);
255
256        if (libtrace->perpkt_thread_count < channels) {
257                fprintf(stderr, "WARNING: pfring interface has %u channels, "
258                                "but this libtrace program has only enough "
259                                "threads to read the first %u channels.",
260                                channels, libtrace->perpkt_thread_count);
261        }
262
263        if (channels < libtrace->perpkt_thread_count)
264                libtrace->perpkt_thread_count = channels;
265       
266
267        for (i = 0; i < channels; i++) {
268                struct pfring_per_stream_t *stream;
269                if (libtrace_list_get_size(FORMAT_DATA->per_stream)<=(size_t)i)
270                        libtrace_list_push_back(FORMAT_DATA->per_stream, &empty);
271
272                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
273                stream->pd = ring[i];
274                if (pfring_start_input_stream(libtrace, stream) != 0) {
275                        iserror = 1;
276                        break;
277                }
278        }
279
280        if (iserror) {
281                /* Error state: free any streams we managed to create */
282                for (i = i - 1; i >= 0; i--) {
283                        struct pfring_per_stream_t *stream;
284                        stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
285
286                        pfring_disable_ring(stream->pd);       
287                        pfring_remove_bpf_filter(stream->pd);
288                        pfring_close(stream->pd);
289                }
290                return -1;
291        }
292        FORMAT_DATA->ringenabled = 1;
293        return 0;
294}
295
296
297static int pfring_init_input(libtrace_t *libtrace) {
298
299        struct pfring_per_stream_t stream_data = ZERO_PFRING_STREAM;
300
301        libtrace->format_data = (struct pfring_format_data_t *)
302                malloc(sizeof(struct pfring_format_data_t));
303        assert(libtrace->format_data != NULL);
304
305        FORMAT_DATA->promisc = -1;
306        FORMAT_DATA->snaplen = LIBTRACE_PACKET_BUFSIZE;
307        FORMAT_DATA->per_stream = libtrace_list_init(sizeof(stream_data));
308        FORMAT_DATA->ringenabled = 0;
309        FORMAT_DATA->bpffilter = NULL;
310
311        libtrace_list_push_back(FORMAT_DATA->per_stream, &stream_data);
312
313        return 0;
314}
315
316static int pfring_config_input(libtrace_t *libtrace, trace_option_t option,
317                void *data) {
318
319        switch (option) {
320                case TRACE_OPTION_SNAPLEN:
321                        FORMAT_DATA->snaplen = *(int *)data;
322                        return 0;
323                case TRACE_OPTION_PROMISC:
324                        FORMAT_DATA->promisc = *(int *)data;
325                        return 0;
326                case TRACE_OPTION_FILTER:
327                        FORMAT_DATA->bpffilter = strdup((char *)data);
328                        return 0;
329                case TRACE_OPTION_HASHER:
330                        /* We can do unidirectional hashing on hardware
331                         * by default, but symmetric hash requires the
332                         * extra ZC or DNA drivers. */
333                        switch (*((enum hasher_types *)data)) {
334                                case HASHER_UNIDIRECTIONAL:
335                                        return 0;
336                                case HASHER_BALANCE:
337                                case HASHER_CUSTOM:
338                                case HASHER_BIDIRECTIONAL:
339                                        return -1;
340                        }
341                        break;
342                case TRACE_OPTION_META_FREQ:
343                        break;
344                case TRACE_OPTION_EVENT_REALTIME:
345                        break;
346        }
347        return -1;
348}
349
350static int pfring_pause_input(libtrace_t *libtrace) {
351        size_t i;
352
353        for (i = 0; i < libtrace_list_get_size(FORMAT_DATA->per_stream); ++i) {
354                struct pfring_per_stream_t *stream;
355                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
356                pfring_disable_ring(stream->pd);       
357                pfring_remove_bpf_filter(stream->pd);
358                pfring_close(stream->pd);
359        }
360
361        FORMAT_DATA->ringenabled = 0;
362        return 0;
363
364}
365
366static int pfring_fin_input(libtrace_t *libtrace) {
367
368        if (libtrace->format_data) {
369                if (FORMAT_DATA->bpffilter)
370                        free(FORMAT_DATA->bpffilter);
371                if (FORMAT_DATA->per_stream) 
372                        libtrace_list_deinit(FORMAT_DATA->per_stream);
373                free(libtrace->format_data);
374        }
375        return 0;
376}
377
378
379static int pfring_get_capture_length(const libtrace_packet_t *packet) {
380        struct libtrace_pfring_header *phdr;
381        phdr = (struct libtrace_pfring_header *)packet->header;
382
383        if (packet->payload == NULL)
384                return 0;
385        if (ntohl(phdr->wlen) < ntohl(phdr->caplen))
386                return ntohl(phdr->wlen);
387        return ntohl(phdr->caplen);
388       
389}
390
391static int pfring_get_wire_length(const libtrace_packet_t *packet) {
392        struct libtrace_pfring_header *phdr;
393        phdr = (struct libtrace_pfring_header *)packet->header;
394        return ntohl(phdr->wlen);
395}
396
397static int pfring_get_framing_length(UNUSED const libtrace_packet_t *packet) {
398        return sizeof(struct libtrace_pfring_header);
399}
400
401static int pfring_prepare_packet(libtrace_t *libtrace UNUSED, 
402                libtrace_packet_t *packet, void *buffer, 
403                libtrace_rt_types_t rt_type, uint32_t flags) {
404
405
406        if (packet->buffer != buffer && packet->buf_control == 
407                        TRACE_CTRL_PACKET) {
408                free(packet->buffer);
409        }
410
411        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
412                packet->buf_control = TRACE_CTRL_PACKET;
413        } else {
414                packet->buf_control = TRACE_CTRL_EXTERNAL;
415        }
416
417        packet->type = rt_type;
418        packet->buffer = buffer;
419        packet->header = buffer;
420        packet->payload = (buffer + sizeof(struct libtrace_pfring_header));
421
422        return 0;
423}
424
425static int pfring_read_generic(libtrace_t *libtrace, libtrace_packet_t *packet,
426                struct pfring_per_stream_t *stream, uint8_t block, 
427                libtrace_message_queue_t *queue)
428{
429
430        struct libtrace_pfring_header *hdr;
431        struct local_pfring_header local;
432        int rc;
433
434        if (packet->buf_control == TRACE_CTRL_EXTERNAL || !packet->buffer) {
435                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
436                if (!packet->buffer) {
437                        trace_set_err(libtrace, errno, 
438                                "Cannot allocate memory for packet buffer");
439                        return -1;
440                }
441        }
442       
443        hdr = (struct libtrace_pfring_header *)packet->buffer;
444        while (block) {
445                if ((rc = pfring_recv(stream->pd, (u_char **)&packet->payload, 
446                        0, (struct pfring_pkthdr *)&local, 0)) == -1)
447                {
448                        trace_set_err(libtrace, errno, "Failed to read packet from pfring:");
449                        return -1;
450                }
451
452                if (rc == 0) {
453                        if (queue && libtrace_message_queue_count(queue) > 0)
454                                return READ_MESSAGE;
455                        continue;
456                }
457                break;
458        }
459
460        if (rc == 0)
461                return 0;
462
463        /* Convert the header fields to network byte order so we can
464         * export them over RT safely. Also deal with 32 vs 64 bit
465         * timevals! */
466        hdr->ts.tv_sec = bswap_host_to_le64((uint64_t)local.ts.tv_sec);
467        hdr->ts.tv_usec = bswap_host_to_le64((uint64_t)local.ts.tv_usec);
468        hdr->caplen = htonl(local.caplen);
469        hdr->wlen = htonl(local.wlen);
470        hdr->ts.tv_sec = htonl(local.ts.tv_sec);
471        hdr->ts.tv_usec = htonl(local.ts.tv_usec);
472        hdr->ext.ts_ns = bswap_host_to_le64(local.ext.ts_ns);
473        hdr->ext.flags = htonl(local.ext.flags);
474        hdr->ext.if_index = htonl(local.ext.if_index);
475        hdr->ext.hash = htonl(local.ext.hash);
476        hdr->ext.tx.bounce_iface = htonl(local.ext.tx.bounce_iface);
477        hdr->ext.parsed_hdr_len = htons(local.ext.parsed_hdr_len);
478        hdr->ext.direction = local.ext.direction;
479
480        /* I think we can ignore parsed as it will only be populated if
481         * we call pfring_parse_pkt (?)
482         */
483
484        packet->trace = libtrace;
485        packet->type = TRACE_RT_DATA_PFRING;
486        packet->header = packet->buffer;
487        packet->error = 1;
488
489        return pfring_get_capture_length(packet) + 
490                        pfring_get_framing_length(packet);
491
492}
493
494static int pfring_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet)
495{
496        return pfring_read_generic(libtrace, packet, FORMAT_DATA_FIRST, 1, NULL);
497}
498
499static libtrace_linktype_t pfring_get_link_type(const libtrace_packet_t *packet UNUSED)
500{
501        return TRACE_TYPE_ETH;
502}
503
504static libtrace_direction_t lt_pfring_set_direction(libtrace_packet_t *packet,
505                libtrace_direction_t dir) {
506
507        struct libtrace_pfring_header *phdr;
508
509        phdr = (struct libtrace_pfring_header *)packet->header;
510        phdr->ext.direction = dir;
511        return dir;     
512}
513
514static libtrace_direction_t pfring_get_direction(
515                const libtrace_packet_t *packet) {
516
517        struct libtrace_pfring_header *phdr;
518        phdr = (struct libtrace_pfring_header *)packet->header;
519        return phdr->ext.direction;
520}
521
522static uint64_t pfring_get_erf_timestamp(const libtrace_packet_t *packet) {
523        uint64_t ts;
524        struct libtrace_pfring_header *phdr;
525        phdr = (struct libtrace_pfring_header *)packet->header;
526
527        if (phdr->ext.ts_ns) {
528                uint64_t tns = bswap_le_to_host64(phdr->ext.ts_ns);
529
530                ts = ((tns / 1000000000) << 32);
531                ts += ((tns % 1000000000) << 32) / 1000000000;
532        } else {
533                ts = (((uint64_t)ntohl(phdr->ts.tv_sec)) << 32);
534                ts += (((uint64_t)(ntohl(phdr->ts.tv_usec)) << 32)/1000000);
535        }
536        return ts;
537               
538
539}
540static size_t pfring_set_capture_length(libtrace_packet_t *packet, size_t size)
541{
542        struct libtrace_pfring_header *phdr;
543        phdr = (struct libtrace_pfring_header *)packet->header;
544
545        if (size > trace_get_capture_length(packet)) {
546                /* Can't make a packet larger */
547                return trace_get_capture_length(packet);
548        }
549
550        packet->capture_length = -1;
551        phdr->caplen = htonl(size);
552        return trace_get_capture_length(packet);
553}
554
555static void pfring_get_statistics(libtrace_t *libtrace, libtrace_stat_t *stat) {
556
557        pfring_stat st;
558
559        size_t i;
560
561        for (i = 0; i < libtrace_list_get_size(FORMAT_DATA->per_stream); ++i) {
562                struct pfring_per_stream_t *stream;
563                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
564
565                if (pfring_stats(stream->pd, &st) != 0) {
566                        trace_set_err(libtrace, errno, "Failed to get statistics for pfring stream %u", (uint32_t)i);
567                        continue;
568                }
569
570                if (stat->dropped_valid) {
571                        stat->dropped += st.drop;
572                } else {
573                        stat->dropped = st.drop;
574                        stat->dropped_valid = 1;
575                }
576
577                if (stat->received_valid) {
578                        stat->received += st.recv;
579                } else {
580                        stat->received = st.recv;
581                        stat->received_valid = 1;
582                }
583        }
584
585}
586
587static libtrace_eventobj_t pfring_event(libtrace_t *libtrace, 
588                libtrace_packet_t *packet) {
589
590        libtrace_eventobj_t event = {0,0,0.0,0};
591        int rc;
592
593        rc = pfring_read_generic(libtrace, packet, FORMAT_DATA_FIRST, 0, NULL);
594       
595        if (rc > 0) {
596                event.size = rc;
597                event.type = TRACE_EVENT_PACKET;
598        } else if (rc == 0) {
599                if (libtrace_halt) {
600                        event.type = TRACE_EVENT_TERMINATE;
601                } else {
602                        event.type = TRACE_EVENT_SLEEP;
603                        event.seconds = 0.0001;
604                }
605        } else {
606                event.type = TRACE_EVENT_TERMINATE;
607        }
608        return event;
609}
610
611static int pfring_pread_packets(libtrace_t *libtrace,
612                libtrace_thread_t *t, 
613                libtrace_packet_t *packets[],
614                size_t nb_packets) {
615
616        size_t readpackets = 0;
617        int rc = 0;
618        struct pfring_per_stream_t *stream = (struct pfring_per_stream_t *)t->format_data;
619        uint8_t block = 1;
620
621        /* Block for the first packet, then read up to nb_packets if they
622         * are available. */
623        do {
624                rc = pfring_read_generic(libtrace, packets[readpackets], 
625                        stream, block, &t->messages);
626                if (rc == READ_MESSAGE) {
627                        if (readpackets == 0) {
628                                return rc;
629                        }
630                        break;
631                }
632                               
633                if (rc == READ_ERROR)
634                        return rc;
635
636                if (rc == 0)
637                        continue;
638               
639                block = 0;
640                readpackets ++;
641                if (readpackets >= nb_packets)
642                        break;
643
644        } while (rc != 0);
645
646        return readpackets;
647}
648
649static int pfring_pregister_thread(libtrace_t *libtrace, libtrace_thread_t *t,
650                bool reading) {
651
652        uint32_t cpus = trace_get_number_of_cores();
653
654        if (reading) {
655                struct pfring_per_stream_t *stream;
656                int tid = 0;
657                if (t->type == THREAD_PERPKT) {
658                        t->format_data = libtrace_list_get_index(FORMAT_DATA->per_stream, t->perpkt_num)->data;
659                        if (t->format_data == NULL) {
660                                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
661                                                "Too many threads registered");
662                                return -1;
663                        }
664                        tid = t->perpkt_num;
665                } else {
666                        t->format_data = FORMAT_DATA_FIRST;
667                }
668
669                stream = t->format_data;
670                if (cpus > 1) {
671                        cpu_set_t cpuset;
672                        uint32_t coreid;
673                        int s;
674
675                        coreid = (tid + 1) % cpus;
676                        CPU_ZERO(&cpuset);
677                        CPU_SET(coreid, &cpuset);
678                        if ((s = pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset)) != 0) {
679                                trace_set_err(libtrace, errno, "Warning "
680                                                "failed to set affinity for "
681                                                "pfring thread");
682                                return -1;
683                        }
684                        stream->affinity = coreid;
685                }
686        }
687
688        return 0;               
689
690}
691
692static struct libtrace_format_t pfringformat = {
693        "pfring",
694        "$Id$",
695        TRACE_FORMAT_PFRING,
696        NULL,                           /* probe filename */
697        NULL,                           /* probe magic */
698        pfring_init_input,                /* init_input */
699        pfring_config_input,              /* config_input */
700        pfring_start_input,               /* start_input */
701        pfring_pause_input,               /* pause_input */
702        NULL,                           /* init_output */
703        NULL,                           /* config_output */
704        NULL,                           /* start_output */
705        pfring_fin_input,                 /* fin_input */
706        NULL,                           /* fin_output */
707        pfring_read_packet,               /* read_packet */
708        pfring_prepare_packet,            /* prepare_packet */
709        NULL,                           /* fin_packet */
710        NULL,                             /* write_packet */
711        pfring_get_link_type,             /* get_link_type */
712        pfring_get_direction,             /* get_direction */
713        lt_pfring_set_direction,             /* set_direction */
714        pfring_get_erf_timestamp,         /* get_erf_timestamp */
715        NULL,               /* get_timeval */
716        NULL,                           /* get_seconds */
717        NULL,                           /* get_timespec */
718        NULL,                           /* seek_erf */
719        NULL,                           /* seek_timeval */
720        NULL,                           /* seek_seconds */
721        pfring_get_capture_length,        /* get_capture_length */
722        pfring_get_wire_length,           /* get_wire_length */
723        pfring_get_framing_length,        /* get_framing_length */
724        pfring_set_capture_length,        /* set_capture_length */
725        NULL,                           /* get_received_packets */
726        NULL,                           /* get_filtered_packets */
727        NULL,                           /* get_dropped_packets */
728        pfring_get_statistics,          /* get_statistics */
729        NULL,                           /* get_fd */
730        pfring_event,              /* trace_event */
731        NULL,                      /* help */
732        NULL,                   /* next pointer */
733        {true, MAX_NUM_RX_CHANNELS},         /* Live, with thread limit */
734        pfring_pstart_input,         /* pstart_input */
735        pfring_pread_packets,        /* pread_packets */
736        pfring_pause_input,        /* ppause */
737        pfring_fin_input,          /* p_fin */
738        pfring_pregister_thread,        /* register thread */ 
739        NULL,                           /* unregister thread */
740        NULL                            /* get thread stats */
741
742};
743
744void pfring_constructor(void) {
745        register_format(&pfringformat);
746}
Note: See TracBrowser for help on using the repository browser.