2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009, 2010 Daniel Borkmann.
4 * Copyright 2014 Tobias Klauser.
5 * Subject to the GPL, version 2.
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <arpa/inet.h>
17 #include <linux/if_ether.h>
25 static inline bool is_tpacket_v3(int sock
)
27 return get_sockopt_tpacket(sock
) == TPACKET_V3
;
30 static inline size_t get_ring_layout_size(struct ring
*ring
, bool v3
)
32 return v3
? sizeof(ring
->layout3
) : sizeof(ring
->layout
);
35 static inline void setup_rx_ring_layout_v3(struct ring
*ring
)
37 /* Pass out, if this will ever change and we do crap on it! */
38 build_bug_on(offsetof(struct tpacket_req
, tp_frame_nr
) !=
39 offsetof(struct tpacket_req3
, tp_frame_nr
) &&
40 sizeof(struct tpacket_req
) !=
41 offsetof(struct tpacket_req3
, tp_retire_blk_tov
));
43 ring
->layout3
.tp_retire_blk_tov
= 100; /* 0: let kernel decide */
44 ring
->layout3
.tp_sizeof_priv
= 0;
45 ring
->layout3
.tp_feature_req_word
= 0;
48 static inline int rx_ring_get_num(struct ring
*ring
, bool v3
)
50 return v3
? ring
->layout3
.tp_block_nr
: ring
->layout
.tp_frame_nr
;
53 static inline size_t rx_ring_get_size(struct ring
*ring
, bool v3
)
55 return v3
? ring
->layout3
.tp_block_size
: ring
->layout
.tp_frame_size
;
58 static inline bool is_tpacket_v3(int sock __maybe_unused
)
63 static inline size_t get_ring_layout_size(struct ring
*ring
, bool v3 __maybe_unused
)
65 return sizeof(ring
->layout
);
68 static inline void setup_rx_ring_layout_v3(struct ring
*ring __maybe_unused
)
72 static inline int rx_ring_get_num(struct ring
*ring
, bool v3 __maybe_unused
)
74 return ring
->layout
.tp_frame_nr
;
77 static inline size_t rx_ring_get_size(struct ring
*ring
, bool v3 __maybe_unused
)
79 return ring
->layout
.tp_frame_size
;
81 #endif /* HAVE_TPACKET3 */
83 void destroy_rx_ring(int sock
, struct ring
*ring
)
86 bool v3
= is_tpacket_v3(sock
);
88 munmap(ring
->mm_space
, ring
->mm_len
);
93 /* In general, this is freed during close(2) anyway. */
97 fmemset(&ring
->layout
, 0, sizeof(ring
->layout
));
98 ret
= setsockopt(sock
, SOL_PACKET
, PACKET_RX_RING
, &ring
->layout
,
99 sizeof(ring
->layout
));
101 panic("Cannot destroy the RX_RING: %s!\n", strerror(errno
));
104 static void setup_rx_ring_layout(int sock
, struct ring
*ring
, size_t size
,
105 bool jumbo_support
, bool v3
)
107 fmemset(&ring
->layout
, 0, sizeof(ring
->layout
));
109 ring
->layout
.tp_block_size
= (jumbo_support
?
110 RUNTIME_PAGE_SIZE
<< 4 :
111 RUNTIME_PAGE_SIZE
<< 2);
113 ring
->layout
.tp_frame_size
= (jumbo_support
?
114 TPACKET_ALIGNMENT
<< 12 :
115 TPACKET_ALIGNMENT
<< 7);
117 ring
->layout
.tp_block_nr
= size
/ ring
->layout
.tp_block_size
;
118 ring
->layout
.tp_frame_nr
= ring
->layout
.tp_block_size
/
119 ring
->layout
.tp_frame_size
*
120 ring
->layout
.tp_block_nr
;
123 setup_rx_ring_layout_v3(ring
);
124 set_sockopt_tpacket_v3(sock
);
126 set_sockopt_tpacket_v2(sock
);
129 ring_verify_layout(ring
);
132 static void create_rx_ring(int sock
, struct ring
*ring
, bool verbose
)
135 bool v3
= is_tpacket_v3(sock
);
136 size_t layout_size
= get_ring_layout_size(ring
, v3
);
139 ret
= setsockopt(sock
, SOL_PACKET
, PACKET_RX_RING
, &ring
->raw
,
142 if (errno
== ENOMEM
&& ring
->layout
.tp_block_nr
> 1) {
143 ring
->layout
.tp_block_nr
>>= 1;
144 ring
->layout
.tp_frame_nr
= ring
->layout
.tp_block_size
/
145 ring
->layout
.tp_frame_size
*
146 ring
->layout
.tp_block_nr
;
150 panic("Cannot allocate RX_RING!\n");
152 ring
->mm_len
= (size_t) ring
->layout
.tp_block_size
* ring
->layout
.tp_block_nr
;
156 printf("RX,V2: %.2Lf MiB, %u Frames, each %u Byte allocated\n",
157 (long double) ring
->mm_len
/ (1 << 20),
158 ring
->layout
.tp_frame_nr
, ring
->layout
.tp_frame_size
);
160 printf("RX,V3: %.2Lf MiB, %u Blocks, each %u Byte allocated\n",
161 (long double) ring
->mm_len
/ (1 << 20),
162 ring
->layout
.tp_block_nr
, ring
->layout
.tp_block_size
);
167 static void alloc_rx_ring_frames(int sock
, struct ring
*ring
)
169 bool v3
= is_tpacket_v3(sock
);
171 alloc_ring_frames_generic(ring
, rx_ring_get_num(ring
, v3
),
172 rx_ring_get_size(ring
, v3
));
175 void ring_rx_setup(struct ring
*ring
, int sock
, size_t size
, int ifindex
,
176 struct pollfd
*poll
, bool v3
, bool jumbo_support
,
179 fmemset(ring
, 0, sizeof(*ring
));
180 setup_rx_ring_layout(sock
, ring
, size
, jumbo_support
, v3
);
181 create_rx_ring(sock
, ring
, verbose
);
182 mmap_ring_generic(sock
, ring
);
183 alloc_rx_ring_frames(sock
, ring
);
184 bind_ring_generic(sock
, ring
, ifindex
, false);
185 prepare_polling(sock
, poll
);
188 void sock_rx_net_stats(int sock
, unsigned long seen
)
191 bool v3
= is_tpacket_v3(sock
);
193 struct tpacket_stats k2
;
194 struct tpacket_stats_v3 k3
;
196 socklen_t slen
= v3
? sizeof(stats
.k3
) : sizeof(stats
.k2
);
198 memset(&stats
, 0, sizeof(stats
));
199 ret
= getsockopt(sock
, SOL_PACKET
, PACKET_STATISTICS
, &stats
, &slen
);
201 uint64_t packets
= stats
.k3
.tp_packets
;
202 uint64_t drops
= stats
.k3
.tp_drops
;
204 printf("\r%12"PRIu64
" packets incoming (%"PRIu64
" unread on exit)\n",
205 v3
? (uint64_t)seen
: packets
, v3
? packets
- seen
: 0);
206 printf("\r%12"PRIu64
" packets passed filter\n", packets
- drops
);
207 printf("\r%12"PRIu64
" packets failed filter (out of space)\n", drops
);
208 if (stats
.k3
.tp_packets
> 0)
209 printf("\r%12.4lf%% packet droprate\n",
210 (1.0 * drops
/ packets
) * 100.0);