summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2012-01-26 10:57:09 +0000
committerPablo Neira Ayuso <pablo@netfilter.org>2012-08-20 13:19:20 +0200
commitc090ef012f7c373e128c93068e6b77d7379a93a8 (patch)
tree0b54019fc111e80a5150e68b844b0c356cbd649b
parent79aecc8c611a246f13b0bb8ba80e31b19930e463 (diff)
downloadlibmnl-c090ef012f7c373e128c93068e6b77d7379a93a8.tar.gz
socket: memory mapped netlink I/O support
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--Make_global.am2
-rw-r--r--include/libmnl/libmnl.h8
-rw-r--r--src/libmnl.map3
-rw-r--r--src/socket.c62
4 files changed, 74 insertions, 1 deletions
diff --git a/Make_global.am b/Make_global.am
index 3665b68..c538f09 100644
--- a/Make_global.am
+++ b/Make_global.am
@@ -21,4 +21,4 @@
LIBVERSION=1:0:1
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_srcdir}/include
-AM_CFLAGS = ${regular_CFLAGS} ${GCC_FVISIBILITY_HIDDEN}
+AM_CFLAGS = ${regular_CFLAGS} ${GCC_FVISIBILITY_HIDDEN} -D_GNU_SOURCE
diff --git a/include/libmnl/libmnl.h b/include/libmnl/libmnl.h
index a647fd9..9b32630 100644
--- a/include/libmnl/libmnl.h
+++ b/include/libmnl/libmnl.h
@@ -26,8 +26,16 @@ extern "C" {
struct mnl_socket;
+enum mnl_ring_types {
+ MNL_RING_RX,
+ MNL_RING_TX,
+};
+
extern struct mnl_socket *mnl_socket_open(int type);
extern int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid);
+extern int mnl_socket_set_ring(struct mnl_socket *nl, unsigned int rx_size, unsigned int tx_size);
+extern struct nl_mmap_hdr *mnl_socket_get_frame(struct mnl_socket *nl, enum mnl_ring_types type);
+extern void mnl_socket_advance_ring(struct mnl_socket *nl, enum mnl_ring_types type);
extern int mnl_socket_close(struct mnl_socket *nl);
extern int mnl_socket_get_fd(const struct mnl_socket *nl);
extern unsigned int mnl_socket_get_portid(const struct mnl_socket *nl);
diff --git a/src/libmnl.map b/src/libmnl.map
index dbc332e..8216b19 100644
--- a/src/libmnl.map
+++ b/src/libmnl.map
@@ -57,6 +57,9 @@ global:
mnl_nlmsg_batch_head;
mnl_nlmsg_batch_is_empty;
mnl_socket_bind;
+ mnl_socket_set_ring;
+ mnl_socket_get_frame;
+ mnl_socket_advance_ring;
mnl_socket_close;
mnl_socket_get_fd;
mnl_socket_get_portid;
diff --git a/src/socket.c b/src/socket.c
index 6d54563..d6f5604 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -10,6 +10,7 @@
#include <libmnl/libmnl.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
@@ -66,9 +67,18 @@
* code tree.
*/
+struct mnl_ring {
+ unsigned int head;
+ void *ring;
+};
+
struct mnl_socket {
int fd;
struct sockaddr_nl addr;
+ unsigned int frame_size;
+ unsigned int frame_nr;
+ struct mnl_ring rx_ring;
+ struct mnl_ring tx_ring;
};
/**
@@ -168,6 +178,58 @@ int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid)
}
EXPORT_SYMBOL(mnl_socket_bind);
+int mnl_socket_set_ring(struct mnl_socket *nl, unsigned int rx_size,
+ unsigned int tx_size)
+{
+ struct nl_mmap_req req = {
+ .nm_block_size = 16 * 4096,
+ .nm_block_nr = 64,
+ .nm_frame_size = 16384,
+ .nm_frame_nr = 256,
+ };
+ unsigned int size;
+ void *ring;
+
+ if (mnl_socket_setsockopt(nl, NETLINK_RX_RING, &req, sizeof(req)) < 0)
+ return -1;
+ if (mnl_socket_setsockopt(nl, NETLINK_TX_RING, &req, sizeof(req)) < 0)
+ return -1;
+
+ size = req.nm_block_nr * req.nm_block_size;
+ ring = mmap(NULL, 2 * size, PROT_READ | PROT_WRITE, MAP_SHARED, nl->fd, 0);
+ if ((long)ring == -1L)
+ return -1;
+
+ nl->frame_size = req.nm_frame_size;
+ nl->frame_nr = req.nm_frame_nr - 1;
+ nl->rx_ring.ring = ring;
+ nl->rx_ring.head = 0;
+ nl->tx_ring.ring = ring + size;
+ nl->tx_ring.head = 0;
+
+ return 0;
+}
+EXPORT_SYMBOL(mnl_socket_set_ring);
+
+struct nl_mmap_hdr *mnl_socket_get_frame(struct mnl_socket *nl,
+ enum mnl_ring_types type)
+{
+ struct mnl_ring *ring;
+
+ ring = type == MNL_RING_RX ? &nl->rx_ring : &nl->tx_ring;
+ return ring->ring + ring->head * nl->frame_size;
+}
+EXPORT_SYMBOL(mnl_socket_get_frame);
+
+void mnl_socket_advance_ring(struct mnl_socket *nl, enum mnl_ring_types type)
+{
+ struct mnl_ring *ring;
+
+ ring = type == MNL_RING_RX ? &nl->rx_ring : &nl->tx_ring;
+ ring->head = ring->head != nl->frame_nr ? ring->head + 1 : 0;
+}
+EXPORT_SYMBOL(mnl_socket_advance_ring);
+
/**
* mnl_socket_sendto - send a netlink message of a certain size
* \param nl netlink socket obtained via mnl_socket_open()