From d2fed854c00f5e27c48bac062fd13d13965afd11 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 2 Nov 2011 17:34:41 +0000 Subject: [PATCH] Move the low level macvlan creation APIs Move the low level macvlan creation APIs into the virnetdevmacvlan.c file where they more naturally belong * util/interface.c, util/interface.h: Remove virNetDevMacVLanCreate and virNetDevMacVLanDelete * util/virnetdevmacvlan.c, util/virnetdevmacvlan.h: Add virNetDevMacVLanCreate and virNetDevMacVLanDelete --- src/util/interface.c | 270 ------------------------------------ src/util/interface.h | 12 -- src/util/virnetdevmacvlan.c | 256 +++++++++++++++++++++++++++++++++- src/util/virnetdevmacvlan.h | 12 ++ 4 files changed, 264 insertions(+), 286 deletions(-) diff --git a/src/util/interface.c b/src/util/interface.c index a1c56f5088..e757c6fd88 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -312,276 +312,6 @@ ifaceGetIPAddress(const char *ifname ATTRIBUTE_UNUSED, #endif /* __linux__ */ -/** - * virNetDevMacVLanCreate: - * - * @ifname: The name the interface is supposed to have; optional parameter - * @type: The type of device, i.e., "macvtap" - * @macaddress: The MAC address of the device - * @srcdev: The name of the 'link' device - * @macvlan_mode: The macvlan mode to use - * @retry: Pointer to integer that will be '1' upon return if an interface - * with the same name already exists and it is worth to try - * again with a different name - * - * Create a macvtap device with the given properties. - * - * Returns 0 on success, -1 on fatal error. - */ -#if defined(__linux__) && WITH_MACVTAP -int -virNetDevMacVLanCreate(const char *ifname, - const char *type, - const unsigned char *macaddress, - const char *srcdev, - uint32_t macvlan_mode, - int *retry) -{ - int rc = 0; - struct nlmsghdr *resp; - struct nlmsgerr *err; - struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; - int ifindex; - unsigned char *recvbuf = NULL; - unsigned int recvbuflen; - struct nl_msg *nl_msg; - struct nlattr *linkinfo, *info_data; - - if (ifaceGetIndex(true, srcdev, &ifindex) < 0) - return -1; - - *retry = 0; - - nl_msg = nlmsg_alloc_simple(RTM_NEWLINK, - 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_u32(nl_msg, IFLA_LINK, ifindex) < 0) - goto buffer_too_small; - - if (nla_put(nl_msg, IFLA_ADDRESS, VIR_MAC_BUFLEN, macaddress) < 0) - goto buffer_too_small; - - if (ifname && - nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) - goto buffer_too_small; - - if (!(linkinfo = nla_nest_start(nl_msg, IFLA_LINKINFO))) - goto buffer_too_small; - - if (nla_put(nl_msg, IFLA_INFO_KIND, strlen(type), type) < 0) - goto buffer_too_small; - - if (macvlan_mode > 0) { - if (!(info_data = nla_nest_start(nl_msg, IFLA_INFO_DATA))) - goto buffer_too_small; - - if (nla_put(nl_msg, IFLA_MACVLAN_MODE, sizeof(macvlan_mode), - &macvlan_mode) < 0) - goto buffer_too_small; - - nla_nest_end(nl_msg, info_data); - } - - nla_nest_end(nl_msg, linkinfo); - - if (nlComm(nl_msg, &recvbuf, &recvbuflen, 0) < 0) { - rc = -1; - goto cleanup; - } - - if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL) - goto malformed_resp; - - resp = (struct nlmsghdr *)recvbuf; - - switch (resp->nlmsg_type) { - case NLMSG_ERROR: - err = (struct nlmsgerr *)NLMSG_DATA(resp); - if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) - goto malformed_resp; - - switch (err->error) { - - case 0: - break; - - case -EEXIST: - *retry = 1; - rc = -1; - break; - - default: - virReportSystemError(-err->error, - _("error creating %s type of interface"), - type); - rc = -1; - } - break; - - case NLMSG_DONE: - break; - - default: - goto malformed_resp; - } - -cleanup: - nlmsg_free(nl_msg); - - VIR_FREE(recvbuf); - - return rc; - -malformed_resp: - nlmsg_free(nl_msg); - - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("malformed netlink response message")); - VIR_FREE(recvbuf); - return -1; - -buffer_too_small: - nlmsg_free(nl_msg); - - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("allocated netlink buffer is too small")); - return -1; -} - -#else - -int virNetDevMacVLanCreate(const char *ifname ATTRIBUTE_UNUSED, - const char *type ATTRIBUTE_UNUSED, - const unsigned char *macaddress ATTRIBUTE_UNUSED, - const char *srcdev ATTRIBUTE_UNUSED, - uint32_t macvlan_mode ATTRIBUTE_UNUSED, - int *retry ATTRIBUTE_UNUSED) -{ - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", -# if defined(__linux__) && !WITH_MACVTAP - _("ifaceMacvtapLinkAdd is not supported since the include " - "files were too old")); -# else - _("ifaceMacvtapLinkAdd is not supported on non-linux " - "platforms")); -# endif - - return -1; -} - -#endif - - -/** - * virNetDevMacVLanDelete: - * - * @ifname: Name of the interface - * - * Tear down an interface with the given name. - * - * Returns 0 on success, -1 on fatal error. - */ -#if defined( __linux__) && WITH_MACVTAP -int virNetDevMacVLanDelete(const char *ifname) -{ - int rc = 0; - struct nlmsghdr *resp; - struct nlmsgerr *err; - struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; - unsigned char *recvbuf = NULL; - 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 (nlComm(nl_msg, &recvbuf, &recvbuflen, 0) < 0) { - rc = -1; - goto cleanup; - } - - if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL) - goto malformed_resp; - - resp = (struct nlmsghdr *)recvbuf; - - 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 %s interface"), - ifname); - rc = -1; - } - break; - - case NLMSG_DONE: - break; - - default: - goto malformed_resp; - } - -cleanup: - nlmsg_free(nl_msg); - - VIR_FREE(recvbuf); - - return rc; - -malformed_resp: - nlmsg_free(nl_msg); - - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("malformed netlink response message")); - VIR_FREE(recvbuf); - return -1; - -buffer_too_small: - nlmsg_free(nl_msg); - - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("allocated netlink buffer is too small")); - return -1; -} - -#else - -int virNetDevMacVLanDelete(const char *ifname ATTRIBUTE_UNUSED) -{ - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", -# if defined(__linux__) && !WITH_MACVTAP - _("ifaceLinkDel is not supported since the include files " - "were too old")); -# else - _("ifaceLinkDel is not supported on non-linux platforms")); -# endif - return -1; -} - -#endif - #if defined(__linux__) && defined(IFLA_PORT_MAX) diff --git a/src/util/interface.h b/src/util/interface.h index a62f26a932..1dd8f35cbd 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -39,18 +39,6 @@ int ifaceGetVlanID(const char *vlanifname, int *vlanid); int ifaceGetIPAddress(const char *ifname, virSocketAddrPtr addr); -int virNetDevMacVLanCreate(const char *ifname, - const char *type, - const unsigned char *macaddress, - const char *srcdev, - uint32_t macvlan_mode, - int *retry) - ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) - ATTRIBUTE_RETURN_CHECK; - -int virNetDevMacVLanDelete(const char *ifname) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; - int ifaceMacvtapLinkDump(bool nltarget_kernel, const char *ifname, int ifindex, struct nlattr **tb, unsigned char **recvbuf, uint32_t (*getPidFunc)(void)); diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c index ab552afb4f..6919d5eb2a 100644 --- a/src/util/virnetdevmacvlan.c +++ b/src/util/virnetdevmacvlan.c @@ -34,7 +34,7 @@ #define VIR_FROM_THIS VIR_FROM_NET -#define macvtapError(code, ...) \ +#define virNetDevError(code, ...) \ virReportErrorHelper(VIR_FROM_NET, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) @@ -73,6 +73,235 @@ VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST, # define MACVTAP_NAME_PREFIX "macvtap" # define MACVTAP_NAME_PATTERN "macvtap%d" +/** + * virNetDevMacVLanCreate: + * + * @ifname: The name the interface is supposed to have; optional parameter + * @type: The type of device, i.e., "macvtap" + * @macaddress: The MAC address of the device + * @srcdev: The name of the 'link' device + * @macvlan_mode: The macvlan mode to use + * @retry: Pointer to integer that will be '1' upon return if an interface + * with the same name already exists and it is worth to try + * again with a different name + * + * Create a macvtap device with the given properties. + * + * Returns 0 on success, -1 on fatal error. + */ +int +virNetDevMacVLanCreate(const char *ifname, + const char *type, + const unsigned char *macaddress, + const char *srcdev, + uint32_t macvlan_mode, + int *retry) +{ + int rc = 0; + struct nlmsghdr *resp; + struct nlmsgerr *err; + struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; + int ifindex; + unsigned char *recvbuf = NULL; + unsigned int recvbuflen; + struct nl_msg *nl_msg; + struct nlattr *linkinfo, *info_data; + + if (ifaceGetIndex(true, srcdev, &ifindex) < 0) + return -1; + + *retry = 0; + + nl_msg = nlmsg_alloc_simple(RTM_NEWLINK, + 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_u32(nl_msg, IFLA_LINK, ifindex) < 0) + goto buffer_too_small; + + if (nla_put(nl_msg, IFLA_ADDRESS, VIR_MAC_BUFLEN, macaddress) < 0) + goto buffer_too_small; + + if (ifname && + nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) + goto buffer_too_small; + + if (!(linkinfo = nla_nest_start(nl_msg, IFLA_LINKINFO))) + goto buffer_too_small; + + if (nla_put(nl_msg, IFLA_INFO_KIND, strlen(type), type) < 0) + goto buffer_too_small; + + if (macvlan_mode > 0) { + if (!(info_data = nla_nest_start(nl_msg, IFLA_INFO_DATA))) + goto buffer_too_small; + + if (nla_put(nl_msg, IFLA_MACVLAN_MODE, sizeof(macvlan_mode), + &macvlan_mode) < 0) + goto buffer_too_small; + + nla_nest_end(nl_msg, info_data); + } + + nla_nest_end(nl_msg, linkinfo); + + if (nlComm(nl_msg, &recvbuf, &recvbuflen, 0) < 0) { + rc = -1; + goto cleanup; + } + + if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL) + goto malformed_resp; + + resp = (struct nlmsghdr *)recvbuf; + + switch (resp->nlmsg_type) { + case NLMSG_ERROR: + err = (struct nlmsgerr *)NLMSG_DATA(resp); + if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) + goto malformed_resp; + + switch (err->error) { + + case 0: + break; + + case -EEXIST: + *retry = 1; + rc = -1; + break; + + default: + virReportSystemError(-err->error, + _("error creating %s type of interface"), + type); + rc = -1; + } + break; + + case NLMSG_DONE: + break; + + default: + goto malformed_resp; + } + +cleanup: + nlmsg_free(nl_msg); + + VIR_FREE(recvbuf); + + return rc; + +malformed_resp: + nlmsg_free(nl_msg); + + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed netlink response message")); + VIR_FREE(recvbuf); + return -1; + +buffer_too_small: + nlmsg_free(nl_msg); + + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("allocated netlink buffer is too small")); + return -1; +} + +/** + * virNetDevMacVLanDelete: + * + * @ifname: Name of the interface + * + * Tear down an interface with the given name. + * + * Returns 0 on success, -1 on fatal error. + */ +int virNetDevMacVLanDelete(const char *ifname) +{ + int rc = 0; + struct nlmsghdr *resp; + struct nlmsgerr *err; + struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; + unsigned char *recvbuf = NULL; + 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 (nlComm(nl_msg, &recvbuf, &recvbuflen, 0) < 0) { + rc = -1; + goto cleanup; + } + + if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL) + goto malformed_resp; + + resp = (struct nlmsghdr *)recvbuf; + + 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 %s interface"), + ifname); + rc = -1; + } + break; + + case NLMSG_DONE: + break; + + default: + goto malformed_resp; + } + +cleanup: + nlmsg_free(nl_msg); + + VIR_FREE(recvbuf); + + return rc; + +malformed_resp: + nlmsg_free(nl_msg); + + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed netlink response message")); + VIR_FREE(recvbuf); + return -1; + +buffer_too_small: + nlmsg_free(nl_msg); + + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("allocated netlink buffer is too small")); + return -1; +} + + /** * virNetDevMacVLanTapOpen: * Open the macvtap's tap device. @@ -332,9 +561,9 @@ create_name: goto disassociate_exit; if (virNetDevBandwidthSet(cr_ifname, bandwidth) < 0) { - macvtapError(VIR_ERR_INTERNAL_ERROR, - _("cannot set bandwidth limits on %s"), - cr_ifname); + virNetDevError(VIR_ERR_INTERNAL_ERROR, + _("cannot set bandwidth limits on %s"), + cr_ifname); rc = -1; goto disassociate_exit; } @@ -392,6 +621,25 @@ int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname, } #else /* ! WITH_MACVTAP */ +int virNetDevMacVLanCreate(const char *ifname ATTRIBUTE_UNUSED, + const char *type ATTRIBUTE_UNUSED, + const unsigned char *macaddress ATTRIBUTE_UNUSED, + const char *srcdev ATTRIBUTE_UNUSED, + uint32_t macvlan_mode ATTRIBUTE_UNUSED, + int *retry ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Cannot create macvlan devices on this platform")); + return -1; +} + +int virNetDevMacVLanDelete(const char *ifname ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Cannot create macvlan devices on this platform")); + return -1; +} + int virNetDevMacVLanCreateWithVPortProfile(const char *ifname ATTRIBUTE_UNUSED, const unsigned char *macaddress ATTRIBUTE_UNUSED, const char *linkdev ATTRIBUTE_UNUSED, diff --git a/src/util/virnetdevmacvlan.h b/src/util/virnetdevmacvlan.h index 9498f7bbaf..73918b801b 100644 --- a/src/util/virnetdevmacvlan.h +++ b/src/util/virnetdevmacvlan.h @@ -39,6 +39,18 @@ enum virNetDevMacVLanMode { }; VIR_ENUM_DECL(virNetDevMacVLanMode) +int virNetDevMacVLanCreate(const char *ifname, + const char *type, + const unsigned char *macaddress, + const char *srcdev, + uint32_t macvlan_mode, + int *retry) + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) + ATTRIBUTE_RETURN_CHECK; + +int virNetDevMacVLanDelete(const char *ifname) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; + int virNetDevMacVLanCreateWithVPortProfile(const char *ifname, const unsigned char *macaddress, const char *linkdev,