docs: add todo's from Sibir's repo
[netsniff-ng.git] / src / ring.h
blob76be0515b9c24bdda33c16ecc0a54bd0a9f583ff
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009, 2010 Daniel Borkmann.
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>
24 #include <sys/poll.h>
26 #include "xutils.h"
27 #include "built_in.h"
28 #include "mtrand.h"
29 #include "die.h"
31 #ifndef PACKET_FANOUT
32 # define PACKET_FANOUT 18
33 # define PACKET_FANOUT_POLICY_HASH 0
34 # define PACKET_FANOUT_POLICY_LB 1
35 # define PACKET_FANOUT_POLICY_DEFAULT PACKET_FANOUT_HASH
36 #endif
38 struct frame_map {
39 struct tpacket2_hdr tp_h __aligned_tpacket;
40 struct sockaddr_ll s_ll;
43 struct ring {
44 struct iovec *frames __cacheline_aligned;
45 uint8_t *mm_space;
46 size_t mm_len;
47 struct tpacket_req layout;
48 struct sockaddr_ll s_ll;
51 static inline void next_slot(unsigned int *it, struct ring *ring)
53 (*it)++;
54 atomic_cmp_swp(it, ring->layout.tp_frame_nr, 0);
57 #if 0
58 static inline void next_slot_prerd(unsigned int *it, struct ring *ring)
60 (*it)++;
61 atomic_cmp_swp(it, ring->layout.tp_frame_nr, 0);
62 prefetch_rd_hi(ring->frames[*it].iov_base);
65 static inline void next_slot_prewr(unsigned int *it, struct ring *ring)
67 (*it)++;
68 atomic_cmp_swp(it, ring->layout.tp_frame_nr, 0);
69 prefetch_wr_hi(ring->frames[*it].iov_base);
71 #else
72 # define next_slot_prerd next_slot
73 # define next_slot_prewr next_slot
74 #endif
76 static inline void next_rnd_slot(unsigned int *it, struct ring *ring)
78 *it = mt_rand_int32() % ring->layout.tp_frame_nr;
81 #define RING_SIZE_FALLBACK (1 << 26)
83 static inline unsigned int ring_size(char *ifname, unsigned int size)
85 if (size > 0)
86 return size;
89 * Device bitrate in bytes times two as ring size.
90 * Fallback => ~ 64,00 MB
91 * 10 MBit => ~ 2,38 MB
92 * 54 MBit => ~ 12,88 MB
93 * 100 MBit => ~ 23,84 MB
94 * 300 MBit => ~ 71,52 MB
95 * 1.000 MBit => ~ 238,42 MB
96 * 10.000 MBit => ~ 2.384.18 MB
98 size = device_bitrate(ifname);
99 size = (size * 1000000) / 8;
100 size = size * 2;
101 if (size == 0)
102 size = RING_SIZE_FALLBACK;
104 return round_up_cacheline(size);
107 enum ring_mode {
108 RING_MODE_EGRESS,
109 RING_MODE_INGRESS,
112 static inline unsigned int ring_frame_size(struct ring *ring)
114 return ring->layout.tp_frame_size;
117 static inline void tpacket_hdr_clone(struct tpacket2_hdr *thdrd,
118 struct tpacket2_hdr *thdrs)
120 thdrd->tp_sec = thdrs->tp_sec;
121 thdrd->tp_nsec = thdrs->tp_nsec;
122 thdrd->tp_snaplen = thdrs->tp_snaplen;
123 thdrd->tp_len = thdrs->tp_len;
126 #ifndef POLLRDNORM
127 # define POLLRDNORM 0x0040
128 #endif
129 #ifndef POLLWRNORM
130 # define POLLWRNORM 0x0100
131 #endif
132 #ifndef POLLRDHUP
133 # define POLLRDHUP 0x2000
134 #endif
136 #define POLL_NEXT_PKT 0
137 #define POLL_MOVE_OUT 1
139 static inline void prepare_polling(int sock, struct pollfd *pfd)
141 memset(pfd, 0, sizeof(*pfd));
142 pfd->fd = sock;
143 pfd->revents = 0;
144 pfd->events = POLLIN | POLLRDNORM | POLLERR;
147 static inline void set_sockopt_fanout(int sock, unsigned int fanout_id,
148 unsigned int fanout_type)
150 unsigned int fanout_arg = (fanout_id | (fanout_type << 16));
151 int ret = setsockopt(sock, SOL_PACKET, PACKET_FANOUT, &fanout_arg,
152 sizeof(fanout_arg));
153 if (ret)
154 panic("No packet fanout support!\n");
157 static inline void set_sockopt_tpacket(int sock)
159 int ret, val = TPACKET_V2;
161 ret = setsockopt(sock, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
162 if (ret)
163 panic("Cannot set tpacketv2!\n");
166 #if defined(__WITH_HARDWARE_TIMESTAMPING)
167 # include <linux/net_tstamp.h>
169 static inline void set_sockopt_hwtimestamp(int sock, const char *dev)
171 int timesource, ret;
172 struct hwtstamp_config hwconfig;
173 struct ifreq ifr;
175 memset(&hwconfig, 0, sizeof(hwconfig));
176 hwconfig.tx_type = HWTSTAMP_TX_ON;
177 hwconfig.rx_filter = HWTSTAMP_FILTER_ALL;
179 memset(&ifr, 0, sizeof(ifr));
180 strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
181 ifr.ifr_data = &hwconfig;
183 ret = ioctl(sock, SIOCSHWTSTAMP, &ifr);
184 if (ret < 0)
185 return;
187 timesource = SOF_TIMESTAMPING_RAW_HARDWARE;
189 ret = setsockopt(sock, SOL_PACKET, PACKET_TIMESTAMP, &timesource,
190 sizeof(timesource));
191 if (ret)
192 panic("Cannot set timestamping!\n");
194 #else
195 static inline void set_sockopt_hwtimestamp(int sock, const char *dev)
197 return;
199 #endif /* defined(__WITH_HARDWARE_TIMESTAMPING) */
200 #endif /* RING_H */