From 0473b45cc16757ccc5392d2d1279d750af54bfb9 Mon Sep 17 00:00:00 2001 From: Laine Stump Date: Tue, 17 Mar 2015 14:27:21 -0400 Subject: [PATCH] util: netlink function to delete any network device libvirt has always used the netlink RTM_DELLINK message to delete macvtap/macvlan devices, but it can actually be used to delete other types of network devices, such as bonds and bridges. This patch makes virNetDevMacVLanDelete() available as a generic function so it can intelligibly be called to delete these other types of interfaces. --- src/libvirt_private.syms | 1 + src/util/virnetlink.c | 89 ++++++++++++++++++++++++++++++++++++++++ src/util/virnetlink.h | 3 +- 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 839702b874..5716ece1d1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1816,6 +1816,7 @@ virNetDevVPortProfileOpTypeToString; # util/virnetlink.h virNetlinkCommand; +virNetlinkDelLink; virNetlinkEventAddClient; virNetlinkEventRemoveClient; virNetlinkEventServiceIsRunning; diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c index d52f66acf5..86c9c9cac2 100644 --- a/src/util/virnetlink.c +++ b/src/util/virnetlink.c @@ -277,6 +277,87 @@ int virNetlinkCommand(struct nl_msg *nl_msg, } +/** + * virNetlinkDelLink: + * + * @ifname: Name of the link + * + * delete a network "link" (aka interface aka device) with the given + * name. This works for many different types of network devices, + * including macvtap and bridges. + * + * Returns 0 on success, -1 on fatal error. + */ +int +virNetlinkDelLink(const char *ifname) +{ + int rc = -1; + struct nlmsghdr *resp = NULL; + struct nlmsgerr *err; + struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; + unsigned int recvbuflen; + struct nl_msg *nl_msg; + + nl_msg = nlmsg_alloc_simple(RTM_DELLINK, + NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); + if (!nl_msg) { + virReportOOMError(); + return -1; + } + + if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0) + goto buffer_too_small; + + if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) + goto buffer_too_small; + + if (virNetlinkCommand(nl_msg, &resp, &recvbuflen, 0, 0, + NETLINK_ROUTE, 0) < 0) { + goto cleanup; + } + + if (recvbuflen < NLMSG_LENGTH(0) || resp == NULL) + goto malformed_resp; + + switch (resp->nlmsg_type) { + case NLMSG_ERROR: + err = (struct nlmsgerr *)NLMSG_DATA(resp); + if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) + goto malformed_resp; + + if (err->error) { + virReportSystemError(-err->error, + _("error destroying network device %s"), + ifname); + goto cleanup; + } + break; + + case NLMSG_DONE: + break; + + default: + goto malformed_resp; + } + + rc = 0; + cleanup: + nlmsg_free(nl_msg); + VIR_FREE(resp); + return rc; + + malformed_resp: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed netlink response message")); + goto cleanup; + + buffer_too_small: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("allocated netlink buffer is too small")); + goto cleanup; +} + + int virNetlinkGetErrorCode(struct nlmsghdr *resp, unsigned int recvbuflen) { @@ -803,6 +884,14 @@ int virNetlinkCommand(struct nl_msg *nl_msg ATTRIBUTE_UNUSED, return -1; } + +int +virNetlinkDelLink(const char *ifname ATTRIBUTE_UNSUPPORTED) +{ + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported)); + return -1; +} + /** * stopNetlinkEventServer: stop the monitor to receive netlink * messages for libvirtd diff --git a/src/util/virnetlink.h b/src/util/virnetlink.h index 1a3e06d913..06c3cd089f 100644 --- a/src/util/virnetlink.h +++ b/src/util/virnetlink.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2013 Red Hat, Inc. + * Copyright (C) 2010-2013, 2015 Red Hat, Inc. * Copyright (C) 2010-2012 IBM Corporation * * This library is free software; you can redistribute it and/or @@ -51,6 +51,7 @@ int virNetlinkCommand(struct nl_msg *nl_msg, struct nlmsghdr **resp, unsigned int *respbuflen, uint32_t src_pid, uint32_t dst_pid, unsigned int protocol, unsigned int groups); +int virNetlinkDelLink(const char *ifname); int virNetlinkGetErrorCode(struct nlmsghdr *resp, unsigned int recvbuflen);