source: lib/format_linux_common.c @ 5ab626a

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

Deprecate trace_get_filtered/accepted/recevied/dropped() in favour of a single function

Adds the single trace_get_statistics function. This allows the structure to be filled
at a point in time, rather than making multiple calls to the library during which state
might have changed.

This has been designed such that the structure can be added to in the future without
breaking old code.

The old internal get_captured_packets was removed from the formats as it was never used.
Eventually we should completely remove get_filtered and received from the formats and replace
them with get_statistics.

In additon some extra fields have added, such as error and captured and the pre-existing
fields are better defined.

The linux formats have been updated to use this new API, which combined with reading
/proc/net/dev returns a full set of statistics.

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