From 0f765f49ac231d99f493f00c0f0986fbeff2615d Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 31 May 2013 11:46:02 +0200 Subject: ring: move duplicate/generic code parts from rx/tx into ring.c We do not want to maintain duplicate code, so move this into a separate file and name those *_generic() helpers. Signed-off-by: Daniel Borkmann --- astraceroute/Makefile | 1 + netsniff-ng/Makefile | 1 + ring.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ ring.h | 4 ++++ ring_rx.c | 43 +++++----------------------------- ring_tx.c | 43 +++++++--------------------------- trafgen/Makefile | 1 + 7 files changed, 85 insertions(+), 72 deletions(-) create mode 100644 ring.c diff --git a/astraceroute/Makefile b/astraceroute/Makefile index 91f0a9e..36e37f0 100644 --- a/astraceroute/Makefile +++ b/astraceroute/Makefile @@ -10,4 +10,5 @@ astraceroute-objs = xmalloc.o \ bpf.o \ geoip.o \ ring_rx.o \ + ring.o \ astraceroute.o diff --git a/netsniff-ng/Makefile b/netsniff-ng/Makefile index b50778f..211c726 100644 --- a/netsniff-ng/Makefile +++ b/netsniff-ng/Makefile @@ -44,6 +44,7 @@ netsniff-ng-objs = dissector.o \ pcap_mm.o \ ring_rx.o \ ring_tx.o \ + ring.o \ tprintf.o \ tstamping.o \ geoip.o \ diff --git a/ring.c b/ring.c new file mode 100644 index 0000000..2899df3 --- /dev/null +++ b/ring.c @@ -0,0 +1,64 @@ +/* + * netsniff-ng - the packet sniffing beast + * Copyright 2009, 2010 Daniel Borkmann. + * Subject to the GPL, version 2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xmalloc.h" +#include "die.h" +#include "ring.h" +#include "built_in.h" + +void mmap_ring_generic(int sock, struct ring *ring) +{ + ring->mm_space = mmap(0, ring->mm_len, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_LOCKED | MAP_POPULATE, sock, 0); + if (ring->mm_space == MAP_FAILED) + panic("Cannot mmap {TX,RX}_RING!\n"); +} + +void alloc_ring_frames_generic(struct ring *ring) +{ + int i; + size_t len = ring->layout.tp_frame_nr * sizeof(*ring->frames); + + ring->frames = xmalloc_aligned(len, CO_CACHE_LINE_SIZE); + fmemset(ring->frames, 0, len); + + for (i = 0; i < ring->layout.tp_frame_nr; ++i) { + ring->frames[i].iov_len = ring->layout.tp_frame_size; + ring->frames[i].iov_base = ring->mm_space + + (i * ring->layout.tp_frame_size); + } +} + +void bind_ring_generic(int sock, struct ring *ring, int ifindex) +{ + int ret; + /* The {TX,RX}_RING registers itself to the networking stack with + * dev_add_pack(), so we have one single RX_RING for all devs + * otherwise you'll get the packet twice. + */ + fmemset(&ring->s_ll, 0, sizeof(ring->s_ll)); + + ring->s_ll.sll_family = AF_PACKET; + ring->s_ll.sll_protocol = htons(ETH_P_ALL); + ring->s_ll.sll_ifindex = ifindex; + ring->s_ll.sll_hatype = 0; + ring->s_ll.sll_halen = 0; + ring->s_ll.sll_pkttype = 0; + + ret = bind(sock, (struct sockaddr *) &ring->s_ll, sizeof(ring->s_ll)); + if (ret < 0) + panic("Cannot bind {TX,RX}_RING!\n"); +} diff --git a/ring.h b/ring.h index 1074e8d..93edb01 100644 --- a/ring.h +++ b/ring.h @@ -141,4 +141,8 @@ static inline int get_sockopt_tpacket(int sock) return __get_sockopt_tpacket(sock); } +extern void mmap_ring_generic(int sock, struct ring *ring); +extern void alloc_ring_frames_generic(struct ring *ring); +extern void bind_ring_generic(int sock, struct ring *ring, int ifindex); + #endif /* RING_H */ diff --git a/ring_rx.c b/ring_rx.c index a3d8e4d..de19568 100644 --- a/ring_rx.c +++ b/ring_rx.c @@ -43,9 +43,11 @@ void setup_rx_ring_layout(int sock, struct ring *ring, unsigned int size, ring->layout.tp_block_size = (jumbo_support ? getpagesize() << 4 : getpagesize() << 2); + ring->layout.tp_frame_size = (jumbo_support ? TPACKET_ALIGNMENT << 12 : TPACKET_ALIGNMENT << 7); + ring->layout.tp_block_nr = size / ring->layout.tp_block_size; ring->layout.tp_frame_nr = ring->layout.tp_block_size / ring->layout.tp_frame_size * @@ -77,6 +79,7 @@ void create_rx_ring(int sock, struct ring *ring, int verbose) retry: ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &ring->raw, v3 ? sizeof(ring->layout3) : sizeof(ring->layout)); + if (errno == ENOMEM && ring->layout.tp_block_nr > 1) { ring->layout.tp_block_nr >>= 1; ring->layout.tp_frame_nr = ring->layout.tp_block_size / @@ -98,49 +101,15 @@ retry: void mmap_rx_ring(int sock, struct ring *ring) { - ring->mm_space = mmap(0, ring->mm_len, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_LOCKED | MAP_POPULATE, sock, 0); - if (ring->mm_space == MAP_FAILED) { - destroy_rx_ring(sock, ring); - panic("Cannot mmap RX_RING!\n"); - } + mmap_ring_generic(sock, ring); } void alloc_rx_ring_frames(struct ring *ring) { - int i; - size_t len = ring->layout.tp_frame_nr * sizeof(*ring->frames); - - ring->frames = xmalloc_aligned(len, CO_CACHE_LINE_SIZE); - fmemset(ring->frames, 0, len); - - for (i = 0; i < ring->layout.tp_frame_nr; ++i) { - ring->frames[i].iov_len = ring->layout.tp_frame_size; - ring->frames[i].iov_base = ring->mm_space + - (i * ring->layout.tp_frame_size); - } + alloc_ring_frames_generic(ring); } void bind_rx_ring(int sock, struct ring *ring, int ifindex) { - int ret; - /* - * The RX_RING registers itself to the networking stack with - * dev_add_pack(), so we have one single RX_RING for all devs - * otherwise you'll get the packet twice. - */ - fmemset(&ring->s_ll, 0, sizeof(ring->s_ll)); - - ring->s_ll.sll_family = AF_PACKET; - ring->s_ll.sll_protocol = htons(ETH_P_ALL); - ring->s_ll.sll_ifindex = ifindex; - ring->s_ll.sll_hatype = 0; - ring->s_ll.sll_halen = 0; - ring->s_ll.sll_pkttype = 0; - - ret = bind(sock, (struct sockaddr *) &ring->s_ll, sizeof(ring->s_ll)); - if (ret < 0) { - destroy_rx_ring(sock, ring); - panic("Cannot bind RX_RING!\n"); - } + bind_ring_generic(sock, ring, ifindex); } diff --git a/ring_tx.c b/ring_tx.c index f4f06a1..18216ac 100644 --- a/ring_tx.c +++ b/ring_tx.c @@ -53,25 +53,28 @@ void setup_tx_ring_layout(int sock, struct ring *ring, unsigned int size, ring->layout.tp_block_size = (jumbo_support ? getpagesize() << 4 : getpagesize() << 2); + ring->layout.tp_frame_size = (jumbo_support ? TPACKET_ALIGNMENT << 12 : TPACKET_ALIGNMENT << 7); + ring->layout.tp_block_nr = size / ring->layout.tp_block_size; ring->layout.tp_frame_nr = ring->layout.tp_block_size / ring->layout.tp_frame_size * ring->layout.tp_block_nr; + set_sockopt_tpacket_v2(sock); + ring_verify_layout(ring); } void create_tx_ring(int sock, struct ring *ring, int verbose) { int ret; - - set_sockopt_tpacket_v2(sock); retry: ret = setsockopt(sock, SOL_PACKET, PACKET_TX_RING, &ring->layout, sizeof(ring->layout)); + if (errno == ENOMEM && ring->layout.tp_block_nr > 1) { ring->layout.tp_block_nr >>= 1; ring->layout.tp_frame_nr = ring->layout.tp_block_size / @@ -94,45 +97,15 @@ retry: void mmap_tx_ring(int sock, struct ring *ring) { - ring->mm_space = mmap(0, ring->mm_len, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_LOCKED | MAP_POPULATE, sock, 0); - if (ring->mm_space == MAP_FAILED) { - destroy_tx_ring(sock, ring); - panic("Cannot mmap TX_RING!\n"); - } + mmap_ring_generic(sock, ring); } void alloc_tx_ring_frames(struct ring *ring) { - int i; - size_t len = ring->layout.tp_frame_nr * sizeof(*ring->frames); - - ring->frames = xmalloc_aligned(len, CO_CACHE_LINE_SIZE); - fmemset(ring->frames, 0, len); - - for (i = 0; i < ring->layout.tp_frame_nr; ++i) { - ring->frames[i].iov_len = ring->layout.tp_frame_size; - ring->frames[i].iov_base = ring->mm_space + - (i * ring->layout.tp_frame_size); - } + alloc_ring_frames_generic(ring); } void bind_tx_ring(int sock, struct ring *ring, int ifindex) { - int ret; - - fmemset(&ring->s_ll, 0, sizeof(ring->s_ll)); - - ring->s_ll.sll_family = AF_PACKET; - ring->s_ll.sll_protocol = htons(ETH_P_ALL); - ring->s_ll.sll_ifindex = ifindex; - ring->s_ll.sll_hatype = 0; - ring->s_ll.sll_halen = 0; - ring->s_ll.sll_pkttype = 0; - - ret = bind(sock, (struct sockaddr *) &ring->s_ll, sizeof(ring->s_ll)); - if (ret < 0) { - destroy_tx_ring(sock, ring); - panic("Cannot bind TX_RING!\n"); - } + bind_ring_generic(sock, ring, ifindex); } diff --git a/trafgen/Makefile b/trafgen/Makefile index b34b98c..8257ad1 100644 --- a/trafgen/Makefile +++ b/trafgen/Makefile @@ -7,6 +7,7 @@ trafgen-objs = xmalloc.o \ xutils.o \ mac80211.o \ ring_tx.o \ + ring.o \ trafgen_lexer.yy.o \ trafgen_parser.tab.o \ trafgen.o -- cgit v1.2.3-54-g00ecf