ring: added fanout api
[netsniff-ng.git] / src / ring.h
blobaee1fa989a45ab56ec49bfb77d95204d064c58e9
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 <string.h>
20 #include <poll.h>
21 #include <sys/poll.h>
23 #include "xsys.h"
24 #include "built_in.h"
25 #include "mtrand.h"
26 #include "die.h"
28 #ifndef PACKET_FANOUT
29 # define PACKET_FANOUT 18
30 # define PACKET_FANOUT_HASH 0
31 # define PACKET_FANOUT_LB 1
32 #endif
34 struct frame_map {
35 struct tpacket_hdr tp_h __aligned_tpacket;
36 struct sockaddr_ll s_ll __aligned_tpacket;
39 struct ring {
40 struct iovec *frames __cacheline_aligned;
41 uint8_t *mm_space __cacheline_aligned;
42 size_t mm_len;
43 struct tpacket_req layout;
44 struct sockaddr_ll s_ll;
47 static inline void next_slot(unsigned int *it, struct ring *ring)
49 (*it)++;
50 atomic_cmp_swp(it, ring->layout.tp_frame_nr, 0);
53 static inline void next_slot_prerd(unsigned int *it, struct ring *ring)
55 (*it)++;
56 atomic_cmp_swp(it, ring->layout.tp_frame_nr, 0);
57 prefetch_rd_hi(ring->frames[*it].iov_base);
60 static inline void next_slot_prewr(unsigned int *it, struct ring *ring)
62 (*it)++;
63 atomic_cmp_swp(it, ring->layout.tp_frame_nr, 0);
64 prefetch_wr_hi(ring->frames[*it].iov_base);
67 static inline void next_rnd_slot(unsigned int *it, struct ring *ring)
69 *it = mt_rand_int32() % ring->layout.tp_frame_nr;
72 #define RING_SIZE_FALLBACK (1 << 26)
74 static inline unsigned int ring_size(char *ifname, unsigned int size)
76 if (size > 0)
77 return size;
80 * Device bitrate in bytes times two as ring size.
81 * Fallback => ~ 64,00 MB
82 * 10 MBit => ~ 2,38 MB
83 * 54 MBit => ~ 12,88 MB
84 * 100 MBit => ~ 23,84 MB
85 * 300 MBit => ~ 71,52 MB
86 * 1.000 MBit => ~ 238,42 MB
87 * 10.000 MBit => ~ 2.384.18 MB
89 size = device_bitrate(ifname);
90 size = (size * 1000000) / 8;
91 size = size * 2;
92 if (size == 0)
93 size = RING_SIZE_FALLBACK;
94 return round_up_cacheline(size);
97 enum ring_mode {
98 RING_MODE_EGRESS,
99 RING_MODE_INGRESS,
102 static inline unsigned int ring_frame_size(struct ring *ring)
104 return ring->layout.tp_frame_size;
107 static inline void tpacket_hdr_clone(struct tpacket_hdr *thdrd,
108 struct tpacket_hdr *thdrs)
110 thdrd->tp_sec = thdrs->tp_sec;
111 thdrd->tp_usec = thdrs->tp_usec;
112 thdrd->tp_snaplen = thdrs->tp_snaplen;
113 thdrd->tp_len = thdrs->tp_len;
116 #ifndef POLLRDNORM
117 # define POLLRDNORM 0x0040
118 #endif
119 #ifndef POLLWRNORM
120 # define POLLWRNORM 0x0100
121 #endif
122 #ifndef POLLRDHUP
123 # define POLLRDHUP 0x2000
124 #endif
126 #define POLL_NEXT_PKT 0
127 #define POLL_MOVE_OUT 1
129 static inline void prepare_polling(int sock, struct pollfd *pfd)
131 memset(pfd, 0, sizeof(*pfd));
132 pfd->fd = sock;
133 pfd->revents = 0;
134 pfd->events = POLLIN | POLLRDNORM | POLLERR;
137 static inline void set_sockopt_fanout(int sock, unsigned int fanout_id,
138 unsigned int fanout_type)
140 unsigned int fanout_arg = (fanout_id | (fanout_type << 16));
141 int ret = setsockopt(sock, SOL_PACKET, PACKET_FANOUT, &fanout_arg,
142 sizeof(fanout_arg));
143 if (ret)
144 panic("No packet fanout support!\n");
147 #endif /* RING_H */