Merge pull request #59 from electronjoe/graceful-SIGTERM-handling
[netsniff-ng-old.git] / ring.h
blob75f4d26a59105178a8ca59febca684c3fa074247
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>
23 #include <sys/poll.h>
25 #include "xutils.h"
26 #include "built_in.h"
27 #include "die.h"
29 #ifndef PACKET_FANOUT
30 # define PACKET_FANOUT 18
31 # define PACKET_FANOUT_POLICY_HASH 0
32 # define PACKET_FANOUT_POLICY_LB 1
33 # define PACKET_FANOUT_POLICY_DEFAULT PACKET_FANOUT_HASH
34 #endif
36 struct frame_map {
37 struct tpacket2_hdr tp_h __aligned_tpacket;
38 struct sockaddr_ll s_ll __align_tpacket(sizeof(struct tpacket2_hdr));
41 struct ring {
42 struct iovec *frames;
43 uint8_t *mm_space;
44 size_t mm_len;
45 struct tpacket_req layout;
46 struct sockaddr_ll s_ll;
49 static inline void next_rnd_slot(unsigned int *it, struct ring *ring)
51 *it = rand() % ring->layout.tp_frame_nr;
54 #define RING_SIZE_FALLBACK (1 << 26)
56 static inline unsigned int ring_size(char *ifname, unsigned int size)
58 if (size > 0)
59 return size;
62 * Device bitrate in bytes times two as ring size.
63 * Fallback => ~ 64,00 MB
64 * 10 MBit => ~ 2,38 MB
65 * 54 MBit => ~ 12,88 MB
66 * 100 MBit => ~ 23,84 MB
67 * 300 MBit => ~ 71,52 MB
68 * 1.000 MBit => ~ 238,42 MB
69 * 10.000 MBit => ~ 2.384.18 MB
71 size = device_bitrate(ifname);
72 size = (size * 1000000) / 8;
73 size = size * 2;
74 if (size == 0)
75 size = RING_SIZE_FALLBACK;
77 return round_up_cacheline(size);
80 static inline unsigned int ring_frame_size(struct ring *ring)
82 return ring->layout.tp_frame_size;
85 static inline void tpacket_hdr_clone(struct tpacket2_hdr *thdrd,
86 struct tpacket2_hdr *thdrs)
88 thdrd->tp_sec = thdrs->tp_sec;
89 thdrd->tp_nsec = thdrs->tp_nsec;
90 thdrd->tp_snaplen = thdrs->tp_snaplen;
91 thdrd->tp_len = thdrs->tp_len;
94 #ifndef POLLRDNORM
95 # define POLLRDNORM 0x0040
96 #endif
97 #ifndef POLLWRNORM
98 # define POLLWRNORM 0x0100
99 #endif
100 #ifndef POLLRDHUP
101 # define POLLRDHUP 0x2000
102 #endif
104 #define POLL_NEXT_PKT 0
105 #define POLL_MOVE_OUT 1
107 static inline void prepare_polling(int sock, struct pollfd *pfd)
109 memset(pfd, 0, sizeof(*pfd));
110 pfd->fd = sock;
111 pfd->revents = 0;
112 pfd->events = POLLIN | POLLRDNORM | POLLERR;
115 static inline void set_sockopt_fanout(int sock, unsigned int fanout_id,
116 unsigned int fanout_type)
118 unsigned int fanout_arg = (fanout_id | (fanout_type << 16));
119 int ret = setsockopt(sock, SOL_PACKET, PACKET_FANOUT, &fanout_arg,
120 sizeof(fanout_arg));
121 if (ret)
122 panic("No packet fanout support!\n");
125 static inline void set_sockopt_tpacket(int sock)
127 int ret, val = TPACKET_V2;
129 ret = setsockopt(sock, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
130 if (ret)
131 panic("Cannot set tpacketv2!\n");
134 #ifdef __WITH_HARDWARE_TIMESTAMPING
135 # include <linux/net_tstamp.h>
137 static inline void set_sockopt_hwtimestamp(int sock, const char *dev)
139 int timesource, ret;
140 struct hwtstamp_config hwconfig;
141 struct ifreq ifr;
143 if (!strncmp("any", dev, strlen("any")))
144 return;
146 memset(&hwconfig, 0, sizeof(hwconfig));
147 hwconfig.tx_type = HWTSTAMP_TX_ON;
148 hwconfig.rx_filter = HWTSTAMP_FILTER_ALL;
150 memset(&ifr, 0, sizeof(ifr));
151 strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
152 ifr.ifr_data = &hwconfig;
154 ret = ioctl(sock, SIOCSHWTSTAMP, &ifr);
155 if (ret < 0) {
156 if (errno == EOPNOTSUPP)
157 return;
158 panic("Cannot set timestamping: %s\n", strerror(errno));
161 timesource = SOF_TIMESTAMPING_RAW_HARDWARE;
163 ret = setsockopt(sock, SOL_PACKET, PACKET_TIMESTAMP, &timesource,
164 sizeof(timesource));
165 if (ret)
166 panic("Cannot set timestamping: %s!\n", strerror(errno));
168 #else
169 static inline void set_sockopt_hwtimestamp(int sock, const char *dev)
171 return;
173 #endif
174 #endif /* RING_H */