source: lib/format_linux_common.c @ 526d9d0

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

Move the accepted packet count to dispatching packets for threads.
Accounting for the doubled count when using a single threaded format.

Rework statistics logic slightly to remove duplicated code.

  • Property mode set to 100644
File size: 21.2 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 file contains the common functions used by both the ring and int
36 * formats.
37 *
38 * Typically these deal with the socket descriptor or common conversions.
39 */
40
41#include "config.h"
42#include "libtrace.h"
43#include "libtrace_int.h"
44#include "format_helper.h"
45#include "libtrace_arphrd.h"
46#include <stdlib.h>
47#include <errno.h>
48#include <unistd.h>
49#include <string.h>
50#include <assert.h>
51
52#ifdef HAVE_INTTYPES_H
53#  include <inttypes.h>
54#else
55# error "Can't find inttypes.h"
56#endif
57
58#include "format_linux_common.h"
59
60#ifdef HAVE_NETPACKET_PACKET_H
61
62int linuxcommon_probe_filename(const char *filename)
63{
64        /* Is this an interface? */
65        return (if_nametoindex(filename) != 0);
66}
67
68/* Compiles a libtrace BPF filter for use with a linux native socket */
69static int linuxnative_configure_bpf(libtrace_t *libtrace,
70                libtrace_filter_t *filter) {
71#ifdef HAVE_LIBPCAP
72        struct ifreq ifr;
73        unsigned int arphrd;
74        libtrace_dlt_t dlt;
75        libtrace_filter_t *f;
76        int sock;
77        pcap_t *pcap;
78
79        /* Take a copy of the filter object as it was passed in */
80        f = (libtrace_filter_t *) malloc(sizeof(libtrace_filter_t));
81        memcpy(f, filter, sizeof(libtrace_filter_t));
82
83        /* If we are passed a filter with "flag" set to zero, then we must
84         * compile the filterstring before continuing. This involves
85         * determining the linktype, passing the filterstring to libpcap to
86         * compile, and saving the result for trace_start() to push into the
87         * kernel.
88         * If flag is set to one, then the filter was probably generated using
89         * trace_create_filter_from_bytecode() and so we don't need to do
90         * anything (we've just copied it above).
91         */
92        if (f->flag == 0) {
93                sock = socket(PF_INET, SOCK_STREAM, 0);
94                memset(&ifr, 0, sizeof(struct ifreq));
95                strncpy(ifr.ifr_name, libtrace->uridata, IF_NAMESIZE);
96                if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0) {
97                        perror("Can't get HWADDR for interface");
98                        return -1;
99                }
100                close(sock);
101
102                arphrd = ifr.ifr_hwaddr.sa_family;
103                dlt = libtrace_to_pcap_dlt(arphrd_type_to_libtrace(arphrd));
104
105                pcap = pcap_open_dead(dlt,
106                                FORMAT_DATA->snaplen);
107
108                if (pcap_compile(pcap, &f->filter, f->filterstring, 0, 0) == -1) {
109                        /* Filter didn't compile, set flag to 0 so we can
110                         * detect this when trace_start() is called and
111                         * produce a useful error
112                         */
113                        f->flag = 0;
114                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
115                                      "Failed to compile BPF filter (%s): %s",
116                                      f->filterstring, pcap_geterr(pcap));
117                } else {
118                        /* Set the "flag" to indicate that the filterstring
119                         * has been compiled
120                         */
121                        f->flag = 1;
122                }
123
124                pcap_close(pcap);
125
126        }
127
128        if (FORMAT_DATA->filter != NULL)
129                free(FORMAT_DATA->filter);
130
131        FORMAT_DATA->filter = f;
132
133        return 0;
134#else
135        return -1
136#endif
137}
138
139int linuxcommon_config_input(libtrace_t *libtrace,
140                trace_option_t option,
141                void *data)
142{
143        switch(option) {
144                case TRACE_OPTION_SNAPLEN:
145                        FORMAT_DATA->snaplen=*(int*)data;
146                        return 0;
147                case TRACE_OPTION_PROMISC:
148                        FORMAT_DATA->promisc=*(int*)data;
149                        return 0;
150                case TRACE_OPTION_FILTER:
151                        return linuxnative_configure_bpf(libtrace,
152                                        (libtrace_filter_t *) data);
153                case TRACE_OPTION_META_FREQ:
154                        /* No meta-data for this format */
155                        break;
156                case TRACE_OPTION_EVENT_REALTIME:
157                        /* Live captures are always going to be in trace time */
158                        break;
159                /* Avoid default: so that future options will cause a warning
160                 * here to remind us to implement it, or flag it as
161                 * unimplementable
162                 */
163        }
164
165        /* Don't set an error - trace_config will try to deal with the
166         * option and will set an error if it fails */
167        return -1;
168}
169
170int linuxcommon_init_input(libtrace_t *libtrace)
171{
172        struct linux_per_stream_t stream_data = ZERO_LINUX_STREAM;
173
174        libtrace->format_data = (struct linux_format_data_t *)
175                malloc(sizeof(struct linux_format_data_t));
176        assert(libtrace->format_data != NULL);
177
178        FORMAT_DATA->per_stream =
179                libtrace_list_init(sizeof(stream_data));
180        assert(FORMAT_DATA->per_stream != NULL);
181
182        libtrace_list_push_back(FORMAT_DATA->per_stream, &stream_data);
183
184        FORMAT_DATA->promisc = -1;
185        FORMAT_DATA->snaplen = LIBTRACE_PACKET_BUFSIZE;
186        FORMAT_DATA->filter = NULL;
187        FORMAT_DATA->stats_valid = 0;
188        FORMAT_DATA->stats.tp_drops = 0;
189        FORMAT_DATA->stats.tp_packets = 0;
190        FORMAT_DATA->max_order = MAX_ORDER;
191        FORMAT_DATA->fanout_flags = PACKET_FANOUT_LB;
192        /* Some examples use pid for the group however that would limit a single
193         * application to use only int/ring format, instead using rand */
194        FORMAT_DATA->fanout_group = (uint16_t) rand();
195        return 0;
196}
197
198int linuxcommon_init_output(libtrace_out_t *libtrace)
199{
200        libtrace->format_data = (struct linux_format_data_out_t*)
201                malloc(sizeof(struct linux_format_data_out_t));
202        assert(libtrace->format_data != NULL);
203
204        FORMAT_DATA_OUT->fd = -1;
205        FORMAT_DATA_OUT->tx_ring = NULL;
206        FORMAT_DATA_OUT->txring_offset = 0;
207        FORMAT_DATA_OUT->queue = 0;
208        FORMAT_DATA_OUT->max_order = MAX_ORDER;
209        return 0;
210}
211
212/* Close an input stream, this is safe to be called part way through
213 * initilisation as a cleanup function assuming streams were set to
214 * ZERO_LINUX_STREAM to begin with.
215 *
216 * This works correctly with both int and ring
217 */
218void linuxcommon_close_input_stream(libtrace_t *libtrace,
219                                    struct linux_per_stream_t *stream) {
220        if (stream->fd != -1)
221                close(stream->fd);
222        stream->fd = -1;
223        if (stream->rx_ring != MAP_FAILED)
224                munmap(stream->rx_ring,
225                       stream->req.tp_block_size *
226                       stream->req.tp_block_nr);
227        stream->rx_ring = MAP_FAILED;
228        FORMAT_DATA->dev_stats.if_name[0] = 0;
229}
230
231#define REPEAT_16(x) x x x x x x x x x x x x x x x x
232#define xstr(s) str(s)
233#define str(s) #s
234
235/* These don't typically reset however an interface does exist to reset them */
236static int linuxcommon_get_dev_statisitics(libtrace_t *libtrace, struct linux_dev_stats *stats) {
237        FILE *file;
238        char line[1024];
239        struct linux_dev_stats tmp_stats;
240
241        file = fopen("/proc/net/dev","r");
242        if (file == NULL) {
243                return -1;
244        }
245
246        /* Skip 2 header lines */
247        fgets(line, sizeof(line), file);
248        fgets(line, sizeof(line), file);
249
250        while (!(feof(file)||ferror(file))) {
251                int tot;
252                fgets(line, sizeof(line), file);
253                tot = sscanf(line, " %"xstr(IF_NAMESIZE)"[^:]:" REPEAT_16(" %"SCNd64),
254                             tmp_stats.if_name,
255                             &tmp_stats.rx_bytes,
256                             &tmp_stats.rx_packets,
257                             &tmp_stats.rx_errors,
258                             &tmp_stats.rx_drops,
259                             &tmp_stats.rx_fifo,
260                             &tmp_stats.rx_frame,
261                             &tmp_stats.rx_compressed,
262                             &tmp_stats.rx_multicast,
263                             &tmp_stats.tx_bytes,
264                             &tmp_stats.tx_packets,
265                             &tmp_stats.tx_errors,
266                             &tmp_stats.tx_drops,
267                             &tmp_stats.tx_fifo,
268                             &tmp_stats.tx_colls,
269                             &tmp_stats.tx_carrier,
270                             &tmp_stats.tx_compressed);
271                if (tot != 17)
272                        continue;
273                if (strncmp(tmp_stats.if_name, libtrace->uridata, IF_NAMESIZE) == 0) {
274                        *stats = tmp_stats;
275                        fclose(file);
276                        return 0;
277                }
278        }
279        fclose(file);
280        return -1;
281}
282
283/* Start an input stream
284 * - Opens the file descriptor
285 * - Sets promiscuous correctly
286 * - Sets socket option
287 * - Add BPF filter
288 *
289 * The output is ready for int directly, for ring the conversion to ring still
290 * needs to take place.
291 */
292int linuxcommon_start_input_stream(libtrace_t *libtrace,
293                                   struct linux_per_stream_t *stream)
294{
295        struct sockaddr_ll addr;
296        const int one = 1;
297        memset(&addr,0,sizeof(addr));
298        libtrace_filter_t *filter = FORMAT_DATA->filter;
299
300        /* Create a raw socket for reading packets on */
301        stream->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
302        if (stream->fd==-1) {
303                trace_set_err(libtrace, errno, "Could not create raw socket");
304                return -1;
305        }
306
307        /* Bind to the capture interface */
308        addr.sll_family = AF_PACKET;
309        addr.sll_protocol = htons(ETH_P_ALL);
310        if (strlen(libtrace->uridata)) {
311                addr.sll_ifindex = if_nametoindex(libtrace->uridata);
312                if (addr.sll_ifindex == 0) {
313                        linuxcommon_close_input_stream(libtrace, stream);
314                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
315                                      "Failed to find interface %s",
316                                      libtrace->uridata);
317                        return -1;
318                }
319        } else {
320                addr.sll_ifindex = 0;
321        }
322        if (bind(stream->fd,
323                 (struct sockaddr*)&addr,
324                 (socklen_t)sizeof(addr))==-1) {
325                linuxcommon_close_input_stream(libtrace, stream);
326                trace_set_err(libtrace, errno,
327                              "Failed to bind to interface %s",
328                              libtrace->uridata);
329                return -1;
330        }
331
332        /* If promisc hasn't been specified, set it to "true" if we're
333         * capturing on one interface, or "false" if we're capturing on
334         * all interfaces.
335         */
336        if (FORMAT_DATA->promisc==-1) {
337                if (addr.sll_ifindex!=0)
338                        FORMAT_DATA->promisc=1;
339                else
340                        FORMAT_DATA->promisc=0;
341        }
342
343        /* Enable promiscuous mode, if requested */
344        if (FORMAT_DATA->promisc) {
345                struct packet_mreq mreq;
346                socklen_t socklen = sizeof(mreq);
347                memset(&mreq,0,sizeof(mreq));
348                mreq.mr_ifindex = addr.sll_ifindex;
349                mreq.mr_type = PACKET_MR_PROMISC;
350                if (setsockopt(stream->fd,
351                               SOL_PACKET,
352                               PACKET_ADD_MEMBERSHIP,
353                               &mreq,
354                               socklen)==-1) {
355                        perror("setsockopt(PROMISC)");
356                }
357        }
358
359        /* Set the timestamp option on the socket - aim for the most detailed
360         * clock resolution possible */
361#ifdef SO_TIMESTAMPNS
362        if (setsockopt(stream->fd,
363                       SOL_SOCKET,
364                       SO_TIMESTAMPNS,
365                       &one,
366                       (socklen_t)sizeof(one))!=-1) {
367                FORMAT_DATA->timestamptype = TS_TIMESPEC;
368        }
369        else
370        /* DANGER: This is a dangling else to only do the next setsockopt()
371         * if we fail the first! */
372#endif
373                if (setsockopt(stream->fd,
374                               SOL_SOCKET,
375                               SO_TIMESTAMP,
376                               &one,
377                               (socklen_t)sizeof(one))!=-1) {
378                        FORMAT_DATA->timestamptype = TS_TIMEVAL;
379                }
380                else
381                        FORMAT_DATA->timestamptype = TS_NONE;
382
383        /* Push BPF filter into the kernel. At this stage we can safely assume
384         * that the filterstring has been compiled, or the filter was supplied
385         * pre-compiled.
386         */
387        if (filter != NULL) {
388                /* Check if the filter was successfully compiled. If not,
389                 * it is probably a bad filter and we should return an error
390                 * before the caller tries to read any packets */
391                if (filter->flag == 0) {
392                        linuxcommon_close_input_stream(libtrace, stream);
393                        trace_set_err(libtrace, TRACE_ERR_BAD_FILTER,
394                                      "Cannot attach a bad filter to %s",
395                                      libtrace->uridata);
396                        return -1;
397                }
398
399                if (setsockopt(stream->fd,
400                               SOL_SOCKET,
401                               SO_ATTACH_FILTER,
402                               &filter->filter,
403                               sizeof(filter->filter)) == -1) {
404                        perror("setsockopt(SO_ATTACH_FILTER)");
405                }
406        }
407
408        /* Consume any buffered packets that were received before the socket
409         * was properly setup, including those which missed the filter and
410         * bind()ing to an interface.
411         *
412         * If packet rate is high this could therotically hang forever. 4K
413         * should be a large enough limit.
414         */
415        int count = 0;
416        void *buf = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
417        while(count < 4096 &&
418                recv(stream->fd,
419                   buf,
420                   (size_t)LIBTRACE_PACKET_BUFSIZE,
421                   MSG_DONTWAIT) != -1) { count++; }
422        free(buf);
423
424        /* Mark that the stats are valid and apply an offset */
425        FORMAT_DATA->stats_valid = 1;
426        /* Offset by number we ate for each stream */
427        FORMAT_DATA->stats.tp_packets -= count;
428
429
430        if (linuxcommon_get_dev_statisitics(libtrace, &FORMAT_DATA->dev_stats) != 0) {
431                /* Mark this as bad */
432                FORMAT_DATA->dev_stats.if_name[0] = 0;
433        }
434
435        return 0;
436}
437
438/**
439 * Converts a socket, either packet_mmap or standard raw socket into a
440 * fanout socket.
441 * NOTE: This means we can read from the socket with multiple queues,
442 * each must be setup (identically) and then this called upon them
443 *
444 * @return 0 success, -1 error
445 */
446inline int linuxcommon_to_packet_fanout(libtrace_t *libtrace,
447                                        struct linux_per_stream_t *stream)
448{
449        int fanout_opt = ((int)FORMAT_DATA->fanout_flags << 16) |
450                         (int)FORMAT_DATA->fanout_group;
451        if (setsockopt(stream->fd, SOL_PACKET, PACKET_FANOUT,
452                        &fanout_opt, sizeof(fanout_opt)) == -1) {
453                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
454                              "Converting the fd to a socket fanout failed %s",
455                              libtrace->uridata);
456                return -1;
457        }
458        return 0;
459}
460
461int linuxcommon_pause_input(libtrace_t *libtrace)
462{
463        size_t i;
464
465        /* Stop and detach each stream */
466        for (i = 0; i < libtrace_list_get_size(FORMAT_DATA->per_stream); ++i) {
467                struct linux_per_stream_t *stream;
468                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
469                linuxcommon_close_input_stream(libtrace, stream);
470        }
471
472        return 0;
473}
474
475int linuxcommon_fin_input(libtrace_t *libtrace)
476{
477        if (libtrace->format_data) {
478                if (FORMAT_DATA->filter != NULL)
479                        free(FORMAT_DATA->filter);
480
481                if (FORMAT_DATA->per_stream)
482                        libtrace_list_deinit(FORMAT_DATA->per_stream);
483
484                free(libtrace->format_data);
485        }
486
487        return 0;
488}
489
490int linuxcommon_pregister_thread(libtrace_t *libtrace,
491                                 libtrace_thread_t *t,
492                                 bool reading) {
493        if (reading) {
494                /* XXX TODO remove this oneday make sure hasher thread still works */
495                struct linux_per_stream_t *stream;
496                stream = libtrace_list_get_index(FORMAT_DATA->per_stream,
497                                                 t->perpkt_num)->data;
498                t->format_data = stream;
499                if (!stream) {
500                        /* This should never happen and indicates an
501                         * internal libtrace bug */
502                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
503                                      "Failed to attached thread %d to a stream",
504                                      t->perpkt_num);
505                        return -1;
506                }
507        }
508        return 0;
509}
510
511int linuxcommon_pconfig_input(libtrace_t *libtrace,
512                              trace_parallel_option_t option,
513                              void *data)
514{
515        switch(option) {
516                case TRACE_OPTION_SET_HASHER:
517                        switch (*((enum hasher_types *)data)) {
518                                case HASHER_BALANCE:
519                                        // Do fanout
520                                        FORMAT_DATA->fanout_flags = PACKET_FANOUT_LB;
521                                        // Or we could balance to the CPU
522                                        return 0;
523                                case HASHER_BIDIRECTIONAL:
524                                case HASHER_UNIDIRECTIONAL:
525                                        FORMAT_DATA->fanout_flags = PACKET_FANOUT_HASH;
526                                        return 0;
527                                case HASHER_CUSTOM:
528                                case HASHER_HARDWARE:
529                                        return -1;
530                        }
531                        break;
532                /* Avoid default: so that future options will cause a warning
533                 * here to remind us to implement it, or flag it as
534                 * unimplementable
535                 */
536        }
537
538        /* Don't set an error - trace_config will try to deal with the
539         * option and will set an error if it fails */
540        return -1;
541}
542
543/* These counters reset with each read */
544static void linuxcommon_update_socket_statistics(libtrace_t *libtrace) {
545        struct tpacket_stats stats;
546        size_t i;
547        socklen_t len = sizeof(stats);
548
549        for (i = 0; i < libtrace_list_get_size(FORMAT_DATA->per_stream); ++i) {
550                struct linux_per_stream_t *stream;
551                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
552                if (stream->fd != -1) {
553                        if (getsockopt(stream->fd,
554                                   SOL_PACKET,
555                                   PACKET_STATISTICS,
556                                   &stats,
557                                   &len) == 0) {
558                                if (FORMAT_DATA->stats_valid==0) {
559                                        FORMAT_DATA->stats.tp_drops = stats.tp_drops;
560                                        FORMAT_DATA->stats.tp_packets = stats.tp_packets;
561                                        FORMAT_DATA->stats_valid = 1;
562                                } else {
563                                        FORMAT_DATA->stats.tp_drops += stats.tp_drops;
564                                        FORMAT_DATA->stats.tp_packets += stats.tp_packets;
565                                }
566                        } else {
567                                perror("getsockopt PACKET_STATISTICS failed");
568                        }
569                }
570        }
571}
572
573#define DEV_DIFF(x) (dev_stats.x - FORMAT_DATA->dev_stats.x)
574/* Note these statistics come from two different sources, the socket itself and
575 * the linux device. As such this means it is highly likely that their is some
576 * margin of error in the returned statisitics, we perform basic sanitising so
577 * that these are not too noticable.
578 */
579void linuxcommon_get_statistics(libtrace_t *libtrace, libtrace_stat_t *stat) {
580        struct linux_dev_stats dev_stats;
581        if (libtrace->format_data == NULL)
582                return;
583        /* Do we need to consider the case after the trace is closed? */
584        if (FORMAT_DATA_FIRST->fd == -1) {
585                /* This is probably a 'dead' trace so obviously we can't query
586                 * the socket for capture counts, can we? */
587                return;
588        }
589
590        dev_stats.if_name[0] = 0; /* This will be set if we retrive valid stats */
591        /* Do we have starting stats to compare to? */
592        if (FORMAT_DATA->dev_stats.if_name[0] != 0) {
593                linuxcommon_get_dev_statisitics(libtrace, &dev_stats);
594        }
595        linuxcommon_update_socket_statistics(libtrace);
596
597        /* filtered count == dev received - socket received */
598        if (FORMAT_DATA->filter != NULL &&
599            FORMAT_DATA->stats_valid &&
600            dev_stats.if_name[0]) {
601                uint64_t filtered = DEV_DIFF(rx_packets) -
602                                    FORMAT_DATA->stats.tp_packets;
603                /* Check the value is sane, due to timing it could be below 0 */
604                if (filtered < UINT64_MAX - 100000) {
605                        stat->filtered += filtered;
606                }
607        }
608
609        /* dropped count == socket dropped + dev dropped */
610        if (FORMAT_DATA->stats_valid) {
611                stat->dropped_valid = 1;
612                stat->dropped = FORMAT_DATA->stats.tp_drops;
613                if (dev_stats.if_name[0]) {
614                        stat->dropped += DEV_DIFF(rx_drops);
615                }
616        }
617
618        /* received count - All good packets even those dropped or filtered */
619        if (dev_stats.if_name[0]) {
620                stat->received_valid = 1;
621                stat->received = DEV_DIFF(rx_packets) + DEV_DIFF(rx_drops);
622        }
623
624        /* captured count - received and but not dropped */
625        if (dev_stats.if_name[0] && FORMAT_DATA->stats_valid) {
626                stat->captured_valid = 1;
627                stat->captured = DEV_DIFF(rx_packets) - FORMAT_DATA->stats.tp_drops;
628        }
629
630        /* errors */
631        if (dev_stats.if_name[0]) {
632                stat->errors_valid = 1;
633                stat->errors = DEV_DIFF(rx_errors);
634        }
635
636}
637
638int linuxcommon_get_fd(const libtrace_t *libtrace) {
639        if (libtrace->format_data == NULL)
640                return -1;
641        return FORMAT_DATA_FIRST->fd;
642}
643
644int linuxcommon_pstart_input(libtrace_t *libtrace,
645                             int (*start_stream)(libtrace_t *, struct linux_per_stream_t*)) {
646        int i = 0;
647        int tot = libtrace->perpkt_thread_count;
648        int iserror = 0;
649        struct linux_per_stream_t empty_stream = ZERO_LINUX_STREAM;
650
651        printf("Calling native pstart packet\n");
652        for (i = 0; i < tot; ++i)
653        {
654                struct linux_per_stream_t *stream;
655                /* Add storage for another stream */
656                if (libtrace_list_get_size(FORMAT_DATA->per_stream) <= (size_t) i)
657                        libtrace_list_push_back(FORMAT_DATA->per_stream, &empty_stream);
658
659                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
660                if (start_stream(libtrace, stream) != 0) {
661                        iserror = 1;
662                        break;
663                }
664                if (linuxcommon_to_packet_fanout(libtrace, stream) != 0)
665                {
666                        iserror = 1;
667                        close(stream->fd);
668                        stream->fd = -1;
669                        break;
670                }
671        }
672
673        if (iserror) {
674                /* Free those that succeeded */
675                for (i = i - 1; i >= 0; i--) {
676                        struct linux_per_stream_t *stream;
677                        stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
678                        linuxcommon_close_input_stream(libtrace, stream);
679                }
680                libtrace_list_deinit(FORMAT_DATA->per_stream);
681                free(libtrace->format_data);
682                libtrace->format_data = NULL;
683                return -1;
684        }
685
686        return 0;
687}
688
689#else /* HAVE_NETPACKET_PACKET_H */
690
691/* No NETPACKET - So this format is not live */
692void linuxcommon_get_statistics(libtrace_t *libtrace UNUSED,
693                                libtrace_stat_t *stat UNUSED) {
694        return;
695}
696
697#endif /* HAVE_NETPACKET_PACKET_H */
698
699
700inline libtrace_direction_t linuxcommon_get_direction(uint8_t pkttype)
701{
702        switch (pkttype) {
703                case PACKET_OUTGOING:
704                case PACKET_LOOPBACK:
705                        return TRACE_DIR_OUTGOING;
706                case PACKET_OTHERHOST:
707                        return TRACE_DIR_OTHER;
708                default:
709                        return TRACE_DIR_INCOMING;
710        }
711}
712
713inline libtrace_direction_t
714linuxcommon_set_direction(struct sockaddr_ll * skadr,
715                          libtrace_direction_t direction)
716{
717        switch (direction) {
718                case TRACE_DIR_OUTGOING:
719                        skadr->sll_pkttype = PACKET_OUTGOING;
720                        return TRACE_DIR_OUTGOING;
721                case TRACE_DIR_INCOMING:
722                        skadr->sll_pkttype = PACKET_HOST;
723                        return TRACE_DIR_INCOMING;
724                case TRACE_DIR_OTHER:
725                        skadr->sll_pkttype = PACKET_OTHERHOST;
726                        return TRACE_DIR_OTHER;
727                default:
728                        return -1;
729        }
730}
731
732inline libtrace_linktype_t linuxcommon_get_link_type(uint16_t linktype)
733{
734        /* Convert the ARPHRD type into an appropriate libtrace link type */
735        switch (linktype) {
736                case LIBTRACE_ARPHRD_ETHER:
737                case LIBTRACE_ARPHRD_LOOPBACK:
738                        return TRACE_TYPE_ETH;
739                case LIBTRACE_ARPHRD_PPP:
740                        return TRACE_TYPE_NONE;
741                case LIBTRACE_ARPHRD_IEEE80211_RADIOTAP:
742                        return TRACE_TYPE_80211_RADIO;
743                case LIBTRACE_ARPHRD_IEEE80211:
744                        return TRACE_TYPE_80211;
745                case LIBTRACE_ARPHRD_SIT:
746                case LIBTRACE_ARPHRD_NONE:
747                        return TRACE_TYPE_NONE;
748                default: /* shrug, beyond me! */
749                        printf("unknown Linux ARPHRD type 0x%04x\n",linktype);
750                        return (libtrace_linktype_t)~0U;
751        }
752}
Note: See TracBrowser for help on using the repository browser.