build: move trafgen_stddef.h to stddef.h
[netsniff-ng.git] / ring_rx.c
blob3c701da6c72426cf84842be68b17aab2abb9c94f
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 getpagesize() << 4 :
50 getpagesize() << 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 printf("RX: %.2Lf MiB, %u Frames, each %u Byte allocated\n",
102 (long double) ring->mm_len / (1 << 20),
103 ring->layout.tp_frame_nr, ring->layout.tp_frame_size);
107 void mmap_rx_ring(int sock, struct ring *ring)
109 mmap_ring_generic(sock, ring);
112 void alloc_rx_ring_frames(int sock, struct ring *ring)
114 int num;
115 size_t size;
116 bool v3 = get_sockopt_tpacket(sock) == TPACKET_V3;
118 if (v3) {
119 num = ring->layout3.tp_block_nr;
120 size = ring->layout3.tp_block_size;
121 } else {
122 num = ring->layout.tp_frame_nr;
123 size = ring->layout.tp_frame_size;
126 alloc_ring_frames_generic(ring, num, size);
129 void bind_rx_ring(int sock, struct ring *ring, int ifindex)
131 bind_ring_generic(sock, ring, ifindex);
134 void sock_rx_net_stats(int sock, unsigned long seen)
136 int ret;
137 bool v3 = get_sockopt_tpacket(sock) == TPACKET_V3;
138 union {
139 struct tpacket_stats k2;
140 struct tpacket_stats_v3 k3;
141 } stats;
142 socklen_t slen = v3 ? sizeof(stats.k3) : sizeof(stats.k2);
144 memset(&stats, 0, sizeof(stats));
145 ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &stats, &slen);
146 if (ret > -1) {
147 uint64_t packets = stats.k3.tp_packets;
148 uint64_t drops = stats.k3.tp_drops;
150 printf("\r%12ld packets incoming (%ld unread on exit)\n",
151 v3 ? seen : packets, v3 ? packets - seen : 0);
152 printf("\r%12ld packets passed filter\n", packets - drops);
153 printf("\r%12ld packets failed filter (out of space)\n", drops);
154 if (stats.k3.tp_packets > 0)
155 printf("\r%12.4lf%% packet droprate\n",
156 (1.0 * drops / packets) * 100.0);