source: lib/format_linux_common.c @ 6cf3ca0

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

Gets the ring format back to a working state, the bulk of the refactoring
is now done.

I've opted to remove the inheritance way of grabbing shared functions
and replaced it with a file containing the common functions. Hopefully
this is more obvious that both int and ring depend on these.

I've also reworked the formats to be stream orientated, which removed
duplicates of heaps of functions. And allows the parallel and single
thread code to be almost identical.

After doing this many of the places where we had differences in
functions between ring and int disappeared.

I've also upped the MAX_ORDER to 11, used in allocating memory
from the kernel for the ring format.
Since this seems to work on the testing machines.
And we'll continue to fallback to smaller values if needed anyway.

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