source: lib/format_linux_ring.c @ 6cf3ca0

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

Gets the ring format back to a working state, the bulk of the refactoring
is now done.

I've opted to remove the inheritance way of grabbing shared functions
and replaced it with a file containing the common functions. Hopefully
this is more obvious that both int and ring depend on these.

I've also reworked the formats to be stream orientated, which removed
duplicates of heaps of functions. And allows the parallel and single
thread code to be almost identical.

After doing this many of the places where we had differences in
functions between ring and int disappeared.

I've also upped the MAX_ORDER to 11, used in allocating memory
from the kernel for the ring format.
Since this seems to work on the testing machines.
And we'll continue to fallback to smaller values if needed anyway.

  • Property mode set to 100644
File size: 23.1 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), -1);
488                if (ret > 0) {
489                        if (pollset[0].revents)
490                                continue;
491                        else
492                                return READ_MESSAGE;
493                } else if (ret < 0) {
494                        if (errno != EINTR)
495                        trace_set_err(libtrace,errno,"poll()");
496                        return -1;
497                } else {
498                        /* Poll timed out - check if we should exit */
499                        if (libtrace_halt)
500                                return 0;
501                        continue;
502                }
503        }
504
505        packet->buffer = header;
506
507        /* If a snaplen was configured, automatically truncate the packet to
508         * the desired length.
509         */
510        snaplen=LIBTRACE_MIN(
511                        (int)LIBTRACE_PACKET_BUFSIZE-(int)sizeof(*header),
512                        (int)FORMAT_DATA->snaplen);
513       
514        TO_TP_HDR2(packet->buffer)->tp_snaplen = LIBTRACE_MIN((unsigned int)snaplen, TO_TP_HDR2(packet->buffer)->tp_len);
515
516        /* Move to next buffer */
517        stream->rxring_offset++;
518        stream->rxring_offset %= FORMAT_DATA->req.tp_frame_nr;
519
520        /* We just need to get prepare_packet to set all our packet pointers
521         * appropriately */
522        if (linuxring_prepare_packet(libtrace, packet, packet->buffer,
523                                packet->type, 0))
524                return -1;
525        return  linuxring_get_framing_length(packet) + 
526                                linuxring_get_capture_length(packet);
527
528}
529
530static int linuxring_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
531        return linuxring_read_stream(libtrace, packet, FORMAT_DATA_FIRST, NULL);
532}
533
534static int linuxring_pread_packets(libtrace_t *libtrace,
535                                   libtrace_thread_t *t,
536                                   libtrace_packet_t *packets[],
537                                   UNUSED size_t nb_packets) {
538        /* For now just read one packet */
539        packets[0]->error = linuxring_read_stream(libtrace, packets[0],
540                                                  t->format_data, &t->messages);
541        if (packets[0]->error >= 1)
542                return 1;
543        else
544                return packets[0]->error;
545}
546
547/* Non-blocking read */
548static libtrace_eventobj_t linuxring_event(libtrace_t *libtrace,
549                                           libtrace_packet_t *packet)
550{
551        struct tpacket2_hdr *header;
552        libtrace_eventobj_t event = {0,0,0.0,0};
553
554        /* We must free the old packet, otherwise select() will instantly
555         * return */
556        ring_release_frame(libtrace, packet);
557
558        /* Fetch the current frame */
559        header = GET_CURRENT_BUFFER(libtrace, FORMAT_DATA_FIRST);
560        if (header->tp_status & TP_STATUS_USER) {
561                /* We have a frame waiting */
562                event.size = trace_read_packet(libtrace, packet);
563                event.type = TRACE_EVENT_PACKET;
564        } else {
565                /* Ok we don't have a packet waiting */
566                event.type = TRACE_EVENT_IOWAIT;
567                event.fd = FORMAT_DATA_FIRST->fd;
568        }
569
570        return event;
571}
572
573/**
574 * Free any resources being kept for this packet, Note: libtrace
575 * will ensure all fields are zeroed correctly.
576 */
577static void linuxring_fin_packet(libtrace_packet_t *packet)
578{
579        libtrace_t *libtrace = packet->trace;
580
581        if (packet->buffer == NULL)
582                return;
583        assert(packet->trace);
584
585        /* If we own the packet (i.e. it's not a copy), we need to free it */
586        if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
587                /* Started should always match the existence of the rx_ring
588                 * in the parallel case still just check the first ring */
589                assert(!!FORMAT_DATA_FIRST->rx_ring ==
590                       !!packet->trace->started);
591                /* If we don't have a ring its already been destroyed */
592                if (FORMAT_DATA_FIRST->rx_ring != MAP_FAILED)
593                        ring_release_frame(packet->trace, packet);
594                else
595                        packet->buffer = NULL;
596        }
597}
598
599static int linuxring_write_packet(libtrace_out_t *libtrace,
600                                  libtrace_packet_t *packet)
601{
602        struct tpacket2_hdr *header;
603        struct pollfd pollset;
604        struct socket_addr;
605        int ret;
606        unsigned max_size;
607        void * off;
608
609        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
610                return 0;
611
612        max_size = FORMAT_DATA_OUT->req.tp_frame_size -
613                TPACKET2_HDRLEN + sizeof(struct sockaddr_ll);
614
615        header = (void *)FORMAT_DATA_OUT->tx_ring +
616                (FORMAT_DATA_OUT->txring_offset *
617                 FORMAT_DATA_OUT->req.tp_frame_size);
618
619        while(header->tp_status != TP_STATUS_AVAILABLE) {
620                /* if none available: wait on more data */
621                pollset.fd = FORMAT_DATA_OUT->fd;
622                pollset.events = POLLOUT;
623                pollset.revents = 0;
624                ret = poll(&pollset, 1, 1000);
625                if (ret < 0 && errno != EINTR) {
626                        perror("poll");
627                        return -1;
628                }
629                if(ret == 0)
630                        /* Timeout something has gone wrong - maybe the queue is
631                         * to large so try issue another send command
632                         */
633                        ret = sendto(FORMAT_DATA_OUT->fd,
634                                     NULL,
635                                     0,
636                                     0,
637                                     (void *)&FORMAT_DATA_OUT->sock_hdr,
638                                     sizeof(FORMAT_DATA_OUT->sock_hdr));
639                        if (ret < 0) {
640                                trace_set_err_out(libtrace, errno,
641                                                  "sendto after timeout "
642                                                  "failed");
643                                return -1;
644                        }
645        }
646
647        header->tp_len = trace_get_capture_length(packet);
648
649        /* We cannot write the whole packet so just write part of it */
650        if (header->tp_len > max_size)
651                header->tp_len = max_size;
652
653        /* Fill packet - no sockaddr_ll in header when writing to the TX_RING */
654        off = ((void *)header) + (TPACKET2_HDRLEN - sizeof(struct sockaddr_ll));
655        memcpy(off, (char *)packet->payload, header->tp_len);
656
657        /* 'Send it' and increase ring pointer to the next frame */
658        header->tp_status = TP_STATUS_SEND_REQUEST;
659        FORMAT_DATA_OUT->txring_offset = (FORMAT_DATA_OUT->txring_offset + 1) %
660                FORMAT_DATA_OUT->req.tp_frame_nr;
661
662        /* Notify kernel there are frames to send */
663        FORMAT_DATA_OUT->queue ++;
664        FORMAT_DATA_OUT->queue %= TX_MAX_QUEUE;
665        if(FORMAT_DATA_OUT->queue == 0){
666                ret = sendto(FORMAT_DATA_OUT->fd,
667                                NULL,
668                                0,
669                                MSG_DONTWAIT,
670                                (void *)&FORMAT_DATA_OUT->sock_hdr,
671                                sizeof(FORMAT_DATA_OUT->sock_hdr));
672                if (ret < 0) {
673                        trace_set_err_out(libtrace, errno, "sendto failed");
674                        return -1;
675                }
676        }
677        return header->tp_len;
678
679}
680
681#ifdef HAVE_NETPACKET_PACKET_H
682
683static void linuxring_help(void)
684{
685        printf("linuxring format module: $Revision: 1793 $\n");
686        printf("Supported input URIs:\n");
687        printf("\tring:eth0\n");
688        printf("\n");
689        printf("Supported output URIs:\n");
690        printf("\tring:eth0\n");
691        printf("\n");
692        return;
693}
694
695static struct libtrace_format_t linuxring = {
696        "ring",
697        "$Id$",
698        TRACE_FORMAT_LINUX_RING,
699        linuxcommon_probe_filename,     /* probe filename */
700        NULL,                           /* probe magic */
701        linuxcommon_init_input,         /* init_input */
702        linuxcommon_config_input,       /* config_input */
703        linuxring_start_input,          /* start_input */
704        linuxcommon_pause_input,        /* pause_input */
705        linuxcommon_init_output,        /* init_output */
706        NULL,                           /* config_output */
707        linuxring_start_output,         /* start_ouput */
708        linuxcommon_fin_input,          /* fin_input */
709        linuxring_fin_output,           /* fin_output */
710        linuxring_read_packet,          /* read_packet */
711        linuxring_prepare_packet,       /* prepare_packet */
712        linuxring_fin_packet,           /* fin_packet */
713        linuxring_write_packet,         /* write_packet */
714        linuxring_get_link_type,        /* get_link_type */
715        linuxring_get_direction,        /* get_direction */
716        linuxring_set_direction,        /* set_direction */
717        NULL,                           /* get_erf_timestamp */
718        linuxring_get_timeval,          /* get_timeval */
719        linuxring_get_timespec,         /* get_timespec */
720        NULL,                           /* get_seconds */
721        NULL,                           /* seek_erf */
722        NULL,                           /* seek_timeval */
723        NULL,                           /* seek_seconds */
724        linuxring_get_capture_length,   /* get_capture_length */
725        linuxring_get_wire_length,      /* get_wire_length */
726        linuxring_get_framing_length,   /* get_framing_length */
727        linuxring_set_capture_length,   /* set_capture_length */
728        NULL,                           /* get_received_packets */
729        linuxcommon_get_filtered_packets,/* get_filtered_packets */
730        linuxcommon_get_dropped_packets,/* get_dropped_packets */
731        linuxcommon_get_captured_packets,/* get_captured_packets */
732        linuxcommon_get_fd,             /* get_fd */
733        linuxring_event,                /* trace_event */
734        linuxring_help,                 /* help */
735        NULL,                           /* next pointer */
736        {true, -1},                     /* Live, no thread limit */
737        linuxring_pstart_input,         /* pstart_input */
738        linuxring_pread_packets,        /* pread_packets */
739        linuxcommon_pause_input,        /* ppause */
740        linuxcommon_fin_input,          /* p_fin */
741        linuxcommon_pconfig_input,      /* pconfig input */
742        linuxcommon_pregister_thread,
743        NULL
744};
745#else
746
747static void linuxring_help(void)
748{
749        printf("linuxring format module: $Revision: 1793 $\n");
750        printf("Not supported on this host\n");
751}
752
753static struct libtrace_format_t linuxring = {
754        "ring",
755        "$Id$",
756        TRACE_FORMAT_LINUX_RING,
757        NULL,                           /* probe filename */
758        NULL,                           /* probe magic */
759        NULL,                           /* init_input */
760        NULL,                           /* config_input */
761        NULL,                           /* start_input */
762        NULL,                           /* pause_input */
763        NULL,                           /* init_output */
764        NULL,                           /* config_output */
765        NULL,                           /* start_ouput */
766        NULL,                           /* fin_input */
767        NULL,                           /* fin_output */
768        NULL,                           /* read_packet */
769        linuxring_prepare_packet,       /* prepare_packet */
770        NULL,                           /* fin_packet */
771        NULL,                           /* write_packet */
772        linuxring_get_link_type,        /* get_link_type */
773        linuxring_get_direction,        /* get_direction */
774        linuxring_set_direction,        /* set_direction */
775        NULL,                           /* get_erf_timestamp */
776        linuxring_get_timeval,          /* get_timeval */
777        linuxring_get_timespec,         /* get_timespec */
778        NULL,                           /* get_seconds */
779        NULL,                           /* seek_erf */
780        NULL,                           /* seek_timeval */
781        NULL,                           /* seek_seconds */
782        linuxring_get_capture_length,   /* get_capture_length */
783        linuxring_get_wire_length,      /* get_wire_length */
784        linuxring_get_framing_length,   /* get_framing_length */
785        linuxring_set_capture_length,   /* set_capture_length */
786        NULL,                           /* get_received_packets */
787        NULL,                           /* get_filtered_packets */
788        NULL,                           /* get_dropped_packets */
789        NULL,                           /* get_captured_packets */
790        NULL,                           /* get_fd */
791        NULL,                           /* trace_event */
792        linuxring_help,                 /* help */
793        NULL,                           /* next pointer */
794        NON_PARALLEL(true)
795};
796#endif
797
798/* TODO: Figure out how to give this format preference over the linux native
799 * formate if the user only specifies an interface */
800void linuxring_constructor(void)
801{
802        register_format(&linuxring);
803}
Note: See TracBrowser for help on using the repository browser.