netsniff-ng: ring: Fix build if tp_vlan_tpid is not available in kernel header
[netsniff-ng.git] / ring.h
blob56c305dd9d4a9817f2951ad79643d0a9ba1c2ebc
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009, 2010 Daniel Borkmann.
4 * Subject to the GPL, version 2.
5 */
7 #ifndef RING_H
8 #define RING_H
11 * "I love the smell of 10GbE in the morning. Smells like ... victory."
12 * - W. Richard Stevens, "Secret Teachings of the UNIX Environment"
15 #include <stdio.h>
16 #include <stdint.h>
17 #include <linux/if_packet.h>
18 #include <linux/socket.h>
19 #include <linux/sockios.h>
20 #include <sys/ioctl.h>
21 #include <string.h>
22 #include <poll.h>
24 #include "built_in.h"
25 #include "die.h"
26 #include "dev.h"
27 #include "config.h"
29 #ifndef POLLRDNORM
30 # define POLLRDNORM 0x0040
31 #endif
33 union tpacket_uhdr {
34 struct tpacket_hdr *h1;
35 struct tpacket2_hdr *h2;
36 #ifdef HAVE_TPACKET3
37 struct tpacket3_hdr *h3;
38 #endif
39 void *raw;
42 #ifdef HAVE_TPACKET3
43 #define tpacket_uhdr(hdr, member, v3) \
44 ((v3) ? ((hdr).h3)->member : ((hdr).h2)->member)
45 #else
46 #define tpacket_uhdr(hdr, member, v3) \
47 (((hdr).h2)->member)
48 #endif /* HAVE_TPACKET3 */
50 static inline uint16_t tpacket_uhdr_vlan_tci(union tpacket_uhdr *hdr, bool v3)
52 #ifdef HAVE_TPACKET3
53 if (v3)
54 return hdr->h3->hv1.tp_vlan_tci;
55 #endif
56 return 0;
59 static inline uint16_t tpacket_uhdr_vlan_proto(union tpacket_uhdr *hdr, bool v3)
61 #if defined(HAVE_TPACKET3) && defined(TP_STATUS_VLAN_TPID_VALID)
62 if (v3)
63 return hdr->h3->hv1.tp_vlan_tpid;
64 #endif
65 return 0;
68 static inline bool tpacket_has_vlan_info(union tpacket_uhdr *hdr)
70 uint32_t valid = 0;
72 #ifdef TP_STATUS_VLAN_TPID_VALID
73 valid = TP_STATUS_VLAN_VALID;
74 #endif
76 return tpacket_uhdr(*hdr, tp_status, true) &
77 (TP_STATUS_VLAN_VALID | valid);
80 struct frame_map {
81 struct tpacket2_hdr tp_h __aligned_tpacket;
82 struct sockaddr_ll s_ll __align_tpacket(sizeof(struct tpacket2_hdr));
85 #ifdef HAVE_TPACKET3
86 struct block_desc {
87 uint32_t version;
88 uint32_t offset_to_priv;
89 struct tpacket_hdr_v1 h1;
91 #endif
93 struct ring {
94 struct iovec *frames;
95 uint8_t *mm_space;
96 size_t mm_len;
97 struct sockaddr_ll s_ll;
98 union {
99 struct tpacket_req layout;
100 #ifdef HAVE_TPACKET3
101 struct tpacket_req3 layout3;
102 #endif
103 uint8_t raw;
107 static inline void next_rnd_slot(unsigned int *it, struct ring *ring)
109 *it = rand() % ring->layout.tp_frame_nr;
112 static inline size_t ring_size(const char *ifname, size_t size)
114 if (size > 0)
115 return size;
118 * Device bitrate in bytes times two as ring size.
119 * Fallback => ~ 64,00 MB
120 * 10 MBit => ~ 2,38 MB
121 * 54 MBit => ~ 12,88 MB
122 * 100 MBit => ~ 23,84 MB
123 * 300 MBit => ~ 71,52 MB
124 * 1.000 MBit => ~ 238,42 MB
125 * 10.000 MBit => ~ 2.384.18 MB
127 size = device_bitrate(ifname);
128 size = (size * 1000000) / 8;
129 size = size * 2;
130 if (size == 0)
131 size = 1 << 26;
133 return round_up_cacheline(size);
136 static inline unsigned int ring_frame_size(struct ring *ring)
138 return ring->layout.tp_frame_size;
141 static inline void ring_verify_layout(struct ring *ring)
143 bug_on(ring->layout.tp_block_size < ring->layout.tp_frame_size);
144 bug_on((ring->layout.tp_block_size % ring->layout.tp_frame_size) != 0);
145 bug_on((ring->layout.tp_block_size % RUNTIME_PAGE_SIZE) != 0);
148 static inline void tpacket_hdr_clone(struct tpacket2_hdr *thdrd,
149 struct tpacket2_hdr *thdrs)
151 thdrd->tp_sec = thdrs->tp_sec;
152 thdrd->tp_nsec = thdrs->tp_nsec;
153 thdrd->tp_snaplen = thdrs->tp_snaplen;
154 thdrd->tp_len = thdrs->tp_len;
157 static inline void prepare_polling(int sock, struct pollfd *pfd)
159 memset(pfd, 0, sizeof(*pfd));
160 pfd->fd = sock;
161 pfd->revents = 0;
162 pfd->events = POLLIN | POLLRDNORM | POLLERR;
165 static inline void __set_sockopt_tpacket(int sock, int val)
167 int ret = setsockopt(sock, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
168 if (ret)
169 panic("Cannot set tpacketv2!\n");
172 static inline void set_sockopt_tpacket_v2(int sock)
174 __set_sockopt_tpacket(sock, TPACKET_V2);
177 #ifdef HAVE_TPACKET3
178 static inline void set_sockopt_tpacket_v3(int sock)
180 __set_sockopt_tpacket(sock, TPACKET_V3);
182 #else
183 static inline void set_sockopt_tpacket_v3(int sock __maybe_unused)
186 #endif
188 static inline int get_sockopt_tpacket(int sock)
190 int val, ret;
191 socklen_t len = sizeof(val);
193 ret = getsockopt(sock, SOL_PACKET, PACKET_VERSION, &val, &len);
194 if (ret)
195 panic("Cannot get tpacket version!\n");
197 return val;
200 extern void mmap_ring_generic(int sock, struct ring *ring);
201 extern void alloc_ring_frames_generic(struct ring *ring, int num, size_t size);
202 extern void bind_ring_generic(int sock, struct ring *ring, int ifindex, bool tx_only);
204 #endif /* RING_H */