tprintf: xutils: Move tput*_safe to tprintf.c
[netsniff-ng.git] / ring.h
blobcbb814432f7013d3d33a0efb478a2f700db71e0b
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 "die.h"
30 #ifndef PACKET_FANOUT
31 # define PACKET_FANOUT 18
32 # define PACKET_FANOUT_POLICY_HASH 0
33 # define PACKET_FANOUT_POLICY_LB 1
34 # define PACKET_FANOUT_POLICY_DEFAULT PACKET_FANOUT_HASH
35 #endif
37 struct frame_map {
38 struct tpacket2_hdr tp_h __aligned_tpacket;
39 struct sockaddr_ll s_ll __align_tpacket(sizeof(struct tpacket2_hdr));
42 struct ring {
43 struct iovec *frames;
44 uint8_t *mm_space;
45 size_t mm_len;
46 struct tpacket_req layout;
47 struct sockaddr_ll s_ll;
50 static inline void next_rnd_slot(unsigned int *it, struct ring *ring)
52 *it = rand() % ring->layout.tp_frame_nr;
55 #define RING_SIZE_FALLBACK (1 << 26)
57 static inline unsigned int ring_size(char *ifname, unsigned int size)
59 if (size > 0)
60 return size;
63 * Device bitrate in bytes times two as ring size.
64 * Fallback => ~ 64,00 MB
65 * 10 MBit => ~ 2,38 MB
66 * 54 MBit => ~ 12,88 MB
67 * 100 MBit => ~ 23,84 MB
68 * 300 MBit => ~ 71,52 MB
69 * 1.000 MBit => ~ 238,42 MB
70 * 10.000 MBit => ~ 2.384.18 MB
72 size = device_bitrate(ifname);
73 size = (size * 1000000) / 8;
74 size = size * 2;
75 if (size == 0)
76 size = RING_SIZE_FALLBACK;
78 return round_up_cacheline(size);
81 enum ring_mode {
82 RING_MODE_EGRESS,
83 RING_MODE_INGRESS,
86 static inline unsigned int ring_frame_size(struct ring *ring)
88 return ring->layout.tp_frame_size;
91 static inline void tpacket_hdr_clone(struct tpacket2_hdr *thdrd,
92 struct tpacket2_hdr *thdrs)
94 thdrd->tp_sec = thdrs->tp_sec;
95 thdrd->tp_nsec = thdrs->tp_nsec;
96 thdrd->tp_snaplen = thdrs->tp_snaplen;
97 thdrd->tp_len = thdrs->tp_len;
100 #ifndef POLLRDNORM
101 # define POLLRDNORM 0x0040
102 #endif
103 #ifndef POLLWRNORM
104 # define POLLWRNORM 0x0100
105 #endif
106 #ifndef POLLRDHUP
107 # define POLLRDHUP 0x2000
108 #endif
110 #define POLL_NEXT_PKT 0
111 #define POLL_MOVE_OUT 1
113 static inline void prepare_polling(int sock, struct pollfd *pfd)
115 memset(pfd, 0, sizeof(*pfd));
116 pfd->fd = sock;
117 pfd->revents = 0;
118 pfd->events = POLLIN | POLLRDNORM | POLLERR;
121 static inline void set_sockopt_fanout(int sock, unsigned int fanout_id,
122 unsigned int fanout_type)
124 unsigned int fanout_arg = (fanout_id | (fanout_type << 16));
125 int ret = setsockopt(sock, SOL_PACKET, PACKET_FANOUT, &fanout_arg,
126 sizeof(fanout_arg));
127 if (ret)
128 panic("No packet fanout support!\n");
131 static inline void set_sockopt_tpacket(int sock)
133 int ret, val = TPACKET_V2;
135 ret = setsockopt(sock, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
136 if (ret)
137 panic("Cannot set tpacketv2!\n");
140 #ifdef __WITH_HARDWARE_TIMESTAMPING
141 # include <linux/net_tstamp.h>
143 static inline void set_sockopt_hwtimestamp(int sock, const char *dev)
145 int timesource, ret;
146 struct hwtstamp_config hwconfig;
147 struct ifreq ifr;
149 if (!strncmp("any", dev, strlen("any")))
150 return;
152 memset(&hwconfig, 0, sizeof(hwconfig));
153 hwconfig.tx_type = HWTSTAMP_TX_ON;
154 hwconfig.rx_filter = HWTSTAMP_FILTER_ALL;
156 memset(&ifr, 0, sizeof(ifr));
157 strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
158 ifr.ifr_data = &hwconfig;
160 ret = ioctl(sock, SIOCSHWTSTAMP, &ifr);
161 if (ret < 0) {
162 if (errno == EOPNOTSUPP)
163 return;
164 panic("Cannot set timestamping: %s\n", strerror(errno));
167 timesource = SOF_TIMESTAMPING_RAW_HARDWARE;
169 ret = setsockopt(sock, SOL_PACKET, PACKET_TIMESTAMP, &timesource,
170 sizeof(timesource));
171 if (ret)
172 panic("Cannot set timestamping: %s!\n", strerror(errno));
174 #else
175 static inline void set_sockopt_hwtimestamp(int sock, const char *dev)
177 return;
179 #endif
180 #endif /* RING_H */