build: Also use proper previous tag for people list
[netsniff-ng.git] / ring_rx.c
blob59cafd32b3dbfbe0aa20a6e9d39797154f56cc27
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009, 2010 Daniel Borkmann.
4 * Subject to the GPL, version 2.
5 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <sys/mman.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <arpa/inet.h>
15 #include <linux/if_ether.h>
17 #include "xmalloc.h"
18 #include "die.h"
19 #include "ring_rx.h"
20 #include "built_in.h"
22 void destroy_rx_ring(int sock, struct ring *ring)
24 int ret;
25 bool v3 = get_sockopt_tpacket(sock) == TPACKET_V3;
27 munmap(ring->mm_space, ring->mm_len);
28 ring->mm_len = 0;
30 xfree(ring->frames);
32 /* In general, this is freed during close(2) anyway. */
33 if (v3)
34 return;
36 fmemset(&ring->layout, 0, sizeof(ring->layout));
37 ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &ring->layout,
38 sizeof(ring->layout));
39 if (unlikely(ret))
40 panic("Cannot destroy the RX_RING: %s!\n", strerror(errno));
43 void setup_rx_ring_layout(int sock, struct ring *ring, unsigned int size,
44 bool jumbo_support, bool v3)
46 fmemset(&ring->layout, 0, sizeof(ring->layout));
48 ring->layout.tp_block_size = (jumbo_support ?
49 RUNTIME_PAGE_SIZE << 4 :
50 RUNTIME_PAGE_SIZE << 2);
52 ring->layout.tp_frame_size = (jumbo_support ?
53 TPACKET_ALIGNMENT << 12 :
54 TPACKET_ALIGNMENT << 7);
56 ring->layout.tp_block_nr = size / ring->layout.tp_block_size;
57 ring->layout.tp_frame_nr = ring->layout.tp_block_size /
58 ring->layout.tp_frame_size *
59 ring->layout.tp_block_nr;
60 if (v3) {
61 /* Pass out, if this will ever change and we do crap on it! */
62 build_bug_on(offsetof(struct tpacket_req, tp_frame_nr) !=
63 offsetof(struct tpacket_req3, tp_frame_nr) &&
64 sizeof(struct tpacket_req) !=
65 offsetof(struct tpacket_req3, tp_retire_blk_tov));
67 ring->layout3.tp_retire_blk_tov = 100; /* 0: let kernel decide */
68 ring->layout3.tp_sizeof_priv = 0;
69 ring->layout3.tp_feature_req_word = 0;
71 set_sockopt_tpacket_v3(sock);
72 } else {
73 set_sockopt_tpacket_v2(sock);
76 ring_verify_layout(ring);
79 void create_rx_ring(int sock, struct ring *ring, int verbose)
81 int ret;
82 bool v3 = get_sockopt_tpacket(sock) == TPACKET_V3;
84 retry:
85 ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &ring->raw,
86 v3 ? sizeof(ring->layout3) : sizeof(ring->layout));
88 if (errno == ENOMEM && ring->layout.tp_block_nr > 1) {
89 ring->layout.tp_block_nr >>= 1;
90 ring->layout.tp_frame_nr = ring->layout.tp_block_size /
91 ring->layout.tp_frame_size *
92 ring->layout.tp_block_nr;
93 goto retry;
95 if (ret < 0)
96 panic("Cannot allocate RX_RING!\n");
98 ring->mm_len = ring->layout.tp_block_size * ring->layout.tp_block_nr;
100 if (verbose) {
101 if (!v3) {
102 printf("RX,V2: %.2Lf MiB, %u Frames, each %u Byte allocated\n",
103 (long double) ring->mm_len / (1 << 20),
104 ring->layout.tp_frame_nr, ring->layout.tp_frame_size);
105 } else {
106 printf("RX,V3: %.2Lf MiB, %u Blocks, each %u Byte allocated\n",
107 (long double) ring->mm_len / (1 << 20),
108 ring->layout.tp_block_nr, ring->layout.tp_block_size);
113 void mmap_rx_ring(int sock, struct ring *ring)
115 mmap_ring_generic(sock, ring);
118 void alloc_rx_ring_frames(int sock, struct ring *ring)
120 int num;
121 size_t size;
122 bool v3 = get_sockopt_tpacket(sock) == TPACKET_V3;
124 if (v3) {
125 num = ring->layout3.tp_block_nr;
126 size = ring->layout3.tp_block_size;
127 } else {
128 num = ring->layout.tp_frame_nr;
129 size = ring->layout.tp_frame_size;
132 alloc_ring_frames_generic(ring, num, size);
135 void bind_rx_ring(int sock, struct ring *ring, int ifindex)
137 bind_ring_generic(sock, ring, ifindex, false);
140 void sock_rx_net_stats(int sock, unsigned long seen)
142 int ret;
143 bool v3 = get_sockopt_tpacket(sock) == TPACKET_V3;
144 union {
145 struct tpacket_stats k2;
146 struct tpacket_stats_v3 k3;
147 } stats;
148 socklen_t slen = v3 ? sizeof(stats.k3) : sizeof(stats.k2);
150 memset(&stats, 0, sizeof(stats));
151 ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &stats, &slen);
152 if (ret > -1) {
153 uint64_t packets = stats.k3.tp_packets;
154 uint64_t drops = stats.k3.tp_drops;
156 printf("\r%12ld packets incoming (%ld unread on exit)\n",
157 v3 ? seen : packets, v3 ? packets - seen : 0);
158 printf("\r%12ld packets passed filter\n", packets - drops);
159 printf("\r%12ld packets failed filter (out of space)\n", drops);
160 if (stats.k3.tp_packets > 0)
161 printf("\r%12.4lf%% packet droprate\n",
162 (1.0 * drops / packets) * 100.0);