[libvirt] [PATCH 1/3] bridge_driver: Return the live state info of a given virtual network

Michal Privoznik mprivozn at redhat.com
Tue Feb 3 16:39:56 UTC 2015


On 02.02.2015 15:08, Lin Ma wrote:
> 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 at suse.com>
> ---
>  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(-)

We don't use TABs. If you ran 'make syntax-check' it would catch the errors.

> 
> 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);

So even if libvirt is build without netcf the flag is still supported? I
don't think so. I mean, it's okay that it's here. But I'm missing the
check in '#else' branch.

>  
>      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));

No. If strdup()-ing fails ...

> +
> +        if (virAsprintf(&if_xml_tmp,
> +                        "<interface type='bridge' name='%s'>"
> +                        "<start mode='none'/><bridge/></interface>",
> +                        bridge) < 0) {

.. this won't produce any meaningful XML.

> +         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                           _("failed to generate temp xml for network"));

Indentation's off.

> +            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

We tend to put comments into /* */

> +        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;

This is not the correct way to free @ret. You need to use VIR_FREE()
otherwise @ret is leaked.

> +            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;
> +                }


You've meant virXPathNodeSet(), right?

> +                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;

Are you aware, that this will produce XML that is not acceptable by
libvirt back, right? E.g. for my 'default' network I get this:

# net-dumpxml --system default
<?xml version="1.0"?>
<interface name="virbr0" type="bridge">
  <bridge>

  </bridge>
  <protocol family="ipv4">
    <ip address="192.168.122.1" prefix="24"/>
  </protocol>
</interface>

This is not a libvirt network XML.

> +            }
> +        }
> +    }
> +    else {
> +        def = network->def;
> +        ret = virNetworkDefFormat(def, flags);
> +    }
> +
> + cleanup:

This introduces yet another label of the very same name we already have.
I think these labels can be merged into one.

> +    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
> +

So what's the good having netcf here, in the driver, if it's used
nowhere but dumpXML()? Moreover, if we init and close the netcf handle
on each function call?

>      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 \
> 

Michal




More information about the libvir-list mailing list