diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 0d443d1e5b2a12c7c6a76b320fc63f7647dc9888..bb7c41a26dd86e3833e3f52986f2afd410974c97 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2485,7 +2485,7 @@ networkStartNetworkVirtual(virNetworkDriverStatePtr driver, def->name); return -1; } - if (virNetDevBridgeCreate(def->bridge) < 0) + if (virNetDevBridgeCreate(def->bridge, &def->mac) < 0) return -1; if (def->mac_specified) { diff --git a/src/util/virnetdevbridge.c b/src/util/virnetdevbridge.c index edf4cc6236de6ab6e1f80efe11b40c0cecc7d0cf..73643495c40210690ec6bf46027e59b66aed1ad8 100644 --- a/src/util/virnetdevbridge.c +++ b/src/util/virnetdevbridge.c @@ -379,7 +379,8 @@ virNetDevBridgePortSetUnicastFlood(const char *brname G_GNUC_UNUSED, */ #if defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR) static int -virNetDevBridgeCreateWithIoctl(const char *brname) +virNetDevBridgeCreateWithIoctl(const char *brname, + const virMacAddr *mac) { VIR_AUTOCLOSE fd = -1; @@ -392,22 +393,36 @@ virNetDevBridgeCreateWithIoctl(const char *brname) return -1; } + if (virNetDevSetMAC(brname, mac) < 0) { + virErrorPtr savederr; + + virErrorPreserveLast(&savederr); + ignore_value(ioctl(fd, SIOCBRDELBR, brname)); + virErrorRestore(&savederr); + return -1; + } + return 0; } #endif #if defined(__linux__) && defined(HAVE_LIBNL) int -virNetDevBridgeCreate(const char *brname) +virNetDevBridgeCreate(const char *brname, + const virMacAddr *mac) { /* use a netlink RTM_NEWLINK message to create the bridge */ int error = 0; + virNetlinkNewLinkData data = { + .mac = mac, + }; + - if (virNetlinkNewLink(brname, "bridge", NULL, &error) < 0) { + if (virNetlinkNewLink(brname, "bridge", &data, &error) < 0) { # if defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR) if (error == -EOPNOTSUPP) { /* fallback to ioctl if netlink doesn't support creating bridges */ - return virNetDevBridgeCreateWithIoctl(brname); + return virNetDevBridgeCreateWithIoctl(brname, mac); } # endif if (error < 0) @@ -423,15 +438,17 @@ virNetDevBridgeCreate(const char *brname) #elif defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR) int -virNetDevBridgeCreate(const char *brname) +virNetDevBridgeCreate(const char *brname, + const virMacAddr *mac) { - return virNetDevBridgeCreateWithIoctl(brname); + return virNetDevBridgeCreateWithIoctl(brname, mac); } #elif defined(HAVE_STRUCT_IFREQ) && defined(SIOCIFCREATE2) int -virNetDevBridgeCreate(const char *brname) +virNetDevBridgeCreate(const char *brname, + const virMacAddr *mac) { struct ifreq ifr; VIR_AUTOCLOSE s = -1; @@ -448,10 +465,21 @@ virNetDevBridgeCreate(const char *brname) if (virNetDevSetName(ifr.ifr_name, brname) == -1) return -1; + if (virNetDevSetMAC(brname, mac) < 0) { + virErrorPtr savederr; + + virErrorPreserveLast(&savederr); + ignore_value(virNetDevBridgeDelete(brname)); + virErrorRestore(&savederr); + return -1; + } + return 0; } #else -int virNetDevBridgeCreate(const char *brname) +int +virNetDevBridgeCreate(const char *brname, + const virMacAddr *mac G_GNUC_UNUSED) { virReportSystemError(ENOSYS, _("Unable to create bridge %s"), brname); diff --git a/src/util/virnetdevbridge.h b/src/util/virnetdevbridge.h index 88284d6beda4031d4009ad02262ddb6d81fa1d99..8137914da83357586b6503fd04de00122ba4fd9d 100644 --- a/src/util/virnetdevbridge.h +++ b/src/util/virnetdevbridge.h @@ -21,7 +21,8 @@ #include "internal.h" #include "virmacaddr.h" -int virNetDevBridgeCreate(const char *brname) +int virNetDevBridgeCreate(const char *brname, + const virMacAddr *mac) ATTRIBUTE_NONNULL(1) G_GNUC_WARN_UNUSED_RESULT; int virNetDevBridgeDelete(const char *brname) ATTRIBUTE_NONNULL(1) G_GNUC_WARN_UNUSED_RESULT;