[libvirt] [PATCH 2/4] network: provide internal API to return IP of a network

Laine Stump laine at laine.org
Thu Jul 7 06:44:51 UTC 2011


The new listenNetwork atribute needs to learn an IP address based on a
named network. This patch provides a function networkGetNetworkAddress
which provides that.

Some networks have an IP address explicitly in their configuration
(ie, those with a forward type of "none", "route", or "nat"). For
those, we can just return the IP address from the config.

The rest will have a physical device associated with them (either via
<bridge name='...'/>, <forward ... dev='...'/>, or possibly via a pool
of interfaces inside the network's <forward> element) and we will need
to ask the kernel for the current IP address of that device (via the
newly added ifaceGetIPAddress
---
 src/libvirt_network.syms    |    1 +
 src/network/bridge_driver.c |   98 +++++++++++++++++++++++++++++++++++++++++++
 src/network/bridge_driver.h |    2 +
 3 files changed, 101 insertions(+), 0 deletions(-)

diff --git a/src/libvirt_network.syms b/src/libvirt_network.syms
index e402b5f..1fe8902 100644
--- a/src/libvirt_network.syms
+++ b/src/libvirt_network.syms
@@ -5,5 +5,6 @@
 # bridge_driver.h
 networkAllocateActualDevice;
 networkBuildDhcpDaemonCommandLine;
+networkGetNetworkAddress;
 networkNotifyActualDevice;
 networkReleaseActualDevice;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 56c77f2..a7453ea 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -55,6 +55,7 @@
 #include "uuid.h"
 #include "iptables.h"
 #include "bridge.h"
+#include "interface.h"
 #include "logging.h"
 #include "dnsmasq.h"
 #include "util/network.h"
@@ -3102,3 +3103,100 @@ cleanup:
     iface->data.network.actual = NULL;
     return ret;
 }
+
+/*
+ * networkGetNetworkAddress:
+ * @netname: the name of a network
+ *
+ * Attempt to return the IP (v4) address associated with the named
+ * network. If a libvirt virtual network, that will be provided in the
+ * configuration. For host bridge and direct (macvtap) networks, we
+ * must do an ioctl to learn the address.
+ *
+ * Note: This function returns the 1st IPv4 address it finds. It might
+ * be useful if it was more flexible, but the current use (getting a
+ * listen address for qemu's vnc/spice graphics server) can only use a
+ * single address anyway.
+ *
+ * Returns a string (which must be free'd by the caller) on success,
+ * or NULL on failure.
+ */
+char *
+networkGetNetworkAddress(const char *netname)
+{
+    struct network_driver *driver = driverState;
+    virNetworkObjPtr network = NULL;
+    virNetworkDefPtr netdef;
+    virNetworkIpDefPtr ipdef;
+    virSocketAddr addr;
+    virSocketAddrPtr addrptr = NULL;
+    char *devname = NULL;
+    char *addrstr = NULL;
+
+    networkDriverLock(driver);
+    network = virNetworkFindByName(&driver->networks, netname);
+    networkDriverUnlock(driver);
+    if (!network) {
+        networkReportError(VIR_ERR_NO_NETWORK,
+                           _("no network with matching name '%s'"),
+                           netname);
+        goto cleanup;
+    }
+    netdef = network->def;
+
+    switch (netdef->forwardType) {
+    case VIR_NETWORK_FORWARD_NONE:
+    case VIR_NETWORK_FORWARD_NAT:
+    case VIR_NETWORK_FORWARD_ROUTE:
+        /* if there's an ipv4def, get it's address */
+        ipdef = virNetworkDefGetIpByIndex(netdef, AF_INET, 0);
+        if (!ipdef) {
+            networkReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("network '%s' doesn't have an IP address"),
+                               netdef->name);
+            break;
+        }
+        addrptr = &ipdef->address;
+        break;
+
+    case VIR_NETWORK_FORWARD_BRIDGE:
+        if ((devname = netdef->bridge))
+            break;
+        /*
+         * If netdef->bridge wasn't set, this is a direct-mode
+         * interface, so purposefully drop through to the next case
+         */
+    case VIR_NETWORK_FORWARD_PRIVATE:
+    case VIR_NETWORK_FORWARD_VEPA:
+    case VIR_NETWORK_FORWARD_PASSTHROUGH:
+        if (netdef->nForwardIfs == 0)
+            devname = netdef->forwardDev;
+        else if (netdef->forwardIfs)
+            devname = netdef->forwardIfs[0].dev;
+
+        if (!devname) {
+            networkReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("network '%s' has no associated interface or bridge"),
+                               netdef->name);
+        }
+        break;
+    }
+
+    if (devname) {
+        if (ifaceGetIPAddress(devname, &addr)) {
+            virReportSystemError(errno,
+                                 _("Failed to get IP address for '%s' (network '%s')"),
+                                 devname, netdef->name);
+        } else {
+            addrptr = &addr;
+        }
+    }
+
+    if (addrptr)
+        addrstr = virSocketFormatAddr(addrptr);
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    return addrstr;
+}
diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h
index 4f6a54d..3c76af2 100644
--- a/src/network/bridge_driver.h
+++ b/src/network/bridge_driver.h
@@ -39,6 +39,8 @@ int networkAllocateActualDevice(virDomainNetDefPtr iface);
 int networkNotifyActualDevice(virDomainNetDefPtr iface);
 int networkReleaseActualDevice(virDomainNetDefPtr iface);
 
+char *networkGetNetworkAddress(const char *netname);
+
 int networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network,
                                       virCommandPtr *cmdout, char *pidfile,
                                       dnsmasqContext *dctx);
-- 
1.7.3.4




More information about the libvir-list mailing list