mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-18 10:35:20 +00:00
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
This commit is contained in:
parent
60acb38abb
commit
66dcb40937
@ -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)
|
|||||||
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)
|
|||||||
_("allocated netlink buffer is too small"));
|
_("allocated netlink buffer is too small"));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#elif defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR)
|
#elif defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR)
|
||||||
int virNetDevBridgeCreate(const char *brname)
|
int
|
||||||
|
virNetDevBridgeCreate(const char *brname)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
return virNetDevBridgeCreateWithIoctl(brname);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user