提交 e6c69718 编写于 作者: L Laine Stump 提交者: Cole Robinson

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
(cherry picked from commit 66dcb409)
上级 14aa9d65
...@@ -394,8 +394,33 @@ virNetDevBridgePortSetUnicastFlood(const char *brname ATTRIBUTE_UNUSED, ...@@ -394,8 +394,33 @@ virNetDevBridgePortSetUnicastFlood(const char *brname ATTRIBUTE_UNUSED,
* *
* Returns 0 in case of success or -1 on failure * 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) #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 */ /* use a netlink RTM_NEWLINK message to create the bridge */
const char *type = "bridge"; const char *type = "bridge";
...@@ -441,6 +466,17 @@ int virNetDevBridgeCreate(const char *brname) ...@@ -441,6 +466,17 @@ int virNetDevBridgeCreate(const char *brname)
switch (err->error) { switch (err->error) {
case 0: case 0:
break; 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: default:
virReportSystemError(-err->error, virReportSystemError(-err->error,
_("error creating bridge interface %s"), _("error creating bridge interface %s"),
...@@ -470,29 +506,19 @@ int virNetDevBridgeCreate(const char *brname) ...@@ -470,29 +506,19 @@ int virNetDevBridgeCreate(const char *brname)
_("allocated netlink buffer is too small")); _("allocated netlink buffer is too small"));
goto cleanup; 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) { #elif defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR)
virReportSystemError(errno, int
_("Unable to create bridge %s"), brname); virNetDevBridgeCreate(const char *brname)
goto cleanup; {
} return virNetDevBridgeCreateWithIoctl(brname);
}
ret = 0;
cleanup:
VIR_FORCE_CLOSE(fd);
return ret;
}
#elif defined(HAVE_STRUCT_IFREQ) && defined(SIOCIFCREATE2) #elif defined(HAVE_STRUCT_IFREQ) && defined(SIOCIFCREATE2)
int virNetDevBridgeCreate(const char *brname) int
virNetDevBridgeCreate(const char *brname)
{ {
int s; int s;
struct ifreq ifr; struct ifreq ifr;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册