From 66dcb4093750aabd637607a1202cb9b9c15f1298 Mon Sep 17 00:00:00 2001 From: Laine Stump Date: Tue, 25 Aug 2015 20:48:19 -0400 Subject: [PATCH] util: fallback to ioctl(SIOCBRADDBR) if netlink RTM_NEWLINK fails commit fc7b23db switched from using ioctl(SIOCBRADDBR) for bridge creation to using a netlink RTM_NEWLINK message with IFLA_INFO_KIND = "bridge", which is the more modern way to create a bridge. However, although older kernels (e.g. 2.6.32, in RHEL6/CentOS6) support creating *some* link types with RTM_NEWLINK, they don't support creating bridges, and there is no compile-time way to figure this out (since the "type" isn't an enum, but rather a character string). This patch moves the body of the SIOCBRADDBR version of virNetDevBridgeCreate() into a static function, calls the new function from the original, and also calls the new function from the RTM_NEWLINK version if the RTM_NEWLINK message generates an EOPNOTSUPP error. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1252780 --- src/util/virnetdevbridge.c | 64 +++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/src/util/virnetdevbridge.c b/src/util/virnetdevbridge.c index aa255d63f1..ae389016ba 100644 --- a/src/util/virnetdevbridge.c +++ b/src/util/virnetdevbridge.c @@ -394,8 +394,33 @@ virNetDevBridgePortSetUnicastFlood(const char *brname ATTRIBUTE_UNUSED, * * Returns 0 in case of success or -1 on failure */ +#if defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR) +static int +virNetDevBridgeCreateWithIoctl(const char *brname) +{ + int fd = -1; + int ret = -1; + + if ((fd = virNetDevSetupControl(NULL, NULL)) < 0) + return -1; + + if (ioctl(fd, SIOCBRADDBR, brname) < 0) { + virReportSystemError(errno, + _("Unable to create bridge %s"), brname); + goto cleanup; + } + + ret = 0; + + cleanup: + VIR_FORCE_CLOSE(fd); + return ret; +} +#endif + #if defined(__linux__) && defined(HAVE_LIBNL) -int virNetDevBridgeCreate(const char *brname) +int +virNetDevBridgeCreate(const char *brname) { /* use a netlink RTM_NEWLINK message to create the bridge */ const char *type = "bridge"; @@ -441,6 +466,17 @@ int virNetDevBridgeCreate(const char *brname) switch (err->error) { case 0: break; + case -EOPNOTSUPP: +# if defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR) + /* fallback to ioctl if netlink doesn't support creating + * bridges + */ + rc = virNetDevBridgeCreateWithIoctl(brname); + goto cleanup; +# endif + /* intentionally fall through if virNetDevBridgeCreateWithIoctl() + * isn't available. + */ default: virReportSystemError(-err->error, _("error creating bridge interface %s"), @@ -470,29 +506,19 @@ int virNetDevBridgeCreate(const char *brname) _("allocated netlink buffer is too small")); goto cleanup; } -#elif defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR) -int virNetDevBridgeCreate(const char *brname) -{ - int fd = -1; - int ret = -1; - if ((fd = virNetDevSetupControl(NULL, NULL)) < 0) - return -1; - if (ioctl(fd, SIOCBRADDBR, brname) < 0) { - virReportSystemError(errno, - _("Unable to create bridge %s"), brname); - goto cleanup; - } +#elif defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR) +int +virNetDevBridgeCreate(const char *brname) +{ + return virNetDevBridgeCreateWithIoctl(brname); +} - ret = 0; - cleanup: - VIR_FORCE_CLOSE(fd); - return ret; -} #elif defined(HAVE_STRUCT_IFREQ) && defined(SIOCIFCREATE2) -int virNetDevBridgeCreate(const char *brname) +int +virNetDevBridgeCreate(const char *brname) { int s; struct ifreq ifr; -- GitLab