Changeset d500159 for lib


Ignore:
Timestamp:
11/28/12 09:13:11 (8 years ago)
Author:
Richard Sanger <rjs51@…>
Branches:
4.0.1-hotfixes, cachetimestamps, develop, dpdk-ndag, etsilive, getfragoff, help, libtrace4, master, ndag_format, pfring, rc-4.0.1, rc-4.0.2, rc-4.0.3, rc-4.0.4, ringdecrementfix, ringperformance, ringtimestampfixes
Children:
17dc71c
Parents:
0a8eb88
Message:

Added new format type ring:. Works just like the old int:. In fact much of the int: code is reused. However ring: uses PACKET_MMAP ring buffers to improve performance

Location:
lib
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • lib/format_linux.c

    r0a8eb88 rd500159  
    77 * Authors: Daniel Lawson
    88 *          Perry Lorier
    9  *          Shane Alcock
     9 *          Shane Alcock
     10 *          Richard Sanger
    1011 *         
    1112 * All rights reserved.
     
    5859#include <assert.h>
    5960
     61#include <poll.h>
     62#include <sys/mman.h>
     63
    6064/* This format module deals with using the Linux Native capture format.
    6165 *
     
    7983
    8084typedef enum { TS_NONE, TS_TIMEVAL, TS_TIMESPEC } timestamptype_t;
     85
     86/* linux/if_packet.h defines. They are here rather than including the header
     87 * this means that we can interpret a ring frame on a kernel that doesn't
     88 * support the format directly.
     89 */
     90#define PACKET_RX_RING  5
     91#define PACKET_VERSION  10
     92#define PACKET_HDRLEN   11
     93#define PACKET_TX_RING  13
     94#define TP_STATUS_USER  0x1
     95#define TP_STATUS_SEND_REQUEST  0x1
     96#define TP_STATUS_AVAILABLE     0x0
     97#define TO_TP_HDR(x)    ((struct tpacket2_hdr *) (x))
     98#define TPACKET_ALIGNMENT       16
     99#define TPACKET_ALIGN(x)        (((x)+TPACKET_ALIGNMENT-1)&~(TPACKET_ALIGNMENT-1))
     100#define TPACKET2_HDRLEN         (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll))
     101
     102enum tpacket_versions {
     103        TPACKET_V1,
     104        TPACKET_V2
     105};
     106
     107struct tpacket2_hdr {
     108        /* Frame status - in use by kernel or libtrace etc. */
     109        __u32   tp_status;
     110        /* Wire length */
     111        __u32   tp_len;
     112        /* Captured length */
     113        __u32   tp_snaplen;
     114        /* Offset in bytes from frame start to the mac (link layer) header */
     115        __u16   tp_mac;
     116        /* Offset in bytes from frame start to the net (network layer) header */
     117        __u16   tp_net;
     118        /* Timestamp */
     119        __u32   tp_sec;
     120        __u32   tp_nsec;
     121        /* Not used VLAN tag control information */
     122        __u16   tp_vlan_tci;
     123        __u16   tp_padding;
     124};
     125
     126struct tpacket_req {
     127        unsigned int tp_block_size;  /* Minimal size of contiguous block */
     128        unsigned int tp_block_nr;    /* Number of blocks */
     129        unsigned int tp_frame_size;  /* Size of frame */
     130        unsigned int tp_frame_nr;    /* Total number of frames */
     131};
    81132
    82133struct linux_format_data_t {
     
    96147        /* Flag indicating whether the statistics are current or not */
    97148        int stats_valid;
     149        /* The rx ring mmap location*/
     150        char * rx_ring;
     151        /* The current frame number within the rx ring */       
     152        int rxring_offset;
     153        /* The format this trace is using linuxring or linuxnative */
     154        libtrace_rt_types_t format;
     155        /* The current ring buffer layout */
     156        struct tpacket_req req;
    98157};
    99158
     
    129188        /* The file descriptor used to write the packets */
    130189        int fd;
     190        /* The tx ring mmap location */
     191        char * tx_ring;
     192        /* The current frame number within the tx ring */       
     193        int txring_offset;
     194        /* The current ring buffer layout */
     195        struct tpacket_req req;
     196        /* Our sockaddr structure, here so we can cache the interface number */
     197        struct sockaddr_ll sock_hdr;
     198        /* The (maximum) number of packets that haven't been written */
     199        int queue;
     200        /* The format this trace is using linuxring or linuxnative */
     201        libtrace_rt_types_t format;
    131202};
     203
     204/* MAX_ORDER is defined in linux/mmzone.h. 10 is default for 2.4 kernel.
     205 * max_order will be decreased by one if the ring buffer fails to allocate.
     206 * Used to get correct sized buffers from the kernel.
     207 */
     208#define MAX_ORDER 10
     209static unsigned int max_order = MAX_ORDER;
     210
     211/* Cached page size, the page size shoudn't be changing */
     212static int pagesize = 0;
     213
     214/* Number of frames in the ring used by both TX and TR rings. More frames
     215 * hopefully means less packet loss, especially if traffic comes in bursts.
     216 */
     217#define CONF_RING_FRAMES        0x100
     218
     219/* The maximum frames allowed to be waiting in the TX_RING before the kernel is
     220 * notified to write them out. Make sure this is less than CONF_RING_FRAMES.
     221 * Performance doesn't seem to increase any more when setting this above 10.
     222 */
     223#define TX_MAX_QUEUE            10
     224
     225/* Get the start of the captured data. I'm not sure if tp_mac (link layer) is
     226 * always guaranteed. If it's not there then just use tp_net.
     227 */
     228#define TP_TRACE_START(mac, net, hdrend) \
     229        ((mac) > (hdrend) && (mac) < (net) ? (mac) : (net))
     230
     231/* Get current frame in the ring buffer*/
     232#define GET_CURRENT_BUFFER(libtrace) ((void *) FORMAT(libtrace->format_data)->rx_ring + \
     233        (FORMAT(libtrace->format_data)->rxring_offset * FORMAT(libtrace->format_data)->req.tp_frame_size))
     234
     235/* Get the sockaddr_ll structure from a frame */
     236#define GET_SOCKADDR_HDR(x)  ((struct sockaddr_ll *) (((char *) (x))\
     237        + TPACKET_ALIGN(sizeof(struct tpacket2_hdr))))
     238
     239#define TPACKET_HDRLEN TPACKET2_HDRLEN
    132240
    133241#define FORMAT(x) ((struct linux_format_data_t*)(x))
    134242#define DATAOUT(x) ((struct linux_output_format_data_t*)((x)->format_data))
    135243
     244
     245/*
     246 * Try figure out the best sizes for the ring buffer. Ensure that:
     247 * - max(Block_size) == page_size << max_order
     248 * - Frame_size == page_size << x (so that block_size%frame_size == 0)
     249 *   This means that there will be no wasted space between blocks
     250 * - Frame_size < block_size
     251 * - Frame_size is as close as possible to LIBTRACE_PACKET_BUFSIZE, but not
     252 *   bigger
     253 * - Frame_nr = Block_nr * (frames per block)
     254 * - CONF_RING_FRAMES is used a minimum number of frames to hold
     255 * - Calculates based on max_order and buf_min
     256 */
     257static void calculate_buffers(struct tpacket_req * req, int fd, char * uri){
     258       
     259        struct ifreq ifr;
     260        unsigned mtu = LIBTRACE_PACKET_BUFSIZE;
     261        pagesize = getpagesize();
     262
     263        /* Don't bother trying to set frame size above mtu linux will drop
     264         * these anyway
     265         */
     266        strcpy(ifr.ifr_name, uri);
     267        if (ioctl(fd, SIOCGIFMTU, (caddr_t) &ifr) >= 0)
     268                mtu = ifr.ifr_mtu;
     269        if(mtu > LIBTRACE_PACKET_BUFSIZE)
     270                mtu = LIBTRACE_PACKET_BUFSIZE;
     271
     272        /* Calculate frame size */
     273        req->tp_frame_size = pagesize;
     274        do {
     275                req->tp_frame_size <<= 1;
     276        } while(req->tp_frame_size < mtu && req->tp_frame_size < LIBTRACE_PACKET_BUFSIZE);
     277        if(req->tp_frame_size > LIBTRACE_PACKET_BUFSIZE)
     278                req->tp_frame_size >>= 1;
     279
     280        /* Calculate block size */
     281        req->tp_block_size = pagesize << max_order;
     282        do{
     283                req->tp_block_size >>= 1;
     284        } while((CONF_RING_FRAMES * req->tp_frame_size) < req->tp_block_size);
     285        req->tp_block_size <<= 1;
     286       
     287        /* Calculate number of blocks */
     288        req->tp_block_nr = (CONF_RING_FRAMES * req->tp_frame_size)
     289                        / req->tp_block_size;
     290        if((CONF_RING_FRAMES * req->tp_frame_size) % req->tp_block_size != 0)
     291                req->tp_block_nr++;
     292
     293        /* Calculate packets such that we use all the space we have to allocated */
     294        req->tp_frame_nr = req->tp_block_nr *
     295                        (req->tp_block_size / req->tp_frame_size);
     296
     297        printf("MaxO 0x%x BS 0x%x BN 0x%x FS 0x%x FN 0x%x\n",
     298                max_order,
     299                req->tp_block_size,
     300                req->tp_block_nr,
     301                req->tp_frame_size,
     302                req->tp_frame_nr);
     303       
     304        /* In case we have some silly values*/
     305        assert(req->tp_block_size);
     306        assert(req->tp_block_nr);
     307        assert(req->tp_frame_size);
     308        assert(req->tp_frame_nr);
     309        assert(req->tp_block_size % req->tp_frame_size == 0);
     310}
     311
    136312static int linuxnative_probe_filename(const char *filename)
    137313{
     
    140316}
    141317
    142 static int linuxnative_init_input(libtrace_t *libtrace)
    143 {
     318static inline void init_input(libtrace_t *libtrace){
    144319        libtrace->format_data = (struct linux_format_data_t *)
    145320                malloc(sizeof(struct linux_format_data_t));
     
    149324        FORMAT(libtrace->format_data)->filter = NULL;
    150325        FORMAT(libtrace->format_data)->stats_valid = 0;
    151 
     326        FORMAT(libtrace->format_data)->rx_ring = NULL;
     327        FORMAT(libtrace->format_data)->rxring_offset = 0;
     328}
     329static int linuxring_init_input(libtrace_t *libtrace)
     330{       
     331        init_input(libtrace);
     332        FORMAT(libtrace->format_data)->format = TRACE_FORMAT_LINUX_RING;
    152333        return 0;
    153334}
    154 
    155 static int linuxnative_init_output(libtrace_out_t *libtrace)
     335static int linuxnative_init_input(libtrace_t *libtrace)
     336{
     337        init_input(libtrace);
     338        FORMAT(libtrace->format_data)->format = TRACE_FORMAT_LINUX_NATIVE;
     339        return 0;
     340}
     341
     342static inline void init_output(libtrace_out_t *libtrace)
    156343{
    157344        libtrace->format_data = (struct linux_output_format_data_t*)
    158345                malloc(sizeof(struct linux_output_format_data_t));
    159346        DATAOUT(libtrace)->fd = -1;
    160 
     347        DATAOUT(libtrace)->tx_ring = NULL;
     348        DATAOUT(libtrace)->txring_offset = 0;
     349        DATAOUT(libtrace)->queue = 0;
     350}
     351static int linuxnative_init_output(libtrace_out_t *libtrace)
     352{
     353        init_output(libtrace);
     354        DATAOUT(libtrace)->format = TRACE_FORMAT_LINUX_NATIVE;
     355        return 0;
     356}
     357static int linuxring_init_output(libtrace_out_t *libtrace)
     358{
     359        init_output(libtrace);
     360        DATAOUT(libtrace)->format = TRACE_FORMAT_LINUX_RING;
    161361        return 0;
    162362}
     
    284484        return 0;
    285485}
     486static inline int socket_to_packetmmap(char * uridata, int ring_type,
     487                                        int fd,
     488                                        struct tpacket_req * req,
     489                                        char ** ring_location){
     490        socklen_t len;
     491        int val;
     492
     493        /* Switch to TPACKET header version 2, we only try support v2 because v1 had problems */
     494        val = TPACKET_V2;
     495        len = sizeof(val);
     496        if(getsockopt(fd,
     497                        SOL_PACKET,
     498                        PACKET_HDRLEN,
     499                        &val,
     500                        &len) == -1){
     501                return -1;
     502        }
     503
     504        val = TPACKET_V2;
     505        if (setsockopt(fd,
     506                        SOL_PACKET,
     507                        PACKET_VERSION,
     508                        &val,
     509                        sizeof(val)) == -1){
     510                return -1;
     511        }
     512
     513        /* Try switch to a ring buffer. If it fails we assume the the kernel 
     514         * cannot allocate a block of that size, so decrease max_block and retry.
     515         */
     516        while(1) {     
     517                if (max_order <= 0) {
     518                        return -1;
     519                }
     520                calculate_buffers(req, fd, uridata);
     521                if (setsockopt(fd,
     522                                SOL_PACKET,
     523                                ring_type,
     524                                req,
     525                                sizeof(struct tpacket_req)) == -1) {
     526                        if(errno == ENOMEM){
     527                                max_order--;
     528                        } else {
     529                                return -1;
     530                        }
     531
     532                } else break;
     533        }
     534       
     535        /* Map the ring buffer into userspace */
     536        *ring_location = mmap(NULL,
     537                                        req->tp_block_size * req->tp_block_nr,
     538                                        PROT_READ | PROT_WRITE,
     539                                        MAP_SHARED,
     540                                        fd, 0);
     541        if(*ring_location == MAP_FAILED){
     542                return -1;
     543        }
     544        return 0;
     545}
     546static int linuxring_start_input(libtrace_t *libtrace){
     547       
     548
     549        /* We set the socket up the same and then convert it to PACKET_MMAP */
     550        if(linuxnative_start_input(libtrace) != 0)
     551                return -1;
     552
     553        /* Make it a packetmmap */
     554        if(socket_to_packetmmap(libtrace->uridata, PACKET_RX_RING, FORMAT(libtrace->format_data)->fd,
     555                 &FORMAT(libtrace->format_data)->req, &FORMAT(libtrace->format_data)->rx_ring) != 0){
     556                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
     557                        "TPACKET2 not supported or ring buffer is too large");
     558                close(DATAOUT(libtrace)->fd);
     559                free(libtrace->format_data);
     560                return -1;
     561        }
     562               
     563        return 0;
     564}
    286565
    287566static int linuxnative_start_output(libtrace_out_t *libtrace)
     
    291570                free(DATAOUT(libtrace));
    292571                return -1;
    293         }
     572        }       
     573
     574        return 0;
     575}
     576
     577static int linuxring_start_output(libtrace_out_t *libtrace)
     578{
     579        /* We set the socket up the same and then convert it to PACKET_MMAP */
     580        if(linuxnative_start_output(libtrace) != 0)
     581                return -1;
     582
     583        /* Make it a packetmmap */
     584        if(socket_to_packetmmap(libtrace->uridata, PACKET_TX_RING, DATAOUT(libtrace)->fd,
     585                 &DATAOUT(libtrace)->req, &DATAOUT(libtrace)->tx_ring) != 0){
     586                trace_set_err_out(libtrace, TRACE_ERR_INIT_FAILED,
     587                        "TPACKET2 not supported or ring buffer is too large");
     588                close(DATAOUT(libtrace)->fd);
     589                free(libtrace->format_data);
     590                return -1;
     591        }
     592       
     593        DATAOUT(libtrace)->sock_hdr.sll_family = AF_PACKET;
     594        DATAOUT(libtrace)->sock_hdr.sll_protocol = 0;
     595        DATAOUT(libtrace)->sock_hdr.sll_ifindex =
     596                                        if_nametoindex(libtrace->uridata);
     597        DATAOUT(libtrace)->sock_hdr.sll_hatype = 0;
     598        DATAOUT(libtrace)->sock_hdr.sll_pkttype = 0;
     599        DATAOUT(libtrace)->sock_hdr.sll_halen = 0;
     600        DATAOUT(libtrace)->queue = 0;   
    294601
    295602        return 0;
     
    302609
    303610        return 0;
     611}
     612static int linuxring_pause_input(libtrace_t *libtrace)
     613{
     614        munmap(FORMAT(libtrace->format_data)->rx_ring,
     615                FORMAT(libtrace->format_data)->req.tp_block_size *
     616                        FORMAT(libtrace->format_data)->req.tp_block_nr);
     617        FORMAT(libtrace->format_data)->rx_ring = NULL;
     618        return linuxnative_pause_input(libtrace);
    304619}
    305620
     
    321636        free(libtrace->format_data);
    322637        return 0;
     638}
     639static int linuxring_fin_output(libtrace_out_t *libtrace)
     640{
     641        /* Make sure any remaining frames get sent */
     642        sendto(DATAOUT(libtrace)->fd,
     643                NULL,
     644                0,
     645                0,
     646                (void *) &DATAOUT(libtrace)->sock_hdr,
     647                sizeof(DATAOUT(libtrace)->sock_hdr));
     648
     649        /* Unmap our data area */
     650        munmap(DATAOUT(libtrace)->tx_ring,
     651                DATAOUT(libtrace)->req.tp_block_size *
     652                        DATAOUT(libtrace)->req.tp_block_nr);
     653
     654        return linuxnative_fin_output(libtrace);
    323655}
    324656
     
    446778}
    447779
     780static int linuxring_prepare_packet(libtrace_t *libtrace,
     781                libtrace_packet_t *packet, void *buffer,
     782                libtrace_rt_types_t rt_type, uint32_t flags) {
     783
     784        if (packet->buffer != buffer &&
     785                        packet->buf_control == TRACE_CTRL_PACKET) {
     786                free(packet->buffer);
     787        }
     788
     789        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
     790                packet->buf_control = TRACE_CTRL_PACKET;
     791        } else
     792                packet->buf_control = TRACE_CTRL_EXTERNAL;
     793
     794
     795        packet->buffer = buffer;
     796        packet->header = buffer;
     797        packet->payload = (char *)buffer +
     798                                        TP_TRACE_START(
     799                                        TO_TP_HDR(packet->header)->tp_mac,
     800                                        TO_TP_HDR(packet->header)->tp_net,
     801                                        TPACKET2_HDRLEN);
     802        packet->type = rt_type;
     803
     804        if (libtrace->format_data == NULL) {
     805                if (linuxnative_init_input(libtrace))
     806                        return -1;
     807        }
     808        return 0;
     809       
     810}
     811
    448812#define LIBTRACE_MIN(a,b) ((a)<(b) ? (a) : (b))
    449813
     
    565929}
    566930
     931#define LIBTRACE_BETWEEN(test,a,b) ((test) >= (a) && (test) < (b))
     932static int linuxring_get_capture_length(const libtrace_packet_t *packet);
     933static int linuxring_get_framing_length(const libtrace_packet_t *packet);
     934
     935static int linuxring_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
     936
     937        struct tpacket2_hdr *header;
     938        struct pollfd pollset; 
     939        int ret;
     940       
     941        /* Free the old packet */
     942        if(packet->buf_control == TRACE_CTRL_PACKET){
     943                free(packet->buffer);
     944        }
     945        if(packet->buf_control == TRACE_CTRL_EXTERNAL) {
     946                struct linux_format_data_t *ftd = FORMAT(libtrace->format_data);
     947               
     948                /* Check it's within our buffer first */
     949                if(LIBTRACE_BETWEEN((char *) packet->buffer,
     950                                (char *) ftd->rx_ring,
     951                                ftd->rx_ring
     952                                + ftd->req.tp_block_size * ftd->req.tp_block_nr)){
     953                        TO_TP_HDR(packet->buffer)->tp_status = 0;
     954                        packet->buffer = NULL;
     955                }
     956        }
     957       
     958        packet->buf_control = TRACE_CTRL_EXTERNAL;
     959        packet->type = TRACE_RT_DATA_LINUX_RING;
     960       
     961        /* Fetch the current frame */
     962        header = GET_CURRENT_BUFFER(libtrace);
     963        assert((((unsigned long) header) & (pagesize - 1)) == 0);
     964
     965        /* TP_STATUS_USER means that we can use the frame.
     966         * When a slot does not have this flag set, the frame is not
     967         * ready for consumption.
     968         */
     969        while (!(header->tp_status & TP_STATUS_USER)) {
     970                pollset.fd = FORMAT(libtrace->format_data)->fd;
     971                pollset.events = POLLIN;
     972                pollset.revents = 0;
     973                /* Wait for more data */
     974                ret = poll(&pollset, 1, -1);
     975                if (ret < 0) {
     976                        if (errno != EINTR)
     977                        trace_set_err(libtrace,errno,"poll()");
     978                        return -1;
     979                }
     980        }
     981
     982        packet->buffer = header;
     983
     984        /* Move to next buffer */
     985        FORMAT(libtrace->format_data)->rxring_offset++;
     986        FORMAT(libtrace->format_data)->rxring_offset %= FORMAT(libtrace->format_data)->req.tp_frame_nr;
     987
     988        /* We just need to get prepare_packet to set all our packet pointers
     989         * appropriately */
     990        if (linuxring_prepare_packet(libtrace, packet, packet->buffer,
     991                                packet->type, 0))
     992                return -1;
     993        return  linuxring_get_framing_length(packet) +
     994                                linuxring_get_capture_length(packet);
     995
     996}
     997
     998
    567999static int linuxnative_write_packet(libtrace_out_t *trace,
    5681000                libtrace_packet_t *packet)
     
    5901022
    5911023}
    592 
    593 static libtrace_linktype_t linuxnative_get_link_type(const struct libtrace_packet_t *packet) {
    594         int linktype=(((struct libtrace_linuxnative_header*)(packet->buffer))
    595                                 ->hdr.sll_hatype);
     1024static int linuxring_write_packet(libtrace_out_t *trace,
     1025                libtrace_packet_t *packet)
     1026{
     1027        struct tpacket2_hdr *header;
     1028        struct pollfd pollset;
     1029        struct socket_addr;
     1030        int ret;
     1031        unsigned max_size;
     1032        void * off;
     1033
     1034        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
     1035                return 0;
     1036
     1037        max_size = DATAOUT(trace)->req.tp_frame_size -
     1038                 - TPACKET_HDRLEN + sizeof(struct sockaddr_ll);
     1039
     1040        header = (void *) DATAOUT(trace)->tx_ring +
     1041        (DATAOUT(trace)->txring_offset * DATAOUT(trace)->req.tp_frame_size);
     1042
     1043        while(header->tp_status != TP_STATUS_AVAILABLE){
     1044                /* if none available: wait on more data */
     1045                pollset.fd = DATAOUT(trace)->fd;
     1046                pollset.events = POLLOUT;
     1047                pollset.revents = 0;
     1048                ret = poll(&pollset, 1, 1000);
     1049                if (ret < 0 && errno != EINTR) {
     1050                        perror("poll");
     1051                        return -1;
     1052                }
     1053                if(ret == 0)
     1054                        /* Timeout something has gone wrong - maybe the queue is
     1055                         * to large so try issue another send command
     1056                         */
     1057                        sendto(DATAOUT(trace)->fd,
     1058                                NULL,
     1059                                0,
     1060                                0,
     1061                                (void *) &DATAOUT(trace)->sock_hdr,
     1062                                sizeof(DATAOUT(trace)->sock_hdr));
     1063        }
     1064       
     1065        header->tp_len = trace_get_capture_length(packet);
     1066
     1067        /* We cannot write the whole packet so just write part of it */
     1068        if (header->tp_len > max_size)
     1069                header->tp_len = max_size;
     1070
     1071        /* Fill packet - no sockaddr_ll in header when writing to the TX_RING */
     1072        off = ((void *) header) + (TPACKET_HDRLEN - sizeof(struct sockaddr_ll));
     1073        memcpy(off,
     1074                (char *) packet->payload,
     1075                header->tp_len);
     1076       
     1077        /* 'Send it' and increase ring pointer to the next frame */
     1078        header->tp_status = TP_STATUS_SEND_REQUEST;
     1079        DATAOUT(trace)->txring_offset = (DATAOUT(trace)->txring_offset + 1) % 
     1080                                                DATAOUT(trace)->req.tp_frame_nr;
     1081
     1082        /* Notify kernel there are frames to send */
     1083        DATAOUT(trace)->queue = (++DATAOUT(trace)->queue) % TX_MAX_QUEUE;
     1084        if(DATAOUT(trace)->queue == 0){
     1085                sendto(DATAOUT(trace)->fd,
     1086                        NULL,
     1087                        0,
     1088                        MSG_DONTWAIT,
     1089                        (void *) &DATAOUT(trace)->sock_hdr,
     1090                        sizeof(DATAOUT(trace)->sock_hdr));
     1091        }
     1092        return header->tp_len;
     1093
     1094}
     1095
     1096static inline libtrace_linktype_t get_libtrace_link_type(int linktype){
    5961097        /* Convert the ARPHRD type into an appropriate libtrace link type */
    597 
    5981098        switch (linktype) {
    5991099                case ARPHRD_ETHER:
     
    6141114        }
    6151115}
    616 
    617 static libtrace_direction_t linuxnative_get_direction(const struct libtrace_packet_t *packet) {
    618         switch (((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype) {
     1116static libtrace_linktype_t linuxnative_get_link_type(const struct libtrace_packet_t *packet) {
     1117        int linktype=(((struct libtrace_linuxnative_header*)(packet->buffer))
     1118                                ->hdr.sll_hatype);
     1119        return get_libtrace_link_type(linktype);
     1120}
     1121static libtrace_linktype_t linuxring_get_link_type(const struct libtrace_packet_t *packet) {
     1122        int linktype= GET_SOCKADDR_HDR(packet->buffer)->sll_hatype;
     1123        return get_libtrace_link_type(linktype);
     1124}
     1125
     1126static inline libtrace_direction_t get_libtrace_direction(int pkttype){
     1127        switch (pkttype) {
    6191128                case PACKET_OUTGOING:
    6201129                case PACKET_LOOPBACK:
     
    6241133        }
    6251134}
    626 
     1135static libtrace_direction_t linuxnative_get_direction(const struct libtrace_packet_t *packet) {
     1136        return get_libtrace_link_type(((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype);
     1137}
     1138static libtrace_direction_t linuxring_get_direction(const struct libtrace_packet_t *packet) {
     1139        return get_libtrace_link_type(GET_SOCKADDR_HDR(packet->buffer)->sll_pkttype);
     1140}
     1141
     1142static libtrace_direction_t set_direction(struct sockaddr_ll * skadr, libtrace_direction_t direction){
     1143        switch (direction) {
     1144                case TRACE_DIR_OUTGOING:
     1145                        skadr->sll_pkttype = PACKET_OUTGOING;
     1146                        return TRACE_DIR_OUTGOING;
     1147                case TRACE_DIR_INCOMING:
     1148                        skadr->sll_pkttype = PACKET_HOST;
     1149                        return TRACE_DIR_INCOMING;
     1150                default:
     1151                        return -1;
     1152        }
     1153}
    6271154static libtrace_direction_t linuxnative_set_direction(
    6281155                libtrace_packet_t *packet,
    6291156                libtrace_direction_t direction) {
    630 
    631         switch (direction) {
    632                 case TRACE_DIR_OUTGOING:
    633                         ((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype = PACKET_OUTGOING;
    634                         return TRACE_DIR_OUTGOING;
    635                 case TRACE_DIR_INCOMING:
    636                         ((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype = PACKET_HOST;
    637                         return TRACE_DIR_INCOMING;
    638                 default:
    639                         return -1;
    640         }
     1157        return set_direction(&((struct libtrace_linuxnative_header*)(packet->buffer))->hdr, direction);
     1158}
     1159static libtrace_direction_t linuxring_set_direction(
     1160                libtrace_packet_t *packet,
     1161                libtrace_direction_t direction) {
     1162        return set_direction(GET_SOCKADDR_HDR(packet->buffer), direction);
    6411163}
    6421164
     
    6591181        }
    6601182}
     1183static struct timespec linuxring_get_timespec(const libtrace_packet_t *packet)
     1184{
     1185        struct timespec ts;
     1186        ts.tv_sec = TO_TP_HDR(packet->buffer)->tp_sec;
     1187        ts.tv_nsec = TO_TP_HDR(packet->buffer)->tp_nsec;
     1188        return ts;
     1189}
     1190
    6611191
    6621192static struct timeval linuxnative_get_timeval(const libtrace_packet_t *packet)
     
    6781208        }
    6791209}
     1210static struct timeval linuxring_get_timeval(const libtrace_packet_t *packet)
     1211{
     1212        struct timeval tv;
     1213        tv.tv_sec = TO_TP_HDR(packet->buffer)->tp_sec;
     1214        tv.tv_usec = TO_TP_HDR(packet->buffer)->tp_nsec / 1000;
     1215        return tv;
     1216}
    6801217
    6811218static int linuxnative_get_capture_length(const libtrace_packet_t *packet)
    6821219{
    6831220        return ((struct libtrace_linuxnative_header*)(packet->buffer))->caplen;
     1221}
     1222
     1223static int linuxring_get_capture_length(const libtrace_packet_t *packet)
     1224{
     1225        return TO_TP_HDR(packet->buffer)->tp_snaplen;
    6841226}
    6851227
     
    6961238}
    6971239
     1240static int linuxring_get_wire_length(const libtrace_packet_t *packet)
     1241{
     1242        int wirelen = TO_TP_HDR(packet->buffer)->tp_len;
     1243
     1244        /* Include the missing FCS */
     1245        if (trace_get_link_type(packet) == TRACE_TYPE_ETH)
     1246                wirelen += 4;
     1247
     1248        return wirelen;
     1249}
     1250
    6981251static int linuxnative_get_framing_length(UNUSED
    6991252                const libtrace_packet_t *packet)
    7001253{
    7011254        return sizeof(struct libtrace_linuxnative_header);
     1255}
     1256
     1257static int linuxring_get_framing_length(const libtrace_packet_t *packet)
     1258{       
     1259        /*
     1260         * Need to make frame_length + capture_length = compelete capture length
     1261         * so include alligment whitespace. So reverse calculate from packet.
     1262         */
     1263        return (char *) packet->payload - (char *) packet->buffer;
    7021264}
    7031265
     
    7171279        linux_hdr = (struct libtrace_linuxnative_header *)packet->header;
    7181280        linux_hdr->caplen = size;
     1281        return trace_get_capture_length(packet);
     1282}
     1283
     1284static size_t linuxring_set_capture_length(libtrace_packet_t *packet,
     1285                size_t size) {
     1286        assert(packet);
     1287        if (size > trace_get_capture_length(packet)) {
     1288                /* We should avoid making a packet larger */
     1289                return trace_get_capture_length(packet);
     1290        }
     1291       
     1292        /* Reset the cached capture length */
     1293        packet->capture_length = -1;
     1294
     1295        TO_TP_HDR(packet->buffer)->tp_len = size;
     1296
    7191297        return trace_get_capture_length(packet);
    7201298}
     
    7971375        return;
    7981376}
     1377
     1378static void linuxring_help(void) {
     1379        printf("linuxring format module: $Revision$\n");
     1380        printf("Supported input URIs:\n");
     1381        printf("\tring:eth0\n");
     1382        printf("\n");
     1383        printf("Supported output URIs:\n");
     1384        printf("\tring:eth0\n");
     1385        printf("\n");
     1386        return;
     1387}
     1388
    7991389static struct libtrace_format_t linuxnative = {
    8001390        "int",
     
    8401430};
    8411431
     1432static struct libtrace_format_t linuxring = {
     1433        "ring",
     1434        "$Id$",
     1435        TRACE_FORMAT_LINUX_RING,
     1436        linuxnative_probe_filename,     /* probe filename */
     1437        NULL,                           /* probe magic */
     1438        linuxring_init_input,           /* init_input */
     1439        linuxnative_config_input,       /* config_input */
     1440        linuxring_start_input,  /* start_input */
     1441        linuxring_pause_input,  /* pause_input */
     1442        linuxring_init_output,  /* init_output */
     1443        NULL,                           /* config_output */
     1444        linuxring_start_output, /* start_ouput */
     1445        linuxnative_fin_input,          /* fin_input */
     1446        linuxring_fin_output,           /* fin_output */
     1447        linuxring_read_packet,  /* read_packet */
     1448        linuxring_prepare_packet,       /* prepare_packet */
     1449        NULL,                           /* fin_packet */
     1450        linuxring_write_packet, /* write_packet */
     1451        linuxring_get_link_type,        /* get_link_type */
     1452        linuxring_get_direction,        /* get_direction */
     1453        linuxring_set_direction,        /* set_direction */
     1454        NULL,                           /* get_erf_timestamp */
     1455        linuxring_get_timeval,  /* get_timeval */
     1456        linuxring_get_timespec, /* get_timespec */
     1457        NULL,                           /* get_seconds */
     1458        NULL,                           /* seek_erf */
     1459        NULL,                           /* seek_timeval */
     1460        NULL,                           /* seek_seconds */
     1461        linuxring_get_capture_length,   /* get_capture_length */
     1462        linuxring_get_wire_length,      /* get_wire_length */
     1463        linuxring_get_framing_length,   /* get_framing_length */
     1464        linuxring_set_capture_length,   /* set_capture_length */
     1465        NULL,                           /* get_received_packets */
     1466        linuxnative_get_filtered_packets,/* get_filtered_packets */
     1467        linuxnative_get_dropped_packets,/* get_dropped_packets */
     1468        linuxnative_get_captured_packets,/* get_captured_packets */
     1469        linuxnative_get_fd,             /* get_fd */
     1470        trace_event_device,             /* trace_event */
     1471        linuxring_help,         /* help */
     1472        NULL
     1473};
     1474
    8421475void linuxnative_constructor(void) {
    8431476        register_format(&linuxnative);
    844 }
     1477        register_format(&linuxring);
     1478}
  • lib/libtrace.h.in

    r64d4398 rd500159  
    302302        TRACE_FORMAT_TSH          =12,  /**< TSH trace format */
    303303        TRACE_FORMAT_ATMHDR       =13,  /**< Legacy ATM header capture */
    304         TRACE_FORMAT_LEGACY_NZIX  =14   /**< Legacy format used for NZIX traces */
     304        TRACE_FORMAT_LEGACY_NZIX  =14,  /**< Legacy format used for NZIX traces */
     305        TRACE_FORMAT_LINUX_RING   =15   /**< Linux native interface capture PACKET_MMAP */
    305306};
    306307
     
    351352        /** RT is encapsulating a Legacy NZIX capture record */
    352353        TRACE_RT_DATA_LEGACY_NZIX=TRACE_RT_DATA_SIMPLE + TRACE_FORMAT_LEGACY_NZIX,
     354        /** RT is encapsulating a Linux native PACKET_MMAP capture record */
     355        TRACE_RT_DATA_LINUX_RING=TRACE_RT_DATA_SIMPLE+TRACE_FORMAT_LINUX_RING,
    353356
    354357        /** As PCAP does not store the linktype with the packet, we need to
Note: See TracChangeset for help on using the changeset viewer.