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.
12 * "I love the smell of 10GbE in the morning. Smells like ... victory."
13 * - W. Richard Stevens, "Secret Teachings of the UNIX Environment"
18 #include <linux/if_packet.h>
19 #include <linux/socket.h>
20 #include <linux/sockios.h>
21 #include <sys/ioctl.h>
33 # define PACKET_FANOUT 18
34 # define PACKET_FANOUT_POLICY_HASH 0
35 # define PACKET_FANOUT_POLICY_LB 1
36 # define PACKET_FANOUT_POLICY_DEFAULT PACKET_FANOUT_HASH
40 struct tpacket_hdr tp_h __aligned_tpacket
;
41 struct sockaddr_ll s_ll __aligned_tpacket
;
45 struct iovec
*frames __cacheline_aligned
;
46 uint8_t *mm_space __cacheline_aligned
;
48 struct tpacket_req layout
;
49 struct sockaddr_ll s_ll
;
52 static inline void next_slot(unsigned int *it
, struct ring
*ring
)
55 atomic_cmp_swp(it
, ring
->layout
.tp_frame_nr
, 0);
58 static inline void next_slot_prerd(unsigned int *it
, struct ring
*ring
)
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
)
68 atomic_cmp_swp(it
, ring
->layout
.tp_frame_nr
, 0);
69 prefetch_wr_hi(ring
->frames
[*it
].iov_base
);
72 static inline void next_rnd_slot(unsigned int *it
, struct ring
*ring
)
74 *it
= mt_rand_int32() % ring
->layout
.tp_frame_nr
;
77 #define RING_SIZE_FALLBACK (1 << 26)
79 static inline unsigned int ring_size(char *ifname
, unsigned int size
)
85 * Device bitrate in bytes times two as ring size.
86 * Fallback => ~ 64,00 MB
87 * 10 MBit => ~ 2,38 MB
88 * 54 MBit => ~ 12,88 MB
89 * 100 MBit => ~ 23,84 MB
90 * 300 MBit => ~ 71,52 MB
91 * 1.000 MBit => ~ 238,42 MB
92 * 10.000 MBit => ~ 2.384.18 MB
94 size
= device_bitrate(ifname
);
95 size
= (size
* 1000000) / 8;
98 size
= RING_SIZE_FALLBACK
;
99 return round_up_cacheline(size
);
107 static inline unsigned int ring_frame_size(struct ring
*ring
)
109 return ring
->layout
.tp_frame_size
;
112 static inline void tpacket_hdr_clone(struct tpacket_hdr
*thdrd
,
113 struct tpacket_hdr
*thdrs
)
115 thdrd
->tp_sec
= thdrs
->tp_sec
;
116 thdrd
->tp_usec
= thdrs
->tp_usec
;
117 thdrd
->tp_snaplen
= thdrs
->tp_snaplen
;
118 thdrd
->tp_len
= thdrs
->tp_len
;
122 # define POLLRDNORM 0x0040
125 # define POLLWRNORM 0x0100
128 # define POLLRDHUP 0x2000
131 #define POLL_NEXT_PKT 0
132 #define POLL_MOVE_OUT 1
134 static inline void prepare_polling(int sock
, struct pollfd
*pfd
)
136 memset(pfd
, 0, sizeof(*pfd
));
139 pfd
->events
= POLLIN
| POLLRDNORM
| POLLERR
;
142 static inline void set_sockopt_fanout(int sock
, unsigned int fanout_id
,
143 unsigned int fanout_type
)
145 unsigned int fanout_arg
= (fanout_id
| (fanout_type
<< 16));
146 int ret
= setsockopt(sock
, SOL_PACKET
, PACKET_FANOUT
, &fanout_arg
,
149 panic("No packet fanout support!\n");
152 #ifndef SO_TIMESTAMPING
153 # define SO_TIMESTAMPING 37
154 # define SCM_TIMESTAMPING SO_TIMESTAMPING
157 #ifndef SO_TIMESTAMPNS
158 # define SO_TIMESTAMPNS 35
162 # define SIOCGSTAMPNS 0x8907
165 #ifndef SIOCSHWTSTAMP
166 # define SIOCSHWTSTAMP 0x89b0
169 #ifndef PACKET_TIMESTAMP
171 SOF_TIMESTAMPING_TX_HARDWARE
= (1<<0),
172 SOF_TIMESTAMPING_TX_SOFTWARE
= (1<<1),
173 SOF_TIMESTAMPING_RX_HARDWARE
= (1<<2),
174 SOF_TIMESTAMPING_RX_SOFTWARE
= (1<<3),
175 SOF_TIMESTAMPING_SOFTWARE
= (1<<4),
176 SOF_TIMESTAMPING_SYS_HARDWARE
= (1<<5),
177 SOF_TIMESTAMPING_RAW_HARDWARE
= (1<<6),
178 SOF_TIMESTAMPING_MASK
=
179 (SOF_TIMESTAMPING_RAW_HARDWARE
- 1) |
180 SOF_TIMESTAMPING_RAW_HARDWARE
183 struct hwtstamp_config
{
189 enum hwtstamp_tx_types
{
192 HWTSTAMP_TX_ONESTEP_SYNC
,
195 enum hwtstamp_rx_filters
{
196 HWTSTAMP_FILTER_NONE
,
200 # define PACKET_TIMESTAMP 17
202 # include <linux/net_tstamp.h>
203 #endif /* PACKET_TIMESTAMP */
205 static inline void set_sockopt_hwtimestamp(int sock
, const char *dev
)
208 struct hwtstamp_config hwconfig
;
211 memset(&hwconfig
, 0, sizeof(hwconfig
));
212 hwconfig
.tx_type
= HWTSTAMP_TX_ON
;
213 hwconfig
.rx_filter
= HWTSTAMP_FILTER_ALL
;
215 memset(&ifr
, 0, sizeof(ifr
));
216 strlcpy(ifr
.ifr_name
, dev
, sizeof(ifr
.ifr_name
));
217 ifr
.ifr_data
= &hwconfig
;
219 ret
= ioctl(sock
, SIOCSHWTSTAMP
, &ifr
);
223 timesource
= SOF_TIMESTAMPING_RAW_HARDWARE
;
225 ret
= setsockopt(sock
, SOL_PACKET
, PACKET_TIMESTAMP
, ×ource
,
228 panic("Cannot set timestamping!\n");