It constructs a temporary static config of the network, Obtains all of attached interfaces information through netcf, Then removes the config. Signed-off-by: Lin Ma <lma@xxxxxxxx> --- include/libvirt/libvirt-network.h | 1 + src/Makefile.am | 3 + src/network/bridge_driver.c | 141 ++++++++++++++++++++++++++++++++++- src/network/bridge_driver_platform.h | 7 ++ tests/Makefile.am | 4 + 5 files changed, 155 insertions(+), 1 deletion(-) diff --git a/include/libvirt/libvirt-network.h b/include/libvirt/libvirt-network.h index 308f27f..9b09546 100644 --- a/include/libvirt/libvirt-network.h +++ b/include/libvirt/libvirt-network.h @@ -30,6 +30,7 @@ typedef enum { VIR_NETWORK_XML_INACTIVE = (1 << 0), /* dump inactive network information */ + VIR_NETWORK_XML_IFACE_ATTACHED = (1 << 1), /* dump current live state */ } virNetworkXMLFlags; /** diff --git a/src/Makefile.am b/src/Makefile.am index b41c6d4..d22ae7e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1412,6 +1412,9 @@ if WITH_NETWORK noinst_LTLIBRARIES += libvirt_driver_network_impl.la libvirt_driver_network_la_SOURCES = libvirt_driver_network_la_LIBADD = libvirt_driver_network_impl.la +if WITH_NETCF +libvirt_driver_network_la_LIBADD += $(NETCF_LIBS) +endif WITH_NETCF if WITH_DRIVER_MODULES mod_LTLIBRARIES += libvirt_driver_network.la libvirt_driver_network_la_LIBADD += ../gnulib/lib/libgnu.la \ diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index c56e8f2..1e49e2e 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -3333,8 +3333,17 @@ static char *networkGetXMLDesc(virNetworkPtr net, virNetworkObjPtr network; virNetworkDefPtr def; char *ret = NULL; +#ifdef WITH_NETCF + struct netcf_if *iface = NULL; + char *bridge = NULL; + char *if_xml_tmp = NULL; + xmlDocPtr xml = NULL; + xmlXPathContextPtr ctxt = NULL; + xmlXPathObjectPtr obj = NULL; +#endif - virCheckFlags(VIR_NETWORK_XML_INACTIVE, NULL); + virCheckFlags(VIR_NETWORK_XML_INACTIVE | + VIR_NETWORK_XML_IFACE_ATTACHED, NULL); if (!(network = networkObjFromNetwork(net))) return ret; @@ -3342,6 +3351,135 @@ static char *networkGetXMLDesc(virNetworkPtr net, if (virNetworkGetXMLDescEnsureACL(net->conn, network->def) < 0) goto cleanup; +#ifdef WITH_NETCF + if ((flags & VIR_NETWORK_XML_INACTIVE) && network->newDef) { + def = network->newDef; + ret = virNetworkDefFormat(def, flags); + } + else if (flags & VIR_NETWORK_XML_IFACE_ATTACHED) { + if (!(network->def->bridge)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("network '%s' does not have a bridge name."), + network->def->name); + goto cleanup; + } + ignore_value(VIR_STRDUP(bridge, network->def->bridge)); + + if (virAsprintf(&if_xml_tmp, + "<interface type='bridge' name='%s'>" + "<start mode='none'/><bridge/></interface>", + bridge) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to generate temp xml for network")); + goto cleanup; + } + + if (ncf_init(&driver->netcf, NULL) != 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to init netcf")); + goto cleanup; + } + + // create a temp bridge configuration file + iface = ncf_define(driver->netcf, if_xml_tmp); + if (!iface) { + virReportError(VIR_ERR_XML_ERROR, + _("failed to define the temp bridge %s"), bridge); + ncf_close(driver->netcf); + goto cleanup; + } + + ret = ncf_if_xml_state(iface); + if (!ret) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("could not get bridge XML description")); + ncf_if_free(iface); + ncf_close(driver->netcf); + goto cleanup; + } + + // remove the temp bridge configuration file + if (ncf_if_undefine(iface) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to undefine the temp bridge %s"), bridge); + ncf_if_free(iface); + ncf_close(driver->netcf); + ret = NULL; + goto cleanup; + } + ncf_if_free(iface); + ncf_close(driver->netcf); + + // remove the dummp tap interface section from the result + if (network->def->mac_specified) { + char *macTapIfName = networkBridgeDummyNicName(network->def->bridge); + if (macTapIfName) { + char mac[VIR_MAC_STRING_BUFLEN]; + xmlNodePtr cur = NULL, matchNode = NULL; + xmlChar *br_xml = NULL; + int br_xml_size; + char buf[64]; + size_t i; + int diff_mac; + virMacAddrFormat(&network->def->mac, mac); + snprintf(buf, sizeof(buf), "./bridge/interface[@name='%s']", + macTapIfName); + if (!(xml = virXMLParseStringCtxt(ret, + _("(bridge interface " + "definition)"), &ctxt))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + ("Failed to parse network configuration")); + VIR_FREE(macTapIfName); + ret = NULL; + goto cleanup; + } + obj = xmlXPathEval(BAD_CAST buf, ctxt); + if (obj == NULL || obj->type != XPATH_NODESET || + obj->nodesetval == NULL || obj->nodesetval->nodeNr == 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("No interface found whose name is %s"), + macTapIfName); + VIR_FREE(macTapIfName); + ret = NULL; + goto cleanup; + } + VIR_FREE(macTapIfName); + for (i = 0; i < obj->nodesetval->nodeNr; i++) { + cur = obj->nodesetval->nodeTab[i]->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE && + xmlStrEqual(cur->name, BAD_CAST "mac")) { + char *tmp_mac = virXMLPropString(cur, "address"); + diff_mac = virMacAddrCompare(tmp_mac, mac); + VIR_FREE(tmp_mac); + if (!diff_mac) { + matchNode = obj->nodesetval->nodeTab[i]; + xmlUnlinkNode(matchNode); + break; + } + } + cur = cur->next; + } + } + xmlDocDumpMemory(xml, &br_xml, &br_xml_size); + ret = (char *)br_xml; + } + } + } + else { + def = network->def; + ret = virNetworkDefFormat(def, flags); + } + + cleanup: + xmlXPathFreeObject(obj); + xmlXPathFreeContext(ctxt); + xmlFreeDoc(xml); + VIR_FREE(if_xml_tmp); + VIR_FREE(bridge); + if (network) + virNetworkObjUnlock(network); +#else if ((flags & VIR_NETWORK_XML_INACTIVE) && network->newDef) def = network->newDef; else @@ -3352,6 +3490,7 @@ static char *networkGetXMLDesc(virNetworkPtr net, cleanup: if (network) virNetworkObjUnlock(network); +#endif return ret; } diff --git a/src/network/bridge_driver_platform.h b/src/network/bridge_driver_platform.h index 1e8264a..43ea1c3 100644 --- a/src/network/bridge_driver_platform.h +++ b/src/network/bridge_driver_platform.h @@ -24,6 +24,9 @@ #ifndef __VIR_BRIDGE_DRIVER_PLATFORM_H__ # define __VIR_BRIDGE_DRIVER_PLATFORM_H__ +#ifdef WITH_NETCF +# include <netcf.h> +#endif # include "internal.h" # include "virthread.h" # include "virdnsmasq.h" @@ -34,6 +37,10 @@ struct _virNetworkDriverState { virMutex lock; +#ifdef WITH_NETCF + struct netcf *netcf; +#endif + virNetworkObjList networks; char *networkConfigDir; diff --git a/tests/Makefile.am b/tests/Makefile.am index 938270c..0662337 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -67,6 +67,10 @@ LDADDS = \ $(GNULIB_LIBS) \ ../src/libvirt.la +if WITH_NETCF +LDADDS += $(NETCF_LIBS) +endif WITH_NETCF + EXTRA_DIST = \ bhyvexml2argvdata \ bhyvexml2xmloutdata \ -- 1.8.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list