|
|
36cfb7 |
From 49e7c0e7c8c9a982fd3aa69bbed4e306a1dcb331 Mon Sep 17 00:00:00 2001
|
|
|
36cfb7 |
From: Hangbin Liu <haliu@redhat.com>
|
|
|
36cfb7 |
Date: Wed, 8 Nov 2017 14:39:12 +0800
|
|
|
36cfb7 |
Subject: [PATCH] lib/libnetlink: re malloc buff if size is not enough
|
|
|
36cfb7 |
|
|
|
36cfb7 |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1380803
|
|
|
36cfb7 |
Upstream Status: iproute2.git net-next commit 2d34851cd341
|
|
|
36cfb7 |
|
|
|
36cfb7 |
commit 2d34851cd341f0e1b3fc17ca3e6e874229f3a1f8
|
|
|
36cfb7 |
Author: Hangbin Liu <liuhangbin@gmail.com>
|
|
|
36cfb7 |
Date: Thu Oct 26 09:41:46 2017 +0800
|
|
|
36cfb7 |
|
|
|
36cfb7 |
lib/libnetlink: re malloc buff if size is not enough
|
|
|
36cfb7 |
|
|
|
36cfb7 |
With commit 72b365e8e0fd ("libnetlink: Double the dump buffer size")
|
|
|
36cfb7 |
we doubled the buffer size to support more VFs. But the VFs number is
|
|
|
36cfb7 |
increasing all the time. Some customers even use more than 200 VFs now.
|
|
|
36cfb7 |
|
|
|
36cfb7 |
We could not double it everytime when the buffer is not enough. Let's just
|
|
|
36cfb7 |
not hard code the buffer size and malloc the correct number when running.
|
|
|
36cfb7 |
|
|
|
36cfb7 |
Introduce function rtnl_recvmsg() to always return a newly allocated buffer.
|
|
|
36cfb7 |
The caller need to free it after using.
|
|
|
36cfb7 |
|
|
|
36cfb7 |
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
|
|
|
36cfb7 |
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
|
|
36cfb7 |
|
|
|
36cfb7 |
Signed-off-by: Hangbin Liu <haliu@redhat.com>
|
|
|
36cfb7 |
---
|
|
|
e138d9 |
lib/libnetlink.c | 114 +++++++++++++++++++++++++++++++++--------------
|
|
|
36cfb7 |
1 file changed, 80 insertions(+), 34 deletions(-)
|
|
|
36cfb7 |
|
|
|
36cfb7 |
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
|
|
|
e138d9 |
index a0578312e83f8..446c9605ba19b 100644
|
|
|
36cfb7 |
--- a/lib/libnetlink.c
|
|
|
36cfb7 |
+++ b/lib/libnetlink.c
|
|
|
36cfb7 |
@@ -386,6 +386,64 @@ static void rtnl_dump_error(const struct rtnl_handle *rth,
|
|
|
36cfb7 |
}
|
|
|
36cfb7 |
}
|
|
|
36cfb7 |
|
|
|
36cfb7 |
+static int __rtnl_recvmsg(int fd, struct msghdr *msg, int flags)
|
|
|
36cfb7 |
+{
|
|
|
36cfb7 |
+ int len;
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
+ do {
|
|
|
36cfb7 |
+ len = recvmsg(fd, msg, flags);
|
|
|
36cfb7 |
+ } while (len < 0 && (errno == EINTR || errno == EAGAIN));
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
+ if (len < 0) {
|
|
|
36cfb7 |
+ fprintf(stderr, "netlink receive error %s (%d)\n",
|
|
|
36cfb7 |
+ strerror(errno), errno);
|
|
|
36cfb7 |
+ return -errno;
|
|
|
36cfb7 |
+ }
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
+ if (len == 0) {
|
|
|
36cfb7 |
+ fprintf(stderr, "EOF on netlink\n");
|
|
|
36cfb7 |
+ return -ENODATA;
|
|
|
36cfb7 |
+ }
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
+ return len;
|
|
|
36cfb7 |
+}
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
+static int rtnl_recvmsg(int fd, struct msghdr *msg, char **answer)
|
|
|
36cfb7 |
+{
|
|
|
36cfb7 |
+ struct iovec *iov = msg->msg_iov;
|
|
|
36cfb7 |
+ char *buf;
|
|
|
36cfb7 |
+ int len;
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
+ iov->iov_base = NULL;
|
|
|
36cfb7 |
+ iov->iov_len = 0;
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
+ len = __rtnl_recvmsg(fd, msg, MSG_PEEK | MSG_TRUNC);
|
|
|
36cfb7 |
+ if (len < 0)
|
|
|
36cfb7 |
+ return len;
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
+ buf = malloc(len);
|
|
|
36cfb7 |
+ if (!buf) {
|
|
|
36cfb7 |
+ fprintf(stderr, "malloc error: not enough buffer\n");
|
|
|
36cfb7 |
+ return -ENOMEM;
|
|
|
36cfb7 |
+ }
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
+ iov->iov_base = buf;
|
|
|
36cfb7 |
+ iov->iov_len = len;
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
+ len = __rtnl_recvmsg(fd, msg, 0);
|
|
|
36cfb7 |
+ if (len < 0) {
|
|
|
36cfb7 |
+ free(buf);
|
|
|
36cfb7 |
+ return len;
|
|
|
36cfb7 |
+ }
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
+ if (answer)
|
|
|
36cfb7 |
+ *answer = buf;
|
|
|
36cfb7 |
+ else
|
|
|
36cfb7 |
+ free(buf);
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
+ return len;
|
|
|
36cfb7 |
+}
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
int rtnl_dump_filter_l(struct rtnl_handle *rth,
|
|
|
36cfb7 |
const struct rtnl_dump_filter_arg *arg)
|
|
|
36cfb7 |
{
|
|
|
36cfb7 |
@@ -397,31 +455,18 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
|
|
|
36cfb7 |
.msg_iov = &iov,
|
|
|
36cfb7 |
.msg_iovlen = 1,
|
|
|
36cfb7 |
};
|
|
|
36cfb7 |
- char buf[32768];
|
|
|
36cfb7 |
+ char *buf;
|
|
|
36cfb7 |
int dump_intr = 0;
|
|
|
36cfb7 |
|
|
|
36cfb7 |
- iov.iov_base = buf;
|
|
|
36cfb7 |
while (1) {
|
|
|
36cfb7 |
int status;
|
|
|
36cfb7 |
const struct rtnl_dump_filter_arg *a;
|
|
|
36cfb7 |
int found_done = 0;
|
|
|
36cfb7 |
int msglen = 0;
|
|
|
36cfb7 |
|
|
|
36cfb7 |
- iov.iov_len = sizeof(buf);
|
|
|
36cfb7 |
- status = recvmsg(rth->fd, &msg, 0);
|
|
|
36cfb7 |
-
|
|
|
36cfb7 |
- if (status < 0) {
|
|
|
36cfb7 |
- if (errno == EINTR || errno == EAGAIN)
|
|
|
36cfb7 |
- continue;
|
|
|
36cfb7 |
- fprintf(stderr, "netlink receive error %s (%d)\n",
|
|
|
36cfb7 |
- strerror(errno), errno);
|
|
|
36cfb7 |
- return -1;
|
|
|
36cfb7 |
- }
|
|
|
36cfb7 |
-
|
|
|
36cfb7 |
- if (status == 0) {
|
|
|
36cfb7 |
- fprintf(stderr, "EOF on netlink\n");
|
|
|
36cfb7 |
- return -1;
|
|
|
36cfb7 |
- }
|
|
|
36cfb7 |
+ status = rtnl_recvmsg(rth->fd, &msg, &buf;;
|
|
|
36cfb7 |
+ if (status < 0)
|
|
|
36cfb7 |
+ return status;
|
|
|
36cfb7 |
|
|
|
36cfb7 |
if (rth->dump_fp)
|
|
|
36cfb7 |
fwrite(buf, 1, NLMSG_ALIGN(status), rth->dump_fp);
|
|
|
36cfb7 |
@@ -446,8 +491,10 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
|
|
|
36cfb7 |
|
|
|
36cfb7 |
if (h->nlmsg_type == NLMSG_DONE) {
|
|
|
36cfb7 |
err = rtnl_dump_done(h);
|
|
|
36cfb7 |
- if (err < 0)
|
|
|
36cfb7 |
+ if (err < 0) {
|
|
|
36cfb7 |
+ free(buf);
|
|
|
36cfb7 |
return -1;
|
|
|
36cfb7 |
+ }
|
|
|
36cfb7 |
|
|
|
36cfb7 |
found_done = 1;
|
|
|
36cfb7 |
break; /* process next filter */
|
|
|
36cfb7 |
@@ -455,19 +502,23 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
|
|
|
36cfb7 |
|
|
|
36cfb7 |
if (h->nlmsg_type == NLMSG_ERROR) {
|
|
|
36cfb7 |
rtnl_dump_error(rth, h);
|
|
|
36cfb7 |
+ free(buf);
|
|
|
36cfb7 |
return -1;
|
|
|
36cfb7 |
}
|
|
|
36cfb7 |
|
|
|
36cfb7 |
if (!rth->dump_fp) {
|
|
|
36cfb7 |
err = a->filter(&nladdr, h, a->arg1);
|
|
|
36cfb7 |
- if (err < 0)
|
|
|
36cfb7 |
+ if (err < 0) {
|
|
|
36cfb7 |
+ free(buf);
|
|
|
36cfb7 |
return err;
|
|
|
36cfb7 |
+ }
|
|
|
36cfb7 |
}
|
|
|
36cfb7 |
|
|
|
36cfb7 |
skip_it:
|
|
|
36cfb7 |
h = NLMSG_NEXT(h, msglen);
|
|
|
36cfb7 |
}
|
|
|
36cfb7 |
}
|
|
|
36cfb7 |
+ free(buf);
|
|
|
36cfb7 |
|
|
|
36cfb7 |
if (found_done) {
|
|
|
36cfb7 |
if (dump_intr)
|
|
|
36cfb7 |
@@ -527,7 +578,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
|
|
|
36cfb7 |
.msg_iov = &iov,
|
|
|
36cfb7 |
.msg_iovlen = 1,
|
|
|
36cfb7 |
};
|
|
|
36cfb7 |
- char buf[32768] = {};
|
|
|
36cfb7 |
+ char *buf;
|
|
|
36cfb7 |
|
|
|
36cfb7 |
n->nlmsg_seq = seq = ++rtnl->seq;
|
|
|
36cfb7 |
|
|
|
36cfb7 |
@@ -540,22 +591,12 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
|
|
|
36cfb7 |
return -1;
|
|
|
36cfb7 |
}
|
|
|
36cfb7 |
|
|
|
36cfb7 |
- iov.iov_base = buf;
|
|
|
36cfb7 |
while (1) {
|
|
|
36cfb7 |
- iov.iov_len = sizeof(buf);
|
|
|
36cfb7 |
- status = recvmsg(rtnl->fd, &msg, 0);
|
|
|
36cfb7 |
+ status = rtnl_recvmsg(rtnl->fd, &msg, &buf;;
|
|
|
36cfb7 |
+
|
|
|
36cfb7 |
+ if (status < 0)
|
|
|
36cfb7 |
+ return status;
|
|
|
36cfb7 |
|
|
|
36cfb7 |
- if (status < 0) {
|
|
|
36cfb7 |
- if (errno == EINTR || errno == EAGAIN)
|
|
|
36cfb7 |
- continue;
|
|
|
36cfb7 |
- fprintf(stderr, "netlink receive error %s (%d)\n",
|
|
|
36cfb7 |
- strerror(errno), errno);
|
|
|
36cfb7 |
- return -1;
|
|
|
36cfb7 |
- }
|
|
|
36cfb7 |
- if (status == 0) {
|
|
|
36cfb7 |
- fprintf(stderr, "EOF on netlink\n");
|
|
|
36cfb7 |
- return -1;
|
|
|
36cfb7 |
- }
|
|
|
36cfb7 |
if (msg.msg_namelen != sizeof(nladdr)) {
|
|
|
36cfb7 |
fprintf(stderr,
|
|
|
36cfb7 |
"sender address length == %d\n",
|
|
|
36cfb7 |
@@ -569,6 +610,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
|
|
|
36cfb7 |
if (l < 0 || len > status) {
|
|
|
36cfb7 |
if (msg.msg_flags & MSG_TRUNC) {
|
|
|
36cfb7 |
fprintf(stderr, "Truncated message\n");
|
|
|
36cfb7 |
+ free(buf);
|
|
|
36cfb7 |
return -1;
|
|
|
36cfb7 |
}
|
|
|
36cfb7 |
fprintf(stderr,
|
|
|
36cfb7 |
@@ -595,6 +637,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
|
|
|
36cfb7 |
if (answer)
|
|
|
36cfb7 |
memcpy(answer, h,
|
|
|
36cfb7 |
MIN(maxlen, h->nlmsg_len));
|
|
|
36cfb7 |
+ free(buf);
|
|
|
36cfb7 |
return 0;
|
|
|
36cfb7 |
}
|
|
|
36cfb7 |
|
|
|
36cfb7 |
@@ -603,12 +646,14 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
|
|
|
36cfb7 |
rtnl_talk_error(h, err, errfn);
|
|
|
36cfb7 |
|
|
|
36cfb7 |
errno = -err->error;
|
|
|
36cfb7 |
+ free(buf);
|
|
|
36cfb7 |
return -1;
|
|
|
36cfb7 |
}
|
|
|
36cfb7 |
|
|
|
36cfb7 |
if (answer) {
|
|
|
36cfb7 |
memcpy(answer, h,
|
|
|
36cfb7 |
MIN(maxlen, h->nlmsg_len));
|
|
|
36cfb7 |
+ free(buf);
|
|
|
36cfb7 |
return 0;
|
|
|
36cfb7 |
}
|
|
|
36cfb7 |
|
|
|
36cfb7 |
@@ -617,6 +662,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
|
|
|
36cfb7 |
status -= NLMSG_ALIGN(len);
|
|
|
36cfb7 |
h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
|
|
|
36cfb7 |
}
|
|
|
36cfb7 |
+ free(buf);
|
|
|
36cfb7 |
|
|
|
36cfb7 |
if (msg.msg_flags & MSG_TRUNC) {
|
|
|
36cfb7 |
fprintf(stderr, "Message truncated\n");
|
|
|
36cfb7 |
--
|
|
|
e138d9 |
2.21.0
|
|
|
36cfb7 |
|