source: lib/format_linux_common.c @ ed6304c5

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

For linux formats int/ring also use dev stats from /proc/net/dev to report
dropped packets.

This accounts for packets that dont even reach the kernel. The drop count
now matches 100% with sent packets.

There could be some slight discrepancies caused packets received between
opening/closing the socket and when we make our call to /proc/net/dev.
However this is a lot more realistic than previous numbers.

We might also be able to caclulate filtered packets from these numbers.

  • Property mode set to 100644
File size: 20.8 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->max_order = MAX_ORDER;
189        FORMAT_DATA->fanout_flags = PACKET_FANOUT_LB;
190        /* Some examples use pid for the group however that would limit a single
191         * application to use only int/ring format, instead using rand */
192        FORMAT_DATA->fanout_group = (uint16_t) rand();
193        return 0;
194}
195
196int linuxcommon_init_output(libtrace_out_t *libtrace)
197{
198        libtrace->format_data = (struct linux_format_data_out_t*)
199                malloc(sizeof(struct linux_format_data_out_t));
200        assert(libtrace->format_data != NULL);
201
202        FORMAT_DATA_OUT->fd = -1;
203        FORMAT_DATA_OUT->tx_ring = NULL;
204        FORMAT_DATA_OUT->txring_offset = 0;
205        FORMAT_DATA_OUT->queue = 0;
206        FORMAT_DATA_OUT->max_order = MAX_ORDER;
207        return 0;
208}
209
210/* Close an input stream, this is safe to be called part way through
211 * initilisation as a cleanup function assuming streams were set to
212 * ZERO_LINUX_STREAM to begin with.
213 *
214 * This works correctly with both int and ring
215 */
216void linuxcommon_close_input_stream(libtrace_t *libtrace,
217                                    struct linux_per_stream_t *stream) {
218        if (stream->fd != -1)
219                close(stream->fd);
220        stream->fd = -1;
221        /* TODO maybe store size against stream XXX */
222        if (stream->rx_ring != MAP_FAILED)
223                munmap(stream->rx_ring,
224                       FORMAT_DATA->req.tp_block_size *
225                       FORMAT_DATA->req.tp_block_nr);
226        stream->rx_ring = MAP_FAILED;
227        FORMAT_DATA->dev_stats.if_name[0] = 0;
228}
229
230#define REPEAT_16(x) x x x x x x x x x x x x x x x x
231#define xstr(s) str(s)
232#define str(s) #s
233
234/* These don't typically reset however an interface does exist to reset them */
235static int linuxcommon_get_dev_statisitics(libtrace_t *libtrace, struct linux_dev_stats *stats) {
236        FILE *file;
237        char line[1024];
238        struct linux_dev_stats tmp_stats;
239
240        file = fopen("/proc/net/dev","r");
241        if (file == NULL) {
242                return -1;
243        }
244
245        /* Skip 2 header lines */
246        fgets(line, sizeof(line), file);
247        fgets(line, sizeof(line), file);
248
249        while (!(feof(file)||ferror(file))) {
250                int tot;
251                fgets(line, sizeof(line), file);
252                tot = sscanf(line, " %"xstr(IF_NAMESIZE)"[^:]:" REPEAT_16(" %"SCNd64),
253                             tmp_stats.if_name,
254                             &tmp_stats.rx_bytes,
255                             &tmp_stats.rx_bytes,
256                             &tmp_stats.rx_errors,
257                             &tmp_stats.rx_drops,
258                             &tmp_stats.rx_fifo,
259                             &tmp_stats.rx_frame,
260                             &tmp_stats.rx_compressed,
261                             &tmp_stats.rx_multicast,
262                             &tmp_stats.tx_bytes,
263                             &tmp_stats.tx_packets,
264                             &tmp_stats.tx_errors,
265                             &tmp_stats.tx_drops,
266                             &tmp_stats.tx_fifo,
267                             &tmp_stats.tx_colls,
268                             &tmp_stats.tx_carrier,
269                             &tmp_stats.tx_compressed);
270                if (tot != 17)
271                        continue;
272                if (strncmp(tmp_stats.if_name, libtrace->uridata, IF_NAMESIZE) == 0) {
273                        *stats = tmp_stats;
274                        fclose(file);
275                        return 0;
276                }
277        }
278        fclose(file);
279        return -1;
280}
281
282/* Start an input stream
283 * - Opens the file descriptor
284 * - Sets promiscuous correctly
285 * - Sets socket option
286 * - Add BPF filter
287 *
288 * The output is ready for int directly, for ring the conversion to ring still
289 * needs to take place.
290 */
291int linuxcommon_start_input_stream(libtrace_t *libtrace,
292                                   struct linux_per_stream_t *stream)
293{
294        struct sockaddr_ll addr;
295        const int one = 1;
296        memset(&addr,0,sizeof(addr));
297        libtrace_filter_t *filter = FORMAT_DATA->filter;
298
299        /* Create a raw socket for reading packets on */
300        stream->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
301        if (stream->fd==-1) {
302                trace_set_err(libtrace, errno, "Could not create raw socket");
303                return -1;
304        }
305
306        /* Bind to the capture interface */
307        addr.sll_family = AF_PACKET;
308        addr.sll_protocol = htons(ETH_P_ALL);
309        if (strlen(libtrace->uridata)) {
310                addr.sll_ifindex = if_nametoindex(libtrace->uridata);
311                if (addr.sll_ifindex == 0) {
312                        linuxcommon_close_input_stream(libtrace, stream);
313                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
314                                      "Failed to find interface %s",
315                                      libtrace->uridata);
316                        return -1;
317                }
318        } else {
319                addr.sll_ifindex = 0;
320        }
321        if (bind(stream->fd,
322                 (struct sockaddr*)&addr,
323                 (socklen_t)sizeof(addr))==-1) {
324                linuxcommon_close_input_stream(libtrace, stream);
325                trace_set_err(libtrace, errno,
326                              "Failed to bind to interface %s",
327                              libtrace->uridata);
328                return -1;
329        }
330
331        /* If promisc hasn't been specified, set it to "true" if we're
332         * capturing on one interface, or "false" if we're capturing on
333         * all interfaces.
334         */
335        if (FORMAT_DATA->promisc==-1) {
336                if (addr.sll_ifindex!=0)
337                        FORMAT_DATA->promisc=1;
338                else
339                        FORMAT_DATA->promisc=0;
340        }
341
342        /* Enable promiscuous mode, if requested */
343        if (FORMAT_DATA->promisc) {
344                struct packet_mreq mreq;
345                socklen_t socklen = sizeof(mreq);
346                memset(&mreq,0,sizeof(mreq));
347                mreq.mr_ifindex = addr.sll_ifindex;
348                mreq.mr_type = PACKET_MR_PROMISC;
349                if (setsockopt(stream->fd,
350                               SOL_PACKET,
351                               PACKET_ADD_MEMBERSHIP,
352                               &mreq,
353                               socklen)==-1) {
354                        perror("setsockopt(PROMISC)");
355                }
356        }
357
358        /* Set the timestamp option on the socket - aim for the most detailed
359         * clock resolution possible */
360#ifdef SO_TIMESTAMPNS
361        if (setsockopt(stream->fd,
362                       SOL_SOCKET,
363                       SO_TIMESTAMPNS,
364                       &one,
365                       (socklen_t)sizeof(one))!=-1) {
366                FORMAT_DATA->timestamptype = TS_TIMESPEC;
367        }
368        else
369        /* DANGER: This is a dangling else to only do the next setsockopt()
370         * if we fail the first! */
371#endif
372                if (setsockopt(stream->fd,
373                               SOL_SOCKET,
374                               SO_TIMESTAMP,
375                               &one,
376                               (socklen_t)sizeof(one))!=-1) {
377                        FORMAT_DATA->timestamptype = TS_TIMEVAL;
378                }
379                else
380                        FORMAT_DATA->timestamptype = TS_NONE;
381
382        /* Push BPF filter into the kernel. At this stage we can safely assume
383         * that the filterstring has been compiled, or the filter was supplied
384         * pre-compiled.
385         */
386        if (filter != NULL) {
387                /* Check if the filter was successfully compiled. If not,
388                 * it is probably a bad filter and we should return an error
389                 * before the caller tries to read any packets */
390                if (filter->flag == 0) {
391                        linuxcommon_close_input_stream(libtrace, stream);
392                        trace_set_err(libtrace, TRACE_ERR_BAD_FILTER,
393                                      "Cannot attach a bad filter to %s",
394                                      libtrace->uridata);
395                        return -1;
396                }
397
398                if (setsockopt(stream->fd,
399                               SOL_SOCKET,
400                               SO_ATTACH_FILTER,
401                               &filter->filter,
402                               sizeof(filter->filter)) == -1) {
403                        perror("setsockopt(SO_ATTACH_FILTER)");
404                } else {
405                        /* The socket accepted the filter, so we need to
406                         * consume any buffered packets that were received
407                         * between opening the socket and applying the filter.
408                         */
409                        void *buf = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
410                        while(recv(stream->fd,
411                                   buf,
412                                   (size_t)LIBTRACE_PACKET_BUFSIZE,
413                                   MSG_DONTWAIT) != -1) { }
414                        free(buf);
415                }
416        }
417
418        FORMAT_DATA->stats_valid = 0;
419        if (linuxcommon_get_dev_statisitics(libtrace, &FORMAT_DATA->dev_stats) != 0) {
420                /* Mark this as bad */
421                FORMAT_DATA->dev_stats.if_name[0] = 0;
422        }
423
424        return 0;
425}
426
427/**
428 * Converts a socket, either packet_mmap or standard raw socket into a
429 * fanout socket.
430 * NOTE: This means we can read from the socket with multiple queues,
431 * each must be setup (identically) and then this called upon them
432 *
433 * @return 0 success, -1 error
434 */
435inline int linuxcommon_to_packet_fanout(libtrace_t *libtrace,
436                                        struct linux_per_stream_t *stream)
437{
438        int fanout_opt = ((int)FORMAT_DATA->fanout_flags << 16) |
439                         (int)FORMAT_DATA->fanout_group;
440        if (setsockopt(stream->fd, SOL_PACKET, PACKET_FANOUT,
441                        &fanout_opt, sizeof(fanout_opt)) == -1) {
442                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
443                              "Converting the fd to a socket fanout failed %s",
444                              libtrace->uridata);
445                return -1;
446        }
447        return 0;
448}
449
450int linuxcommon_pause_input(libtrace_t *libtrace)
451{
452        size_t i;
453
454        /* Stop and detach each stream */
455        for (i = 0; i < libtrace_list_get_size(FORMAT_DATA->per_stream); ++i) {
456                struct linux_per_stream_t *stream;
457                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
458                linuxcommon_close_input_stream(libtrace, stream);
459        }
460
461        return 0;
462}
463
464int linuxcommon_fin_input(libtrace_t *libtrace)
465{
466        if (libtrace->format_data) {
467                if (FORMAT_DATA->filter != NULL)
468                        free(FORMAT_DATA->filter);
469
470                if (FORMAT_DATA->per_stream)
471                        libtrace_list_deinit(FORMAT_DATA->per_stream);
472
473                free(libtrace->format_data);
474        }
475
476        return 0;
477}
478
479int linuxcommon_pregister_thread(libtrace_t *libtrace,
480                                 libtrace_thread_t *t,
481                                 bool reading) {
482        fprintf(stderr, "registering thread %d!!\n", t->perpkt_num);
483        if (reading) {
484                /* XXX TODO remove this oneday make sure hasher thread still works */
485                struct linux_per_stream_t *stream;
486                stream = libtrace_list_get_index(FORMAT_DATA->per_stream,
487                                                 t->perpkt_num)->data;
488                t->format_data = stream;
489                if (!stream) {
490                        /* This should never happen and indicates an
491                         * internal libtrace bug */
492                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
493                                      "Failed to attached thread %d to a stream",
494                                      t->perpkt_num);
495                        return -1;
496                }
497        }
498        return 0;
499}
500
501int linuxcommon_pconfig_input(libtrace_t *libtrace,
502                              trace_parallel_option_t option,
503                              void *data)
504{
505        switch(option) {
506                case TRACE_OPTION_SET_HASHER:
507                        switch (*((enum hasher_types *)data)) {
508                                case HASHER_BALANCE:
509                                        // Do fanout
510                                        FORMAT_DATA->fanout_flags = PACKET_FANOUT_LB;
511                                        // Or we could balance to the CPU
512                                        return 0;
513                                case HASHER_BIDIRECTIONAL:
514                                case HASHER_UNIDIRECTIONAL:
515                                        FORMAT_DATA->fanout_flags = PACKET_FANOUT_HASH;
516                                        return 0;
517                                case HASHER_CUSTOM:
518                                case HASHER_HARDWARE:
519                                        return -1;
520                        }
521                        break;
522                /* Avoid default: so that future options will cause a warning
523                 * here to remind us to implement it, or flag it as
524                 * unimplementable
525                 */
526        }
527
528        /* Don't set an error - trace_config will try to deal with the
529         * option and will set an error if it fails */
530        return -1;
531}
532
533/* These counters reset with each read */
534static void linuxcommon_update_socket_statistics(libtrace_t *libtrace) {
535        struct tpacket_stats stats;
536        size_t i;
537        socklen_t len = sizeof(stats);
538
539        for (i = 0; i < libtrace_list_get_size(FORMAT_DATA->per_stream); ++i) {
540                struct linux_per_stream_t *stream;
541                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
542                if (stream->fd != -1) {
543                        if (getsockopt(stream->fd,
544                                   SOL_PACKET,
545                                   PACKET_STATISTICS,
546                                   &stats,
547                                   &len) == 0) {
548                                if (FORMAT_DATA->stats_valid==0) {
549                                        FORMAT_DATA->stats.tp_drops = stats.tp_drops;
550                                        FORMAT_DATA->stats.tp_packets = stats.tp_packets;
551                                        FORMAT_DATA->stats_valid = 1;
552                                } else {
553                                        FORMAT_DATA->stats.tp_drops += stats.tp_drops;
554                                        FORMAT_DATA->stats.tp_packets += stats.tp_packets;
555                                }
556                        } else {
557                                perror("getsockopt PACKET_STATISTICS failed");
558                        }
559                }
560        }
561}
562
563/* Number of packets that passed filtering */
564uint64_t linuxcommon_get_captured_packets(libtrace_t *libtrace) {
565        if (libtrace->format_data == NULL)
566                return UINT64_MAX;
567        if (FORMAT_DATA_FIRST->fd == -1) {
568                /* This is probably a 'dead' trace so obviously we can't query
569                 * the socket for capture counts, can we? */
570                return UINT64_MAX;
571        }
572        linuxcommon_update_socket_statistics(libtrace);
573        if (FORMAT_DATA->stats_valid)
574                return FORMAT_DATA->stats.tp_packets;
575        else
576                return UINT64_MAX;
577}
578
579/* Number of packets that got past filtering and were then dropped because
580 * of lack of space.
581 *
582 * We could also try read from /sys/class/net/ethX/statistics/ to get
583 * real drop counters and stuff.
584 */
585uint64_t linuxcommon_get_dropped_packets(libtrace_t *libtrace) {
586        struct linux_dev_stats dev_stats;
587        uint64_t adjustment = 0;
588        if (libtrace->format_data == NULL)
589                return UINT64_MAX;
590        if (FORMAT_DATA_FIRST->fd == -1) {
591                /* This is probably a 'dead' trace so obviously we can't query
592                 * the socket for drop counts, can we? */
593                return UINT64_MAX;
594        }
595        // Do we have starting stats to compare to?
596        if (FORMAT_DATA->dev_stats.if_name[0] != 0) {
597                if (linuxcommon_get_dev_statisitics(libtrace, &dev_stats) == 0) {
598                        adjustment = dev_stats.rx_drops - FORMAT_DATA->dev_stats.rx_drops;
599                }
600        }
601        linuxcommon_update_socket_statistics(libtrace);
602        if (FORMAT_DATA->stats_valid)
603                return FORMAT_DATA->stats.tp_drops + adjustment;
604        else
605                return UINT64_MAX;
606}
607
608/* Linux doesn't keep track how many packets were seen before filtering
609 * so we can't tell how many packets were filtered.  Bugger.  So annoying.
610 *
611 * Since we tell libtrace that we do support filtering, if we don't declare
612 * this here as failing, libtrace will happily report for us that it didn't
613 * filter any packets, so don't lie -- return that we don't know.
614 */
615uint64_t linuxcommon_get_filtered_packets(libtrace_t *trace UNUSED) {
616        return UINT64_MAX;
617}
618
619int linuxcommon_get_fd(const libtrace_t *libtrace) {
620        if (libtrace->format_data == NULL)
621                return -1;
622        return FORMAT_DATA_FIRST->fd;
623}
624
625int linuxcommon_pstart_input(libtrace_t *libtrace,
626                             int (*start_stream)(libtrace_t *, struct linux_per_stream_t*)) {
627        int i = 0;
628        int tot = libtrace->perpkt_thread_count;
629        int iserror = 0;
630        struct linux_per_stream_t empty_stream = ZERO_LINUX_STREAM;
631
632        printf("Calling native pstart packet\n");
633        for (i = 0; i < tot; ++i)
634        {
635                struct linux_per_stream_t *stream;
636                /* Add storage for another stream */
637                if (libtrace_list_get_size(FORMAT_DATA->per_stream) <= (size_t) i)
638                        libtrace_list_push_back(FORMAT_DATA->per_stream, &empty_stream);
639
640                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
641                if (start_stream(libtrace, stream) != 0) {
642                        iserror = 1;
643                        break;
644                }
645                if (linuxcommon_to_packet_fanout(libtrace, stream) != 0)
646                {
647                        iserror = 1;
648                        close(stream->fd);
649                        stream->fd = -1;
650                        break;
651                }
652        }
653
654        if (iserror) {
655                /* Free those that succeeded */
656                for (i = i - 1; i >= 0; i--) {
657                        struct linux_per_stream_t *stream;
658                        stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
659                        linuxcommon_close_input_stream(libtrace, stream);
660                }
661                libtrace_list_deinit(FORMAT_DATA->per_stream);
662                free(libtrace->format_data);
663                libtrace->format_data = NULL;
664                return -1;
665        }
666
667        return 0;
668}
669
670#else /* HAVE_NETPACKET_PACKET_H */
671
672/* No NETPACKET - So this format is not live */
673uint64_t linuxcommon_get_filtered_packets(libtrace_t *trace UNUSED) {
674        return UINT64_MAX;
675}
676
677uint64_t linuxcommon_get_captured_packets(libtrace_t *trace UNUSED) {
678        return UINT64_MAX;
679}
680
681uint64_t linuxcommon_get_dropped_packets(libtrace_t *trace UNUSED) {
682        return UINT64_MAX;
683}
684
685#endif /* HAVE_NETPACKET_PACKET_H */
686
687
688inline libtrace_direction_t linuxcommon_get_direction(uint8_t pkttype)
689{
690        switch (pkttype) {
691                case PACKET_OUTGOING:
692                case PACKET_LOOPBACK:
693                        return TRACE_DIR_OUTGOING;
694                case PACKET_OTHERHOST:
695                        return TRACE_DIR_OTHER;
696                default:
697                        return TRACE_DIR_INCOMING;
698        }
699}
700
701inline libtrace_direction_t
702linuxcommon_set_direction(struct sockaddr_ll * skadr,
703                          libtrace_direction_t direction)
704{
705        switch (direction) {
706                case TRACE_DIR_OUTGOING:
707                        skadr->sll_pkttype = PACKET_OUTGOING;
708                        return TRACE_DIR_OUTGOING;
709                case TRACE_DIR_INCOMING:
710                        skadr->sll_pkttype = PACKET_HOST;
711                        return TRACE_DIR_INCOMING;
712                case TRACE_DIR_OTHER:
713                        skadr->sll_pkttype = PACKET_OTHERHOST;
714                        return TRACE_DIR_OTHER;
715                default:
716                        return -1;
717        }
718}
719
720inline libtrace_linktype_t linuxcommon_get_link_type(uint16_t linktype)
721{
722        /* Convert the ARPHRD type into an appropriate libtrace link type */
723        switch (linktype) {
724                case LIBTRACE_ARPHRD_ETHER:
725                case LIBTRACE_ARPHRD_LOOPBACK:
726                        return TRACE_TYPE_ETH;
727                case LIBTRACE_ARPHRD_PPP:
728                        return TRACE_TYPE_NONE;
729                case LIBTRACE_ARPHRD_IEEE80211_RADIOTAP:
730                        return TRACE_TYPE_80211_RADIO;
731                case LIBTRACE_ARPHRD_IEEE80211:
732                        return TRACE_TYPE_80211;
733                case LIBTRACE_ARPHRD_SIT:
734                case LIBTRACE_ARPHRD_NONE:
735                        return TRACE_TYPE_NONE;
736                default: /* shrug, beyond me! */
737                        printf("unknown Linux ARPHRD type 0x%04x\n",linktype);
738                        return (libtrace_linktype_t)~0U;
739        }
740}
Note: See TracBrowser for help on using the repository browser.