From: Chris Mi <chrism@mellanox.com>
To: netdev@vger.kernel.org
Cc: gerlitz.or@gmail.com, stephen@networkplumber.org,
dsahern@gmail.com, marcelo.leitner@gmail.com, phil@nwl.cc
Subject: [patch iproute2 v8 1/2] lib/libnetlink: Add functions rtnl_talk_msg and rtnl_talk_iov
Date: Wed, 10 Jan 2018 12:27:41 +0900 [thread overview]
Message-ID: <20180110032742.8127-2-chrism@mellanox.com> (raw)
In-Reply-To: <20180110032742.8127-1-chrism@mellanox.com>
rtnl_talk can only send a single message to kernel. Add two functions
rtnl_talk_msg and rtnl_talk_iov that can send multiple messages to kernel.
rtnl_talk_msg takes struct msghdr * as argument.
rtnl_talk_iov takes struct iovec * and iovlen as arguments.
Signed-off-by: Chris Mi <chrism@mellanox.com>
---
include/libnetlink.h | 6 ++++
lib/libnetlink.c | 82 ++++++++++++++++++++++++++++++++++++++++------------
2 files changed, 70 insertions(+), 18 deletions(-)
diff --git a/include/libnetlink.h b/include/libnetlink.h
index a4d83b9e..e9a63dbc 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -96,6 +96,12 @@ int rtnl_dump_filter_nc(struct rtnl_handle *rth,
int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
struct nlmsghdr **answer)
__attribute__((warn_unused_result));
+int rtnl_talk_msg(struct rtnl_handle *rtnl, struct msghdr *m,
+ struct nlmsghdr **answer)
+ __attribute__((warn_unused_result));
+int rtnl_talk_iov(struct rtnl_handle *rtnl, struct iovec *iovec, size_t iovlen,
+ struct nlmsghdr **answer)
+ __attribute__((warn_unused_result));
int rtnl_talk_extack(struct rtnl_handle *rtnl, struct nlmsghdr *n,
struct nlmsghdr **answer, nl_ext_ack_fn_t errfn)
__attribute__((warn_unused_result));
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index 00e6ce0c..183825c7 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -581,39 +581,43 @@ static void rtnl_talk_error(struct nlmsghdr *h, struct nlmsgerr *err,
strerror(-err->error));
}
-static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
- struct nlmsghdr **answer,
- bool show_rtnl_err, nl_ext_ack_fn_t errfn)
+static int __rtnl_talk_msg(struct rtnl_handle *rtnl, struct msghdr *m,
+ struct nlmsghdr **answer,
+ bool show_rtnl_err, nl_ext_ack_fn_t errfn)
{
- int status;
- unsigned int seq;
- struct nlmsghdr *h;
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
- struct iovec iov = {
- .iov_base = n,
- .iov_len = n->nlmsg_len
- };
+ int i, status, iovlen = m->msg_iovlen;
+ struct iovec iov;
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
+ unsigned int seq = 0;
+ struct nlmsghdr *h;
char *buf;
- n->nlmsg_seq = seq = ++rtnl->seq;
-
- if (answer == NULL)
- n->nlmsg_flags |= NLM_F_ACK;
+ for (i = 0; i < iovlen; i++) {
+ struct iovec *v;
+ v = &m->msg_iov[i];
+ h = v->iov_base;
+ h->nlmsg_seq = seq = ++rtnl->seq;
+ if (answer == NULL)
+ h->nlmsg_flags |= NLM_F_ACK;
+ }
- status = sendmsg(rtnl->fd, &msg, 0);
+ status = sendmsg(rtnl->fd, m, 0);
if (status < 0) {
perror("Cannot talk to rtnetlink");
return -1;
}
+ i = 0;
while (1) {
+next:
status = rtnl_recvmsg(rtnl->fd, &msg, &buf);
+ ++i;
if (status < 0)
return status;
@@ -642,7 +646,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
if (nladdr.nl_pid != 0 ||
h->nlmsg_pid != rtnl->local.nl_pid ||
- h->nlmsg_seq != seq) {
+ h->nlmsg_seq > seq || h->nlmsg_seq < seq - iovlen) {
/* Don't forget to skip that message. */
status -= NLMSG_ALIGN(len);
h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
@@ -662,7 +666,10 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
*answer = (struct nlmsghdr *)buf;
else
free(buf);
- return 0;
+ if (h->nlmsg_seq == seq)
+ return 0;
+ else
+ goto next;
}
if (rtnl->proto != NETLINK_SOCK_DIAG &&
@@ -671,7 +678,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
errno = -err->error;
free(buf);
- return -1;
+ return -i;
}
if (answer) {
@@ -698,12 +705,51 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
}
}
+static int __rtnl_talk_iov(struct rtnl_handle *rtnl, struct iovec *msg_iov,
+ size_t iovlen, struct nlmsghdr **answer,
+ bool show_rtnl_err, nl_ext_ack_fn_t errfn)
+{
+ struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
+ struct msghdr msg = {
+ .msg_name = &nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = msg_iov,
+ .msg_iovlen = iovlen,
+ };
+
+ return __rtnl_talk_msg(rtnl, &msg, answer, show_rtnl_err, errfn);
+}
+
+static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
+ struct nlmsghdr **answer,
+ bool show_rtnl_err, nl_ext_ack_fn_t errfn)
+{
+ struct iovec iov = {
+ .iov_base = n,
+ .iov_len = n->nlmsg_len
+ };
+
+ return __rtnl_talk_iov(rtnl, &iov, 1, answer, show_rtnl_err, errfn);
+}
+
int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
struct nlmsghdr **answer)
{
return __rtnl_talk(rtnl, n, answer, true, NULL);
}
+int rtnl_talk_msg(struct rtnl_handle *rtnl, struct msghdr *m,
+ struct nlmsghdr **answer)
+{
+ return __rtnl_talk_msg(rtnl, m, answer, true, NULL);
+}
+
+int rtnl_talk_iov(struct rtnl_handle *rtnl, struct iovec *iovec, size_t iovlen,
+ struct nlmsghdr **answer)
+{
+ return __rtnl_talk_iov(rtnl, iovec, iovlen, answer, true, NULL);
+}
+
int rtnl_talk_extack(struct rtnl_handle *rtnl, struct nlmsghdr *n,
struct nlmsghdr **answer,
nl_ext_ack_fn_t errfn)
--
2.14.2
next prev parent reply other threads:[~2018-01-10 3:27 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-10 3:27 [patch iproute2 v8 0/2] tc: Add batchsize feature to batch mode Chris Mi
2018-01-10 3:27 ` Chris Mi [this message]
2018-01-10 19:20 ` [patch iproute2 v8 1/2] lib/libnetlink: Add functions rtnl_talk_msg and rtnl_talk_iov David Ahern
2018-01-10 20:12 ` Phil Sutter
2018-01-11 15:08 ` Phil Sutter
2018-01-12 0:06 ` David Ahern
2018-01-11 5:34 ` Chris Mi
2018-01-10 3:27 ` [patch iproute2 v8 2/2] tc: Add batchsize feature for filter and actions Chris Mi
2018-01-10 11:42 ` Marcelo Ricardo Leitner
2018-01-11 5:32 ` Chris Mi
2018-01-10 19:41 ` David Ahern
2018-01-11 5:39 ` Chris Mi
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=20180110032742.8127-2-chrism@mellanox.com \
--to=chrism@mellanox.com \
--cc=dsahern@gmail.com \
--cc=gerlitz.or@gmail.com \
--cc=marcelo.leitner@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=phil@nwl.cc \
--cc=stephen@networkplumber.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).