source: lib/format_linux_ring.c @ 10c47a0

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

Fixes DAG DUCK reporting for parallel libtrace.
In parallel libtrace DUCK is only ever sent to the first thread.

It is now up each formats pread_packet to tag the trace along with
the error (AKA bytes read) to each packet.

Change logic in parallel libtrace to alwaus prefer pread over read if
it exists.

Fix some unresolved conflict in DPDK that I missed, that was ifdef'd out.

  • Property mode set to 100644
File size: 23.7 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#ifdef HAVE_NETPACKET_PACKET_H
66/* Get current frame in the ring buffer*/
67#define GET_CURRENT_BUFFER(stream) \
68        ((void *)stream->rx_ring +                              \
69         (stream->rxring_offset *                               \
70          stream->req.tp_frame_size))
71#endif
72
73/* Get the start of the captured data. I'm not sure if tp_mac (link layer) is
74 * always guaranteed. If it's not there then just use tp_net.
75 */
76#define TP_TRACE_START(mac, net, hdrend) \
77        ((mac) > (hdrend) && (mac) < (net) ? (mac) : (net))
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
354static libtrace_linktype_t
355linuxring_get_link_type(const struct libtrace_packet_t *packet)
356{
357        uint16_t linktype = GET_SOCKADDR_HDR(packet->buffer)->sll_hatype;
358        return linuxcommon_get_link_type(linktype);
359}
360
361static libtrace_direction_t
362linuxring_get_direction(const struct libtrace_packet_t *packet) {
363        return linuxcommon_get_direction(GET_SOCKADDR_HDR(packet->buffer)->
364                                         sll_pkttype);
365}
366
367static libtrace_direction_t
368linuxring_set_direction(libtrace_packet_t *packet,
369                        libtrace_direction_t direction) {
370        return linuxcommon_set_direction(GET_SOCKADDR_HDR(packet->buffer), direction);
371}
372
373static struct timeval linuxring_get_timeval(const libtrace_packet_t *packet)
374{
375        struct timeval tv;
376        tv.tv_sec = TO_TP_HDR2(packet->buffer)->tp_sec;
377        tv.tv_usec = TO_TP_HDR2(packet->buffer)->tp_nsec / 1000;
378        return tv;
379}
380
381static struct timespec linuxring_get_timespec(const libtrace_packet_t *packet)
382{
383        struct timespec ts;
384        ts.tv_sec = TO_TP_HDR2(packet->buffer)->tp_sec;
385        ts.tv_nsec = TO_TP_HDR2(packet->buffer)->tp_nsec;
386        return ts;
387}
388
389static int linuxring_get_capture_length(const libtrace_packet_t *packet)
390{
391        return TO_TP_HDR2(packet->buffer)->tp_snaplen;
392}
393
394static int linuxring_get_wire_length(const libtrace_packet_t *packet)
395{
396        int wirelen = TO_TP_HDR2(packet->buffer)->tp_len;
397
398        /* Include the missing FCS */
399        if (trace_get_link_type(packet) == TRACE_TYPE_ETH)
400                wirelen += 4;
401
402        return wirelen;
403}
404
405static int linuxring_get_framing_length(const libtrace_packet_t *packet)
406{
407        /*
408         * Need to make frame_length + capture_length = complete capture length
409         * so include alignment whitespace. So reverse calculate from packet.
410         */
411        return (char *)packet->payload - (char *)packet->buffer;
412}
413
414static size_t linuxring_set_capture_length(libtrace_packet_t *packet,
415                                           size_t size)
416{
417        assert(packet);
418        if (size > trace_get_capture_length(packet)) {
419                /* We should avoid making a packet larger */
420                return trace_get_capture_length(packet);
421        }
422
423        /* Reset the cached capture length */
424        packet->capture_length = -1;
425
426        TO_TP_HDR2(packet->buffer)->tp_snaplen = size;
427
428        return trace_get_capture_length(packet);
429}
430
431static int linuxring_prepare_packet(libtrace_t *libtrace UNUSED,
432                                    libtrace_packet_t *packet, void *buffer,
433                                    libtrace_rt_types_t rt_type, uint32_t flags)
434{
435        if (packet->buffer != buffer &&
436            packet->buf_control == TRACE_CTRL_PACKET) {
437                free(packet->buffer);
438        }
439
440        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER)
441                packet->buf_control = TRACE_CTRL_PACKET;
442        else
443                packet->buf_control = TRACE_CTRL_EXTERNAL;
444
445
446        packet->buffer = buffer;
447        packet->header = buffer;
448        packet->payload = (char *)buffer +
449                TP_TRACE_START(TO_TP_HDR2(packet->header)->tp_mac,
450                               TO_TP_HDR2(packet->header)->tp_net,
451                               TPACKET2_HDRLEN);
452        packet->type = rt_type;
453
454        return 0;
455}
456#define LIBTRACE_MIN(a,b) ((a)<(b) ? (a) : (b))
457inline static int linuxring_read_stream(libtrace_t *libtrace,
458                                        libtrace_packet_t *packet,
459                                        struct linux_per_stream_t *stream,
460                                        libtrace_message_queue_t *queue) {
461
462        struct tpacket2_hdr *header;
463        int ret;
464        unsigned int snaplen;
465        struct pollfd pollset[2];
466
467        ring_release_frame(libtrace, packet);
468       
469        packet->buf_control = TRACE_CTRL_EXTERNAL;
470        packet->type = TRACE_RT_DATA_LINUX_RING;
471       
472        /* Fetch the current frame */
473        header = GET_CURRENT_BUFFER(stream);
474        assert((((unsigned long) header) & (pagesize - 1)) == 0);
475
476        /* TP_STATUS_USER means that we can use the frame.
477         * When a slot does not have this flag set, the frame is not
478         * ready for consumption.
479         */
480        while (!(header->tp_status & TP_STATUS_USER)) {
481                pollset[0].fd = stream->fd;
482                pollset[0].events = POLLIN;
483                pollset[0].revents = 0;
484                if (queue) {
485                        pollset[1].fd = libtrace_message_queue_get_fd(queue);
486                        pollset[1].events = POLLIN;
487                        pollset[1].revents = 0;
488                }
489                /* Wait for more data or a message */
490                ret = poll(pollset, (queue ? 2 : 1), 500);
491                if (ret > 0) {
492                        if (pollset[0].revents == POLLIN)
493                                continue;
494                        else if (queue && pollset[1].revents == POLLIN)
495                                return READ_MESSAGE;
496                        else if (queue && pollset[1].revents) {
497                                /* Internal error */
498                                trace_set_err(libtrace,TRACE_ERR_BAD_STATE,
499                                              "Message queue error %d poll()",
500                                              pollset[1].revents);
501                                return READ_ERROR;
502                        } else {
503                                /* Try get the error from the socket */
504                                int err = ENETDOWN;
505                                socklen_t len = sizeof(err);
506                                getsockopt(stream->fd, SOL_SOCKET, SO_ERROR,
507                                           &err, &len);
508                                trace_set_err(libtrace, err,
509                                              "Socket error revents=%d poll()",
510                                              pollset[0].revents);
511                                return READ_ERROR;
512                        }
513                } else if (ret < 0) {
514                        if (errno != EINTR) {
515                                trace_set_err(libtrace,errno,"poll()");
516                                return -1;
517                        }
518                } else {
519                        /* Poll timed out - check if we should exit */
520                        if (libtrace_halt)
521                                return 0;
522                        continue;
523                }
524        }
525
526        packet->buffer = header;
527        packet->trace = libtrace;
528
529        /* If a snaplen was configured, automatically truncate the packet to
530         * the desired length.
531         */
532        snaplen=LIBTRACE_MIN(
533                        (int)LIBTRACE_PACKET_BUFSIZE-(int)sizeof(*header),
534                        (int)FORMAT_DATA->snaplen);
535       
536        TO_TP_HDR2(packet->buffer)->tp_snaplen = LIBTRACE_MIN((unsigned int)snaplen, TO_TP_HDR2(packet->buffer)->tp_len);
537
538        /* Move to next buffer */
539        stream->rxring_offset++;
540        stream->rxring_offset %= stream->req.tp_frame_nr;
541
542        /* We just need to get prepare_packet to set all our packet pointers
543         * appropriately */
544        if (linuxring_prepare_packet(libtrace, packet, packet->buffer,
545                                packet->type, 0))
546                return -1;
547        return  linuxring_get_framing_length(packet) + 
548                                linuxring_get_capture_length(packet);
549
550}
551
552static int linuxring_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
553        return linuxring_read_stream(libtrace, packet, FORMAT_DATA_FIRST, NULL);
554}
555
556static int linuxring_pread_packets(libtrace_t *libtrace,
557                                   libtrace_thread_t *t,
558                                   libtrace_packet_t *packets[],
559                                   UNUSED size_t nb_packets) {
560        /* For now just read one packet */
561        packets[0]->error = linuxring_read_stream(libtrace, packets[0],
562                                                  t->format_data, &t->messages);
563        if (packets[0]->error >= 1)
564                return 1;
565        else
566                return packets[0]->error;
567}
568
569/* Non-blocking read */
570static libtrace_eventobj_t linuxring_event(libtrace_t *libtrace,
571                                           libtrace_packet_t *packet)
572{
573        struct tpacket2_hdr *header;
574        libtrace_eventobj_t event = {0,0,0.0,0};
575
576        /* We must free the old packet, otherwise select() will instantly
577         * return */
578        ring_release_frame(libtrace, packet);
579
580        /* Fetch the current frame */
581        header = GET_CURRENT_BUFFER(FORMAT_DATA_FIRST);
582        if (header->tp_status & TP_STATUS_USER) {
583                /* We have a frame waiting */
584                event.size = trace_read_packet(libtrace, packet);
585                event.type = TRACE_EVENT_PACKET;
586        } else {
587                /* Ok we don't have a packet waiting */
588                event.type = TRACE_EVENT_IOWAIT;
589                event.fd = FORMAT_DATA_FIRST->fd;
590        }
591
592        return event;
593}
594
595/**
596 * Free any resources being kept for this packet, Note: libtrace
597 * will ensure all fields are zeroed correctly.
598 */
599static void linuxring_fin_packet(libtrace_packet_t *packet)
600{
601        libtrace_t *libtrace = packet->trace;
602
603        if (packet->buffer == NULL)
604                return;
605        assert(packet->trace);
606
607        /* If we own the packet (i.e. it's not a copy), we need to free it */
608        if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
609                /* Started should always match the existence of the rx_ring
610                 * in the parallel case still just check the first ring */
611                assert(!!FORMAT_DATA_FIRST->rx_ring ==
612                       !!packet->trace->started);
613                /* If we don't have a ring its already been destroyed */
614                if (FORMAT_DATA_FIRST->rx_ring != MAP_FAILED)
615                        ring_release_frame(packet->trace, packet);
616                else
617                        packet->buffer = NULL;
618        }
619}
620
621static int linuxring_write_packet(libtrace_out_t *libtrace,
622                                  libtrace_packet_t *packet)
623{
624        struct tpacket2_hdr *header;
625        struct pollfd pollset;
626        struct socket_addr;
627        int ret;
628        unsigned max_size;
629        void * off;
630
631        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
632                return 0;
633
634        max_size = FORMAT_DATA_OUT->req.tp_frame_size -
635                TPACKET2_HDRLEN + sizeof(struct sockaddr_ll);
636
637        header = (void *)FORMAT_DATA_OUT->tx_ring +
638                (FORMAT_DATA_OUT->txring_offset *
639                 FORMAT_DATA_OUT->req.tp_frame_size);
640
641        while(header->tp_status != TP_STATUS_AVAILABLE) {
642                /* if none available: wait on more data */
643                pollset.fd = FORMAT_DATA_OUT->fd;
644                pollset.events = POLLOUT;
645                pollset.revents = 0;
646                ret = poll(&pollset, 1, 1000);
647                if (ret < 0 && errno != EINTR) {
648                        perror("poll");
649                        return -1;
650                }
651                if(ret == 0)
652                        /* Timeout something has gone wrong - maybe the queue is
653                         * to large so try issue another send command
654                         */
655                        ret = sendto(FORMAT_DATA_OUT->fd,
656                                     NULL,
657                                     0,
658                                     0,
659                                     (void *)&FORMAT_DATA_OUT->sock_hdr,
660                                     sizeof(FORMAT_DATA_OUT->sock_hdr));
661                        if (ret < 0) {
662                                trace_set_err_out(libtrace, errno,
663                                                  "sendto after timeout "
664                                                  "failed");
665                                return -1;
666                        }
667        }
668
669        header->tp_len = trace_get_capture_length(packet);
670
671        /* We cannot write the whole packet so just write part of it */
672        if (header->tp_len > max_size)
673                header->tp_len = max_size;
674
675        /* Fill packet - no sockaddr_ll in header when writing to the TX_RING */
676        off = ((void *)header) + (TPACKET2_HDRLEN - sizeof(struct sockaddr_ll));
677        memcpy(off, (char *)packet->payload, header->tp_len);
678
679        /* 'Send it' and increase ring pointer to the next frame */
680        header->tp_status = TP_STATUS_SEND_REQUEST;
681        FORMAT_DATA_OUT->txring_offset = (FORMAT_DATA_OUT->txring_offset + 1) %
682                FORMAT_DATA_OUT->req.tp_frame_nr;
683
684        /* Notify kernel there are frames to send */
685        FORMAT_DATA_OUT->queue ++;
686        FORMAT_DATA_OUT->queue %= TX_MAX_QUEUE;
687        if(FORMAT_DATA_OUT->queue == 0){
688                ret = sendto(FORMAT_DATA_OUT->fd,
689                                NULL,
690                                0,
691                                MSG_DONTWAIT,
692                                (void *)&FORMAT_DATA_OUT->sock_hdr,
693                                sizeof(FORMAT_DATA_OUT->sock_hdr));
694                if (ret < 0) {
695                        trace_set_err_out(libtrace, errno, "sendto failed");
696                        return -1;
697                }
698        }
699        return header->tp_len;
700
701}
702
703#ifdef HAVE_NETPACKET_PACKET_H
704
705static void linuxring_help(void)
706{
707        printf("linuxring format module: $Revision: 1793 $\n");
708        printf("Supported input URIs:\n");
709        printf("\tring:eth0\n");
710        printf("\n");
711        printf("Supported output URIs:\n");
712        printf("\tring:eth0\n");
713        printf("\n");
714        return;
715}
716
717static struct libtrace_format_t linuxring = {
718        "ring",
719        "$Id$",
720        TRACE_FORMAT_LINUX_RING,
721        linuxcommon_probe_filename,     /* probe filename */
722        NULL,                           /* probe magic */
723        linuxcommon_init_input,         /* init_input */
724        linuxcommon_config_input,       /* config_input */
725        linuxring_start_input,          /* start_input */
726        linuxcommon_pause_input,        /* pause_input */
727        linuxcommon_init_output,        /* init_output */
728        NULL,                           /* config_output */
729        linuxring_start_output,         /* start_ouput */
730        linuxcommon_fin_input,          /* fin_input */
731        linuxring_fin_output,           /* fin_output */
732        linuxring_read_packet,          /* read_packet */
733        linuxring_prepare_packet,       /* prepare_packet */
734        linuxring_fin_packet,           /* fin_packet */
735        linuxring_write_packet,         /* write_packet */
736        linuxring_get_link_type,        /* get_link_type */
737        linuxring_get_direction,        /* get_direction */
738        linuxring_set_direction,        /* set_direction */
739        NULL,                           /* get_erf_timestamp */
740        linuxring_get_timeval,          /* get_timeval */
741        linuxring_get_timespec,         /* get_timespec */
742        NULL,                           /* get_seconds */
743        NULL,                           /* seek_erf */
744        NULL,                           /* seek_timeval */
745        NULL,                           /* seek_seconds */
746        linuxring_get_capture_length,   /* get_capture_length */
747        linuxring_get_wire_length,      /* get_wire_length */
748        linuxring_get_framing_length,   /* get_framing_length */
749        linuxring_set_capture_length,   /* set_capture_length */
750        NULL,                           /* get_received_packets */
751        NULL,                           /* get_filtered_packets */
752        NULL,                           /* get_dropped_packets */
753        linuxcommon_get_statistics,     /* get_statistics */
754        linuxcommon_get_fd,             /* get_fd */
755        linuxring_event,                /* trace_event */
756        linuxring_help,                 /* help */
757        NULL,                           /* next pointer */
758        {true, -1},                     /* Live, no thread limit */
759        linuxring_pstart_input,         /* pstart_input */
760        linuxring_pread_packets,        /* pread_packets */
761        linuxcommon_pause_input,        /* ppause */
762        linuxcommon_fin_input,          /* p_fin */
763        linuxcommon_pconfig_input,      /* pconfig input */
764        linuxcommon_pregister_thread,   /* register thread */
765        NULL,                           /* unregister thread */
766        NULL                            /* get thread stats */
767};
768#else
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
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.