source: lib/format_linux_common.h @ ac6ac7f

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

Various fixes to the linux format to support compiling on BSD

  • Property mode set to 100644
File size: 11.9 KB
Line 
1/* Various definitions required for the linux format. They were moved here,
2 * because format_linux.c had a lot of header information before the actual
3 * code. The linux headers have been copied into here rather than included to
4 * support RT on machines that don't have the linux headers (like a mac for
5 * example.
6 */
7
8#ifndef FORMAT_LINUX_COMMON_H
9#define FORMAT_LINUX_COMMON_H
10
11#include "libtrace.h"
12#include "libtrace_int.h"
13
14#ifdef HAVE_NETPACKET_PACKET_H
15
16#include <sys/socket.h>
17#include <netpacket/packet.h>
18#include <net/ethernet.h>
19#include <net/if_arp.h>
20
21#include <net/if.h>
22#include <sys/ioctl.h>
23#include <poll.h>
24#include <sys/mman.h>
25
26#include <fcntl.h>
27
28/* MAX_ORDER is defined in linux/mmzone.h. 11 is default for 3.0 kernels.
29 * max_order will be decreased by one if the ring buffer fails to allocate.
30 * Used to get the correct sized buffers from the kernel.
31 */
32#define MAX_ORDER 11
33/* Number of frames in the ring used by both TX and TR rings. More frames
34 * hopefully means less packet loss, especially if traffic comes in bursts.
35 */
36#define CONF_RING_FRAMES        0x100
37
38/* The maximum frames allowed to be waiting in the TX_RING before the kernel is
39 * notified to write them out. Make sure this is less than CONF_RING_FRAMES.
40 * Performance doesn't seem to increase any more when setting this above 10.
41 */
42#define TX_MAX_QUEUE            10
43
44#else   /* HAVE_NETPACKET_PACKET_H */
45
46/* Need to know what a sockaddr_ll looks like */
47struct sockaddr_ll {
48        uint16_t sll_family;
49        uint16_t sll_protocol;
50        int32_t  sll_ifindex;
51        uint16_t sll_hatype;
52        uint8_t  sll_pkttype;
53        uint8_t  sll_halen;
54        uint8_t  sll_addr[8];
55};
56
57/* Packet types.  */
58#define PACKET_HOST             0               /* To us.  */
59#define PACKET_BROADCAST        1               /* To all.  */
60#define PACKET_MULTICAST        2               /* To group.  */
61#define PACKET_OTHERHOST        3               /* To someone else.  */
62#define PACKET_OUTGOING         4               /* Originated by us . */
63#define PACKET_LOOPBACK         5
64#define PACKET_FASTROUTE        6
65
66/* Packet socket options.  */
67
68#define PACKET_ADD_MEMBERSHIP           1
69#define PACKET_DROP_MEMBERSHIP          2
70#define PACKET_RECV_OUTPUT              3
71#define PACKET_RX_RING                  5
72#define PACKET_STATISTICS               6
73
74#endif /* HAVE_NETPACKET_PACKET_H */
75
76struct tpacket_stats {
77        unsigned int tp_packets;
78        unsigned int tp_drops;
79};
80
81typedef enum { TS_NONE, TS_TIMEVAL, TS_TIMESPEC } timestamptype_t;
82
83/* linux/if_packet.h defines. They are here rather than including the header
84 * this means that we can interpret a ring frame on a kernel that doesn't
85 * support the format directly.
86 */
87#define PACKET_RX_RING  5
88#define PACKET_VERSION  10
89#define PACKET_HDRLEN   11
90#define PACKET_TX_RING  13
91#define PACKET_FANOUT   18
92#define TP_STATUS_USER  0x1
93#define TP_STATUS_SEND_REQUEST  0x1
94#define TP_STATUS_AVAILABLE     0x0
95#define TO_TP_HDR2(x)   ((struct tpacket2_hdr *) (x))
96#define TO_TP_HDR3(x)   ((struct tpacket3_hdr *) (x))
97#define TPACKET_ALIGNMENT       16
98#define TPACKET_ALIGN(x)        (((x)+TPACKET_ALIGNMENT-1)&~(TPACKET_ALIGNMENT-1))
99#define TPACKET2_HDRLEN         (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll))
100#define TPACKET3_HDRLEN         (TPACKET_ALIGN(sizeof(struct tpacket3_hdr)) + sizeof(struct sockaddr_ll))
101
102
103/* Since 3.1 kernel we have packet_fanout support */
104// schedule to socket by skb's rxhash - the implementation is bi-directional
105#define PACKET_FANOUT_HASH              0
106// schedule round robin
107#define PACKET_FANOUT_LB                1
108// schedule to the same socket that received the packet
109#define PACKET_FANOUT_CPU               2
110// Something to do with fragmented packets and hashing problems !! TODO figure out if this needs to be on
111#define PACKET_FANOUT_FLAG_DEFRAG       0x8000
112/* Included but unused by libtrace since Linux 3.10 */
113// if one socket if full roll over to the next
114#define PACKET_FANOUT_ROLLOVER          3
115// This flag makes any other system roll over
116#define PACKET_FANOUT_FLAG_ROLLOVER     0x1000
117/* Included but unused by libtrace since Linux 3.12 */
118// schedule random
119#define PACKET_FANOUT_RND               4
120
121
122enum tpacket_versions {
123        TPACKET_V1,
124        TPACKET_V2,
125        TPACKET_V3
126};
127
128struct tpacket2_hdr {
129        /* Frame status - in use by kernel or libtrace etc. */
130        uint32_t        tp_status;
131        /* Wire length */
132        uint32_t        tp_len;
133        /* Captured length */
134        uint32_t        tp_snaplen;
135        /* Offset in bytes from frame start to the mac (link layer) header */
136        uint16_t        tp_mac;
137        /* Offset in bytes from frame start to the net (network layer) header */
138        uint16_t        tp_net;
139        /* Timestamp */
140        uint32_t        tp_sec;
141        uint32_t        tp_nsec;
142        /* Not used VLAN tag control information */
143        uint16_t        tp_vlan_tci;
144        uint16_t        tp_padding;
145};
146
147struct tpacket_hdr_variant1 {
148        uint32_t        tp_rxhash;
149        uint32_t        tp_vlan_tci;
150};
151
152struct tpacket3_hdr {
153        uint32_t                tp_next_offset;
154        uint32_t                tp_sec;
155        uint32_t                tp_nsec;
156        uint32_t                tp_snaplen;
157        uint32_t                tp_len;
158        uint32_t                tp_status;
159        uint16_t                tp_mac;
160        uint16_t                tp_net;
161        /* pkt_hdr variants */
162        union {
163                struct tpacket_hdr_variant1 hv1;
164        };
165};
166
167struct tpacket_req {
168        unsigned int tp_block_size;  /* Minimal size of contiguous block */
169        unsigned int tp_block_nr;    /* Number of blocks */
170        unsigned int tp_frame_size;  /* Size of frame */
171        unsigned int tp_frame_nr;    /* Total number of frames */
172};
173
174#ifndef IF_NAMESIZE
175#define IF_NAMESIZE 16
176#endif
177
178/* A structure we use to hold statistic counters from the network cards
179 * as accessed via the /proc/net/dev
180 */
181struct linux_dev_stats {
182        char if_name[IF_NAMESIZE];
183        uint64_t rx_bytes;
184        uint64_t rx_packets;
185        uint64_t rx_errors;
186        uint64_t rx_drops;
187        uint64_t rx_fifo;
188        uint64_t rx_frame;
189        uint64_t rx_compressed;
190        uint64_t rx_multicast;
191        uint64_t tx_bytes;
192        uint64_t tx_packets;
193        uint64_t tx_errors;
194        uint64_t tx_drops;
195        uint64_t tx_fifo;
196        uint64_t tx_colls;
197        uint64_t tx_carrier;
198        uint64_t tx_compressed;
199};
200
201/* Note that this structure is passed over the wire in rt encapsulation, and
202 * thus we need to be careful with data sizes.  timeval's and timespec's
203 * can also change their size on 32/64 machines.
204 */
205struct linux_format_data_t {
206        /* The snap length for the capture */
207        int snaplen;
208        /* Flag indicating whether the interface should be placed in
209         * promiscuous mode */
210        int promisc;
211        /* The timestamp format used by the capture */
212        timestamptype_t timestamptype;
213        /* A BPF filter that is applied to every captured packet */
214        libtrace_filter_t *filter;
215        /* Statistics for the capture process, e.g. dropped packet counts */
216        struct tpacket_stats stats;
217        /* Statistics for the NIC rather than the socket */
218        struct linux_dev_stats dev_stats;
219        /* Flag indicating whether the statistics are current or not */
220        int stats_valid;
221        /* Used to determine buffer size for the ring buffer */
222        uint32_t max_order;
223        /* Used for the parallel case, fanout is the mode */
224        uint16_t fanout_flags;
225        /* The group lets Linux know which sockets to group together
226         * so we use a random here to try avoid collisions */
227        uint16_t fanout_group;
228        /* When running in parallel mode this is malloc'd with an array
229         * file descriptors from packet fanout will use, here we assume/hope
230         * that every ring can get setup the same */
231        libtrace_list_t *per_stream;
232};
233
234struct linux_format_data_out_t {
235        /* The file descriptor used to write the packets */
236        int fd;
237        /* The tx ring mmap location */
238        char * tx_ring;
239        /* The current frame number within the tx ring */
240        int txring_offset;
241        /* The current ring buffer layout */
242        struct tpacket_req req;
243        /* Our sockaddr structure, here so we can cache the interface number */
244        struct sockaddr_ll sock_hdr;
245        /* The (maximum) number of packets that haven't been written */
246        int queue;
247        /* The format this trace is using linuxring or linuxnative */
248        libtrace_rt_types_t format;
249        /* Used to determine buffer size for the ring buffer */
250        uint32_t max_order;
251};
252
253struct linux_per_stream_t {
254        /* File descriptor for the memory mapped stream */
255        int fd;
256        /* Memory mapped buffer */
257        char *rx_ring;
258        /* Offset within the mapped buffer */
259        int rxring_offset;
260        /* The ring buffer layout */
261        struct tpacket_req req;
262} ALIGN_STRUCT(CACHE_LINE_SIZE);
263
264#define ZERO_LINUX_STREAM {-1, MAP_FAILED, 0, {0}}
265
266
267/* Format header for encapsulating packets captured using linux native */
268struct libtrace_linuxnative_header {
269        /* Timestamp of the packet, as a timeval */
270        struct {
271                uint32_t tv_sec;
272                uint32_t tv_usec;
273        } tv;
274        /* Timestamp of the packet, as a timespec */
275        struct {
276                uint32_t tv_sec;
277                uint32_t tv_nsec;
278        } ts;
279        /* The timestamp format used by the process that captured this packet */
280        uint8_t timestamptype;
281        /* Wire length */
282        uint32_t wirelen;
283        /* Capture length */
284        uint32_t caplen;
285        /* The linux native header itself */
286        struct sockaddr_ll hdr;
287};
288
289/* Helper macros to make addressing data in the above structures easier */
290#define DATA(x) ((struct linux_format_data_t *)x->format_data)
291#define DATA_OUT(x) ((struct linux_format_data_out_t *)x->format_data)
292#define STREAM_DATA(x) ((struct linux_per_stream_t *)x->data)
293
294#define FORMAT_DATA DATA(libtrace)
295#define FORMAT_DATA_OUT DATA_OUT(libtrace)
296
297#define FORMAT_DATA_HEAD FORMAT_DATA->per_stream->head
298#define FORMAT_DATA_FIRST ((struct linux_per_stream_t *)FORMAT_DATA_HEAD->data)
299
300/* Get the sockaddr_ll structure from a frame */
301#define GET_SOCKADDR_HDR(x)  ((struct sockaddr_ll *) (((char *) (x))\
302        + TPACKET_ALIGN(sizeof(struct tpacket2_hdr))))
303
304/* Common functions */
305#ifdef HAVE_NETPACKET_PACKET_H
306int linuxcommon_init_input(libtrace_t *libtrace);
307int linuxcommon_init_output(libtrace_out_t *libtrace);
308int linuxcommon_probe_filename(const char *filename);
309int linuxcommon_config_input(libtrace_t *libtrace, trace_option_t option,
310                             void *data);
311void linuxcommon_close_input_stream(libtrace_t *libtrace,
312                                    struct linux_per_stream_t *stream);
313int linuxcommon_start_input_stream(libtrace_t *libtrace,
314                                   struct linux_per_stream_t *stream);
315inline int linuxcommon_to_packet_fanout(libtrace_t *libtrace,
316                                        struct linux_per_stream_t *stream);
317int linuxcommon_pause_input(libtrace_t *libtrace);
318int linuxcommon_get_fd(const libtrace_t *libtrace);
319int linuxcommon_fin_input(libtrace_t *libtrace);
320int linuxcommon_pregister_thread(libtrace_t *libtrace,
321                                 libtrace_thread_t *t,
322                                 bool reading);
323int linuxcommon_pstart_input(libtrace_t *libtrace,
324                             int (*start_stream)(libtrace_t *, struct linux_per_stream_t*));
325#endif /* HAVE_NETPACKET_PACKET_H */
326
327void linuxcommon_get_statistics(libtrace_t *libtrace, libtrace_stat_t *stat);
328
329static inline libtrace_direction_t linuxcommon_get_direction(uint8_t pkttype)
330{
331        switch (pkttype) {
332                case PACKET_OUTGOING:
333                case PACKET_LOOPBACK:
334                        return TRACE_DIR_OUTGOING;
335                case PACKET_OTHERHOST:
336                        return TRACE_DIR_OTHER;
337                default:
338                        return TRACE_DIR_INCOMING;
339        }
340}
341
342static inline libtrace_direction_t
343linuxcommon_set_direction(struct sockaddr_ll * skadr,
344                          libtrace_direction_t direction)
345{
346        switch (direction) {
347                case TRACE_DIR_OUTGOING:
348                        skadr->sll_pkttype = PACKET_OUTGOING;
349                        return TRACE_DIR_OUTGOING;
350                case TRACE_DIR_INCOMING:
351                        skadr->sll_pkttype = PACKET_HOST;
352                        return TRACE_DIR_INCOMING;
353                case TRACE_DIR_OTHER:
354                        skadr->sll_pkttype = PACKET_OTHERHOST;
355                        return TRACE_DIR_OTHER;
356                default:
357                        return -1;
358        }
359}
360
361static inline libtrace_linktype_t linuxcommon_get_link_type(uint16_t linktype)
362{
363        /* Convert the ARPHRD type into an appropriate libtrace link type */
364        switch (linktype) {
365                case LIBTRACE_ARPHRD_ETHER:
366                case LIBTRACE_ARPHRD_LOOPBACK:
367                        return TRACE_TYPE_ETH;
368                case LIBTRACE_ARPHRD_PPP:
369                        return TRACE_TYPE_NONE;
370                case LIBTRACE_ARPHRD_IEEE80211_RADIOTAP:
371                        return TRACE_TYPE_80211_RADIO;
372                case LIBTRACE_ARPHRD_IEEE80211:
373                        return TRACE_TYPE_80211;
374                case LIBTRACE_ARPHRD_SIT:
375                case LIBTRACE_ARPHRD_NONE:
376                        return TRACE_TYPE_NONE;
377                default: /* shrug, beyond me! */
378                        printf("unknown Linux ARPHRD type 0x%04x\n",linktype);
379                        return (libtrace_linktype_t)~0U;
380        }
381}
382
383#endif /* FORMAT_LINUX_COMMON_H */
Note: See TracBrowser for help on using the repository browser.