On 03/15/2017 10:45 AM, Cédric Bosdonnat wrote:
virNetlinkCommand() processes only one response message, while some
netlink commands like routes dumping need to process several ones.
"while some netlink commands, like route dumping, need to process several."
Add virNetlinkDumpCommand() as a virNetlinkCommand() sister.
---
src/libvirt_private.syms | 1 +
src/util/virnetlink.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++
src/util/virnetlink.h | 9 ++++++++
3 files changed, 68 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4efea0098..1f25e42d8 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2127,6 +2127,7 @@ virNetDevVPortProfileOpTypeToString;
# util/virnetlink.h
virNetlinkCommand;
virNetlinkDelLink;
+virNetlinkDumpCommand;
virNetlinkDumpLink;
virNetlinkEventAddClient;
virNetlinkEventRemoveClient;
diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
index be00351db..9bc1f0f2b 100644
--- a/src/util/virnetlink.c
+++ b/src/util/virnetlink.c
@@ -335,6 +335,52 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
return ret;
}
+int
+virNetlinkDumpCommand(struct nl_msg *nl_msg,
+ virNetlinkDumpCallback callback,
+ uint32_t src_pid, uint32_t dst_pid,
+ unsigned int protocol, unsigned int groups,
+ void *opaque)
+{
+ int ret = -1;
+ bool end = false;
+ int len = 0;
+ struct nlmsghdr *resp = NULL;
+ struct nlmsghdr *msg = NULL;
+
+ struct sockaddr_nl nladdr = {
+ .nl_family = AF_NETLINK,
+ .nl_pid = dst_pid,
+ .nl_groups = 0,
+ };
+ virNetlinkHandle *nlhandle = NULL;
+
+ if (!(nlhandle = virNetlinkSendRequest(nl_msg, src_pid, nladdr,
+ protocol, groups)))
+ goto cleanup;
+
+ while (!end) {
+ len = nl_recv(nlhandle, &nladdr, (unsigned char **)&resp, NULL);
+
+ for (msg = resp; NLMSG_OK(msg, len); msg = NLMSG_NEXT(msg, len)) {
+ if (msg->nlmsg_type == NLMSG_DONE)
+ end = true;
+
+ if (virNetlinkGetErrorCode(msg, len) < 0)
+ goto cleanup;
Seeing this reminded me - a followup patch to add
virNetlinkGetErrorCode() to virNetlinkCommand() (and remove it, or the
equivalent open code, from all its callers) would be nice. Not required
for this series though...
ACK. (Nice job of refactoring to reuse the existing code btw :-)
+
+ if (callback(msg, opaque) < 0)
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+
+ cleanup:
+ virNetlinkFree(nlhandle);
+ return ret;
+}
+
/**
* virNetlinkDumpLink:
*
@@ -1061,6 +1107,18 @@ int virNetlinkCommand(struct nl_msg *nl_msg ATTRIBUTE_UNUSED,
return -1;
}
+int
+virNetlinkDumpCommand(struct nl_msg *nl_msg ATTRIBUTE_UNUSED,
+ virNetlinkDumpCallback callback ATTRIBUTE_UNUSED,
+ uint32_t src_pid ATTRIBUTE_UNUSED,
+ uint32_t dst_pid ATTRIBUTE_UNUSED,
+ unsigned int protocol ATTRIBUTE_UNUSED,
+ unsigned int groups ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported));
+ return -1;
+}
int
virNetlinkDumpLink(const char *ifname ATTRIBUTE_UNUSED,
diff --git a/src/util/virnetlink.h b/src/util/virnetlink.h
index 11e817c82..088b01343 100644
--- a/src/util/virnetlink.h
+++ b/src/util/virnetlink.h
@@ -52,6 +52,15 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
uint32_t src_pid, uint32_t dst_pid,
unsigned int protocol, unsigned int groups);
+typedef int (*virNetlinkDumpCallback)(const struct nlmsghdr *resp,
+ void *data);
+
+int virNetlinkDumpCommand(struct nl_msg *nl_msg,
+ virNetlinkDumpCallback callback,
+ uint32_t src_pid, uint32_t dst_pid,
+ unsigned int protocol, unsigned int groups,
+ void *opaque);
+
typedef int (*virNetlinkDelLinkFallback)(const char *ifname);
int virNetlinkDelLink(const char *ifname, virNetlinkDelLinkFallback fallback);