source: lib/format_linux_ring.c @ 9d89626

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

Various fixes to the linux format to support compiling on BSD

  • Property mode set to 100644
File size: 23.8 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *          Richard Sanger
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 *
31 * $Id$
32 *
33 */
34
35/* This format module deals with using the Linux Ring capture format (also
36 * known as PACKET_MMAP).
37 *
38 * Linux Ring is a LIVE capture format.
39 *
40 * This format also supports writing which will write packets out to the
41 * network as a form of packet replay. This should not be confused with the
42 * RT protocol which is intended to transfer captured packet records between
43 * RT-speaking programs.
44 */
45
46#include "config.h"
47#include "libtrace.h"
48#include "libtrace_int.h"
49#include "format_helper.h"
50#include "libtrace_arphrd.h"
51#include <stdlib.h>
52#include <errno.h>
53#include <unistd.h>
54#include <string.h>
55#include <assert.h>
56
57#ifdef HAVE_INTTYPES_H
58#  include <inttypes.h>
59#else
60# error "Can't find inttypes.h"
61#endif
62
63#include "format_linux_common.h"
64
65/* Get the start of the captured data. I'm not sure if tp_mac (link layer) is
66 * always guaranteed. If it's not there then just use tp_net.
67 */
68#define TP_TRACE_START(mac, net, hdrend) \
69        ((mac) > (hdrend) && (mac) < (net) ? (mac) : (net))
70
71#ifdef HAVE_NETPACKET_PACKET_H
72/* Get current frame in the ring buffer*/
73#define GET_CURRENT_BUFFER(stream) \
74        ((void *)stream->rx_ring +                              \
75         (stream->rxring_offset *                               \
76          stream->req.tp_frame_size))
77
78/* Cached page size, the page size shouldn't be changing */
79static int pagesize = 0;
80
81/*
82 * Try figure out the best sizes for the ring buffer. Ensure that:
83 * - max(Block_size) == page_size << max_order
84 * - Frame_size == page_size << x (so that block_size%frame_size == 0)
85 *   This means that there will be no wasted space between blocks
86 * - Frame_size < block_size
87 * - Frame_size is as close as possible to LIBTRACE_PACKET_BUFSIZE, but not
88 *   bigger
89 * - Frame_nr = Block_nr * (frames per block)
90 * - CONF_RING_FRAMES is used a minimum number of frames to hold
91 * - Calculates based on max_order and buf_min
92 */
93static void calculate_buffers(struct tpacket_req * req, int fd, char * uri,
94                uint32_t max_order)
95{
96        struct ifreq ifr;
97        unsigned max_frame = LIBTRACE_PACKET_BUFSIZE;
98        pagesize = getpagesize();
99
100        strcpy(ifr.ifr_name, uri);
101        /* Don't bother trying to set frame size above mtu linux will drop
102         * these anyway.
103         *
104         * Remember, that our frame also has to include a TPACKET header!
105         */
106        if (ioctl(fd, SIOCGIFMTU, (caddr_t)&ifr) >= 0)
107                max_frame = ifr.ifr_mtu + TPACKET_ALIGN(TPACKET2_HDRLEN);
108        if (max_frame > LIBTRACE_PACKET_BUFSIZE)
109                max_frame = LIBTRACE_PACKET_BUFSIZE;
110
111        /* Calculate frame size */
112        req->tp_frame_size = pagesize;
113        while (req->tp_frame_size < max_frame &&
114              req->tp_frame_size < LIBTRACE_PACKET_BUFSIZE) {
115                req->tp_frame_size <<= 1;
116        }
117        if (req->tp_frame_size > LIBTRACE_PACKET_BUFSIZE)
118                req->tp_frame_size >>= 1;
119
120        /* Calculate block size */
121        req->tp_block_size = pagesize << max_order;
122        /* If max order is too high this might become 0 */
123        if (req->tp_block_size == 0) {
124                calculate_buffers(req, fd, uri, max_order-1);
125                return;
126        }
127        do {
128                req->tp_block_size >>= 1;
129        } while ((CONF_RING_FRAMES * req->tp_frame_size) <= req->tp_block_size);
130        req->tp_block_size <<= 1;
131
132        /* Calculate number of blocks */
133        req->tp_block_nr = (CONF_RING_FRAMES * req->tp_frame_size)
134                / req->tp_block_size;
135        if((CONF_RING_FRAMES * req->tp_frame_size) % req->tp_block_size != 0)
136                req->tp_block_nr++;
137
138        /* Calculate packets such that we use all the space we have to
139         * allocated */
140        req->tp_frame_nr = req->tp_block_nr *
141                (req->tp_block_size / req->tp_frame_size);
142
143        /*
144        printf("MaxO 0x%x BS 0x%x BN 0x%x FS 0x%x FN 0x%x\n",
145                max_order,
146                req->tp_block_size,
147                req->tp_block_nr,
148                req->tp_frame_size,
149                req->tp_frame_nr);
150        */
151
152        /* In case we have some silly values*/
153        assert(req->tp_block_size);
154        assert(req->tp_block_nr);
155        assert(req->tp_frame_size);
156        assert(req->tp_frame_nr);
157        assert(req->tp_block_size % req->tp_frame_size == 0);
158}
159
160static inline int socket_to_packetmmap(char * uridata, int ring_type,
161                                        int fd,
162                                        struct tpacket_req * req,
163                                        char ** ring_location,
164                                        uint32_t *max_order,
165                                        char *error) {
166        int val;
167
168        /* Switch to TPACKET header version 2, we only try support v2 because
169         * v1 had problems with data type consistancy */
170        val = TPACKET_V2;
171        if (setsockopt(fd,
172                       SOL_PACKET,
173                       PACKET_VERSION,
174                       &val,
175                       sizeof(val)) == -1) {
176                strncpy(error, "TPACKET2 not supported", 2048);
177                return -1;
178        }
179
180        /* Try switch to a ring buffer. If it fails we assume the the kernel
181         * cannot allocate a block of that size, so decrease max_block and
182         * retry.
183         */
184        while(1) {
185                if (*max_order <= 0) {
186                        strncpy(error,
187                                "Cannot allocate enough memory for ring buffer",
188                                2048);
189                        return -1;
190                }
191                calculate_buffers(req, fd, uridata, *max_order);
192                if (setsockopt(fd,
193                               SOL_PACKET,
194                               ring_type,
195                               req,
196                               sizeof(struct tpacket_req)) == -1) {
197                        if(errno == ENOMEM) {
198                                (*max_order)--;
199                        } else {
200                                strncpy(error,
201                                        "Error setting the ring buffer size",
202                                        2048);
203                                return -1;
204                        }
205
206                } else break;
207        }
208
209        /* Map the ring buffer into userspace */
210        *ring_location = mmap(NULL,
211                              req->tp_block_size * req->tp_block_nr,
212                              PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
213        if(*ring_location == MAP_FAILED) {
214                strncpy(error, "Failed to map memory for ring buffer", 2048);
215                return -1;
216        }
217
218        return 0;
219}
220
221/* Release a frame back to the kernel or free() if it's a malloc'd buffer
222 */
223inline static void ring_release_frame(libtrace_t *libtrace UNUSED,
224                                      libtrace_packet_t *packet)
225{
226        /* Free the old packet */
227        if(packet->buffer == NULL)
228                return;
229
230        if(packet->buf_control == TRACE_CTRL_PACKET){
231                free(packet->buffer);
232                packet->buffer = NULL;
233        }
234
235        if(packet->buf_control == TRACE_CTRL_EXTERNAL) {
236                //struct linux_format_data_t *ftd = FORMAT_DATA;
237                /* Check it's within our buffer first - consider the pause
238                 * resume case it might have already been free'd lets hope we
239                 * get another buffer */
240                // TODO: For now let any one free anything
241                /*if(LIBTRACE_BETWEEN((char *) packet->buffer,
242                                (char *) ftd->rx_ring,
243                                ftd->rx_ring +
244                                ftd->req.tp_block_size *
245                                ftd->req.tp_block_nr)){*/
246                TO_TP_HDR2(packet->buffer)->tp_status = 0;
247                packet->buffer = NULL;
248                /*}*/
249        }
250}
251
252static inline int linuxring_start_input_stream(libtrace_t *libtrace,
253                                               struct linux_per_stream_t *stream) {
254        char error[2048];
255
256        /* We set the socket up the same and then convert it to PACKET_MMAP */
257        if (linuxcommon_start_input_stream(libtrace, stream) < 0)
258                return -1;
259
260        strncpy(error, "No known error", 2048);
261
262        /* Make it a packetmmap */
263        if(socket_to_packetmmap(libtrace->uridata, PACKET_RX_RING,
264                                stream->fd,
265                                &stream->req,
266                                &stream->rx_ring,
267                                &FORMAT_DATA->max_order,
268                                error) != 0) {
269                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
270                              "Initialisation of packet MMAP failed: %s",
271                              error);
272                linuxcommon_close_input_stream(libtrace, stream);
273                return -1;
274        }
275
276        return 0;
277}
278
279static int linuxring_start_input(libtrace_t *libtrace)
280{
281        int ret = linuxring_start_input_stream(libtrace, FORMAT_DATA_FIRST);
282        if (ret != 0) {
283                libtrace_list_deinit(FORMAT_DATA->per_stream);
284                free(libtrace->format_data);
285                libtrace->format_data = NULL;
286        }
287        return ret;
288}
289
290static int linuxring_pstart_input(libtrace_t *libtrace) {
291        return linuxcommon_pstart_input(libtrace, linuxring_start_input_stream);
292}
293
294static int linuxring_start_output(libtrace_out_t *libtrace)
295{
296        char error[2048];
297        FORMAT_DATA_OUT->fd = socket(PF_PACKET, SOCK_RAW, 0);
298        if (FORMAT_DATA_OUT->fd==-1) {
299                free(FORMAT_DATA_OUT);
300                trace_set_err_out(libtrace, errno, "Failed to create raw socket");
301                return -1;
302        }
303
304        /* Make it a packetmmap */
305        if(socket_to_packetmmap(libtrace->uridata, PACKET_TX_RING,
306                                FORMAT_DATA_OUT->fd,
307                                &FORMAT_DATA_OUT->req,
308                                &FORMAT_DATA_OUT->tx_ring,
309                                &FORMAT_DATA_OUT->max_order,
310                                error) != 0) {
311                trace_set_err_out(libtrace, TRACE_ERR_INIT_FAILED,
312                                  "Initialisation of packet MMAP failed: %s",
313                                  error);
314                close(FORMAT_DATA_OUT->fd);
315                free(FORMAT_DATA_OUT);
316                libtrace->format_data = NULL;
317                return -1;
318        }
319
320        FORMAT_DATA_OUT->sock_hdr.sll_family = AF_PACKET;
321        FORMAT_DATA_OUT->sock_hdr.sll_protocol = 0;
322        FORMAT_DATA_OUT->sock_hdr.sll_ifindex =
323                if_nametoindex(libtrace->uridata);
324        FORMAT_DATA_OUT->sock_hdr.sll_hatype = 0;
325        FORMAT_DATA_OUT->sock_hdr.sll_pkttype = 0;
326        FORMAT_DATA_OUT->sock_hdr.sll_halen = 0;
327        FORMAT_DATA_OUT->queue = 0;
328
329        return 0;
330}
331
332static int linuxring_fin_output(libtrace_out_t *libtrace)
333{
334        /* Make sure any remaining frames get sent */
335        sendto(FORMAT_DATA_OUT->fd,
336               NULL,
337               0,
338               0,
339               (void *) &FORMAT_DATA_OUT->sock_hdr,
340               sizeof(FORMAT_DATA_OUT->sock_hdr));
341
342        /* Unmap our data area */
343        munmap(FORMAT_DATA_OUT->tx_ring,
344               FORMAT_DATA_OUT->req.tp_block_size *
345               FORMAT_DATA_OUT->req.tp_block_nr);
346
347        /* Free the socket */
348        close(FORMAT_DATA_OUT->fd);
349        FORMAT_DATA_OUT->fd=-1;
350        free(libtrace->format_data);
351        return 0;
352}
353#endif /* HAVE_NETPACKET_PACKET_H */
354
355static libtrace_linktype_t
356linuxring_get_link_type(const struct libtrace_packet_t *packet)
357{
358        uint16_t linktype = GET_SOCKADDR_HDR(packet->buffer)->sll_hatype;
359        return linuxcommon_get_link_type(linktype);
360}
361
362static libtrace_direction_t
363linuxring_get_direction(const struct libtrace_packet_t *packet) {
364        return linuxcommon_get_direction(GET_SOCKADDR_HDR(packet->buffer)->
365                                         sll_pkttype);
366}
367
368static libtrace_direction_t
369linuxring_set_direction(libtrace_packet_t *packet,
370                        libtrace_direction_t direction) {
371        return linuxcommon_set_direction(GET_SOCKADDR_HDR(packet->buffer), direction);
372}
373
374static struct timeval linuxring_get_timeval(const libtrace_packet_t *packet)
375{
376        struct timeval tv;
377        tv.tv_sec = TO_TP_HDR2(packet->buffer)->tp_sec;
378        tv.tv_usec = TO_TP_HDR2(packet->buffer)->tp_nsec / 1000;
379        return tv;
380}
381
382static struct timespec linuxring_get_timespec(const libtrace_packet_t *packet)
383{
384        struct timespec ts;
385        ts.tv_sec = TO_TP_HDR2(packet->buffer)->tp_sec;
386        ts.tv_nsec = TO_TP_HDR2(packet->buffer)->tp_nsec;
387        return ts;
388}
389
390static int linuxring_get_capture_length(const libtrace_packet_t *packet)
391{
392        return TO_TP_HDR2(packet->buffer)->tp_snaplen;
393}
394
395static int linuxring_get_wire_length(const libtrace_packet_t *packet)
396{
397        int wirelen = TO_TP_HDR2(packet->buffer)->tp_len;
398
399        /* Include the missing FCS */
400        if (trace_get_link_type(packet) == TRACE_TYPE_ETH)
401                wirelen += 4;
402
403        return wirelen;
404}
405
406static int linuxring_get_framing_length(const libtrace_packet_t *packet)
407{
408        /*
409         * Need to make frame_length + capture_length = complete capture length
410         * so include alignment whitespace. So reverse calculate from packet.
411         */
412        return (char *)packet->payload - (char *)packet->buffer;
413}
414
415static size_t linuxring_set_capture_length(libtrace_packet_t *packet,
416                                           size_t size)
417{
418        assert(packet);
419        if (size > trace_get_capture_length(packet)) {
420                /* We should avoid making a packet larger */
421                return trace_get_capture_length(packet);
422        }
423
424        /* Reset the cached capture length */
425        packet->capture_length = -1;
426
427        TO_TP_HDR2(packet->buffer)->tp_snaplen = size;
428
429        return trace_get_capture_length(packet);
430}
431
432static int linuxring_prepare_packet(libtrace_t *libtrace UNUSED,
433                                    libtrace_packet_t *packet, void *buffer,
434                                    libtrace_rt_types_t rt_type, uint32_t flags)
435{
436        if (packet->buffer != buffer &&
437            packet->buf_control == TRACE_CTRL_PACKET) {
438                free(packet->buffer);
439        }
440
441        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER)
442                packet->buf_control = TRACE_CTRL_PACKET;
443        else
444                packet->buf_control = TRACE_CTRL_EXTERNAL;
445
446
447        packet->buffer = buffer;
448        packet->header = buffer;
449        packet->payload = (char *)buffer +
450                TP_TRACE_START(TO_TP_HDR2(packet->header)->tp_mac,
451                               TO_TP_HDR2(packet->header)->tp_net,
452                               TPACKET2_HDRLEN);
453        packet->type = rt_type;
454
455        return 0;
456}
457
458#ifdef HAVE_NETPACKET_PACKET_H
459#define LIBTRACE_MIN(a,b) ((a)<(b) ? (a) : (b))
460inline static int linuxring_read_stream(libtrace_t *libtrace,
461                                        libtrace_packet_t *packet,
462                                        struct linux_per_stream_t *stream,
463                                        libtrace_message_queue_t *queue) {
464
465        struct tpacket2_hdr *header;
466        int ret;
467        unsigned int snaplen;
468        struct pollfd pollset[2];
469
470        ring_release_frame(libtrace, packet);
471       
472        packet->buf_control = TRACE_CTRL_EXTERNAL;
473        packet->type = TRACE_RT_DATA_LINUX_RING;
474       
475        /* Fetch the current frame */
476        header = GET_CURRENT_BUFFER(stream);
477        assert((((unsigned long) header) & (pagesize - 1)) == 0);
478
479        /* TP_STATUS_USER means that we can use the frame.
480         * When a slot does not have this flag set, the frame is not
481         * ready for consumption.
482         */
483        while (!(header->tp_status & TP_STATUS_USER)) {
484                pollset[0].fd = stream->fd;
485                pollset[0].events = POLLIN;
486                pollset[0].revents = 0;
487                if (queue) {
488                        pollset[1].fd = libtrace_message_queue_get_fd(queue);
489                        pollset[1].events = POLLIN;
490                        pollset[1].revents = 0;
491                }
492                /* Wait for more data or a message */
493                ret = poll(pollset, (queue ? 2 : 1), 500);
494                if (ret > 0) {
495                        if (pollset[0].revents == POLLIN)
496                                continue;
497                        else if (queue && pollset[1].revents == POLLIN)
498                                return READ_MESSAGE;
499                        else if (queue && pollset[1].revents) {
500                                /* Internal error */
501                                trace_set_err(libtrace,TRACE_ERR_BAD_STATE,
502                                              "Message queue error %d poll()",
503                                              pollset[1].revents);
504                                return READ_ERROR;
505                        } else {
506                                /* Try get the error from the socket */
507                                int err = ENETDOWN;
508                                socklen_t len = sizeof(err);
509                                getsockopt(stream->fd, SOL_SOCKET, SO_ERROR,
510                                           &err, &len);
511                                trace_set_err(libtrace, err,
512                                              "Socket error revents=%d poll()",
513                                              pollset[0].revents);
514                                return READ_ERROR;
515                        }
516                } else if (ret < 0) {
517                        if (errno != EINTR) {
518                                trace_set_err(libtrace,errno,"poll()");
519                                return -1;
520                        }
521                } else {
522                        /* Poll timed out - check if we should exit */
523                        if (libtrace_halt)
524                                return 0;
525                        continue;
526                }
527        }
528
529        packet->buffer = header;
530        packet->trace = libtrace;
531
532        /* If a snaplen was configured, automatically truncate the packet to
533         * the desired length.
534         */
535        snaplen=LIBTRACE_MIN(
536                        (int)LIBTRACE_PACKET_BUFSIZE-(int)sizeof(*header),
537                        (int)FORMAT_DATA->snaplen);
538       
539        TO_TP_HDR2(packet->buffer)->tp_snaplen = LIBTRACE_MIN((unsigned int)snaplen, TO_TP_HDR2(packet->buffer)->tp_len);
540
541        /* Move to next buffer */
542        stream->rxring_offset++;
543        stream->rxring_offset %= stream->req.tp_frame_nr;
544
545        /* We just need to get prepare_packet to set all our packet pointers
546         * appropriately */
547        if (linuxring_prepare_packet(libtrace, packet, packet->buffer,
548                                packet->type, 0))
549                return -1;
550        return  linuxring_get_framing_length(packet) + 
551                                linuxring_get_capture_length(packet);
552
553}
554
555static int linuxring_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
556        return linuxring_read_stream(libtrace, packet, FORMAT_DATA_FIRST, NULL);
557}
558
559static int linuxring_pread_packets(libtrace_t *libtrace,
560                                   libtrace_thread_t *t,
561                                   libtrace_packet_t *packets[],
562                                   UNUSED size_t nb_packets) {
563        /* For now just read one packet */
564        packets[0]->error = linuxring_read_stream(libtrace, packets[0],
565                                                  t->format_data, &t->messages);
566        if (packets[0]->error >= 1)
567                return 1;
568        else
569                return packets[0]->error;
570}
571
572/* Non-blocking read */
573static libtrace_eventobj_t linuxring_event(libtrace_t *libtrace,
574                                           libtrace_packet_t *packet)
575{
576        struct tpacket2_hdr *header;
577        libtrace_eventobj_t event = {0,0,0.0,0};
578
579        /* We must free the old packet, otherwise select() will instantly
580         * return */
581        ring_release_frame(libtrace, packet);
582
583        /* Fetch the current frame */
584        header = GET_CURRENT_BUFFER(FORMAT_DATA_FIRST);
585        if (header->tp_status & TP_STATUS_USER) {
586                /* We have a frame waiting */
587                event.size = trace_read_packet(libtrace, packet);
588                event.type = TRACE_EVENT_PACKET;
589        } else {
590                /* Ok we don't have a packet waiting */
591                event.type = TRACE_EVENT_IOWAIT;
592                event.fd = FORMAT_DATA_FIRST->fd;
593        }
594
595        return event;
596}
597
598/**
599 * Free any resources being kept for this packet, Note: libtrace
600 * will ensure all fields are zeroed correctly.
601 */
602static void linuxring_fin_packet(libtrace_packet_t *packet)
603{
604        libtrace_t *libtrace = packet->trace;
605
606        if (packet->buffer == NULL)
607                return;
608        assert(packet->trace);
609
610        /* If we own the packet (i.e. it's not a copy), we need to free it */
611        if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
612                /* Started should always match the existence of the rx_ring
613                 * in the parallel case still just check the first ring */
614                assert(!!FORMAT_DATA_FIRST->rx_ring ==
615                       !!packet->trace->started);
616                /* If we don't have a ring its already been destroyed */
617                if (FORMAT_DATA_FIRST->rx_ring != MAP_FAILED)
618                        ring_release_frame(packet->trace, packet);
619                else
620                        packet->buffer = NULL;
621        }
622}
623
624static int linuxring_write_packet(libtrace_out_t *libtrace,
625                                  libtrace_packet_t *packet)
626{
627        struct tpacket2_hdr *header;
628        struct pollfd pollset;
629        struct socket_addr;
630        int ret;
631        unsigned max_size;
632        void * off;
633
634        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
635                return 0;
636
637        max_size = FORMAT_DATA_OUT->req.tp_frame_size -
638                TPACKET2_HDRLEN + sizeof(struct sockaddr_ll);
639
640        header = (void *)FORMAT_DATA_OUT->tx_ring +
641                (FORMAT_DATA_OUT->txring_offset *
642                 FORMAT_DATA_OUT->req.tp_frame_size);
643
644        while(header->tp_status != TP_STATUS_AVAILABLE) {
645                /* if none available: wait on more data */
646                pollset.fd = FORMAT_DATA_OUT->fd;
647                pollset.events = POLLOUT;
648                pollset.revents = 0;
649                ret = poll(&pollset, 1, 1000);
650                if (ret < 0 && errno != EINTR) {
651                        perror("poll");
652                        return -1;
653                }
654                if(ret == 0)
655                        /* Timeout something has gone wrong - maybe the queue is
656                         * to large so try issue another send command
657                         */
658                        ret = sendto(FORMAT_DATA_OUT->fd,
659                                     NULL,
660                                     0,
661                                     0,
662                                     (void *)&FORMAT_DATA_OUT->sock_hdr,
663                                     sizeof(FORMAT_DATA_OUT->sock_hdr));
664                        if (ret < 0) {
665                                trace_set_err_out(libtrace, errno,
666                                                  "sendto after timeout "
667                                                  "failed");
668                                return -1;
669                        }
670        }
671
672        header->tp_len = trace_get_capture_length(packet);
673
674        /* We cannot write the whole packet so just write part of it */
675        if (header->tp_len > max_size)
676                header->tp_len = max_size;
677
678        /* Fill packet - no sockaddr_ll in header when writing to the TX_RING */
679        off = ((void *)header) + (TPACKET2_HDRLEN - sizeof(struct sockaddr_ll));
680        memcpy(off, (char *)packet->payload, header->tp_len);
681
682        /* 'Send it' and increase ring pointer to the next frame */
683        header->tp_status = TP_STATUS_SEND_REQUEST;
684        FORMAT_DATA_OUT->txring_offset = (FORMAT_DATA_OUT->txring_offset + 1) %
685                FORMAT_DATA_OUT->req.tp_frame_nr;
686
687        /* Notify kernel there are frames to send */
688        FORMAT_DATA_OUT->queue ++;
689        FORMAT_DATA_OUT->queue %= TX_MAX_QUEUE;
690        if(FORMAT_DATA_OUT->queue == 0){
691                ret = sendto(FORMAT_DATA_OUT->fd,
692                                NULL,
693                                0,
694                                MSG_DONTWAIT,
695                                (void *)&FORMAT_DATA_OUT->sock_hdr,
696                                sizeof(FORMAT_DATA_OUT->sock_hdr));
697                if (ret < 0) {
698                        trace_set_err_out(libtrace, errno, "sendto failed");
699                        return -1;
700                }
701        }
702        return header->tp_len;
703
704}
705
706static void linuxring_help(void)
707{
708        printf("linuxring format module: $Revision: 1793 $\n");
709        printf("Supported input URIs:\n");
710        printf("\tring:eth0\n");
711        printf("\n");
712        printf("Supported output URIs:\n");
713        printf("\tring:eth0\n");
714        printf("\n");
715        return;
716}
717
718static struct libtrace_format_t linuxring = {
719        "ring",
720        "$Id$",
721        TRACE_FORMAT_LINUX_RING,
722        linuxcommon_probe_filename,     /* probe filename */
723        NULL,                           /* probe magic */
724        linuxcommon_init_input,         /* init_input */
725        linuxcommon_config_input,       /* config_input */
726        linuxring_start_input,          /* start_input */
727        linuxcommon_pause_input,        /* pause_input */
728        linuxcommon_init_output,        /* init_output */
729        NULL,                           /* config_output */
730        linuxring_start_output,         /* start_ouput */
731        linuxcommon_fin_input,          /* fin_input */
732        linuxring_fin_output,           /* fin_output */
733        linuxring_read_packet,          /* read_packet */
734        linuxring_prepare_packet,       /* prepare_packet */
735        linuxring_fin_packet,           /* fin_packet */
736        linuxring_write_packet,         /* write_packet */
737        linuxring_get_link_type,        /* get_link_type */
738        linuxring_get_direction,        /* get_direction */
739        linuxring_set_direction,        /* set_direction */
740        NULL,                           /* get_erf_timestamp */
741        linuxring_get_timeval,          /* get_timeval */
742        linuxring_get_timespec,         /* get_timespec */
743        NULL,                           /* get_seconds */
744        NULL,                           /* seek_erf */
745        NULL,                           /* seek_timeval */
746        NULL,                           /* seek_seconds */
747        linuxring_get_capture_length,   /* get_capture_length */
748        linuxring_get_wire_length,      /* get_wire_length */
749        linuxring_get_framing_length,   /* get_framing_length */
750        linuxring_set_capture_length,   /* set_capture_length */
751        NULL,                           /* get_received_packets */
752        NULL,                           /* get_filtered_packets */
753        NULL,                           /* get_dropped_packets */
754        linuxcommon_get_statistics,     /* get_statistics */
755        linuxcommon_get_fd,             /* get_fd */
756        linuxring_event,                /* trace_event */
757        linuxring_help,                 /* help */
758        NULL,                           /* next pointer */
759        {true, -1},                     /* Live, no thread limit */
760        linuxring_pstart_input,         /* pstart_input */
761        linuxring_pread_packets,        /* pread_packets */
762        linuxcommon_pause_input,        /* ppause */
763        linuxcommon_fin_input,          /* p_fin */
764        linuxcommon_pregister_thread,   /* register thread */
765        NULL,                           /* unregister thread */
766        NULL                            /* get thread stats */
767};
768#else /* HAVE_NETPACKET_PACKET_H */
769
770static void linuxring_help(void)
771{
772        printf("linuxring format module: $Revision: 1793 $\n");
773        printf("Not supported on this host\n");
774}
775
776static struct libtrace_format_t linuxring = {
777        "ring",
778        "$Id$",
779        TRACE_FORMAT_LINUX_RING,
780        NULL,                           /* probe filename */
781        NULL,                           /* probe magic */
782        NULL,                           /* init_input */
783        NULL,                           /* config_input */
784        NULL,                           /* start_input */
785        NULL,                           /* pause_input */
786        NULL,                           /* init_output */
787        NULL,                           /* config_output */
788        NULL,                           /* start_ouput */
789        NULL,                           /* fin_input */
790        NULL,                           /* fin_output */
791        NULL,                           /* read_packet */
792        linuxring_prepare_packet,       /* prepare_packet */
793        NULL,                           /* fin_packet */
794        NULL,                           /* write_packet */
795        linuxring_get_link_type,        /* get_link_type */
796        linuxring_get_direction,        /* get_direction */
797        linuxring_set_direction,        /* set_direction */
798        NULL,                           /* get_erf_timestamp */
799        linuxring_get_timeval,          /* get_timeval */
800        linuxring_get_timespec,         /* get_timespec */
801        NULL,                           /* get_seconds */
802        NULL,                           /* seek_erf */
803        NULL,                           /* seek_timeval */
804        NULL,                           /* seek_seconds */
805        linuxring_get_capture_length,   /* get_capture_length */
806        linuxring_get_wire_length,      /* get_wire_length */
807        linuxring_get_framing_length,   /* get_framing_length */
808        linuxring_set_capture_length,   /* set_capture_length */
809        NULL,                           /* get_received_packets */
810        NULL,                           /* get_filtered_packets */
811        NULL,                           /* get_dropped_packets */
812        linuxcommon_get_statistics,     /* get_statistics */
813        NULL,                           /* get_fd */
814        NULL,                           /* trace_event */
815        linuxring_help,                 /* help */
816        NULL,                           /* next pointer */
817        NON_PARALLEL(true)
818};
819#endif /* HAVE_NETPACKET_PACKET_H */
820
821/* TODO: Figure out how to give this format preference over the linux native
822 * formate if the user only specifies an interface */
823void linuxring_constructor(void)
824{
825        register_format(&linuxring);
826}
Note: See TracBrowser for help on using the repository browser.