2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009, 2010 Daniel Borkmann.
4 * Copyright 2014, 2015 Tobias Klauser.
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>
31 # define POLLRDNORM 0x0040
35 struct tpacket_hdr
*h1
;
36 struct tpacket2_hdr
*h2
;
38 struct tpacket3_hdr
*h3
;
44 #define tpacket_uhdr(hdr, member, v3) \
45 ((v3) ? ((hdr).h3)->member : ((hdr).h2)->member)
47 #define tpacket_uhdr(hdr, member, v3) \
49 #endif /* HAVE_TPACKET3 */
51 static inline uint16_t tpacket_uhdr_vlan_tci(union tpacket_uhdr
*hdr __maybe_unused
,
52 bool v3 __maybe_unused
)
56 return hdr
->h3
->hv1
.tp_vlan_tci
;
61 static inline uint16_t tpacket_uhdr_vlan_proto(union tpacket_uhdr
*hdr __maybe_unused
,
62 bool v3 __maybe_unused
)
64 #if defined(HAVE_TPACKET3) && defined(TP_STATUS_VLAN_TPID_VALID)
66 return hdr
->h3
->hv1
.tp_vlan_tpid
;
71 static inline bool tpacket_has_vlan_info(union tpacket_uhdr
*hdr
)
75 #ifdef TP_STATUS_VLAN_VALID
76 valid
|= TP_STATUS_VLAN_VALID
;
79 #ifdef TP_STATUS_VLAN_TPID_VALID
80 valid
|= TP_STATUS_VLAN_TPID_VALID
;
83 return tpacket_uhdr(*hdr
, tp_status
, true) & valid
;
87 struct tpacket2_hdr tp_h __aligned_tpacket
;
88 struct sockaddr_ll s_ll
__align_tpacket(sizeof(struct tpacket2_hdr
));
94 uint32_t offset_to_priv
;
95 struct tpacket_hdr_v1 h1
;
100 struct iovec
*frames
;
103 struct sockaddr_ll s_ll
;
105 struct tpacket_req layout
;
107 struct tpacket_req3 layout3
;
113 static inline void next_rnd_slot(unsigned int *it
, struct ring
*ring
)
115 *it
= rand() % ring
->layout
.tp_frame_nr
;
118 static inline size_t ring_size(const char *ifname
, size_t size
)
124 * Device bitrate in bytes times two as ring size.
125 * Fallback => ~ 64,00 MB
126 * 10 MBit => ~ 2,38 MB
127 * 54 MBit => ~ 12,88 MB
128 * 100 MBit => ~ 23,84 MB
129 * 300 MBit => ~ 71,52 MB
130 * 1.000 MBit => ~ 238,42 MB
131 * 10.000 MBit => ~ 2.384.18 MB
133 size
= device_bitrate(ifname
);
134 size
= (size
* 1000000) / 8;
139 return round_up_cacheline(size
);
142 static inline unsigned int ring_frame_size(struct ring
*ring
)
144 return ring
->layout
.tp_frame_size
;
147 static inline void ring_verify_layout(struct ring
*ring
)
149 bug_on(ring
->layout
.tp_block_size
< ring
->layout
.tp_frame_size
);
150 bug_on((ring
->layout
.tp_block_size
% ring
->layout
.tp_frame_size
) != 0);
151 bug_on((ring
->layout
.tp_block_size
% RUNTIME_PAGE_SIZE
) != 0);
154 static inline void shrink_ring_layout_generic(struct ring
*ring
)
156 ring
->layout
.tp_block_nr
>>= 1;
157 ring
->layout
.tp_frame_nr
= ring
->layout
.tp_block_size
/
158 ring
->layout
.tp_frame_size
*
159 ring
->layout
.tp_block_nr
;
162 static inline void tpacket_hdr_clone(struct tpacket2_hdr
*thdrd
,
163 struct tpacket2_hdr
*thdrs
)
165 thdrd
->tp_sec
= thdrs
->tp_sec
;
166 thdrd
->tp_nsec
= thdrs
->tp_nsec
;
167 thdrd
->tp_snaplen
= thdrs
->tp_snaplen
;
168 thdrd
->tp_len
= thdrs
->tp_len
;
171 static inline void prepare_polling(int sock
, struct pollfd
*pfd
)
173 memset(pfd
, 0, sizeof(*pfd
));
176 pfd
->events
= POLLIN
| POLLRDNORM
| POLLERR
;
179 static inline void __set_sockopt_tpacket(int sock
, int val
)
181 int ret
= setsockopt(sock
, SOL_PACKET
, PACKET_VERSION
, &val
, sizeof(val
));
183 panic("Cannot set tpacketv2!\n");
186 static inline void set_sockopt_tpacket_v2(int sock
)
188 __set_sockopt_tpacket(sock
, TPACKET_V2
);
192 static inline void set_sockopt_tpacket_v3(int sock
)
194 __set_sockopt_tpacket(sock
, TPACKET_V3
);
197 static inline void set_sockopt_tpacket_v3(int sock __maybe_unused
)
202 static inline int get_sockopt_tpacket(int sock
)
205 socklen_t len
= sizeof(val
);
207 ret
= getsockopt(sock
, SOL_PACKET
, PACKET_VERSION
, &val
, &len
);
209 panic("Cannot get tpacket version!\n");
214 extern void setup_ring_layout_generic(struct ring
*ring
, size_t size
,
216 extern void mmap_ring_generic(int sock
, struct ring
*ring
);
217 extern void alloc_ring_frames_generic(struct ring
*ring
, size_t num
, size_t size
);
218 extern void bind_ring_generic(int sock
, struct ring
*ring
, int ifindex
, bool tx_only
);