ring_tx: handle EINTR from sendto
[netsniff-ng.git] / ring.h
blobd411fc44b6d1cece368795d63f9bdd642afed6bc
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009, 2010 Daniel Borkmann.
4 * Copyright 2014, 2015 Tobias Klauser.
5 * Subject to the GPL, version 2.
6 */
8 #ifndef RING_H
9 #define RING_H
12 * "I love the smell of 10GbE in the morning. Smells like ... victory."
13 * - W. Richard Stevens, "Secret Teachings of the UNIX Environment"
16 #include <stdio.h>
17 #include <stdint.h>
18 #include <linux/if_packet.h>
19 #include <linux/socket.h>
20 #include <linux/sockios.h>
21 #include <sys/ioctl.h>
22 #include <string.h>
23 #include <poll.h>
25 #include "built_in.h"
26 #include "die.h"
27 #include "dev.h"
28 #include "config.h"
30 #ifndef POLLRDNORM
31 # define POLLRDNORM 0x0040
32 #endif
34 union tpacket_uhdr {
35 struct tpacket_hdr *h1;
36 struct tpacket2_hdr *h2;
37 #ifdef HAVE_TPACKET3
38 struct tpacket3_hdr *h3;
39 #endif
40 void *raw;
43 #ifdef HAVE_TPACKET3
44 #define tpacket_uhdr(hdr, member, v3) \
45 ((v3) ? ((hdr).h3)->member : ((hdr).h2)->member)
46 #else
47 #define tpacket_uhdr(hdr, member, v3) \
48 (((hdr).h2)->member)
49 #endif /* HAVE_TPACKET3 */
51 static inline uint16_t tpacket_uhdr_vlan_tci(union tpacket_uhdr *hdr __maybe_unused,
52 bool v3 __maybe_unused)
54 #ifdef HAVE_TPACKET3
55 if (v3)
56 return hdr->h3->hv1.tp_vlan_tci;
57 #endif
58 return 0;
61 static inline uint16_t tpacket_uhdr_vlan_proto(union tpacket_uhdr *hdr __maybe_unused,
62 bool v3 __maybe_unused)
64 #if defined(HAVE_TPACKET3) && defined(TP_STATUS_VLAN_TPID_VALID)
65 if (v3)
66 return hdr->h3->hv1.tp_vlan_tpid;
67 #endif
68 return 0;
71 static inline bool tpacket_has_vlan_info(union tpacket_uhdr *hdr)
73 uint32_t valid = 0;
75 #ifdef TP_STATUS_VLAN_VALID
76 valid |= TP_STATUS_VLAN_VALID;
77 #endif
79 #ifdef TP_STATUS_VLAN_TPID_VALID
80 valid |= TP_STATUS_VLAN_TPID_VALID;
81 #endif
83 return tpacket_uhdr(*hdr, tp_status, true) & valid;
86 struct frame_map {
87 struct tpacket2_hdr tp_h __aligned_tpacket;
88 struct sockaddr_ll s_ll __align_tpacket(sizeof(struct tpacket2_hdr));
91 #ifdef HAVE_TPACKET3
92 struct block_desc {
93 uint32_t version;
94 uint32_t offset_to_priv;
95 struct tpacket_hdr_v1 h1;
97 #endif
99 struct ring {
100 struct iovec *frames;
101 uint8_t *mm_space;
102 size_t mm_len;
103 struct sockaddr_ll s_ll;
104 union {
105 struct tpacket_req layout;
106 #ifdef HAVE_TPACKET3
107 struct tpacket_req3 layout3;
108 #endif
109 uint8_t raw;
113 static inline void next_rnd_slot(unsigned int *it, struct ring *ring)
115 *it = rand() % ring->layout.tp_frame_nr;
118 static inline size_t ring_size(const char *ifname, size_t size)
120 if (size > 0)
121 return size;
124 * Device bitrate in bytes times two as ring size.
125 * Fallback => ~ 64,00 MB
126 * 10 MBit => ~ 2,38 MB
127 * 54 MBit => ~ 12,88 MB
128 * 100 MBit => ~ 23,84 MB
129 * 300 MBit => ~ 71,52 MB
130 * 1.000 MBit => ~ 238,42 MB
131 * 10.000 MBit => ~ 2.384.18 MB
133 size = device_bitrate(ifname);
134 size = (size * 1000000) / 8;
135 size = size * 2;
136 if (size == 0)
137 size = 1 << 26;
139 return round_up_cacheline(size);
142 static inline unsigned int ring_frame_size(struct ring *ring)
144 return ring->layout.tp_frame_size;
147 static inline void ring_verify_layout(struct ring *ring)
149 bug_on(ring->layout.tp_block_size < ring->layout.tp_frame_size);
150 bug_on((ring->layout.tp_block_size % ring->layout.tp_frame_size) != 0);
151 bug_on((ring->layout.tp_block_size % RUNTIME_PAGE_SIZE) != 0);
154 static inline void shrink_ring_layout_generic(struct ring *ring)
156 ring->layout.tp_block_nr >>= 1;
157 ring->layout.tp_frame_nr = ring->layout.tp_block_size /
158 ring->layout.tp_frame_size *
159 ring->layout.tp_block_nr;
162 static inline void tpacket_hdr_clone(struct tpacket2_hdr *thdrd,
163 struct tpacket2_hdr *thdrs)
165 thdrd->tp_sec = thdrs->tp_sec;
166 thdrd->tp_nsec = thdrs->tp_nsec;
167 thdrd->tp_snaplen = thdrs->tp_snaplen;
168 thdrd->tp_len = thdrs->tp_len;
171 static inline void prepare_polling(int sock, struct pollfd *pfd)
173 memset(pfd, 0, sizeof(*pfd));
174 pfd->fd = sock;
175 pfd->revents = 0;
176 pfd->events = POLLIN | POLLRDNORM | POLLERR;
179 static inline void __set_sockopt_tpacket(int sock, int val)
181 int ret = setsockopt(sock, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
182 if (ret)
183 panic("Cannot set tpacketv2!\n");
186 static inline void set_sockopt_tpacket_v2(int sock)
188 __set_sockopt_tpacket(sock, TPACKET_V2);
191 #ifdef HAVE_TPACKET3
192 static inline void set_sockopt_tpacket_v3(int sock)
194 __set_sockopt_tpacket(sock, TPACKET_V3);
196 #else
197 static inline void set_sockopt_tpacket_v3(int sock __maybe_unused)
200 #endif
202 static inline int get_sockopt_tpacket(int sock)
204 int val, ret;
205 socklen_t len = sizeof(val);
207 ret = getsockopt(sock, SOL_PACKET, PACKET_VERSION, &val, &len);
208 if (ret)
209 panic("Cannot get tpacket version!\n");
211 return val;
214 extern void setup_ring_layout_generic(struct ring *ring, size_t size,
215 bool jumbo_support);
216 extern void mmap_ring_generic(int sock, struct ring *ring);
217 extern void alloc_ring_frames_generic(struct ring *ring, size_t num, size_t size);
218 extern void bind_ring_generic(int sock, struct ring *ring, int ifindex, bool tx_only);
220 #endif /* RING_H */