source: lib/format_linux_ring.c @ e4f27d1

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

Move the ring sizes to the stream structures, it's possible rings could end up different sizes.
Other than that their are many operation related to reading packets which rely upon it and
it seems more natural to include this against the stream.

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