[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20171225084658.24076-2-chrism@mellanox.com>
Date: Mon, 25 Dec 2017 17:46:55 +0900
From: Chris Mi <chrism@...lanox.com>
To: netdev@...r.kernel.org
Cc: gerlitz.or@...il.com, stephen@...workplumber.org, dsahern@...il.com
Subject: [patch iproute2 v3 1/4] lib/libnetlink: Add a function rtnl_talk_msg
rtnl_talk can only send a single message to kernel. Add a new function
rtnl_talk_msg that can send multiple messages to kernel.
Signed-off-by: Chris Mi <chrism@...lanox.com>
---
include/libnetlink.h | 3 ++
lib/libnetlink.c | 92 ++++++++++++++++++++++++++++++++++++++++------------
2 files changed, 74 insertions(+), 21 deletions(-)
diff --git a/include/libnetlink.h b/include/libnetlink.h
index a4d83b9e..e95fad75 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -96,6 +96,9 @@ 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_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..f5f675cf 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -581,36 +581,21 @@ 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_check_ack(struct rtnl_handle *rtnl, struct nlmsghdr **answer,
+ bool show_rtnl_err, nl_ext_ack_fn_t errfn,
+ unsigned int seq)
{
int status;
- unsigned int seq;
- struct nlmsghdr *h;
+ char *buf;
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
- struct iovec iov = {
- .iov_base = n,
- .iov_len = n->nlmsg_len
- };
+ struct nlmsghdr *h;
+ struct iovec iov;
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
- char *buf;
-
- n->nlmsg_seq = seq = ++rtnl->seq;
-
- if (answer == NULL)
- n->nlmsg_flags |= NLM_F_ACK;
-
- status = sendmsg(rtnl->fd, &msg, 0);
- if (status < 0) {
- perror("Cannot talk to rtnetlink");
- return -1;
- }
while (1) {
status = rtnl_recvmsg(rtnl->fd, &msg, &buf);
@@ -698,12 +683,77 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
}
}
+static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
+ struct nlmsghdr **answer,
+ bool show_rtnl_err, nl_ext_ack_fn_t errfn)
+{
+ unsigned int seq;
+ int status;
+ struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
+ struct iovec iov = {
+ .iov_base = n,
+ .iov_len = n->nlmsg_len
+ };
+ struct msghdr msg = {
+ .msg_name = &nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+
+ n->nlmsg_seq = seq = ++rtnl->seq;
+
+ if (answer == NULL)
+ n->nlmsg_flags |= NLM_F_ACK;
+
+ status = sendmsg(rtnl->fd, &msg, 0);
+ if (status < 0) {
+ perror("Cannot talk to rtnetlink");
+ return -1;
+ }
+
+ return __rtnl_check_ack(rtnl, answer, show_rtnl_err, errfn, seq);
+}
+
+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 iovlen = m->msg_iovlen;
+ unsigned int seq = 0;
+ struct nlmsghdr *n;
+ struct iovec *v;
+ int i, status;
+
+ for (i = 0; i < iovlen; i++) {
+ v = &m->msg_iov[i];
+ n = v->iov_base;
+ n->nlmsg_seq = seq = ++rtnl->seq;
+ if (answer == NULL)
+ n->nlmsg_flags |= NLM_F_ACK;
+ }
+
+ status = sendmsg(rtnl->fd, m, 0);
+ if (status < 0) {
+ perror("Cannot talk to rtnetlink");
+ return -1;
+ }
+
+ return __rtnl_check_ack(rtnl, answer, show_rtnl_err, errfn, seq);
+}
+
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_extack(struct rtnl_handle *rtnl, struct nlmsghdr *n,
struct nlmsghdr **answer,
nl_ext_ack_fn_t errfn)
--
2.14.3
Powered by blists - more mailing lists