--- Begin Message ---
* mnl_ring_send
Just wraping mnl_socket_sendto
* mnl_ring_poll
used nl-mmap branch examples
* mnl_ring_poll_rxframe
wait and get rx frame in single call using
mnl_ring_poll below
* mnl_ring_discard_frames
mark unused to all frame
Signed-off-by: Ken-ichirou MATSUZAWA <chamas@xxxxxxxxxxxxx>
---
include/libmnl/libmnl.h | 6 ++
src/libmnl.map | 4 ++
src/mmap.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 169 insertions(+)
diff --git a/include/libmnl/libmnl.h b/include/libmnl/libmnl.h
index 11abb04..a8991ce 100644
--- a/include/libmnl/libmnl.h
+++ b/include/libmnl/libmnl.h
@@ -223,6 +223,12 @@ extern int mnl_ring_unmap(struct mnl_ring_socket *nlm);
extern struct nl_mmap_hdr *mnl_ring_get_frame(struct mnl_ring_socket *nlm, enum mnl_ring_types type);
extern int mnl_ring_advance(struct mnl_ring_socket *nlm, enum mnl_ring_types type);
+/* non-minimalistic 1 [nonmin1] */
+extern ssize_t mnl_ring_send(struct mnl_ring_socket *nlm);
+extern int mnl_ring_poll(const struct mnl_ring_socket *nlm, int timeout);
+extern struct nl_mmap_hdr *mnl_ring_poll_rxframe(struct mnl_ring_socket *nlm);
+extern int mnl_ring_discard_frames(struct mnl_ring_socket *nlm, enum mnl_ring_types type);
+
/*
* other declarations
*/
diff --git a/src/libmnl.map b/src/libmnl.map
index 73de08f..2a36a5c 100644
--- a/src/libmnl.map
+++ b/src/libmnl.map
@@ -78,4 +78,8 @@ LIBMNL_1.2 {
mnl_ring_unmap;
mnl_ring_get_frame;
mnl_ring_advance;
+ mnl_ring_send;
+ mnl_ring_poll;
+ mnl_ring_poll_rxframe;
+ mnl_ring_discard_frames;
} LIBMNL_1.1;
diff --git a/src/mmap.c b/src/mmap.c
index 348fa89..78fbb1f 100644
--- a/src/mmap.c
+++ b/src/mmap.c
@@ -225,3 +225,162 @@ EXPORT_SYMBOL(mnl_ring_advance);
/**
* @}
*/
+
+/**
+ * mnl_ring_send - sending notification
+ * \param nlm ring descriptor
+ *
+ * Just wraping mnl_socket_sendto
+ */
+ssize_t mnl_ring_send(struct mnl_ring_socket *nlm)
+{
+ ssize_t ret;
+ int err;
+ socklen_t errlen = sizeof(err);
+
+ ret = mnl_socket_sendto(nlm->sock, NULL, 0);
+ if (ret < 0)
+ return ret;
+ /*
+ * single frame with multiple message which requires ack may
+ * cause ENOBUFS. Should we check here? or in mnl_ring_poll() below
+ */
+ if (getsockopt(mnl_socket_get_fd(nlm->sock), SOL_SOCKET, SO_ERROR, &err, &errlen) < 0)
+ return -1;
+ if (err) {
+ errno = err;
+ return -1;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(mnl_ring_send);
+
+/**
+ * mnl_ring_poll - wait for receiving
+ * \param nlm ring descriptor
+ * \timeout timeout sec
+ *
+ * This is used nl-mmap branch examples
+ */
+int mnl_ring_poll(const struct mnl_ring_socket *nlm, int timeout)
+{
+ int ret, err;
+ socklen_t errlen = sizeof(err);
+ struct pollfd pfds[1];
+
+ pfds[0].fd = mnl_socket_get_fd(nlm->sock);
+ pfds[0].events = POLLIN | POLLERR;
+ pfds[0].revents = 0;
+
+ while (1) {
+ ret = poll(pfds, 1, timeout);
+ if (ret == 0)
+ return ret;
+
+ if (ret < 0) {
+ if (errno != EINTR)
+ return ret;
+ continue;
+ }
+
+ /* Check for errors */
+ if (pfds[0].revents & POLLERR) {
+ if (getsockopt(pfds[0].fd, SOL_SOCKET, SO_ERROR, &err, &errlen) < 0)
+ return -1;
+ errno = err;
+ return -1;
+ }
+
+ if (pfds[0].revents & POLLIN)
+ return ret;
+ }
+}
+EXPORT_SYMBOL(mnl_ring_poll);
+
+/**
+ * mnl_ring_poll_rxframe - wait and get rx frame in single call
+ * \param nlm ring descriptor
+ *
+ * Refering /Documentation/networking/netlink_mmap.txt
+ */
+struct nl_mmap_hdr *mnl_ring_poll_rxframe(struct mnl_ring_socket *nlm)
+{
+ ssize_t len;
+ struct nl_mmap_hdr *hdr;
+ unsigned int started, head;
+ int ret;
+
+ hdr = mnl_ring_get_frame(nlm, MNL_RING_RX);
+ if (hdr == NULL)
+ return NULL;
+poll:
+ while (hdr->nm_status != NL_MMAP_STATUS_VALID && hdr->nm_status != NL_MMAP_STATUS_COPY) {
+ ret = mnl_ring_poll(nlm, -1);
+ if (ret < 0)
+ return NULL;
+ hdr = mnl_ring_get_frame(nlm, MNL_RING_RX);
+ }
+
+ started = nlm->rx_ring->head;
+ while (1) {
+ if (hdr->nm_status == NL_MMAP_STATUS_VALID) {
+ /* Regular memory mapped frame */
+
+ /* Release empty message immediately. May happen
+ * on error during message construction
+ */
+ if (hdr->nm_len == 0) {
+ hdr->nm_status = NL_MMAP_STATUS_UNUSED;
+ head = mnl_ring_advance(nlm, MNL_RING_RX);
+ if (started == head)
+ goto poll;
+ continue;
+ }
+ return hdr;
+ } else if (hdr->nm_status == NL_MMAP_STATUS_COPY) {
+ /* Frame queued to socket receive queue */
+
+ /* dirty hack to return nl_mmap_hdr, can I? */
+ len = mnl_socket_recvfrom(nlm->sock, hdr + NL_MMAP_HDRLEN,
+ nlm->rx_ring->frame_size - NL_MMAP_HDRLEN);
+ if (len <= 0) {
+ hdr->nm_status = NL_MMAP_STATUS_UNUSED;
+ goto poll; /* not cotinue? */
+ }
+ return hdr;
+ }
+ }
+}
+EXPORT_SYMBOL(mnl_ring_poll_rxframe);
+
+/**
+ * mnl_ring_discard_frames - set NL_MMAP_STATUS_UNUSED all frame
+ * \param nlm ring descriptor
+ * \param type ring type either MNL_RING_RX or MNL_RING_TX
+ *
+ * This can be implemented by minimalistic functions but
+ * it seems tedious
+ */
+int mnl_ring_discard_frames(struct mnl_ring_socket *nlm, enum mnl_ring_types type)
+{
+ struct mnl_ring *ring;
+ struct nl_mmap_hdr *hdr;
+ unsigned int start;
+
+ ring = get_mnl_ring(nlm, type);
+ if (ring == NULL) {
+ errno = EBADR;
+ return -1;
+ }
+
+ start = ring->head;
+ do {
+ hdr = mnl_ring_get_frame(nlm, type);
+ hdr->nm_status = NL_MMAP_STATUS_UNUSED;
+ mnl_ring_advance(nlm, type);
+ } while (ring->head != start);
+
+ return 1;
+}
+EXPORT_SYMBOL(mnl_ring_discard_frames);
--
1.8.4.rc3
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
--- End Message ---