source: lib/format_linux.c @ 9e429e8

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 9e429e8 was 9e429e8, checked in by Richard Sanger <rsangerarj@…>, 7 years ago

Merge remote-tracking branch 'upsteam/master' into develop

Conflicts:

README
lib/format_dpdk.c
lib/format_linux.c
lib/trace.c

  • Property mode set to 100644
File size: 64.1 KB
RevLine 
[97e39a7]1/*
2 * This file is part of libtrace
3 *
[238d50a]4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
[97e39a7]7 * Authors: Daniel Lawson
[238d50a]8 *          Perry Lorier
[d500159]9 *          Shane Alcock
10 *          Richard Sanger
[97e39a7]11 *         
12 * All rights reserved.
13 *
14 * This code has been developed by the University of Waikato WAND
15 * research group. For further information please see http://www.wand.net.nz/
16 *
17 * libtrace is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * libtrace is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with libtrace; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30 *
[293999b]31 * $Id$
[97e39a7]32 *
33 */
34
[528eb6e]35/* This format module deals with using the Linux Native capture format.
36 *
37 * Linux Native is a LIVE capture format.
38 *
39 * This format also supports writing which will write packets out to the
40 * network as a form of packet replay. This should not be confused with the
41 * RT protocol which is intended to transfer captured packet records between
42 * RT-speaking programs.
43 */
[238d50a]44
[528eb6e]45#include "config.h"
[97e39a7]46#include "libtrace.h"
47#include "libtrace_int.h"
48#include "format_helper.h"
[528eb6e]49#include "libtrace_arphrd.h"
[91b72d3]50#include <stdlib.h>
[528eb6e]51#include <errno.h>
52#include <unistd.h>
53#include <string.h>
54#include <assert.h>
[97e39a7]55
56#ifdef HAVE_INTTYPES_H
57#  include <inttypes.h>
58#else
59# error "Can't find inttypes.h"
60#endif
61
[b4c3f61]62#ifdef HAVE_NETPACKET_PACKET_H
[528eb6e]63
[97e39a7]64#include <sys/socket.h>
65#include <netpacket/packet.h>
66#include <net/ethernet.h>
67#include <net/if_arp.h>
68
[edb18ce]69#include <net/if.h>
70#include <sys/ioctl.h>
[d500159]71#include <poll.h>
72#include <sys/mman.h>
73
[29bbef0]74#include <fcntl.h>
75
[528eb6e]76/* MAX_ORDER is defined in linux/mmzone.h. 10 is default for 2.4 kernel.
77 * max_order will be decreased by one if the ring buffer fails to allocate.
78 * Used to get correct sized buffers from the kernel.
[238d50a]79 */
[528eb6e]80#define MAX_ORDER 10
[238d50a]81
[5b825b3]82/* Cached page size, the page size shouldn't be changing */
[528eb6e]83static int pagesize = 0;
84
85/* Number of frames in the ring used by both TX and TR rings. More frames
86 * hopefully means less packet loss, especially if traffic comes in bursts.
87 */
88#define CONF_RING_FRAMES        0x100
89
90/* The maximum frames allowed to be waiting in the TX_RING before the kernel is
91 * notified to write them out. Make sure this is less than CONF_RING_FRAMES.
92 * Performance doesn't seem to increase any more when setting this above 10.
93 */
94#define TX_MAX_QUEUE            10
95
96/* Get current frame in the ring buffer*/
97#define GET_CURRENT_BUFFER(libtrace) ((void *) FORMAT(libtrace->format_data)->rx_ring + \
98        (FORMAT(libtrace->format_data)->rxring_offset * FORMAT(libtrace->format_data)->req.tp_frame_size))
99
100
101#else   /* HAVE_NETPACKET_PACKET_H */
102/* Need to know what a sockaddr_ll looks like */
103struct sockaddr_ll {
104        uint16_t sll_family;
105        uint16_t sll_protocol;
106        int32_t  sll_ifindex;
107        uint16_t sll_hatype;
108        uint8_t  sll_pkttype;
109        uint8_t  sll_halen;
110        uint8_t  sll_addr[8];
111};
112
113/* Packet types.  */
114
115#define PACKET_HOST             0               /* To us.  */
116#define PACKET_BROADCAST        1               /* To all.  */
117#define PACKET_MULTICAST        2               /* To group.  */
118#define PACKET_OTHERHOST        3               /* To someone else.  */
119#define PACKET_OUTGOING         4               /* Originated by us . */
120#define PACKET_LOOPBACK         5
121#define PACKET_FASTROUTE        6
122
123/* Packet socket options.  */
124
125#define PACKET_ADD_MEMBERSHIP           1
126#define PACKET_DROP_MEMBERSHIP          2
127#define PACKET_RECV_OUTPUT              3
128#define PACKET_RX_RING                  5
129#define PACKET_STATISTICS               6
130
131
[b4c3f61]132#endif /* HAVE_NETPACKET_PACKET_H */
[89404f5]133
[50bbce8]134struct tpacket_stats {
135        unsigned int tp_packets;
136        unsigned int tp_drops;
137};
138
[1aa4bf7]139typedef enum { TS_NONE, TS_TIMEVAL, TS_TIMESPEC } timestamptype_t;
140
[d500159]141/* linux/if_packet.h defines. They are here rather than including the header
142 * this means that we can interpret a ring frame on a kernel that doesn't
143 * support the format directly.
144 */
[6ba84d9]145
146
[d500159]147#define PACKET_RX_RING  5
148#define PACKET_VERSION  10
149#define PACKET_HDRLEN   11
150#define PACKET_TX_RING  13
[29bbef0]151#define PACKET_FANOUT   18
[d500159]152#define TP_STATUS_USER  0x1
153#define TP_STATUS_SEND_REQUEST  0x1
154#define TP_STATUS_AVAILABLE     0x0
155#define TO_TP_HDR(x)    ((struct tpacket2_hdr *) (x))
156#define TPACKET_ALIGNMENT       16
157#define TPACKET_ALIGN(x)        (((x)+TPACKET_ALIGNMENT-1)&~(TPACKET_ALIGNMENT-1))
[6ba84d9]158#define TPACKET_HDRLEN         (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll))
[d500159]159
[29bbef0]160/* Since 3.1 kernel we have packet_fanout support */
161// schedule to socket by skb's rxhash - the implementation is bi-directional
162#define PACKET_FANOUT_HASH              0
163// schedule round robin
164#define PACKET_FANOUT_LB                1
165// schedule to the same socket that received the packet
166#define PACKET_FANOUT_CPU               2
167// Something to do with fragmented packets and hashing problems !! TODO figure out if this needs to be on
168#define PACKET_FANOUT_FLAG_DEFRAG       0x8000
[f9a70ca]169/* Included but unused by libtrace since Linux 3.10 */
[29bbef0]170// if one socket if full roll over to the next
171#define PACKET_FANOUT_ROLLOVER          3
172// This flag makes any other system roll over
173#define PACKET_FANOUT_FLAG_ROLLOVER     0x1000
[f9a70ca]174/* Included but unused by libtrace since Linux 3.12 */
[29bbef0]175// schedule random
176#define PACKET_FANOUT_RND               4
177
178
[d500159]179enum tpacket_versions {
180        TPACKET_V1,
181        TPACKET_V2
182};
183
184struct tpacket2_hdr {
185        /* Frame status - in use by kernel or libtrace etc. */
[528eb6e]186        uint32_t        tp_status;
[d500159]187        /* Wire length */
[528eb6e]188        uint32_t        tp_len;
[d500159]189        /* Captured length */
[528eb6e]190        uint32_t        tp_snaplen;
[d500159]191        /* Offset in bytes from frame start to the mac (link layer) header */
[528eb6e]192        uint16_t        tp_mac;
[d500159]193        /* Offset in bytes from frame start to the net (network layer) header */
[528eb6e]194        uint16_t        tp_net;
[d500159]195        /* Timestamp */
[528eb6e]196        uint32_t        tp_sec;
197        uint32_t        tp_nsec;
[d500159]198        /* Not used VLAN tag control information */
[528eb6e]199        uint16_t        tp_vlan_tci;
200        uint16_t        tp_padding;
[d500159]201};
202
203struct tpacket_req {
204        unsigned int tp_block_size;  /* Minimal size of contiguous block */
205        unsigned int tp_block_nr;    /* Number of blocks */
206        unsigned int tp_frame_size;  /* Size of frame */
207        unsigned int tp_frame_nr;    /* Total number of frames */
208};
209
[29bbef0]210struct linux_per_thread_t {
211        char *rx_ring;
212        int rxring_offset;
213        int fd;
214        // The flag layout should be the same for all (I Hope)
215        // max_order
[50ce607]216} ALIGN_STRUCT(CACHE_LINE_SIZE);
[29bbef0]217
[238d50a]218struct linux_format_data_t {
219        /* The file descriptor being used for the capture */
[97e39a7]220        int fd;
[238d50a]221        /* The snap length for the capture */
[411f3c7]222        int snaplen;
[238d50a]223        /* Flag indicating whether the interface should be placed in
224         * promiscuous mode */
[411f3c7]225        int promisc;
[238d50a]226        /* The timestamp format used by the capture */ 
[1aa4bf7]227        timestamptype_t timestamptype;
[238d50a]228        /* A BPF filter that is applied to every captured packet */
[394706e]229        libtrace_filter_t *filter;
[238d50a]230        /* Statistics for the capture process, e.g. dropped packet counts */
[50bbce8]231        struct tpacket_stats stats;
[238d50a]232        /* Flag indicating whether the statistics are current or not */
[50bbce8]233        int stats_valid;
[d500159]234        /* The rx ring mmap location*/
235        char * rx_ring;
236        /* The current frame number within the rx ring */       
237        int rxring_offset;
[6ba84d9]238        /* The actual format being used - ring vs int */
[d500159]239        libtrace_rt_types_t format;
240        /* The current ring buffer layout */
241        struct tpacket_req req;
[6ba84d9]242        /* Used to determine buffer size for the ring buffer */ 
243        uint32_t max_order;
[29bbef0]244        /* Used for the parallel case, fanout is the mode */
245        uint16_t fanout_flags;
246        /* The group lets Linux know which sockets to group together
247         * so we use a random here to try avoid collisions */
248        uint16_t fanout_group;
249        /* When running in parallel mode this is malloc'd with an array
250         * file descriptors from packet fanout will use, here we assume/hope
251         * that every ring can get setup the same */
252        struct linux_per_thread_t *per_thread;
[97e39a7]253};
254
[1aa4bf7]255
[238d50a]256/* Note that this structure is passed over the wire in rt encapsulation, and
257 * thus we need to be careful with data sizes.  timeval's and timespec's
258 * can also change their size on 32/64 machines.
[7fa118f]259 */
[238d50a]260
261/* Format header for encapsulating packets captured using linux native */
[97e39a7]262struct libtrace_linuxnative_header {
[238d50a]263        /* Timestamp of the packet, as a timeval */
[7fa118f]264        struct {
265                uint32_t tv_sec;
266                uint32_t tv_usec;
267        } tv;
[238d50a]268        /* Timestamp of the packet, as a timespec */
[7fa118f]269        struct {
270                uint32_t tv_sec;
271                uint32_t tv_nsec;
272        } ts;
[238d50a]273        /* The timestamp format used by the process that captured this packet */
[7fa118f]274        uint8_t timestamptype;
[238d50a]275        /* Wire length */
[7fa118f]276        uint32_t wirelen;
[238d50a]277        /* Capture length */
[7fa118f]278        uint32_t caplen;
[238d50a]279        /* The linux native header itself */
[97e39a7]280        struct sockaddr_ll hdr;
281};
282
[238d50a]283struct linux_output_format_data_t {
284        /* The file descriptor used to write the packets */
[e4e95499]285        int fd;
[d500159]286        /* The tx ring mmap location */
287        char * tx_ring;
288        /* The current frame number within the tx ring */       
289        int txring_offset;
290        /* The current ring buffer layout */
291        struct tpacket_req req;
292        /* Our sockaddr structure, here so we can cache the interface number */
293        struct sockaddr_ll sock_hdr;
294        /* The (maximum) number of packets that haven't been written */
295        int queue;
296        /* The format this trace is using linuxring or linuxnative */
297        libtrace_rt_types_t format;
[6ba84d9]298        /* Used to determine buffer size for the ring buffer */ 
299        uint32_t max_order;
[e4e95499]300};
301
[528eb6e]302/* Get the sockaddr_ll structure from a frame */
303#define GET_SOCKADDR_HDR(x)  ((struct sockaddr_ll *) (((char *) (x))\
304        + TPACKET_ALIGN(sizeof(struct tpacket2_hdr))))
[d500159]305
[528eb6e]306#define FORMAT(x) ((struct linux_format_data_t*)(x))
[50ce607]307#define PERPKT_FORMAT(x) ((struct linux_per_thread_t*)(x->format_data))
[528eb6e]308#define DATAOUT(x) ((struct linux_output_format_data_t*)((x)->format_data))
[d500159]309
310/* Get the start of the captured data. I'm not sure if tp_mac (link layer) is
311 * always guaranteed. If it's not there then just use tp_net.
312 */
313#define TP_TRACE_START(mac, net, hdrend) \
314        ((mac) > (hdrend) && (mac) < (net) ? (mac) : (net))
315
[97e39a7]316
[b4c3f61]317#ifdef HAVE_NETPACKET_PACKET_H
[d500159]318/*
319 * Try figure out the best sizes for the ring buffer. Ensure that:
320 * - max(Block_size) == page_size << max_order
321 * - Frame_size == page_size << x (so that block_size%frame_size == 0)
322 *   This means that there will be no wasted space between blocks
323 * - Frame_size < block_size
324 * - Frame_size is as close as possible to LIBTRACE_PACKET_BUFSIZE, but not
325 *   bigger
326 * - Frame_nr = Block_nr * (frames per block)
327 * - CONF_RING_FRAMES is used a minimum number of frames to hold
328 * - Calculates based on max_order and buf_min
329 */
[6ba84d9]330static void calculate_buffers(struct tpacket_req * req, int fd, char * uri,
331                uint32_t max_order){
[d500159]332       
333        struct ifreq ifr;
[6ba84d9]334        unsigned max_frame = LIBTRACE_PACKET_BUFSIZE;
[d500159]335        pagesize = getpagesize();
336
[6ba84d9]337        strcpy(ifr.ifr_name, uri);
[d500159]338        /* Don't bother trying to set frame size above mtu linux will drop
[6ba84d9]339         * these anyway.
340         *
341         * Remember, that our frame also has to include a TPACKET header!
[d500159]342         */
343        if (ioctl(fd, SIOCGIFMTU, (caddr_t) &ifr) >= 0) 
[5b825b3]344                max_frame = ifr.ifr_mtu + TPACKET_ALIGN(TPACKET_HDRLEN);
[6ba84d9]345        if (max_frame > LIBTRACE_PACKET_BUFSIZE)
346                max_frame = LIBTRACE_PACKET_BUFSIZE;
[d500159]347
348        /* Calculate frame size */
349        req->tp_frame_size = pagesize;
[6ba84d9]350        while(req->tp_frame_size < max_frame && 
351                        req->tp_frame_size < LIBTRACE_PACKET_BUFSIZE){
[d500159]352                req->tp_frame_size <<= 1;
[f240823]353        }
[d500159]354        if(req->tp_frame_size > LIBTRACE_PACKET_BUFSIZE)
355                req->tp_frame_size >>= 1;
356
357        /* Calculate block size */
358        req->tp_block_size = pagesize << max_order;
359        do{
360                req->tp_block_size >>= 1;
[f240823]361        } while((CONF_RING_FRAMES * req->tp_frame_size) <= req->tp_block_size);
[d500159]362        req->tp_block_size <<= 1;
363       
364        /* Calculate number of blocks */
365        req->tp_block_nr = (CONF_RING_FRAMES * req->tp_frame_size) 
366                        / req->tp_block_size;
367        if((CONF_RING_FRAMES * req->tp_frame_size) % req->tp_block_size != 0)
368                req->tp_block_nr++;
369
370        /* Calculate packets such that we use all the space we have to allocated */
371        req->tp_frame_nr = req->tp_block_nr * 
372                        (req->tp_block_size / req->tp_frame_size);
373
[6ba84d9]374        /*
375        printf("MaxO 0x%x BS 0x%x BN 0x%x FS 0x%x FN 0x%x\n",
[d500159]376                max_order,
377                req->tp_block_size,
378                req->tp_block_nr,
379                req->tp_frame_size,
[6ba84d9]380                req->tp_frame_nr);
381        */
[d500159]382       
383        /* In case we have some silly values*/
384        assert(req->tp_block_size);
385        assert(req->tp_block_nr);
386        assert(req->tp_frame_size);
387        assert(req->tp_frame_nr);
388        assert(req->tp_block_size % req->tp_frame_size == 0);
389}
390
[528eb6e]391
[91b72d3]392static int linuxnative_probe_filename(const char *filename)
393{
394        /* Is this an interface? */
395        return (if_nametoindex(filename) != 0);
396}
397
[d500159]398static inline void init_input(libtrace_t *libtrace){
[238d50a]399        libtrace->format_data = (struct linux_format_data_t *)
400                malloc(sizeof(struct linux_format_data_t));
[411f3c7]401        FORMAT(libtrace->format_data)->fd = -1;
[3ed9a80]402        FORMAT(libtrace->format_data)->promisc = -1;
[cdcaef6]403        FORMAT(libtrace->format_data)->snaplen = LIBTRACE_PACKET_BUFSIZE;
[394706e]404        FORMAT(libtrace->format_data)->filter = NULL;
[50bbce8]405        FORMAT(libtrace->format_data)->stats_valid = 0;
[d500159]406        FORMAT(libtrace->format_data)->rx_ring = NULL;
407        FORMAT(libtrace->format_data)->rxring_offset = 0;
[f19c3e9]408        FORMAT(libtrace->format_data)->max_order = MAX_ORDER;
[29bbef0]409        FORMAT(libtrace->format_data)->fanout_flags = PACKET_FANOUT_LB; // This might be best or alternatively PACKET_FANOUT_LB
410        // Some examples use pid for the group however that would limit a single
411        // application to use only int/ring format, instead using rand
412        FORMAT(libtrace->format_data)->fanout_group = (uint16_t) rand();
413        FORMAT(libtrace->format_data)->per_thread = NULL;
[d500159]414}
415static int linuxring_init_input(libtrace_t *libtrace) 
416{       
417        init_input(libtrace);
[82facc5]418        FORMAT(libtrace->format_data)->format = TRACE_RT_DATA_LINUX_RING;
[d500159]419        return 0;
420}
421static int linuxnative_init_input(libtrace_t *libtrace) 
422{
423        init_input(libtrace);
[82facc5]424        FORMAT(libtrace->format_data)->format = TRACE_RT_DATA_LINUX_NATIVE;
[411f3c7]425        return 0;
426}
427
[d500159]428static inline void init_output(libtrace_out_t *libtrace)
[e4e95499]429{
[238d50a]430        libtrace->format_data = (struct linux_output_format_data_t*)
431                malloc(sizeof(struct linux_output_format_data_t));
[e4e95499]432        DATAOUT(libtrace)->fd = -1;
[d500159]433        DATAOUT(libtrace)->tx_ring = NULL;
434        DATAOUT(libtrace)->txring_offset = 0;
435        DATAOUT(libtrace)->queue = 0;
[f19c3e9]436        DATAOUT(libtrace)->max_order = MAX_ORDER;
[d500159]437}
438static int linuxnative_init_output(libtrace_out_t *libtrace)
439{
440        init_output(libtrace);
441        DATAOUT(libtrace)->format = TRACE_FORMAT_LINUX_NATIVE;
442        return 0;
443}
444static int linuxring_init_output(libtrace_out_t *libtrace)
445{
446        init_output(libtrace);
447        DATAOUT(libtrace)->format = TRACE_FORMAT_LINUX_RING;
[e4e95499]448        return 0;
449}
450
[411f3c7]451static int linuxnative_start_input(libtrace_t *libtrace)
452{
453        struct sockaddr_ll addr;
[d0fd73c]454        int one = 1;
[9a5b234]455        memset(&addr,0,sizeof(addr));
[394706e]456        libtrace_filter_t *filter = FORMAT(libtrace->format_data)->filter;
[238d50a]457       
458        /* Create a raw socket for reading packets on */
[97e39a7]459        FORMAT(libtrace->format_data)->fd = 
460                                socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
461        if (FORMAT(libtrace->format_data)->fd==-1) {
[4b6495c3]462                trace_set_err(libtrace, errno, "Could not create raw socket");
[97e39a7]463                free(libtrace->format_data);
[9f1b6ee]464                libtrace->format_data = NULL;
[566e404]465                return -1;
[97e39a7]466        }
[238d50a]467
468        /* Bind to the capture interface */
[97e39a7]469        addr.sll_family = AF_PACKET;
470        addr.sll_protocol = htons(ETH_P_ALL);
471        if (strlen(libtrace->uridata)) {
472                addr.sll_ifindex = if_nametoindex(libtrace->uridata);
473                if (addr.sll_ifindex == 0) {
474                        close(FORMAT(libtrace->format_data)->fd);
[205809b]475                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Failed to find interface %s", libtrace->uridata);
[97e39a7]476                        free(libtrace->format_data);
[9f1b6ee]477                        libtrace->format_data = NULL;
[566e404]478                        return -1;
[97e39a7]479                }
480        }
481        else {
482                addr.sll_ifindex = 0;
483        }
484        if (bind(FORMAT(libtrace->format_data)->fd,
485                                (struct sockaddr*)&addr,
[4bd8a5b]486                                (socklen_t)sizeof(addr))==-1) {
[97e39a7]487                free(libtrace->format_data);
[9f1b6ee]488                libtrace->format_data = NULL;
[4b6495c3]489                trace_set_err(libtrace, errno, "Failed to bind to interface %s", libtrace->uridata);
[566e404]490                return -1;
[97e39a7]491        }
[3ed9a80]492
493        /* If promisc hasn't been specified, set it to "true" if we're
494         * capturing on one interface, or "false" if we're capturing on
495         * all interfaces.
496         */ 
497        if (FORMAT(libtrace->format_data)->promisc==-1) {
498                if (addr.sll_ifindex!=0)
499                        FORMAT(libtrace->format_data)->promisc=1;
500                else
501                        FORMAT(libtrace->format_data)->promisc=0;
502        }
[238d50a]503       
504        /* Enable promiscuous mode, if requested */                     
[3ed9a80]505        if (FORMAT(libtrace->format_data)->promisc) {
[97e39a7]506                struct packet_mreq mreq;
507                socklen_t socklen = sizeof(mreq);
[9a5b234]508                memset(&mreq,0,sizeof(mreq));
[97e39a7]509                mreq.mr_ifindex = addr.sll_ifindex;
510                mreq.mr_type = PACKET_MR_PROMISC;
[cdcaef6]511                if (setsockopt(FORMAT(libtrace->format_data)->fd,
[97e39a7]512                                SOL_PACKET,
513                                PACKET_ADD_MEMBERSHIP,
514                                &mreq,
[cdcaef6]515                                socklen)==-1) {
516                        perror("setsockopt(PROMISC)");
517                }
[97e39a7]518        }
[238d50a]519
520        /* Set the timestamp option on the socket - aim for the most detailed
521         * clock resolution possible */
[1aa4bf7]522#ifdef SO_TIMESTAMPNS
523        if (setsockopt(FORMAT(libtrace->format_data)->fd,
524                        SOL_SOCKET,
525                        SO_TIMESTAMPNS,
526                        &one,
527                        (socklen_t)sizeof(one))!=-1) {
528                FORMAT(libtrace->format_data)->timestamptype = TS_TIMESPEC;
529        }
530        else
531        /* DANGER: This is a dangling else to only do the next setsockopt() if we fail the first! */
532#endif
[3b10b9f]533        if (setsockopt(FORMAT(libtrace->format_data)->fd,
[d0fd73c]534                        SOL_SOCKET,
535                        SO_TIMESTAMP,
536                        &one,
[1aa4bf7]537                        (socklen_t)sizeof(one))!=-1) {
538                FORMAT(libtrace->format_data)->timestamptype = TS_TIMEVAL;
[3b10b9f]539        }
[1aa4bf7]540        else 
541                FORMAT(libtrace->format_data)->timestamptype = TS_NONE;
[d0fd73c]542
[3a14f3b]543        /* Push BPF filter into the kernel. At this stage we can safely assume
544         * that the filterstring has been compiled, or the filter was supplied
545         * pre-compiled.
[394706e]546         */
547        if (filter != NULL) {
[b8d8186]548                /* Check if the filter was successfully compiled. If not,
549                 * it is probably a bad filter and we should return an error
550                 * before the caller tries to read any packets */
551                if (filter->flag == 0) {
552                        return -1;
553                }
554               
[394706e]555                if (setsockopt(FORMAT(libtrace->format_data)->fd,
556                                        SOL_SOCKET,
557                                        SO_ATTACH_FILTER,
558                                        &filter->filter,
559                                        sizeof(filter->filter)) == -1) {
560                        perror("setsockopt(SO_ATTACH_FILTER)");
561                } else { 
562                        /* The socket accepted the filter, so we need to
563                         * consume any buffered packets that were received
564                         * between opening the socket and applying the filter.
565                         */
566                        void *buf = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
567                        while(recv(FORMAT(libtrace->format_data)->fd,
568                                        buf,
569                                        (size_t) LIBTRACE_PACKET_BUFSIZE,
570                                        MSG_DONTWAIT) != -1) { }
571                        free(buf);
572                }
573        }
[50bbce8]574
575        FORMAT(libtrace->format_data)->stats_valid=0;
[394706e]576                                       
[566e404]577        return 0;
[97e39a7]578}
[f19c3e9]579static inline int socket_to_packetmmap( char * uridata, int ring_type, 
[d500159]580                                        int fd, 
581                                        struct tpacket_req * req,
[6ba84d9]582                                        char ** ring_location,
[f19c3e9]583                                        uint32_t *max_order,
584                                        char *error){
[d500159]585        int val;
586
587        /* Switch to TPACKET header version 2, we only try support v2 because v1 had problems */
588
589        val = TPACKET_V2;
590        if (setsockopt(fd, 
591                        SOL_PACKET, 
592                        PACKET_VERSION, 
593                        &val, 
594                        sizeof(val)) == -1){
[f19c3e9]595                strncpy(error, "TPACKET2 not supported", 2048);
[d500159]596                return -1;
597        }
598
599        /* Try switch to a ring buffer. If it fails we assume the the kernel 
600         * cannot allocate a block of that size, so decrease max_block and retry.
601         */
602        while(1) {     
[6ba84d9]603                if (*max_order <= 0) {
[f19c3e9]604                        strncpy(error,"Cannot allocate enough memory for ring buffer", 2048);
[d500159]605                        return -1;
606                }
[6ba84d9]607                calculate_buffers(req, fd, uridata, *max_order);
[d500159]608                if (setsockopt(fd, 
609                                SOL_PACKET, 
610                                ring_type, 
611                                req, 
612                                sizeof(struct tpacket_req)) == -1) {
613                        if(errno == ENOMEM){
[6ba84d9]614                                (*max_order)--;
[d500159]615                        } else {
[f19c3e9]616                                strncpy(error, "Error setting the ring buffer size", 2048);
[d500159]617                                return -1;
618                        }
619
620                } else break;
621        }
622       
623        /* Map the ring buffer into userspace */
624        *ring_location = mmap(NULL, 
625                                        req->tp_block_size * req->tp_block_nr, 
626                                        PROT_READ | PROT_WRITE, 
627                                        MAP_SHARED, 
628                                        fd, 0);
629        if(*ring_location == MAP_FAILED){
[f19c3e9]630                strncpy(error, "Failed to map memory for ring buffer", 2048);
[d500159]631                return -1;
632        }
633        return 0;
634}
[f19c3e9]635
[29bbef0]636/**
637 * Converts a socket, either packet_mmap or standard raw socket into a
638 * fanout socket.
639 * NOTE: This means we can read from the socket with multiple queues,
640 * each must be setup (identically) and then this called upon them
641 *
642 * @return 0 success, -1 error
643 */
644static inline int socket_to_packet_fanout(int fd, 
645                                        uint16_t fanout_flags,
646                                        uint16_t fanout_group) {
647        int fanout_opt = ((int)fanout_flags << 16) | (int)fanout_group;
648        if (setsockopt(fd, SOL_PACKET, PACKET_FANOUT,
649                        &fanout_opt, sizeof(fanout_opt)) == -1) {
650                return -1;
651        }
652        return 0;
653}
654
655static int linuxnative_ppause_input(libtrace_t *libtrace)
656{
657        int i;
[17a3dff]658        int tot = libtrace->perpkt_thread_count;
[29bbef0]659        printf("CAlling native pause packet\n");
660       
661        for (i = 0; i < tot; i++) {
662                close(FORMAT(libtrace->format_data)->per_thread[i].fd);
663        }
664       
665        free(FORMAT(libtrace->format_data)->per_thread);
666        FORMAT(libtrace->format_data)->per_thread = NULL;
667        return 0;
668}
669
670static int linuxring_start_input(libtrace_t *libtrace)
671{
672        char error[2048];
[d500159]673
674        /* We set the socket up the same and then convert it to PACKET_MMAP */
675        if(linuxnative_start_input(libtrace) != 0)
676                return -1;
677
[0989e3e]678        strncpy(error, "No known error", 2048);
679
[d500159]680        /* Make it a packetmmap */
[6ba84d9]681        if(socket_to_packetmmap(libtrace->uridata, PACKET_RX_RING, 
682                        FORMAT(libtrace->format_data)->fd,
683                        &FORMAT(libtrace->format_data)->req, 
684                        &FORMAT(libtrace->format_data)->rx_ring,
[f19c3e9]685                        &FORMAT(libtrace->format_data)->max_order,
686                        error) != 0){
[5ea8d25]687                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Initialisation of packet MMAP failed: %s", error);
[d500159]688                close(DATAOUT(libtrace)->fd);
689                free(libtrace->format_data);
[f19c3e9]690                libtrace->format_data = NULL;
[d500159]691                return -1;
692        }
[6ba84d9]693
[d500159]694        return 0;
695}
[97e39a7]696
[29bbef0]697static int linuxnative_pstart_input(libtrace_t *libtrace) {
698        int i = 0;
[17a3dff]699        int tot = libtrace->perpkt_thread_count;
[29bbef0]700        int iserror = 0;
701        // We store this here otherwise it will be leaked if the memory doesn't know
702        struct linux_per_thread_t *per_thread = NULL;
703       
704        if (!FORMAT(libtrace->format_data)->per_thread) {
[50ce607]705                //per_thread = calloc(tot, sizeof(struct linux_per_thread_t));
706                posix_memalign((void **)&per_thread, CACHE_LINE_SIZE, tot*sizeof(struct linux_per_thread_t));
[29bbef0]707                FORMAT(libtrace->format_data)->per_thread = per_thread;
708        } else {
709                // Whats going on this might not work 100%
710                // We assume all sockets have been closed ;)
[17a3dff]711                printf("Pause and then start called again lets hope that perpkt_thread_count hasn't changed\n");
[29bbef0]712        }
713       
714        printf("Calling native pstart packet\n");
715        for (i = 0; i < tot; ++i)
716        {
[82facc5]717                if (FORMAT(libtrace->format_data)->format == TRACE_RT_DATA_LINUX_NATIVE) {
[29bbef0]718                        if (linuxnative_start_input(libtrace) != 0) {
719                                iserror = 1;
720                                break;
721                        }
722                } else {
723                        // This must be ring
724                        if (linuxring_start_input(libtrace) != 0) {
725                                iserror = 1;
726                                break;
727                        }
728                }
729                if (socket_to_packet_fanout(FORMAT(libtrace->format_data)->fd, FORMAT(libtrace->format_data)->fanout_flags, FORMAT(libtrace->format_data)->fanout_group) != 0)
730                {
731                        iserror = 1;
732                        // Clean up here to keep consistent with every one else
733                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Converting the fd to a socket fanout failed");
734                        close(FORMAT(libtrace->format_data)->fd);
735                        free(libtrace->format_data);
736                        libtrace->format_data = NULL;
737                        break;
738                }
739                per_thread[i].fd = FORMAT(libtrace->format_data)->fd;
[82facc5]740                if (FORMAT(libtrace->format_data)->format == TRACE_RT_DATA_LINUX_RING) {
[29bbef0]741                        per_thread[i].rxring_offset = FORMAT(libtrace->format_data)->rxring_offset;
742                        per_thread[i].rx_ring = FORMAT(libtrace->format_data)->rx_ring;
743                }
744        }
745       
746        // Roll back those that failed - by this point in time the format_data
747        // has been freed
748        if (iserror) {
749                for (i = i - 1; i >= 0; i--) {
750                        close(per_thread[i].fd);
751                }
752                free(per_thread);
753                per_thread = NULL;
754                return -1;
755        }
756       
757        return 0;
758}
759
[50ce607]760static int linux_pregister_thread(libtrace_t *libtrace, libtrace_thread_t *t, bool reading) {
761        fprintf(stderr, "registering thread %d!!\n", t->perpkt_num);
762    if (reading) {
763        if(t->type == THREAD_PERPKT) {
764            t->format_data = &FORMAT(libtrace->format_data)->per_thread[t->perpkt_num];
765        } else {
766            t->format_data = &FORMAT(libtrace->format_data)->per_thread[0];
767        }
768    }
769    return 0;
770}
771
[e4e95499]772static int linuxnative_start_output(libtrace_out_t *libtrace)
773{
[0a8eb88]774        DATAOUT(libtrace)->fd = socket(PF_PACKET, SOCK_RAW, 0);
775        if (DATAOUT(libtrace)->fd==-1) {
776                free(DATAOUT(libtrace));
[e4e95499]777                return -1;
[29bbef0]778        }
[d500159]779
780        return 0;
781}
782
783static int linuxring_start_output(libtrace_out_t *libtrace)
784{
[f19c3e9]785        char error[2048];       
[d500159]786        /* We set the socket up the same and then convert it to PACKET_MMAP */
787        if(linuxnative_start_output(libtrace) != 0)
788                return -1;
789
790        /* Make it a packetmmap */
[6ba84d9]791        if(socket_to_packetmmap(libtrace->uridata, PACKET_TX_RING, 
792                        DATAOUT(libtrace)->fd,
793                        &DATAOUT(libtrace)->req, 
794                        &DATAOUT(libtrace)->tx_ring,
[f19c3e9]795                        &DATAOUT(libtrace)->max_order,
796                        error) != 0){
[5ea8d25]797                trace_set_err_out(libtrace, TRACE_ERR_INIT_FAILED, "Initialisation of packet MMAP failed: %s", error);
[d500159]798                close(DATAOUT(libtrace)->fd);
799                free(libtrace->format_data);
[f19c3e9]800                libtrace->format_data = NULL;
[d500159]801                return -1;
[e4e95499]802        }
[d500159]803       
804        DATAOUT(libtrace)->sock_hdr.sll_family = AF_PACKET;
805        DATAOUT(libtrace)->sock_hdr.sll_protocol = 0;
806        DATAOUT(libtrace)->sock_hdr.sll_ifindex = 
807                                        if_nametoindex(libtrace->uridata);
808        DATAOUT(libtrace)->sock_hdr.sll_hatype = 0;
809        DATAOUT(libtrace)->sock_hdr.sll_pkttype = 0;
810        DATAOUT(libtrace)->sock_hdr.sll_halen = 0;
811        DATAOUT(libtrace)->queue = 0;   
[e4e95499]812
813        return 0;
814}
815
[411f3c7]816static int linuxnative_pause_input(libtrace_t *libtrace)
817{
[97e39a7]818        close(FORMAT(libtrace->format_data)->fd);
[411f3c7]819        FORMAT(libtrace->format_data)->fd=-1;
820
821        return 0;
822}
[29bbef0]823
[d500159]824static int linuxring_pause_input(libtrace_t *libtrace)
825{
826        munmap(FORMAT(libtrace->format_data)->rx_ring, 
827                FORMAT(libtrace->format_data)->req.tp_block_size *
828                        FORMAT(libtrace->format_data)->req.tp_block_nr);
829        FORMAT(libtrace->format_data)->rx_ring = NULL;
830        return linuxnative_pause_input(libtrace);
831}
[411f3c7]832
833static int linuxnative_fin_input(libtrace_t *libtrace) 
834{
[9f1b6ee]835        if (libtrace->format_data) {
836                if (FORMAT(libtrace->format_data)->filter != NULL)
837                        free(FORMAT(libtrace->format_data)->filter);
[4b6495c3]838                free(libtrace->format_data);
[9f1b6ee]839        }
[394706e]840       
[97e39a7]841        return 0;
842}
843
[e4e95499]844static int linuxnative_fin_output(libtrace_out_t *libtrace)
845{
846        close(DATAOUT(libtrace)->fd);
847        DATAOUT(libtrace)->fd=-1;
848        free(libtrace->format_data);
849        return 0;
850}
[d500159]851static int linuxring_fin_output(libtrace_out_t *libtrace)
852{
853        /* Make sure any remaining frames get sent */
854        sendto(DATAOUT(libtrace)->fd, 
855                NULL, 
856                0, 
857                0, 
858                (void *) &DATAOUT(libtrace)->sock_hdr, 
859                sizeof(DATAOUT(libtrace)->sock_hdr));
860
861        /* Unmap our data area */
862        munmap(DATAOUT(libtrace)->tx_ring,
863                DATAOUT(libtrace)->req.tp_block_size * 
864                        DATAOUT(libtrace)->req.tp_block_nr);
865
866        return linuxnative_fin_output(libtrace);
867}
[e4e95499]868
[238d50a]869/* Compiles a libtrace BPF filter for use with a linux native socket */
[394706e]870static int linuxnative_configure_bpf(libtrace_t *libtrace, 
871                libtrace_filter_t *filter) {
872#ifdef HAVE_LIBPCAP
873        struct ifreq ifr;
874        unsigned int arphrd;
875        libtrace_dlt_t dlt;
876        libtrace_filter_t *f;
877        int sock;
878        pcap_t *pcap;
879
[3a14f3b]880        /* Take a copy of the filter object as it was passed in */
[394706e]881        f = (libtrace_filter_t *) malloc(sizeof(libtrace_filter_t));
882        memcpy(f, filter, sizeof(libtrace_filter_t));
883       
[3a14f3b]884        /* If we are passed a filter with "flag" set to zero, then we must
885         * compile the filterstring before continuing. This involves
886         * determining the linktype, passing the filterstring to libpcap to
887         * compile, and saving the result for trace_start() to push into the
888         * kernel.
889         * If flag is set to one, then the filter was probably generated using
890         * trace_create_filter_from_bytecode() and so we don't need to do
891         * anything (we've just copied it above).
892         */
893        if (f->flag == 0) {
894                sock = socket(PF_INET, SOCK_STREAM, 0);
895                memset(&ifr, 0, sizeof(struct ifreq));
896                strncpy(ifr.ifr_name, libtrace->uridata, IF_NAMESIZE);
897                if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0) {
898                        perror("Can't get HWADDR for interface");
899                        return -1;
900                }
[f2fae49]901                close(sock);
[3a14f3b]902
903                arphrd = ifr.ifr_hwaddr.sa_family;
904                dlt = libtrace_to_pcap_dlt(arphrd_type_to_libtrace(arphrd));
905
906                pcap = pcap_open_dead(dlt, 
907                                FORMAT(libtrace->format_data)->snaplen);
[394706e]908
[3a14f3b]909                if (pcap_compile(pcap, &f->filter, f->filterstring, 0, 0) == -1) {
[b8d8186]910                        /* Filter didn't compile, set flag to 0 so we can
911                         * detect this when trace_start() is called and
912                         * produce a useful error
913                         */
914                        f->flag = 0;
915                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, 
916                                        "Failed to compile BPF filter (%s): %s",
917                                        f->filterstring, pcap_geterr(pcap));
918                } else {
919                        /* Set the "flag" to indicate that the filterstring
920                         * has been compiled
921                         */
922                        f->flag = 1;
[3a14f3b]923                }
[394706e]924
[3a14f3b]925                pcap_close(pcap);
926               
927        }
928       
[394706e]929        if (FORMAT(libtrace->format_data)->filter != NULL)
930                free(FORMAT(libtrace->format_data)->filter);
931       
932        FORMAT(libtrace->format_data)->filter = f;
[3a14f3b]933       
[394706e]934        return 0;
935#else
936        return -1
937#endif
938}
[411f3c7]939static int linuxnative_config_input(libtrace_t *libtrace,
940                trace_option_t option,
941                void *data)
942{
943        switch(option) {
944                case TRACE_OPTION_SNAPLEN:
945                        FORMAT(libtrace->format_data)->snaplen=*(int*)data;
946                        return 0;
947                case TRACE_OPTION_PROMISC:
948                        FORMAT(libtrace->format_data)->promisc=*(int*)data;
949                        return 0;
950                case TRACE_OPTION_FILTER:
[394706e]951                        return linuxnative_configure_bpf(libtrace, 
952                                        (libtrace_filter_t *) data);
[646aca1]953                case TRACE_OPTION_META_FREQ:
[cd7eec7]954                        /* No meta-data for this format */
955                        break;
[646aca1]956                case TRACE_OPTION_EVENT_REALTIME:
[238d50a]957                        /* Live captures are always going to be in trace time */
[646aca1]958                        break;
[411f3c7]959                /* Avoid default: so that future options will cause a warning
960                 * here to remind us to implement it, or flag it as
961                 * unimplementable
962                 */
963        }
[205809b]964       
[708f9ae]965        /* Don't set an error - trace_config will try to deal with the
966         * option and will set an error if it fails */
[411f3c7]967        return -1;
968}
[b4c3f61]969#endif /* HAVE_NETPACKET_PACKET_H */
[411f3c7]970
[29bbef0]971
972static int linuxnative_pconfig_input(libtrace_t *libtrace,
973                trace_parallel_option_t option,
974                void *data)
975{
976        switch(option) {
977                case TRACE_OPTION_SET_HASHER:
978                        switch (*((enum hasher_types *)data)) {
979                                case HASHER_BALANCE:
980                                        // Do fanout
981                                        FORMAT(libtrace->format_data)->fanout_flags = PACKET_FANOUT_LB;
982                                        // Or we could balance to the CPU
983                                        return 0;
984                                case HASHER_BIDIRECTIONAL:
985                                case HASHER_UNIDIRECTIONAL:
986                                        FORMAT(libtrace->format_data)->fanout_flags = PACKET_FANOUT_HASH;
987                                        return 0;
988                                case HASHER_CUSTOM:
989                                case HASHER_HARDWARE:
990                                        return -1;
991                        }
992                        break;
993                /* Avoid default: so that future options will cause a warning
994                 * here to remind us to implement it, or flag it as
995                 * unimplementable
996                 */
997        }
998       
999        /* Don't set an error - trace_config will try to deal with the
1000         * option and will set an error if it fails */
1001        return -1;
1002}
1003
1004
[528eb6e]1005static int linuxnative_prepare_packet(libtrace_t *libtrace UNUSED, 
[f0fb38f]1006                libtrace_packet_t *packet, void *buffer, 
1007                libtrace_rt_types_t rt_type, uint32_t flags) {
1008
1009        if (packet->buffer != buffer &&
1010                        packet->buf_control == TRACE_CTRL_PACKET) {
1011                free(packet->buffer);
1012        }
1013
1014        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
1015                packet->buf_control = TRACE_CTRL_PACKET;
1016        } else
1017                packet->buf_control = TRACE_CTRL_EXTERNAL;
1018
1019
1020        packet->buffer = buffer;
1021        packet->header = buffer;
1022        packet->payload = (char *)buffer + 
1023                sizeof(struct libtrace_linuxnative_header);
1024        packet->type = rt_type;
1025
[528eb6e]1026        /*
[f0fb38f]1027        if (libtrace->format_data == NULL) {
1028                if (linuxnative_init_input(libtrace))
1029                        return -1;
1030        }
[528eb6e]1031        */
[f0fb38f]1032        return 0;
1033       
1034}
1035
[528eb6e]1036static int linuxring_prepare_packet(libtrace_t *libtrace UNUSED, 
[d500159]1037                libtrace_packet_t *packet, void *buffer, 
1038                libtrace_rt_types_t rt_type, uint32_t flags) {
1039
1040        if (packet->buffer != buffer &&
1041                        packet->buf_control == TRACE_CTRL_PACKET) {
1042                free(packet->buffer);
1043        }
1044
1045        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
1046                packet->buf_control = TRACE_CTRL_PACKET;
1047        } else
1048                packet->buf_control = TRACE_CTRL_EXTERNAL;
1049
1050
1051        packet->buffer = buffer;
1052        packet->header = buffer;
1053        packet->payload = (char *)buffer + 
1054                                        TP_TRACE_START(
1055                                        TO_TP_HDR(packet->header)->tp_mac, 
1056                                        TO_TP_HDR(packet->header)->tp_net, 
[6ba84d9]1057                                        TPACKET_HDRLEN);
[d500159]1058        packet->type = rt_type;
1059
[528eb6e]1060        /*
[d500159]1061        if (libtrace->format_data == NULL) {
1062                if (linuxnative_init_input(libtrace))
1063                        return -1;
1064        }
[528eb6e]1065        */
[d500159]1066        return 0;
1067       
1068}
1069
[411f3c7]1070#define LIBTRACE_MIN(a,b) ((a)<(b) ? (a) : (b))
1071
[3b10b9f]1072/* 20 isn't enough on x86_64 */
1073#define CMSG_BUF_SIZE 128
[528eb6e]1074
[b4c3f61]1075#ifdef HAVE_NETPACKET_PACKET_H
[29bbef0]1076libtrace_thread_t * get_thread_table(libtrace_t *libtrace) ;
1077inline static int linuxnative_read_packet_fd(libtrace_t *libtrace, libtrace_packet_t *packet, int fd, const int check_queue) 
[e4e95499]1078{
[566e404]1079        struct libtrace_linuxnative_header *hdr;
[d0fd73c]1080        struct msghdr msghdr;
1081        struct iovec iovec;
1082        unsigned char controlbuf[CMSG_BUF_SIZE];
1083        struct cmsghdr *cmsg;
[411f3c7]1084        int snaplen;
[29bbef0]1085
[f0fb38f]1086        uint32_t flags = 0;
[63af502]1087        fd_set readfds;
1088        struct timeval tout;
1089        int ret;
[f0fb38f]1090       
[566e404]1091        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
[4bd8a5b]1092                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
[cdcaef6]1093                if (!packet->buffer) {
1094                        perror("Cannot allocate buffer");
1095                }
[566e404]1096        }
1097
[f0fb38f]1098        flags |= TRACE_PREP_OWN_BUFFER;
1099       
[cab58c5]1100        packet->type = TRACE_RT_DATA_LINUX_NATIVE;
[566e404]1101
[85a79b0]1102        hdr=(struct libtrace_linuxnative_header*)packet->buffer;
[411f3c7]1103        snaplen=LIBTRACE_MIN(
1104                        (int)LIBTRACE_PACKET_BUFSIZE-(int)sizeof(*hdr),
1105                        (int)FORMAT(libtrace->format_data)->snaplen);
[d0fd73c]1106
[238d50a]1107        /* Prepare the msghdr and iovec for the kernel to write the
1108         * captured packet into. The msghdr will point to the part of our
1109         * buffer reserved for sll header, while the iovec will point at
1110         * the buffer following the sll header. */
1111
[d0fd73c]1112        msghdr.msg_name = &hdr->hdr;
1113        msghdr.msg_namelen = sizeof(struct sockaddr_ll);
1114
1115        msghdr.msg_iov = &iovec;
1116        msghdr.msg_iovlen = 1;
1117
1118        msghdr.msg_control = &controlbuf;
1119        msghdr.msg_controllen = CMSG_BUF_SIZE;
1120        msghdr.msg_flags = 0;
1121
[1f44884]1122        iovec.iov_base = (void*)(packet->buffer+sizeof(*hdr));
[d0fd73c]1123        iovec.iov_len = snaplen;
[29bbef0]1124       
1125        if (check_queue) {
1126                // Check for a packet - TODO only Linux has MSG_DONTWAIT should use fctl O_NONBLOCK
[17c5749]1127                hdr->wirelen = recvmsg(fd, &msghdr, MSG_DONTWAIT | MSG_TRUNC);
[50ce607]1128                if ((int) hdr->wirelen == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
[29bbef0]1129                        // Do message queue check or select
1130                        int ret;
1131                        fd_set rfds;
1132                        FD_ZERO(&rfds);
1133                        FD_SET(fd, &rfds);
1134                        FD_SET(get_thread_table(libtrace)->messages.pipefd[0], &rfds);
1135                        int largestfd = fd > get_thread_table(libtrace)->messages.pipefd[0] ? fd : get_thread_table(libtrace)->messages.pipefd[0];
1136                        do {
1137                                ret = select(largestfd+1, &rfds, NULL, NULL, NULL);
1138                                if (ret == -1 && errno != EINTR)
1139                                        perror("Select() failed");
1140                        }
1141                        while (ret == -1);
1142                       
1143                        assert (ret == 1 || ret == 2); // No timeout 0 is not an option
1144                       
1145                        if (FD_ISSET(get_thread_table(libtrace)->messages.pipefd[0], &rfds)) {
1146                                // Not an error but check the message queue we have something
1147                                return -2;
1148                        }
1149                        // Otherwise we must have a packet
1150                        hdr->wirelen = recvmsg(fd, &msghdr, 0);
1151                }
1152        } else {
[63af502]1153        /* Use select to allow us to time out occasionally to check if someone
1154         * has hit Ctrl-C or otherwise wants us to stop reading and return
1155         * so they can exit their program.
1156         */
1157
1158        while (1) {
1159                tout.tv_sec = 0;
1160                tout.tv_usec = 500000;
1161                FD_ZERO(&readfds);
1162                FD_SET(FORMAT(libtrace->format_data)->fd, &readfds);
1163
1164                ret = select(FORMAT(libtrace->format_data)->fd + 1, &readfds,
1165                                NULL, NULL, &tout);
1166                if (ret < 0 && errno != EINTR) {
1167                        trace_set_err(libtrace, errno, "select");
1168                        return -1;
1169                } else if (ret < 0) {
1170                        continue;
1171                } 
1172               
1173                if (FD_ISSET(FORMAT(libtrace->format_data)->fd, &readfds)) {
1174                        /* There's something available for us to read */
1175                        break;
1176                }
1177
1178               
1179                /* If we get here, we timed out -- check if we should halt */
1180                if (libtrace_halt)
1181                        return 0;
1182        }
1183        hdr->wirelen = recvmsg(FORMAT(libtrace->format_data)->fd, &msghdr, MSG_TRUNC);
[29bbef0]1184        }
[d0fd73c]1185
[9e429e8]1186                       
1187                       
[29bbef0]1188       
[d7e8e67]1189        if (hdr->wirelen==~0U) {
[d0fd73c]1190                trace_set_err(libtrace,errno,"recvmsg");
[97e39a7]1191                return -1;
[d0fd73c]1192        }
[97e39a7]1193
[d7e8e67]1194        hdr->caplen=LIBTRACE_MIN((unsigned int)snaplen,(unsigned int)hdr->wirelen);
[411f3c7]1195
[238d50a]1196        /* Extract the timestamps from the msghdr and store them in our
1197         * linux native encapsulation, so that we can preserve the formatting
1198         * across multiple architectures */
1199
[d0fd73c]1200        for (cmsg = CMSG_FIRSTHDR(&msghdr);
1201                        cmsg != NULL;
1202                        cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
1203                if (cmsg->cmsg_level == SOL_SOCKET
1204                        && cmsg->cmsg_type == SO_TIMESTAMP
[3b10b9f]1205                        && cmsg->cmsg_len <= CMSG_LEN(sizeof(struct timeval))) {
[c69b593]1206                       
1207                        struct timeval *tv;
1208                        tv = (struct timeval *)CMSG_DATA(cmsg);
1209                       
1210                       
1211                        hdr->tv.tv_sec = tv->tv_sec;
1212                        hdr->tv.tv_usec = tv->tv_usec;
[1aa4bf7]1213                        hdr->timestamptype = TS_TIMEVAL;
1214                        break;
1215                } 
1216#ifdef SO_TIMESTAMPNS
1217                else if (cmsg->cmsg_level == SOL_SOCKET
1218                        && cmsg->cmsg_type == SO_TIMESTAMPNS
1219                        && cmsg->cmsg_len <= CMSG_LEN(sizeof(struct timespec))) {
[c69b593]1220
1221                        struct timespec *tv;
1222                        tv = (struct timespec *)CMSG_DATA(cmsg);
1223
1224                        hdr->ts.tv_sec = tv->tv_sec;
1225                        hdr->ts.tv_nsec = tv->tv_nsec;
[1aa4bf7]1226                        hdr->timestamptype = TS_TIMESPEC;
[d0fd73c]1227                        break;
1228                }
[1aa4bf7]1229#endif
[d0fd73c]1230        }
1231
[238d50a]1232        /* Did we not get given a timestamp? Try to get one from the
1233         * file descriptor directly */
[1aa4bf7]1234        if (cmsg == NULL) {
[7fa118f]1235                struct timeval tv;
[29bbef0]1236                if (ioctl(fd, SIOCGSTAMP,&tv)==0) {
[7fa118f]1237                        hdr->tv.tv_sec = tv.tv_sec;
1238                        hdr->tv.tv_usec = tv.tv_usec;
[1aa4bf7]1239                        hdr->timestamptype = TS_TIMEVAL;
1240                }
1241                else {
1242                        hdr->timestamptype = TS_NONE;
1243                }
1244        }
[97e39a7]1245
[238d50a]1246        /* Buffer contains all of our packet (including our custom header) so
1247         * we just need to get prepare_packet to set all our packet pointers
1248         * appropriately */
1249       
[f0fb38f]1250        if (linuxnative_prepare_packet(libtrace, packet, packet->buffer,
1251                                packet->type, flags))
1252                return -1;
1253       
[97e39a7]1254        return hdr->wirelen+sizeof(*hdr);
1255}
1256
[29bbef0]1257static int linuxnative_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) 
1258{
1259        int fd = FORMAT(libtrace->format_data)->fd;
1260        return linuxnative_read_packet_fd(libtrace, packet, fd, 0);
1261}
1262
[50ce607]1263static int linuxnative_pread_packet(libtrace_t *libtrace, libtrace_thread_t *t, libtrace_packet_t *packet)
[29bbef0]1264{
[bcfe4ea]1265        int fd = PERPKT_FORMAT(t)->fd;
1266        //fprintf(stderr, "Thread number is #%d fd=%d\n", t->perpkt_num, PERPKT_FORMAT(t)->fd);
[29bbef0]1267        return linuxnative_read_packet_fd(libtrace, packet, fd, 1);
1268}
1269
[d500159]1270#define LIBTRACE_BETWEEN(test,a,b) ((test) >= (a) && (test) < (b))
1271static int linuxring_get_capture_length(const libtrace_packet_t *packet);
1272static int linuxring_get_framing_length(const libtrace_packet_t *packet);
1273
[f240823]1274/* Release a frame back to the kernel or free() if it's a malloc'd buffer
1275 */
[29bbef0]1276inline static void ring_release_frame(libtrace_t *libtrace, libtrace_packet_t *packet){
[d500159]1277        /* Free the old packet */
[f240823]1278        if(packet->buffer == NULL)
1279                return;
1280
[d500159]1281        if(packet->buf_control == TRACE_CTRL_PACKET){
1282                free(packet->buffer);
[f240823]1283                packet->buffer = NULL;
[d500159]1284        }
1285        if(packet->buf_control == TRACE_CTRL_EXTERNAL) {
1286                struct linux_format_data_t *ftd = FORMAT(libtrace->format_data);
1287               
[29bbef0]1288                /* Check it's within our buffer first - consider the pause resume case it might have already been free'd lets hope we get another buffer */
1289                // For now let any one free anything
1290                /*if(LIBTRACE_BETWEEN((char *) packet->buffer,
[d500159]1291                                (char *) ftd->rx_ring,
1292                                ftd->rx_ring
[29bbef0]1293                                + ftd->req.tp_block_size * ftd->req.tp_block_nr)){*/
[d500159]1294                        TO_TP_HDR(packet->buffer)->tp_status = 0;
1295                        packet->buffer = NULL;
[29bbef0]1296                /*}*/
[d500159]1297        }
[f240823]1298}
1299
[29bbef0]1300/**
1301 * Free any resources being kept for this packet, Note: libtrace
1302 * will ensure all fields are zeroed correctly.
1303 */
1304static void linuxring_fin_packet(libtrace_packet_t *packet)
1305{
[b4b6b75]1306
1307        if (packet->buffer == NULL)
1308                return;
[29bbef0]1309        assert(packet->trace);
1310       
1311        // Started should always match the existence of the rx_ring
1312        assert(!!FORMAT(packet->trace->format_data)->rx_ring == !!packet->trace->started);
1313       
1314        // Our packets are always under our control
1315        assert(packet->buf_control == TRACE_CTRL_EXTERNAL);
1316       
1317        if (FORMAT(packet->trace->format_data)->rx_ring) // If we don't have a ring its already been destroyed or paused
1318                ring_release_frame(packet->trace, packet);
1319        else
1320                packet->buffer = NULL;
1321}
1322
1323inline static int linuxring_read_packet_fd(libtrace_t *libtrace, libtrace_packet_t *packet, int fd, int *rxring_offset, char *rx_ring, int message) {
[f240823]1324
1325        struct tpacket2_hdr *header;
1326        int ret;
[d1af45d]1327        unsigned int snaplen;
[f240823]1328       
1329        ring_release_frame(libtrace, packet);
[d500159]1330       
1331        packet->buf_control = TRACE_CTRL_EXTERNAL;
1332        packet->type = TRACE_RT_DATA_LINUX_RING;
1333       
1334        /* Fetch the current frame */
[29bbef0]1335        header = ((void*) rx_ring) + *rxring_offset * FORMAT(libtrace->format_data)->req.tp_frame_size; // GET_CURRENT_BUFFER(libtrace);
[d500159]1336        assert((((unsigned long) header) & (pagesize - 1)) == 0);
1337
[63af502]1338        while (1) {
[29bbef0]1339                if (message) {
1340                        struct pollfd pollset[2];
1341                        pollset[0].fd = fd;
1342                        pollset[0].events = POLLIN;
1343                        pollset[0].revents = 0;
1344                        pollset[1].fd = libtrace_message_queue_get_fd(&get_thread_table(libtrace)->messages);
1345                        pollset[1].events = POLLIN;
1346                        pollset[1].revents = 0;
1347                        /* Wait for more data or a message*/
1348                        ret = poll(pollset, 2, -1);
1349                        if (ret < 0) {
1350                                if (errno != EINTR)
1351                                        trace_set_err(libtrace,errno,"poll()");
1352                                return -1;
1353                        }
1354                        // Check for a message otherwise loop
1355                        if (pollset[1].revents)
1356                                return -2;
1357                } else {
1358                        struct pollfd pollset;
1359                        pollset.fd = fd;
1360                        pollset.events = POLLIN;
1361                        pollset.revents = 0;
1362
1363                        /* Wait for more data or a message*/
[63af502]1364                ret = poll(&pollset, 1, 500);
[29bbef0]1365                        if (ret < 0) {
1366                                if (errno != EINTR)
1367                                        trace_set_err(libtrace,errno,"poll()");
1368                                return -1;
[63af502]1369                } else if (ret == 0) {
1370                        /* Poll timed out - check if we should exit */
1371                        if (libtrace_halt)
1372                                return 0;
1373                        continue;
1374                }
1375
1376                /* TP_STATUS_USER means that we can use the frame.
1377                 * When a slot does not have this flag set, the frame is not
1378                 * ready for consumption.
1379                 */
1380                if (header->tp_status & TP_STATUS_USER)
1381                        break;
[d500159]1382                }
1383        }
1384
1385        packet->buffer = header;
1386
[d1af45d]1387        /* If a snaplen was configured, automatically truncate the packet to
1388         * the desired length.
1389         */
1390        snaplen=LIBTRACE_MIN(
1391                        (int)LIBTRACE_PACKET_BUFSIZE-(int)sizeof(*header),
1392                        (int)FORMAT(libtrace->format_data)->snaplen);
1393       
1394        TO_TP_HDR(packet->buffer)->tp_snaplen = LIBTRACE_MIN((unsigned int)snaplen, TO_TP_HDR(packet->buffer)->tp_len);
1395
[d500159]1396        /* Move to next buffer */
[29bbef0]1397        (*rxring_offset)++;
1398        *rxring_offset %= FORMAT(libtrace->format_data)->req.tp_frame_nr;
[d500159]1399
1400        /* We just need to get prepare_packet to set all our packet pointers
1401         * appropriately */
1402        if (linuxring_prepare_packet(libtrace, packet, packet->buffer,
1403                                packet->type, 0))
1404                return -1;
1405        return  linuxring_get_framing_length(packet) + 
1406                                linuxring_get_capture_length(packet);
1407
1408}
1409
[29bbef0]1410static int linuxring_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
1411        int fd = FORMAT(libtrace->format_data)->fd;
1412        int *rxring_offset = &FORMAT(libtrace->format_data)->rxring_offset;
1413        char *rx_ring = FORMAT(libtrace->format_data)->rx_ring;
1414        return linuxring_read_packet_fd(libtrace, packet, fd, rxring_offset, rx_ring, 0);
1415}
1416
[50ce607]1417static int linuxring_pread_packet(libtrace_t *libtrace, libtrace_thread_t *t, libtrace_packet_t *packet) {
[f9a70ca]1418        //fprintf(stderr, "Thread number is #%d\n", t->perpkt_num);
[50ce607]1419        int fd = PERPKT_FORMAT(t)->fd;
1420        int *rxring_offset = &PERPKT_FORMAT(t)->rxring_offset;
1421        char *rx_ring = PERPKT_FORMAT(t)->rx_ring;
[29bbef0]1422        return linuxring_read_packet_fd(libtrace, packet, fd, rxring_offset, rx_ring, 1);
1423}
1424
[f240823]1425/* Non-blocking read */
1426static libtrace_eventobj_t linuxring_event(libtrace_t *libtrace, libtrace_packet_t *packet) {
1427        struct tpacket2_hdr *header;
1428        libtrace_eventobj_t event = {0,0,0.0,0};
1429
1430        /* We must free the old packet, otherwise select() will instantly return
1431         */
1432        ring_release_frame(libtrace, packet);
1433
1434        /* Fetch the current frame */
1435        header = GET_CURRENT_BUFFER(libtrace);
1436        if(header->tp_status & TP_STATUS_USER){
1437                /* We have a frame waiting */
[c70f59f]1438                event.size = trace_read_packet(libtrace, packet);
[f240823]1439                event.type = TRACE_EVENT_PACKET;
1440        } else {
1441                /* Ok we don't have a packet waiting */
1442                event.type = TRACE_EVENT_IOWAIT;
1443                event.fd = FORMAT(libtrace->format_data)->fd;
1444        }
1445
1446        return event;
1447}
1448
[d500159]1449
[e4e95499]1450static int linuxnative_write_packet(libtrace_out_t *trace, 
[85a79b0]1451                libtrace_packet_t *packet) 
[e4e95499]1452{
1453        struct sockaddr_ll hdr;
[ebafa5d]1454        int ret = 0;
[e4e95499]1455
[5f329ab]1456        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
1457                return 0;
1458
[e4e95499]1459        hdr.sll_family = AF_PACKET;
1460        hdr.sll_protocol = 0;
[030aa3f]1461        hdr.sll_ifindex = if_nametoindex(trace->uridata);
[e4e95499]1462        hdr.sll_hatype = 0;
1463        hdr.sll_pkttype = 0;
[99ff3d9]1464        hdr.sll_halen = htons(6); /* FIXME */
[013de36e]1465        memcpy(hdr.sll_addr,packet->payload,(size_t)ntohs(hdr.sll_halen));
[e4e95499]1466
[238d50a]1467        /* This is pretty easy, just send the payload using sendto() (after
1468         * setting up the sll header properly, of course) */
[ebafa5d]1469        ret = sendto(DATAOUT(trace)->fd,
[e4e95499]1470                        packet->payload,
1471                        trace_get_capture_length(packet),
1472                        0,
[4bd8a5b]1473                        (struct sockaddr*)&hdr, (socklen_t)sizeof(hdr));
[e4e95499]1474
[ebafa5d]1475        if (ret < 0) {
1476                trace_set_err_out(trace, errno, "sendto failed");
1477        }
1478
1479        return ret;
[e4e95499]1480}
[50ce607]1481
[d500159]1482static int linuxring_write_packet(libtrace_out_t *trace, 
1483                libtrace_packet_t *packet)
1484{
1485        struct tpacket2_hdr *header;
1486        struct pollfd pollset;
1487        struct socket_addr;
1488        int ret; 
1489        unsigned max_size;
1490        void * off;
[e4e95499]1491
[d500159]1492        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
1493                return 0;
1494
1495        max_size = DATAOUT(trace)->req.tp_frame_size - 
1496                 - TPACKET_HDRLEN + sizeof(struct sockaddr_ll);
1497
1498        header = (void *) DATAOUT(trace)->tx_ring + 
1499        (DATAOUT(trace)->txring_offset * DATAOUT(trace)->req.tp_frame_size);
1500
1501        while(header->tp_status != TP_STATUS_AVAILABLE){
1502                /* if none available: wait on more data */
1503                pollset.fd = DATAOUT(trace)->fd;
1504                pollset.events = POLLOUT;
1505                pollset.revents = 0;
1506                ret = poll(&pollset, 1, 1000);
1507                if (ret < 0 && errno != EINTR) {
1508                        perror("poll");
1509                        return -1;
1510                }
1511                if(ret == 0) 
1512                        /* Timeout something has gone wrong - maybe the queue is
1513                         * to large so try issue another send command
1514                         */
[ebafa5d]1515                        ret = sendto(DATAOUT(trace)->fd, 
[d500159]1516                                NULL, 
1517                                0, 
1518                                0, 
1519                                (void *) &DATAOUT(trace)->sock_hdr, 
1520                                sizeof(DATAOUT(trace)->sock_hdr));
[ebafa5d]1521                        if (ret < 0) {
1522                                trace_set_err_out(trace, errno, 
1523                                                "sendto after timeout failed");
1524                                return -1;
1525                        }
[d500159]1526        }
1527       
1528        header->tp_len = trace_get_capture_length(packet);
1529
1530        /* We cannot write the whole packet so just write part of it */
1531        if (header->tp_len > max_size)
1532                header->tp_len = max_size;
[238d50a]1533
[d500159]1534        /* Fill packet - no sockaddr_ll in header when writing to the TX_RING */
1535        off = ((void *) header) + (TPACKET_HDRLEN - sizeof(struct sockaddr_ll));
1536        memcpy(off, 
1537                (char *) packet->payload, 
1538                header->tp_len);
1539       
1540        /* 'Send it' and increase ring pointer to the next frame */
1541        header->tp_status = TP_STATUS_SEND_REQUEST;
1542        DATAOUT(trace)->txring_offset = (DATAOUT(trace)->txring_offset + 1) % 
1543                                                DATAOUT(trace)->req.tp_frame_nr;
1544
1545        /* Notify kernel there are frames to send */
[b4c3f61]1546        DATAOUT(trace)->queue ++;
1547        DATAOUT(trace)->queue %= TX_MAX_QUEUE;
[d500159]1548        if(DATAOUT(trace)->queue == 0){
[ebafa5d]1549                ret = sendto(DATAOUT(trace)->fd, 
1550                                NULL, 
1551                                0, 
1552                                MSG_DONTWAIT, 
1553                                (void *) &DATAOUT(trace)->sock_hdr, 
1554                                sizeof(DATAOUT(trace)->sock_hdr));
1555                if (ret < 0) {
1556                        trace_set_err_out(trace, errno, "sendto failed");
1557                        return -1;
1558                }
[d500159]1559        }
1560        return header->tp_len;
1561
1562}
[b4c3f61]1563#endif /* HAVE_NETPACKET_PACKET_H */
[d500159]1564
[17dc71c]1565static inline libtrace_linktype_t get_libtrace_link_type(uint16_t linktype){
[d500159]1566        /* Convert the ARPHRD type into an appropriate libtrace link type */
[fc2e63f]1567        switch (linktype) {
[528eb6e]1568                case LIBTRACE_ARPHRD_ETHER:
1569                case LIBTRACE_ARPHRD_LOOPBACK:
[97e39a7]1570                        return TRACE_TYPE_ETH;
[528eb6e]1571                case LIBTRACE_ARPHRD_PPP:
[8c747709]1572                        return TRACE_TYPE_NONE;
[528eb6e]1573                case LIBTRACE_ARPHRD_IEEE80211_RADIOTAP:
[ef3660cb]1574                        return TRACE_TYPE_80211_RADIO;
[528eb6e]1575                case LIBTRACE_ARPHRD_IEEE80211:
[ef3660cb]1576                        return TRACE_TYPE_80211;
[528eb6e]1577                case LIBTRACE_ARPHRD_SIT:
1578                case LIBTRACE_ARPHRD_NONE:
[496b8e5]1579                        return TRACE_TYPE_NONE;
[97e39a7]1580                default: /* shrug, beyond me! */
[9cad9c9]1581                        printf("unknown Linux ARPHRD type 0x%04x\n",linktype);
[85a79b0]1582                        return (libtrace_linktype_t)~0U;
[97e39a7]1583        }
1584}
[d500159]1585static libtrace_linktype_t linuxnative_get_link_type(const struct libtrace_packet_t *packet) {
[17dc71c]1586        uint16_t linktype=(((struct libtrace_linuxnative_header*)(packet->buffer))
[d500159]1587                                ->hdr.sll_hatype);
1588        return get_libtrace_link_type(linktype);
1589}
1590static libtrace_linktype_t linuxring_get_link_type(const struct libtrace_packet_t *packet) {
[17dc71c]1591        uint16_t linktype= GET_SOCKADDR_HDR(packet->buffer)->sll_hatype;
[d500159]1592        return get_libtrace_link_type(linktype);
1593}
[97e39a7]1594
[17dc71c]1595static inline libtrace_direction_t get_libtrace_direction(uint8_t pkttype){
[d500159]1596        switch (pkttype) {
[97e39a7]1597                case PACKET_OUTGOING:
[27bd348]1598                case PACKET_LOOPBACK:
[431548c5]1599                        return TRACE_DIR_OUTGOING;
[7a529a9]1600                case PACKET_OTHERHOST:
1601                        return TRACE_DIR_OTHER;
[97e39a7]1602                default:
[431548c5]1603                        return TRACE_DIR_INCOMING;
[97e39a7]1604        }
1605}
[d500159]1606static libtrace_direction_t linuxnative_get_direction(const struct libtrace_packet_t *packet) {
[17dc71c]1607        return get_libtrace_direction(((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype);
[d500159]1608}
1609static libtrace_direction_t linuxring_get_direction(const struct libtrace_packet_t *packet) {
[17dc71c]1610        return get_libtrace_direction(GET_SOCKADDR_HDR(packet->buffer)->sll_pkttype);
[d500159]1611}
[97e39a7]1612
[d500159]1613static libtrace_direction_t set_direction(struct sockaddr_ll * skadr, libtrace_direction_t direction){
[1008250]1614        switch (direction) {
1615                case TRACE_DIR_OUTGOING:
[d500159]1616                        skadr->sll_pkttype = PACKET_OUTGOING;
[1008250]1617                        return TRACE_DIR_OUTGOING;
1618                case TRACE_DIR_INCOMING:
[d500159]1619                        skadr->sll_pkttype = PACKET_HOST;
[1008250]1620                        return TRACE_DIR_INCOMING;
[7a529a9]1621                case TRACE_DIR_OTHER:
1622                        skadr->sll_pkttype = PACKET_OTHERHOST;
1623                        return TRACE_DIR_OTHER;
[1008250]1624                default:
1625                        return -1;
1626        }
1627}
[d500159]1628static libtrace_direction_t linuxnative_set_direction(
1629                libtrace_packet_t *packet,
1630                libtrace_direction_t direction) {
1631        return set_direction(&((struct libtrace_linuxnative_header*)(packet->buffer))->hdr, direction);
1632}
1633static libtrace_direction_t linuxring_set_direction(
1634                libtrace_packet_t *packet,
1635                libtrace_direction_t direction) {
1636        return set_direction(GET_SOCKADDR_HDR(packet->buffer), direction);
1637}
[1008250]1638
[1aa4bf7]1639static struct timespec linuxnative_get_timespec(const libtrace_packet_t *packet) 
1640{
1641        struct libtrace_linuxnative_header *hdr = 
1642                (struct libtrace_linuxnative_header*) packet->buffer;
1643        /* We have to upconvert from timeval to timespec */
1644        if (hdr->timestamptype == TS_TIMEVAL) {
1645                struct timespec ts;
1646                ts.tv_sec = hdr->tv.tv_sec;
1647                ts.tv_nsec = hdr->tv.tv_usec*1000;
1648                return ts;
1649        }
[7fa118f]1650        else {
1651                struct timespec ts;
1652                ts.tv_sec = hdr->ts.tv_sec;
1653                ts.tv_nsec = hdr->ts.tv_nsec;
1654                return ts;
1655        }
[1aa4bf7]1656}
[d500159]1657static struct timespec linuxring_get_timespec(const libtrace_packet_t *packet) 
1658{
1659        struct timespec ts;
1660        ts.tv_sec = TO_TP_HDR(packet->buffer)->tp_sec;
1661        ts.tv_nsec = TO_TP_HDR(packet->buffer)->tp_nsec;
1662        return ts;
1663}
1664
[1aa4bf7]1665
[411f3c7]1666static struct timeval linuxnative_get_timeval(const libtrace_packet_t *packet) 
1667{
[1aa4bf7]1668        struct libtrace_linuxnative_header *hdr = 
1669                (struct libtrace_linuxnative_header*) packet->buffer;
1670        /* We have to downconvert from timespec to timeval */
1671        if (hdr->timestamptype == TS_TIMESPEC) {
1672                struct timeval tv;
1673                tv.tv_sec = hdr->ts.tv_sec;
1674                tv.tv_usec = hdr->ts.tv_nsec/1000;
1675                return tv;
1676        }
[7fa118f]1677        else {
1678                struct timeval tv;
1679                tv.tv_sec = hdr->tv.tv_sec;
1680                tv.tv_usec = hdr->tv.tv_usec;
1681                return tv;
1682        }
[97e39a7]1683}
[d500159]1684static struct timeval linuxring_get_timeval(const libtrace_packet_t *packet) 
1685{
1686        struct timeval tv;
1687        tv.tv_sec = TO_TP_HDR(packet->buffer)->tp_sec;
1688        tv.tv_usec = TO_TP_HDR(packet->buffer)->tp_nsec / 1000;
1689        return tv;
1690}
[97e39a7]1691
[411f3c7]1692static int linuxnative_get_capture_length(const libtrace_packet_t *packet)
1693{
1694        return ((struct libtrace_linuxnative_header*)(packet->buffer))->caplen;
1695}
1696
[d500159]1697static int linuxring_get_capture_length(const libtrace_packet_t *packet)
1698{
1699        return TO_TP_HDR(packet->buffer)->tp_snaplen;
1700}
1701
[411f3c7]1702static int linuxnative_get_wire_length(const libtrace_packet_t *packet) 
1703{
[078bd65]1704
1705        int wirelen = ((struct libtrace_linuxnative_header*)(packet->buffer))->wirelen;
1706
1707        /* Include the missing FCS */
1708        if (trace_get_link_type(packet) == TRACE_TYPE_ETH)
1709                wirelen += 4;
1710
1711        return wirelen;
[97e39a7]1712}
1713
[d500159]1714static int linuxring_get_wire_length(const libtrace_packet_t *packet) 
1715{
1716        int wirelen = TO_TP_HDR(packet->buffer)->tp_len;
1717
1718        /* Include the missing FCS */
1719        if (trace_get_link_type(packet) == TRACE_TYPE_ETH)
1720                wirelen += 4;
1721
1722        return wirelen;
1723}
1724
[85a79b0]1725static int linuxnative_get_framing_length(UNUSED
1726                const libtrace_packet_t *packet) 
[411f3c7]1727{
[97e39a7]1728        return sizeof(struct libtrace_linuxnative_header);
1729}
1730
[d500159]1731static int linuxring_get_framing_length(const libtrace_packet_t *packet)
1732{       
1733        /*
[6ba84d9]1734         * Need to make frame_length + capture_length = complete capture length
[d500159]1735         * so include alligment whitespace. So reverse calculate from packet.
1736         */
1737        return (char *) packet->payload - (char *) packet->buffer;
1738}
1739
[f68d5b8]1740static size_t linuxnative_set_capture_length(libtrace_packet_t *packet, 
1741                size_t size) {
1742
1743        struct libtrace_linuxnative_header *linux_hdr = NULL;
1744        assert(packet);
1745        if (size > trace_get_capture_length(packet)) {
1746                /* We should avoid making a packet larger */
1747                return trace_get_capture_length(packet);
1748        }
1749       
1750        /* Reset the cached capture length */
1751        packet->capture_length = -1;
1752
1753        linux_hdr = (struct libtrace_linuxnative_header *)packet->header;
1754        linux_hdr->caplen = size;
1755        return trace_get_capture_length(packet);
1756}
1757
[d500159]1758static size_t linuxring_set_capture_length(libtrace_packet_t *packet, 
1759                size_t size) {
1760        assert(packet);
1761        if (size > trace_get_capture_length(packet)) {
1762                /* We should avoid making a packet larger */
1763                return trace_get_capture_length(packet);
1764        }
1765       
1766        /* Reset the cached capture length */
1767        packet->capture_length = -1;
1768
[7a529a9]1769        TO_TP_HDR(packet->buffer)->tp_snaplen = size;
[d500159]1770
1771        return trace_get_capture_length(packet);
1772}
1773
[97e39a7]1774static int linuxnative_get_fd(const libtrace_t *trace) {
[f0fb38f]1775        if (trace->format_data == NULL)
1776                return -1;
[97e39a7]1777        return FORMAT(trace->format_data)->fd;
1778}
1779
[25a9201]1780/* Linux doesn't keep track how many packets were seen before filtering
1781 * so we can't tell how many packets were filtered.  Bugger.  So annoying.
[4f87b817]1782 *
1783 * Since we tell libtrace that we do support filtering, if we don't declare
1784 * this here as failing, libtrace will happily report for us that it didn't
1785 * filter any packets, so don't lie -- return that we don't know.
[25a9201]1786 */
[d267f4d]1787static uint64_t linuxnative_get_filtered_packets(libtrace_t *trace UNUSED) {
[25a9201]1788        return UINT64_MAX;
1789}
1790
[238d50a]1791/* Number of packets that passed filtering */
[50bbce8]1792static uint64_t linuxnative_get_captured_packets(libtrace_t *trace) {
[f9a70ca]1793        struct tpacket_stats stats;
1794
[f0fb38f]1795        if (trace->format_data == NULL)
1796                return UINT64_MAX;
1797        if (FORMAT(trace->format_data)->fd == -1) {
1798                /* This is probably a 'dead' trace so obviously we can't query
1799                 * the socket for capture counts, can we? */
1800                return UINT64_MAX;
1801        }
[528eb6e]1802
[f9a70ca]1803#ifdef HAVE_NETPACKET_PACKET_H
1804
1805        if ((FORMAT(trace->format_data)->stats_valid & 1)
1806                || FORMAT(trace->format_data)->stats_valid == 0) {
1807                if (FORMAT(trace->format_data)->per_thread) {
[2498008]1808                        int i;
[f9a70ca]1809                        FORMAT(trace->format_data)->stats.tp_drops = 0;
1810                        FORMAT(trace->format_data)->stats.tp_packets = 0;
1811                        for (i = 0; i < trace->perpkt_thread_count; ++i) {
1812                                socklen_t len = sizeof(stats);
1813                                getsockopt(FORMAT(trace->format_data)->per_thread[i].fd,
1814                                           SOL_PACKET,
1815                                           PACKET_STATISTICS,
1816                                           &stats,
1817                                           &len);
1818                                FORMAT(trace->format_data)->stats.tp_drops += stats.tp_drops;
1819                                FORMAT(trace->format_data)->stats.tp_packets += stats.tp_packets;
1820                        }
1821                        FORMAT(trace->format_data)->stats_valid |= 1;
1822                } else {
1823                        socklen_t len = sizeof(FORMAT(trace->format_data)->stats);
1824                        getsockopt(FORMAT(trace->format_data)->fd,
1825                                   SOL_PACKET,
1826                                   PACKET_STATISTICS,
1827                                   &FORMAT(trace->format_data)->stats,
1828                                   &len);
1829                        FORMAT(trace->format_data)->stats_valid |= 1;
1830                }
[50bbce8]1831        }
1832
1833        return FORMAT(trace->format_data)->stats.tp_packets;
[528eb6e]1834#else
1835        return UINT64_MAX;
1836#endif
[50bbce8]1837}
1838
[25a9201]1839/* Number of packets that got past filtering and were then dropped because
1840 * of lack of space
1841 */
[50bbce8]1842static uint64_t linuxnative_get_dropped_packets(libtrace_t *trace) {
[f9a70ca]1843        struct tpacket_stats stats;
[f0fb38f]1844        if (trace->format_data == NULL)
1845                return UINT64_MAX;
1846        if (FORMAT(trace->format_data)->fd == -1) {
1847                /* This is probably a 'dead' trace so obviously we can't query
1848                 * the socket for drop counts, can we? */
1849                return UINT64_MAX;
1850        }
[f9a70ca]1851
[b4c3f61]1852#ifdef HAVE_NETPACKET_PACKET_H 
[95fee28]1853        if ((FORMAT(trace->format_data)->stats_valid & 2)
[f9a70ca]1854                || (FORMAT(trace->format_data)->stats_valid==0)) {
1855                if (FORMAT(trace->format_data)->per_thread) {
[2498008]1856                        int i;
[f9a70ca]1857                        FORMAT(trace->format_data)->stats.tp_drops = 0;
1858                        FORMAT(trace->format_data)->stats.tp_packets = 0;
1859                        for (i = 0; i < trace->perpkt_thread_count; ++i) {
1860                                socklen_t len = sizeof(stats);
1861                                getsockopt(FORMAT(trace->format_data)->per_thread[i].fd,
1862                                           SOL_PACKET,
1863                                           PACKET_STATISTICS,
1864                                           &stats,
1865                                           &len);
1866                                FORMAT(trace->format_data)->stats.tp_drops += stats.tp_drops;
1867                                FORMAT(trace->format_data)->stats.tp_packets += stats.tp_packets;
1868                        }
1869                        FORMAT(trace->format_data)->stats_valid |= 2;
1870                } else {
1871                        socklen_t len = sizeof(FORMAT(trace->format_data)->stats);
1872                        getsockopt(FORMAT(trace->format_data)->fd,
1873                                   SOL_PACKET,
1874                                   PACKET_STATISTICS,
1875                                   &FORMAT(trace->format_data)->stats,
1876                                   &len);
1877                        FORMAT(trace->format_data)->stats_valid |= 2;
1878                }
[50bbce8]1879        }
1880
1881        return FORMAT(trace->format_data)->stats.tp_drops;
[528eb6e]1882#else
1883        return UINT64_MAX;
1884#endif
[50bbce8]1885}
1886
[b4c3f61]1887#ifdef HAVE_NETPACKET_PACKET_H
[33d83d4]1888static void linuxnative_help(void) {
[c909fad]1889        printf("linuxnative format module: $Revision: 1793 $\n");
[97e39a7]1890        printf("Supported input URIs:\n");
[238d50a]1891        printf("\tint:eth0\n");
[97e39a7]1892        printf("\n");
1893        printf("Supported output URIs:\n");
[238d50a]1894        printf("\tint:eth0\n");
[97e39a7]1895        printf("\n");
1896        return;
1897}
[d500159]1898
1899static void linuxring_help(void) {
[c909fad]1900        printf("linuxring format module: $Revision: 1793 $\n");
[d500159]1901        printf("Supported input URIs:\n");
1902        printf("\tring:eth0\n");
1903        printf("\n");
1904        printf("Supported output URIs:\n");
1905        printf("\tring:eth0\n");
1906        printf("\n");
1907        return;
1908}
1909
[97e39a7]1910static struct libtrace_format_t linuxnative = {
1911        "int",
[293999b]1912        "$Id$",
[97e39a7]1913        TRACE_FORMAT_LINUX_NATIVE,
[91b72d3]1914        linuxnative_probe_filename,     /* probe filename */
1915        NULL,                           /* probe magic */
[97e39a7]1916        linuxnative_init_input,         /* init_input */
[411f3c7]1917        linuxnative_config_input,       /* config_input */
1918        linuxnative_start_input,        /* start_input */
1919        linuxnative_pause_input,        /* pause_input */
[e4e95499]1920        linuxnative_init_output,        /* init_output */
[97e39a7]1921        NULL,                           /* config_output */
[e4e95499]1922        linuxnative_start_output,       /* start_ouput */
[97e39a7]1923        linuxnative_fin_input,          /* fin_input */
[e4e95499]1924        linuxnative_fin_output,         /* fin_output */
[97e39a7]1925        linuxnative_read_packet,        /* read_packet */
[f0fb38f]1926        linuxnative_prepare_packet,     /* prepare_packet */
[97e39a7]1927        NULL,                           /* fin_packet */
[e4e95499]1928        linuxnative_write_packet,       /* write_packet */
[97e39a7]1929        linuxnative_get_link_type,      /* get_link_type */
1930        linuxnative_get_direction,      /* get_direction */
[1008250]1931        linuxnative_set_direction,      /* set_direction */
[97e39a7]1932        NULL,                           /* get_erf_timestamp */
1933        linuxnative_get_timeval,        /* get_timeval */
[1aa4bf7]1934        linuxnative_get_timespec,       /* get_timespec */
[97e39a7]1935        NULL,                           /* get_seconds */
1936        NULL,                           /* seek_erf */
1937        NULL,                           /* seek_timeval */
1938        NULL,                           /* seek_seconds */
[411f3c7]1939        linuxnative_get_capture_length, /* get_capture_length */
[97e39a7]1940        linuxnative_get_wire_length,    /* get_wire_length */
1941        linuxnative_get_framing_length, /* get_framing_length */
[f68d5b8]1942        linuxnative_set_capture_length, /* set_capture_length */
[f2fae49]1943        NULL,                           /* get_received_packets */
[25a9201]1944        linuxnative_get_filtered_packets,/* get_filtered_packets */
[50bbce8]1945        linuxnative_get_dropped_packets,/* get_dropped_packets */
1946        linuxnative_get_captured_packets,/* get_captured_packets */
[97e39a7]1947        linuxnative_get_fd,             /* get_fd */
[0801187]1948        trace_event_device,             /* trace_event */
[97e39a7]1949        linuxnative_help,               /* help */
[b13b939]1950        NULL,                                   /* next pointer */
1951        {true, -1},              /* Live, no thread limit */
[29bbef0]1952        linuxnative_pstart_input,                       /* pstart_input */
1953        linuxnative_pread_packet,                       /* pread_packet */
1954        linuxnative_ppause_input,                       /* ppause */
1955        linuxnative_fin_input,                          /* p_fin */
[50ce607]1956        linuxnative_pconfig_input,                      /* pconfig input */
1957        linux_pregister_thread,
1958        NULL
[97e39a7]1959};
1960
[d500159]1961static struct libtrace_format_t linuxring = {
1962        "ring",
1963        "$Id$",
1964        TRACE_FORMAT_LINUX_RING,
1965        linuxnative_probe_filename,     /* probe filename */
1966        NULL,                           /* probe magic */
1967        linuxring_init_input,           /* init_input */
1968        linuxnative_config_input,       /* config_input */
1969        linuxring_start_input,  /* start_input */
1970        linuxring_pause_input,  /* pause_input */
1971        linuxring_init_output,  /* init_output */
1972        NULL,                           /* config_output */
1973        linuxring_start_output, /* start_ouput */
1974        linuxnative_fin_input,          /* fin_input */
1975        linuxring_fin_output,           /* fin_output */
1976        linuxring_read_packet,  /* read_packet */
1977        linuxring_prepare_packet,       /* prepare_packet */
[29bbef0]1978        linuxring_fin_packet,                           /* fin_packet */
[d500159]1979        linuxring_write_packet, /* write_packet */
1980        linuxring_get_link_type,        /* get_link_type */
1981        linuxring_get_direction,        /* get_direction */
1982        linuxring_set_direction,        /* set_direction */
1983        NULL,                           /* get_erf_timestamp */
1984        linuxring_get_timeval,  /* get_timeval */
1985        linuxring_get_timespec, /* get_timespec */
1986        NULL,                           /* get_seconds */
1987        NULL,                           /* seek_erf */
1988        NULL,                           /* seek_timeval */
1989        NULL,                           /* seek_seconds */
1990        linuxring_get_capture_length,   /* get_capture_length */
1991        linuxring_get_wire_length,      /* get_wire_length */
1992        linuxring_get_framing_length,   /* get_framing_length */
1993        linuxring_set_capture_length,   /* set_capture_length */
1994        NULL,                           /* get_received_packets */
1995        linuxnative_get_filtered_packets,/* get_filtered_packets */
1996        linuxnative_get_dropped_packets,/* get_dropped_packets */
1997        linuxnative_get_captured_packets,/* get_captured_packets */
1998        linuxnative_get_fd,             /* get_fd */
[f240823]1999        linuxring_event,                /* trace_event */
[d500159]2000        linuxring_help,         /* help */
[b13b939]2001        NULL,                           /* next pointer */
2002        {true, -1},              /* Live, no thread limit */
[29bbef0]2003        linuxnative_pstart_input,                       /* pstart_input */
2004        linuxring_pread_packet,                 /* pread_packet */
2005        linuxnative_ppause_input,                       /* ppause */
2006        linuxnative_fin_input,                          /* p_fin */
[50ce607]2007        linuxnative_pconfig_input,
2008        linux_pregister_thread,
2009        NULL
[d500159]2010};
[528eb6e]2011#else
2012static void linuxnative_help(void) {
[c909fad]2013        printf("linuxnative format module: $Revision: 1793 $\n");
[528eb6e]2014        printf("Not supported on this host\n");
2015}
2016static void linuxring_help(void) {
[c909fad]2017        printf("linuxring format module: $Revision: 1793 $\n");
[528eb6e]2018        printf("Not supported on this host\n");
2019}
2020
2021static struct libtrace_format_t linuxnative = {
2022        "int",
2023        "$Id$",
2024        TRACE_FORMAT_LINUX_NATIVE,
2025        NULL,                           /* probe filename */
2026        NULL,                           /* probe magic */
2027        NULL,                           /* init_input */
2028        NULL,                           /* config_input */
2029        NULL,                           /* start_input */
2030        NULL,                           /* pause_input */
2031        NULL,                           /* init_output */
2032        NULL,                           /* config_output */
2033        NULL,                           /* start_ouput */
2034        NULL,                           /* fin_input */
2035        NULL,                           /* fin_output */
2036        NULL,                           /* read_packet */
2037        linuxnative_prepare_packet,     /* prepare_packet */
2038        NULL,                           /* fin_packet */
2039        NULL,                           /* write_packet */
2040        linuxnative_get_link_type,      /* get_link_type */
2041        linuxnative_get_direction,      /* get_direction */
2042        linuxnative_set_direction,      /* set_direction */
2043        NULL,                           /* get_erf_timestamp */
2044        linuxnative_get_timeval,        /* get_timeval */
2045        linuxnative_get_timespec,       /* get_timespec */
2046        NULL,                           /* get_seconds */
2047        NULL,                           /* seek_erf */
2048        NULL,                           /* seek_timeval */
2049        NULL,                           /* seek_seconds */
2050        linuxnative_get_capture_length, /* get_capture_length */
2051        linuxnative_get_wire_length,    /* get_wire_length */
2052        linuxnative_get_framing_length, /* get_framing_length */
2053        linuxnative_set_capture_length, /* set_capture_length */
2054        NULL,                           /* get_received_packets */
2055        linuxnative_get_filtered_packets,/* get_filtered_packets */
2056        linuxnative_get_dropped_packets,/* get_dropped_packets */
2057        linuxnative_get_captured_packets,/* get_captured_packets */
2058        linuxnative_get_fd,             /* get_fd */
2059        trace_event_device,             /* trace_event */
2060        linuxnative_help,               /* help */
[b13b939]2061        NULL,                   /* next pointer */
2062        NON_PARALLEL(true)
[528eb6e]2063};
2064
2065static struct libtrace_format_t linuxring = {
2066        "ring",
2067        "$Id$",
2068        TRACE_FORMAT_LINUX_RING,
2069        NULL,                           /* probe filename */
2070        NULL,                           /* probe magic */
2071        NULL,                           /* init_input */
2072        NULL,                           /* config_input */
2073        NULL,                           /* start_input */
2074        NULL,                           /* pause_input */
2075        NULL,                           /* init_output */
2076        NULL,                           /* config_output */
2077        NULL,                           /* start_ouput */
2078        NULL,                           /* fin_input */
2079        NULL,                           /* fin_output */
2080        NULL,                           /* read_packet */
2081        linuxring_prepare_packet,       /* prepare_packet */
2082        NULL,                           /* fin_packet */
2083        NULL,                           /* write_packet */
2084        linuxring_get_link_type,        /* get_link_type */
2085        linuxring_get_direction,        /* get_direction */
2086        linuxring_set_direction,        /* set_direction */
2087        NULL,                           /* get_erf_timestamp */
2088        linuxring_get_timeval,          /* get_timeval */
2089        linuxring_get_timespec,         /* get_timespec */
2090        NULL,                           /* get_seconds */
2091        NULL,                           /* seek_erf */
2092        NULL,                           /* seek_timeval */
2093        NULL,                           /* seek_seconds */
2094        linuxring_get_capture_length,   /* get_capture_length */
2095        linuxring_get_wire_length,      /* get_wire_length */
2096        linuxring_get_framing_length,   /* get_framing_length */
2097        linuxring_set_capture_length,   /* set_capture_length */
2098        NULL,                           /* get_received_packets */
2099        linuxnative_get_filtered_packets,/* get_filtered_packets */
2100        linuxnative_get_dropped_packets,/* get_dropped_packets */
2101        linuxnative_get_captured_packets,/* get_captured_packets */
2102        linuxnative_get_fd,             /* get_fd */
2103        NULL,                           /* trace_event */
2104        linuxring_help,                 /* help */
[b13b939]2105        NULL,                   /* next pointer */
2106        NON_PARALLEL(true)
[528eb6e]2107};
2108
2109#endif /* HAVE_NETPACKET_PACKET_H */
2110
[d500159]2111
[33d83d4]2112void linuxnative_constructor(void) {
[6ba84d9]2113        /* TODO: once we're happy with ring:, it would be a good idea to
2114         * swap the order of these calls so that ring: is preferred over
2115         * int: if the user just gives an interface name as an input without
2116         * explicitly choosing a format.
2117         */
[97e39a7]2118        register_format(&linuxnative);
[d500159]2119        register_format(&linuxring);
[97e39a7]2120}
Note: See TracBrowser for help on using the repository browser.