diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 3b227db6f3ffd9c0f30f92129cb4edcc8285a333..09e091616250040d818e3bccf3cd179217ca82cb 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -41,6 +41,7 @@ # include "virbitmap.h" # include "networkcommon_conf.h" # include "virobject.h" +# include "virmacmap.h" typedef enum { VIR_NETWORK_FORWARD_NONE = 0, @@ -284,6 +285,9 @@ struct _virNetworkObj { unsigned long long floor_sum; /* sum of all 'floor'-s of attached NICs */ unsigned int taint; + + /* Immutable pointer, self locking APIs */ + virMacMapPtr macmap; }; virNetworkObjPtr virNetworkObjNew(void); diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 073f5019a7029d6bb345f05d7d2ce1e1e5ee3232..ae1589d8c962109aa27d7c6af9d705b32b68ac99 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -289,6 +289,17 @@ networkRadvdConfigFileName(virNetworkDriverStatePtr driver, return configfile; } +static char * +networkMacMgrFileName(virNetworkDriverStatePtr driver, + const char *bridge) +{ + char *filename; + + ignore_value(virAsprintf(&filename, "%s/%s.macs", + driver->dnsmasqStateDir, bridge)); + return filename; +} + /* do needed cleanup steps and remove the network from the list */ static int networkRemoveInactive(virNetworkDriverStatePtr driver, @@ -300,6 +311,7 @@ networkRemoveInactive(virNetworkDriverStatePtr driver, char *configfile = NULL; char *radvdpidbase = NULL; char *statusfile = NULL; + char *macMapFile = NULL; dnsmasqContext *dctx = NULL; virNetworkDefPtr def = virNetworkObjGetPersistentDef(net); @@ -329,12 +341,18 @@ networkRemoveInactive(virNetworkDriverStatePtr driver, if (!(statusfile = virNetworkConfigFile(driver->stateDir, def->name))) goto cleanup; + if (!(macMapFile = networkMacMgrFileName(driver, def->bridge))) + goto cleanup; + /* dnsmasq */ dnsmasqDelete(dctx); unlink(leasefile); unlink(customleasefile); unlink(configfile); + /* MAC map manager */ + unlink(macMapFile); + /* radvd */ unlink(radvdconfigfile); virPidFileDelete(driver->pidDir, radvdpidbase); @@ -354,10 +372,71 @@ networkRemoveInactive(virNetworkDriverStatePtr driver, VIR_FREE(radvdconfigfile); VIR_FREE(radvdpidbase); VIR_FREE(statusfile); + VIR_FREE(macMapFile); dnsmasqContextFree(dctx); return ret; } +static int +networkMacMgrAdd(virNetworkDriverStatePtr driver, + virNetworkObjPtr network, + const char *domain, + const virMacAddr *mac) +{ + char macStr[VIR_MAC_STRING_BUFLEN]; + char *file = NULL; + int ret = -1; + + if (!network->macmap) + return 0; + + virMacAddrFormat(mac, macStr); + + if (!(file = networkMacMgrFileName(driver, network->def->bridge))) + goto cleanup; + + if (virMacMapAdd(network->macmap, domain, macStr) < 0) + goto cleanup; + + if (virMacMapWriteFile(network->macmap, file) < 0) + goto cleanup; + + ret = 0; + cleanup: + VIR_FREE(file); + return ret; +} + +static int +networkMacMgrDel(virNetworkDriverStatePtr driver, + virNetworkObjPtr network, + const char *domain, + const virMacAddr *mac) +{ + char macStr[VIR_MAC_STRING_BUFLEN]; + char *file = NULL; + int ret = -1; + + if (!network->macmap) + return 0; + + virMacAddrFormat(mac, macStr); + + if (!(file = networkMacMgrFileName(driver, network->def->bridge))) + goto cleanup; + + if (virMacMapRemove(network->macmap, domain, macStr) < 0) + goto cleanup; + + if (virMacMapWriteFile(network->macmap, file) < 0) + goto cleanup; + + ret = 0; + cleanup: + VIR_FREE(file); + return ret; +} + static char * networkBridgeDummyNicName(const char *brname) { @@ -430,11 +509,13 @@ networkUpdateState(virNetworkObjPtr obj, /* Try and read dnsmasq/radvd pids of active networks */ if (obj->active && obj->def->ips && (obj->def->nips > 0)) { char *radvdpidbase; + char *macMapFile; ignore_value(virPidFileReadIfAlive(driver->pidDir, obj->def->name, &obj->dnsmasqPid, dnsmasqCapsGetBinaryPath(dnsmasq_caps))); + radvdpidbase = networkRadvdPidfileBasename(obj->def->name); if (!radvdpidbase) goto cleanup; @@ -443,6 +524,17 @@ networkUpdateState(virNetworkObjPtr obj, radvdpidbase, &obj->radvdPid, RADVD)); VIR_FREE(radvdpidbase); + + if (!(macMapFile = networkMacMgrFileName(driver, obj->def->bridge))) + goto cleanup; + + if (virFileExists(macMapFile) && + !(obj->macmap = virMacMapNew(macMapFile))) { + VIR_FREE(macMapFile); + goto cleanup; + } + + VIR_FREE(macMapFile); } ret = 0; @@ -2127,6 +2219,7 @@ networkStartNetworkVirtual(virNetworkDriverStatePtr driver, virNetworkIPDefPtr ipdef; virNetDevIPRoutePtr routedef; char *macTapIfName = NULL; + char *macMapFile = NULL; int tapfd = -1; /* Check to see if any network IP collides with an existing route */ @@ -2173,6 +2266,10 @@ networkStartNetworkVirtual(virNetworkDriverStatePtr driver, } } + if (!(macMapFile = networkMacMgrFileName(driver, network->def->bridge)) || + !(network->macmap = virMacMapNew(macMapFile))) + goto err1; + /* Set bridge options */ /* delay is configured in seconds, but virNetDevBridgeSetSTPDelay @@ -2272,6 +2369,7 @@ networkStartNetworkVirtual(virNetworkDriverStatePtr driver, goto err5; VIR_FREE(macTapIfName); + VIR_FREE(macMapFile); return 0; @@ -2308,6 +2406,7 @@ networkStartNetworkVirtual(virNetworkDriverStatePtr driver, ignore_value(virNetDevTapDelete(macTapIfName, NULL)); VIR_FREE(macTapIfName); } + VIR_FREE(macMapFile); err0: if (!save_err) @@ -2329,6 +2428,8 @@ networkShutdownNetworkVirtual(virNetworkDriverStatePtr driver, if (network->def->bandwidth) virNetDevBandwidthClear(network->def->bridge); + virObjectUnref(network->macmap); + if (network->radvdPid > 0) { char *radvdpidbase; @@ -4353,6 +4454,9 @@ networkAllocateActualDevice(virDomainDefPtr dom, } } + if (networkMacMgrAdd(driver, network, dom->name, &iface->mac) < 0) + goto error; + if (virNetDevVPortProfileCheckComplete(virtport, true) < 0) goto error; @@ -4739,6 +4843,8 @@ networkReleaseActualDevice(virDomainDefPtr dom, } success: + networkMacMgrDel(driver, network, dom->name, &iface->mac); + if (iface->data.network.actual) { netdef->connections--; if (dev)