source: lib/format_linux_common.c @ a978dec

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

Fix bugs with resuming int/ring formats

Fix int/ring reset statistics on resume.
Fix ring was not zeroing the offset before restarting.

  • 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        stream->rxring_offset = 0;
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
425        /* Mark that the stats are valid and apply an offset */
426        FORMAT_DATA->stats_valid = 1;
427        /* Offset by number we ate for each stream and reset stats after pause */
428        FORMAT_DATA->stats.tp_packets = -count;
429        FORMAT_DATA->stats.tp_drops = 0;
430
431        if (linuxcommon_get_dev_statisitics(libtrace, &FORMAT_DATA->dev_stats) != 0) {
432                /* Mark this as bad */
433                FORMAT_DATA->dev_stats.if_name[0] = 0;
434        }
435
436        return 0;
437}
438
439/**
440 * Converts a socket, either packet_mmap or standard raw socket into a
441 * fanout socket.
442 * NOTE: This means we can read from the socket with multiple queues,
443 * each must be setup (identically) and then this called upon them
444 *
445 * @return 0 success, -1 error
446 */
447inline int linuxcommon_to_packet_fanout(libtrace_t *libtrace,
448                                        struct linux_per_stream_t *stream)
449{
450        int fanout_opt = ((int)FORMAT_DATA->fanout_flags << 16) |
451                         (int)FORMAT_DATA->fanout_group;
452        if (setsockopt(stream->fd, SOL_PACKET, PACKET_FANOUT,
453                        &fanout_opt, sizeof(fanout_opt)) == -1) {
454                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
455                              "Converting the fd to a socket fanout failed %s",
456                              libtrace->uridata);
457                return -1;
458        }
459        return 0;
460}
461
462int linuxcommon_pause_input(libtrace_t *libtrace)
463{
464        size_t i;
465
466        /* Stop and detach each stream */
467        for (i = 0; i < libtrace_list_get_size(FORMAT_DATA->per_stream); ++i) {
468                struct linux_per_stream_t *stream;
469                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
470                linuxcommon_close_input_stream(libtrace, stream);
471        }
472
473        return 0;
474}
475
476int linuxcommon_fin_input(libtrace_t *libtrace)
477{
478        if (libtrace->format_data) {
479                if (FORMAT_DATA->filter != NULL)
480                        free(FORMAT_DATA->filter);
481
482                if (FORMAT_DATA->per_stream)
483                        libtrace_list_deinit(FORMAT_DATA->per_stream);
484
485                free(libtrace->format_data);
486        }
487
488        return 0;
489}
490
491int linuxcommon_pregister_thread(libtrace_t *libtrace,
492                                 libtrace_thread_t *t,
493                                 bool reading) {
494        if (reading) {
495                /* XXX TODO remove this oneday make sure hasher thread still works */
496                struct linux_per_stream_t *stream;
497                stream = libtrace_list_get_index(FORMAT_DATA->per_stream,
498                                                 t->perpkt_num)->data;
499                t->format_data = stream;
500                if (!stream) {
501                        /* This should never happen and indicates an
502                         * internal libtrace bug */
503                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
504                                      "Failed to attached thread %d to a stream",
505                                      t->perpkt_num);
506                        return -1;
507                }
508        }
509        return 0;
510}
511
512int linuxcommon_pconfig_input(libtrace_t *libtrace,
513                              trace_parallel_option_t option,
514                              void *data)
515{
516        switch(option) {
517                case TRACE_OPTION_SET_HASHER:
518                        switch (*((enum hasher_types *)data)) {
519                                case HASHER_BALANCE:
520                                        // Do fanout
521                                        FORMAT_DATA->fanout_flags = PACKET_FANOUT_LB;
522                                        // Or we could balance to the CPU
523                                        return 0;
524                                case HASHER_BIDIRECTIONAL:
525                                case HASHER_UNIDIRECTIONAL:
526                                        FORMAT_DATA->fanout_flags = PACKET_FANOUT_HASH;
527                                        return 0;
528                                case HASHER_CUSTOM:
529                                case HASHER_HARDWARE:
530                                        return -1;
531                        }
532                        break;
533                /* Avoid default: so that future options will cause a warning
534                 * here to remind us to implement it, or flag it as
535                 * unimplementable
536                 */
537        }
538
539        /* Don't set an error - trace_config will try to deal with the
540         * option and will set an error if it fails */
541        return -1;
542}
543
544/* These counters reset with each read */
545static void linuxcommon_update_socket_statistics(libtrace_t *libtrace) {
546        struct tpacket_stats stats;
547        size_t i;
548        socklen_t len = sizeof(stats);
549
550        for (i = 0; i < libtrace_list_get_size(FORMAT_DATA->per_stream); ++i) {
551                struct linux_per_stream_t *stream;
552                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
553                if (stream->fd != -1) {
554                        if (getsockopt(stream->fd,
555                                   SOL_PACKET,
556                                   PACKET_STATISTICS,
557                                   &stats,
558                                   &len) == 0) {
559                                if (FORMAT_DATA->stats_valid==0) {
560                                        FORMAT_DATA->stats.tp_drops = stats.tp_drops;
561                                        FORMAT_DATA->stats.tp_packets = stats.tp_packets;
562                                        FORMAT_DATA->stats_valid = 1;
563                                } else {
564                                        FORMAT_DATA->stats.tp_drops += stats.tp_drops;
565                                        FORMAT_DATA->stats.tp_packets += stats.tp_packets;
566                                }
567                        } else {
568                                perror("getsockopt PACKET_STATISTICS failed");
569                        }
570                }
571        }
572}
573
574#define DEV_DIFF(x) (dev_stats.x - FORMAT_DATA->dev_stats.x)
575/* Note these statistics come from two different sources, the socket itself and
576 * the linux device. As such this means it is highly likely that their is some
577 * margin of error in the returned statisitics, we perform basic sanitising so
578 * that these are not too noticable.
579 */
580void linuxcommon_get_statistics(libtrace_t *libtrace, libtrace_stat_t *stat) {
581        struct linux_dev_stats dev_stats;
582        if (libtrace->format_data == NULL)
583                return;
584        /* Do we need to consider the case after the trace is closed? */
585        if (FORMAT_DATA_FIRST->fd == -1) {
586                /* This is probably a 'dead' trace so obviously we can't query
587                 * the socket for capture counts, can we? */
588                return;
589        }
590
591        dev_stats.if_name[0] = 0; /* This will be set if we retrive valid stats */
592        /* Do we have starting stats to compare to? */
593        if (FORMAT_DATA->dev_stats.if_name[0] != 0) {
594                linuxcommon_get_dev_statisitics(libtrace, &dev_stats);
595        }
596        linuxcommon_update_socket_statistics(libtrace);
597
598        /* filtered count == dev received - socket received */
599        if (FORMAT_DATA->filter != NULL &&
600            FORMAT_DATA->stats_valid &&
601            dev_stats.if_name[0]) {
602                uint64_t filtered = DEV_DIFF(rx_packets) -
603                                    FORMAT_DATA->stats.tp_packets;
604                /* Check the value is sane, due to timing it could be below 0 */
605                if (filtered < UINT64_MAX - 100000) {
606                        stat->filtered += filtered;
607                }
608        }
609
610        /* dropped count == socket dropped + dev dropped */
611        if (FORMAT_DATA->stats_valid) {
612                stat->dropped_valid = 1;
613                stat->dropped = FORMAT_DATA->stats.tp_drops;
614                if (dev_stats.if_name[0]) {
615                        stat->dropped += DEV_DIFF(rx_drops);
616                }
617        }
618
619        /* received count - All good packets even those dropped or filtered */
620        if (dev_stats.if_name[0]) {
621                stat->received_valid = 1;
622                stat->received = DEV_DIFF(rx_packets) + DEV_DIFF(rx_drops);
623        }
624
625        /* captured count - received and but not dropped */
626        if (dev_stats.if_name[0] && FORMAT_DATA->stats_valid) {
627                stat->captured_valid = 1;
628                stat->captured = DEV_DIFF(rx_packets) - FORMAT_DATA->stats.tp_drops;
629        }
630
631        /* errors */
632        if (dev_stats.if_name[0]) {
633                stat->errors_valid = 1;
634                stat->errors = DEV_DIFF(rx_errors);
635        }
636
637}
638
639int linuxcommon_get_fd(const libtrace_t *libtrace) {
640        if (libtrace->format_data == NULL)
641                return -1;
642        return FORMAT_DATA_FIRST->fd;
643}
644
645int linuxcommon_pstart_input(libtrace_t *libtrace,
646                             int (*start_stream)(libtrace_t *, struct linux_per_stream_t*)) {
647        int i = 0;
648        int tot = libtrace->perpkt_thread_count;
649        int iserror = 0;
650        struct linux_per_stream_t empty_stream = ZERO_LINUX_STREAM;
651
652        printf("Calling native pstart packet\n");
653        for (i = 0; i < tot; ++i)
654        {
655                struct linux_per_stream_t *stream;
656                /* Add storage for another stream */
657                if (libtrace_list_get_size(FORMAT_DATA->per_stream) <= (size_t) i)
658                        libtrace_list_push_back(FORMAT_DATA->per_stream, &empty_stream);
659
660                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
661                if (start_stream(libtrace, stream) != 0) {
662                        iserror = 1;
663                        break;
664                }
665                if (linuxcommon_to_packet_fanout(libtrace, stream) != 0)
666                {
667                        iserror = 1;
668                        close(stream->fd);
669                        stream->fd = -1;
670                        break;
671                }
672        }
673
674        if (iserror) {
675                /* Free those that succeeded */
676                for (i = i - 1; i >= 0; i--) {
677                        struct linux_per_stream_t *stream;
678                        stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
679                        linuxcommon_close_input_stream(libtrace, stream);
680                }
681                libtrace_list_deinit(FORMAT_DATA->per_stream);
682                free(libtrace->format_data);
683                libtrace->format_data = NULL;
684                return -1;
685        }
686
687        return 0;
688}
689
690#else /* HAVE_NETPACKET_PACKET_H */
691
692/* No NETPACKET - So this format is not live */
693void linuxcommon_get_statistics(libtrace_t *libtrace UNUSED,
694                                libtrace_stat_t *stat UNUSED) {
695        return;
696}
697
698#endif /* HAVE_NETPACKET_PACKET_H */
699
700
701inline libtrace_direction_t linuxcommon_get_direction(uint8_t pkttype)
702{
703        switch (pkttype) {
704                case PACKET_OUTGOING:
705                case PACKET_LOOPBACK:
706                        return TRACE_DIR_OUTGOING;
707                case PACKET_OTHERHOST:
708                        return TRACE_DIR_OTHER;
709                default:
710                        return TRACE_DIR_INCOMING;
711        }
712}
713
714inline libtrace_direction_t
715linuxcommon_set_direction(struct sockaddr_ll * skadr,
716                          libtrace_direction_t direction)
717{
718        switch (direction) {
719                case TRACE_DIR_OUTGOING:
720                        skadr->sll_pkttype = PACKET_OUTGOING;
721                        return TRACE_DIR_OUTGOING;
722                case TRACE_DIR_INCOMING:
723                        skadr->sll_pkttype = PACKET_HOST;
724                        return TRACE_DIR_INCOMING;
725                case TRACE_DIR_OTHER:
726                        skadr->sll_pkttype = PACKET_OTHERHOST;
727                        return TRACE_DIR_OTHER;
728                default:
729                        return -1;
730        }
731}
732
733inline libtrace_linktype_t linuxcommon_get_link_type(uint16_t linktype)
734{
735        /* Convert the ARPHRD type into an appropriate libtrace link type */
736        switch (linktype) {
737                case LIBTRACE_ARPHRD_ETHER:
738                case LIBTRACE_ARPHRD_LOOPBACK:
739                        return TRACE_TYPE_ETH;
740                case LIBTRACE_ARPHRD_PPP:
741                        return TRACE_TYPE_NONE;
742                case LIBTRACE_ARPHRD_IEEE80211_RADIOTAP:
743                        return TRACE_TYPE_80211_RADIO;
744                case LIBTRACE_ARPHRD_IEEE80211:
745                        return TRACE_TYPE_80211;
746                case LIBTRACE_ARPHRD_SIT:
747                case LIBTRACE_ARPHRD_NONE:
748                        return TRACE_TYPE_NONE;
749                default: /* shrug, beyond me! */
750                        printf("unknown Linux ARPHRD type 0x%04x\n",linktype);
751                        return (libtrace_linktype_t)~0U;
752        }
753}
Note: See TracBrowser for help on using the repository browser.