From: Ken-ichirou MATSUZAWA <chamaken@gmail.com>
To: Pablo Neira Ayuso <pablo@netfilter.org>, netfilter-devel@vger.kernel.org
Subject: [libmnl PATCH 4/9] mmap: add helper - nonmin1
Date: Sun, 08 Dec 2013 00:12:18 +0900 [thread overview]
Message-ID: <87ob4s8zl9.wl%chamaken@gmail.com> (raw)
[-- Attachment #0: Type: message/rfc822, Size: 5558 bytes --]
* 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@h4.dion.ne.jp>
---
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
reply other threads:[~2013-12-07 15:12 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87ob4s8zl9.wl%chamaken@gmail.com \
--to=chamaken@gmail.com \
--cc=netfilter-devel@vger.kernel.org \
--cc=pablo@netfilter.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.