source: lib/format_linux_ring.c @ 8bcc925

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 8bcc925 was 3e89670, checked in by Richard Sanger <rsangerarj@…>, 6 years ago

Get the error code from the socket correctly in the case of an error in ring:

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