diff options
author | Patrick McHardy <kaber@trash.net> | 2012-01-26 10:57:09 +0000 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-08-20 13:19:20 +0200 |
commit | c090ef012f7c373e128c93068e6b77d7379a93a8 (patch) | |
tree | 0b54019fc111e80a5150e68b844b0c356cbd649b | |
parent | 79aecc8c611a246f13b0bb8ba80e31b19930e463 (diff) | |
download | libmnl-c090ef012f7c373e128c93068e6b77d7379a93a8.tar.gz |
socket: memory mapped netlink I/O support
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | Make_global.am | 2 | ||||
-rw-r--r-- | include/libmnl/libmnl.h | 8 | ||||
-rw-r--r-- | src/libmnl.map | 3 | ||||
-rw-r--r-- | src/socket.c | 62 |
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() |