[libvirt] [PATCH 02/10] conf: Network - add ability to read/write XML DHCP state

TJ libvirt at iam.tj
Thu Feb 28 02:37:25 UTC 2013


From: "TJ" <libvirt at iam.tj>

Maintain backwards XML compatibility by assuming existing default values
and only adding the additional XML properties if settings are not
default.

Signed-off-by: TJ <linux at iam.tj>
---
 src/conf/network_conf.c | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 3fc01cf..259de0a 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -828,6 +828,19 @@ virNetworkDHCPDefParseXML(const char *networkName,
 {
 
     xmlNodePtr cur;
+    char *tmp = NULL;
+
+    def->dhcp_enabled = true;
+    if ((tmp = virXMLPropString(node, "enabled"))) {
+        def->dhcp_enabled = strncmp("no", tmp, 2) == 0 ? false : def->dhcp_enabled;
+        VIR_FREE(tmp);
+    }
+
+    def->dhcp_relay = false;
+    if ((tmp = virXMLPropString(node, "relay"))) {
+        def->dhcp_relay = strncmp("yes", tmp, 3) == 0 ? true : def->dhcp_relay;
+	VIR_FREE(tmp);
+    }
 
     cur = node->children;
     while (cur != NULL) {
@@ -2180,12 +2193,19 @@ virNetworkIpDefFormat(virBufferPtr buf,
         virBufferEscapeString(buf, "<tftp root='%s' />\n",
                               def->tftproot);
     }
-    if ((def->nranges || def->nhosts)) {
+    if ((def->nranges || def->nhosts) || 
+         !def->dhcp_enabled || def->dhcp_relay) {
         int ii;
-        virBufferAddLit(buf, "<dhcp>\n");
+        virBufferAddLit(buf, "<dhcp");
+        if (!def->dhcp_enabled)
+	    virBufferAddLit(buf, " enabled='no'");
+	if (def->dhcp_relay)
+	    virBufferAddLit(buf, " relay='yes'");
+	virBufferAddLit(buf, ">\n");
+
         virBufferAdjustIndent(buf, 2);
 
-        for (ii = 0 ; ii < def->nranges ; ii++) {
+        for (ii = 0 ; def->nranges && ii < def->nranges ; ii++) {
             char *saddr = virSocketAddrFormat(&def->ranges[ii].start);
             if (!saddr)
                 goto error;
@@ -2199,7 +2219,7 @@ virNetworkIpDefFormat(virBufferPtr buf,
             VIR_FREE(saddr);
             VIR_FREE(eaddr);
         }
-        for (ii = 0 ; ii < def->nhosts ; ii++) {
+        for (ii = 0 ; def->nhosts && ii < def->nhosts ; ii++) {
             virBufferAddLit(buf, "<host ");
             if (def->hosts[ii].mac)
                 virBufferAsprintf(buf, "mac='%s' ", def->hosts[ii].mac);
-- 
1.8.1.2.433.g9808ce0.dirty


>From 79a655340f1febc7c35ea4e0a7e0f30ec03e4795 Mon Sep 17 00:00:00 2001
In-Reply-To: <512E724A.10805 at iam.tj>
References: <512E724A.10805 at iam.tj>
From: "TJ" <libvirt at iam.tj>
Date: Tue, 26 Feb 2013 17:11:52 +0000
Subject: [PATCH 03/10] conf: Network - add pointers to enabled virNetworkIpDef
 DHCP settings
To: libvir-list at redhat.com

Having previously introduced DHCP enabled and relay state within the
virNetworkIpDef structure - which can be one of many on each network -
these pointers allow us to track and easily access the DHCP state for
IPv4 and IPv6 when setting up the network without having to iterate
every virNetworkIpDef to find the DHCP state.

Signed-off-by: TJ <linux at iam.tj>
---
 src/conf/network_conf.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 8400eab..1889c45 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -231,6 +231,8 @@ struct _virNetworkDef {
     virPortGroupDefPtr portGroups;
     virNetDevBandwidthPtr bandwidth;
     virNetDevVlan vlan;
+    virNetworkIpDefPtr ipv4_dhcp;
+    virNetworkIpDefPtr ipv6_dhcp;
 };
 
 typedef struct _virNetworkObj virNetworkObj;
-- 
1.8.1.2.433.g9808ce0.dirty


>From 5ce7f49d7e0ebf0eeb9595d305c2b70895f4e4db Mon Sep 17 00:00:00 2001
In-Reply-To: <512E724A.10805 at iam.tj>
References: <512E724A.10805 at iam.tj>
From: "TJ" <libvirt at iam.tj>
Date: Tue, 26 Feb 2013 17:14:36 +0000
Subject: [PATCH 04/10] conf: Network - keep track of active DHCP stanza in
 virNetworkDef
To: libvir-list at redhat.com

To avoid iterating all virNetworkIpDef entries when determining
DHCP state keep track of the first enabled DHCP stanza in the
network definition itself, for both IPv4 and IPv6.

A by-product of this change is it allows the XML to contain more
than one IP->DHCP stanza. The active DHCP stanza is the first enabled
DHCP stanza.
All other stanzas are retained which adds flexibility when multiple
interfaces and routes might come and go since an alternative DHCP
stanza can be selected and a refresh operation performed without
needing to destroy/edit/start the network.

Signed-off-by: TJ <linux at iam.tj>
---
 src/conf/network_conf.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 259de0a..c5eab01 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -1882,6 +1882,13 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
             if (ret < 0)
                 goto error;
             def->nips++;
+	    /* use only the first enabled DHCP definition */
+	    if (!def->ipv4_dhcp && def->ips[ii].dhcp_enabled &&
+		VIR_SOCKET_ADDR_IS_FAMILY(&def->ips[ii].address, AF_INET))
+		def->ipv4_dhcp = &def->ips[ii];
+	    if (!def->ipv6_dhcp && def->ips[ii].dhcp_enabled &&
+		VIR_SOCKET_ADDR_IS_FAMILY(&def->ips[ii].address, AF_INET6))
+		def->ipv6_dhcp = &def->ips[ii];
         }
     }
     VIR_FREE(ipNodes);
-- 
1.8.1.2.433.g9808ce0.dirty


>From ed60402970098706b49e3d71c008520168968277 Mon Sep 17 00:00:00 2001
In-Reply-To: <512E724A.10805 at iam.tj>
References: <512E724A.10805 at iam.tj>
From: "TJ" <libvirt at iam.tj>
Date: Tue, 26 Feb 2013 17:43:46 +0000
Subject: [PATCH 05/10] network: Bridge - use IPv4 and IPv6 active DHCP stanza
 pointers
To: libvir-list at redhat.com

Rather than iterate through virNetworkIPDef arrays multiple times
use the new virNetworkDef ipv4_dhcp and ipv6_dhcp active stanza
pointers.

Signed-off-by: TJ <linux at iam.tj>
---
 src/network/bridge_driver.c | 63 +++++++++++----------------------------------
 1 file changed, 15 insertions(+), 48 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 0932cf8..8410c93 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -810,24 +810,16 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
         }
     }
 
-    /* Find the first dhcp for both IPv4 and IPv6 */
-    for (ii = 0, ipv4def = NULL, ipv6def = NULL, ipv6SLAAC = false;
-         (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
-         ii++) {
-        if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET)) {
-            if (ipdef->nranges || ipdef->nhosts) {
-                if (ipv4def) {
-                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                                   _("For IPv4, multiple DHCP definitions "
-                                     "cannot be specified."));
-                    goto cleanup;
-                } else {
-                    ipv4def = ipdef;
-                }
-            }
-        }
-        if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) {
-            if (ipdef->nranges || ipdef->nhosts) {
+    ipv4def = ipv6def = NULL;
+    ipdef = network->def->ipv4_dhcp;
+    if (ipdef && (ipdef->nranges || ipdef->nhosts))
+        ipv4def = ipdef;
+
+    ipdef = network->def->ipv6_dhcp;
+    if (ipdef) {
+        if (ipdef->nranges || ipdef->nhosts) {
+            ipv6def = ipdef;
+
                 if (!DNSMASQ_DHCPv6_SUPPORT(caps)) {
                     unsigned long version = dnsmasqCapsGetVersion(caps);
                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -842,18 +834,9 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
                                    DNSMASQ_DHCPv6_MINOR_REQD);
                     goto cleanup;
                 }
-                if (ipv6def) {
-                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                                   _("For IPv6, multiple DHCP definitions "
-                                     "cannot be specified."));
-                    goto cleanup;
-                } else {
-                    ipv6def = ipdef;
-                }
-            } else {
-                ipv6SLAAC = true;
-            }
-        }
+	}
+    } else {
+        ipv6SLAAC = true;
     }
 
     if (ipv6def && ipv6SLAAC) {
@@ -1160,25 +1143,9 @@ networkRefreshDhcpDaemon(struct network_driver *driver,
     if (!(dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR)))
         goto cleanup;
 
-    /* Look for first IPv4 address that has dhcp defined.
-     * We only support dhcp-host config on one IPv4 subnetwork
-     * and on one IPv6 subnetwork.
-     */
-    ipv4def = NULL;
-    for (ii = 0;
-         (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
-         ii++) {
-        if (!ipv4def && (ipdef->nranges || ipdef->nhosts))
-            ipv4def = ipdef;
-    }
+    ipv4def = network->def->ipv4_dhcp;
 
-    ipv6def = NULL;
-    for (ii = 0;
-         (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET6, ii));
-         ii++) {
-        if (!ipv6def && (ipdef->nranges || ipdef->nhosts))
-            ipv6def = ipdef;
-    }
+    ipv6def = network->def->ipv6_dhcp;
 
     if (ipv4def && (networkBuildDnsmasqDhcpHostsList(dctx, ipv4def) < 0))
            goto cleanup;
-- 
1.8.1.2.433.g9808ce0.dirty


>From bc6995ebc1ea078b10c574df3f9264d0053627d2 Mon Sep 17 00:00:00 2001
In-Reply-To: <512E724A.10805 at iam.tj>
References: <512E724A.10805 at iam.tj>
From: "TJ" <libvirt at iam.tj>
Date: Tue, 26 Feb 2013 20:26:58 +0000
Subject: [PATCH 06/10] network: Bridge - Add support for a DHCP Relay Agent
To: libvir-list at redhat.com

A DHCP relay daemon will be started that will forward all DHCP/BOOTP
requests on the bridge network via the first declared forward
interface. The relay is broadcast rather than routed so no IP address
is needed on the bridge.

The XML <relay> element's "relay" property of the active DHCP stanza
defaults to 'no'. Set it to 'yes' to enable the relay:

<ip ...>
 <dhcp relay='yes'/>
</ip>

The relay will not be started if the "enable" property is 'no':

<ip ...>
 <dhcp enable='no' relay='yes'/>
</ip>

Signed-off-by: TJ <linux at iam.tj>
---
 src/network/bridge_driver.c | 146 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 146 insertions(+)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 8410c93..c02d3de 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -587,6 +587,145 @@ cleanup:
      * which is later saved into a file
      */
 
+static virNetworkIpDefPtr
+networkGetActiveDhcp(virNetworkObjPtr network)
+{
+    virNetworkIpDefPtr dhcp = NULL;
+
+    if (network->def && network->def->ipv4_dhcp)
+        dhcp = network->def->ipv4_dhcp;
+
+    if (!dhcp &&
+        network->def && network->def->ipv6_dhcp)
+        dhcp = network->def->ipv6_dhcp;
+
+    return dhcp;
+}
+
+static int
+networkBuildDhcpRelayArgv(virNetworkObjPtr network,
+                        const char *pidfile,
+                        virCommandPtr cmd)
+{
+    int ret = -1;
+
+    /* PID file */
+    virCommandAddArgList(cmd, "-r", pidfile, NULL);
+
+    /* Listen for DHCP requests on the bridge interface */
+    virCommandAddArgList(cmd, "-i", network->def->bridge, NULL);
+
+    /* Use the first forwarding device to broadcast to the upstream DHCP server */
+    if (network->def->forward.nifs > 0) {
+        virCommandAddArgList(cmd, "-b", network->def->forward.ifs[0].device.dev, NULL);
+	ret = 0;
+    } else
+	virReportSystemError(VIR_ERR_INVALID_INTERFACE,
+	    _("DHCP relay requires at least one network %s\n"),
+              "<forward ... dev='eth?'/> or <interface dev='eth?'/>");
+
+    return ret;
+}
+
+static int
+networkBuildDhcpRelayCommandLine(virNetworkObjPtr network, virCommandPtr *cmdout,
+                                  char *pidfile)
+{
+    virCommandPtr cmd = NULL;
+    int ret = -1;
+
+    cmd = virCommandNew(DHCPRELAY);
+    if (networkBuildDhcpRelayArgv(network, pidfile, cmd) < 0) {
+        goto cleanup;
+    }
+
+    if (cmdout)
+        *cmdout = cmd;
+    ret = 0;
+cleanup:
+    if (ret < 0)
+        virCommandFree(cmd);
+    return ret;
+}
+
+static int
+networkStartDhcpRelayDaemon(struct network_driver *driver ATTRIBUTE_UNUSED,
+                             virNetworkObjPtr network)
+{
+    virCommandPtr cmd = NULL;
+    virNetworkIpDefPtr ipdef = NULL;
+    char *pidfile = NULL;
+    char *tmp = NULL;
+    int pid_len;
+    int ret = 0;
+    const char *dhcprelay = "dhcprelay_";
+
+    ipdef = networkGetActiveDhcp(network);
+    /* Prepare for DHCP relay agent */
+    if (ipdef && ipdef->dhcp_enabled && ipdef->dhcp_relay) {
+	ret = -1;
+
+        if (virFileMakePath(NETWORK_PID_DIR) < 0) {
+            virReportSystemError(errno,
+                                 _("cannot create directory %s"),
+                                 NETWORK_PID_DIR);
+            goto cleanup;
+        }
+
+        pid_len = strlen(dhcprelay) + strlen(network->def->name);
+        if ( VIR_ALLOC_N(tmp, pid_len+1) >= 0) {
+	    tmp = strcpy(tmp, dhcprelay);
+	    tmp = strncat(tmp, network->def->name, pid_len);
+	    if (!(pidfile = virPidFileBuildPath(NETWORK_PID_DIR, tmp))) {
+	        virReportOOMError();
+	        goto cleanup;
+	    }
+        } else {
+	    virReportOOMError();
+	    goto cleanup;
+	}
+
+        ret = networkBuildDhcpRelayCommandLine(network, &cmd, pidfile);
+        if (ret < 0)
+	    goto cleanup;
+
+        ret = virCommandRun(cmd, NULL);
+        if (ret < 0)
+	    goto cleanup;
+	
+        ret = virPidFileRead(NETWORK_PID_DIR, pidfile, &network->dhcprelayPid);
+        if (ret < 0)
+	    virReportSystemError(errno, _("%s is not running"), DHCPRELAY);
+
+cleanup:
+        VIR_FREE(tmp);
+        VIR_FREE(pidfile);
+        virCommandFree(cmd);
+    }
+    return ret;
+}
+
+static int
+networkRestartDhcpRelayDaemon(struct network_driver *driver,
+                              virNetworkObjPtr network)
+{
+    /* if there is a running DHCP relay agent, kill it */
+    if (network->dhcprelayPid > 0) {
+        networkKillDaemon(network->dhcprelayPid, DHCPRELAY,
+                          network->def->name);
+        network->dhcprelayPid = -1;
+    }
+    /* now start the daemon if it should be started */
+    return networkStartDhcpRelayDaemon(driver, network);
+}
+
+static int
+networkRefreshDhcpRelayDaemon(struct network_driver *driver,
+                              virNetworkObjPtr network)
+{
+    return networkRestartDhcpRelayDaemon(driver, network);
+}
+
 static int
 networkBuildDnsmasqDhcpHostsList(dnsmasqContext *dctx,
                                  virNetworkIpDefPtr ipdef)
@@ -1496,6 +1635,7 @@ networkRefreshDaemons(struct network_driver *driver)
              * dnsmasq and/or radvd, or restart them if they've
              * disappeared.
              */
+            networkRefreshDhcpRelayDaemon(driver, network);
             networkRefreshDhcpDaemon(driver, network);
             networkRefreshRadvd(driver, network);
         }
@@ -2462,6 +2602,10 @@ networkStartNetworkVirtual(struct network_driver *driver,
         networkStartDhcpDaemon(driver, network) < 0)
         goto err3;
 
+    /* start DHCP relay-agent (doesn't need IP address(es) to function) */
+    if (networkStartDhcpRelayDaemon(driver, network) < 0)
+	goto err3;
+
     /* start radvd if there are any ipv6 addresses */
     if (v6present && networkStartRadvd(driver, network) < 0)
         goto err4;
@@ -3276,6 +3420,8 @@ networkUpdate(virNetworkPtr net,
              */
             if (networkRestartDhcpDaemon(driver, network) < 0)
                 goto cleanup;
+            if (networkRestartDhcpRelayDaemon(driver, network) < 0)
+                goto cleanup;
 
         } else if (section == VIR_NETWORK_SECTION_IP_DHCP_HOST) {
             /* if we previously weren't listening for dhcp and now we
-- 
1.8.1.2.433.g9808ce0.dirty


>From 94c8cf891f83fd26b1ba608ed6be4315058493dd Mon Sep 17 00:00:00 2001
In-Reply-To: <512E724A.10805 at iam.tj>
References: <512E724A.10805 at iam.tj>
From: "TJ" <libvirt at iam.tj>
Date: Tue, 26 Feb 2013 21:22:47 +0000
Subject: [PATCH 07/10] network: Bridge - don't offer dnsmasq DHCP services
 when DHCP relay is enabled
To: libvir-list at redhat.com

When dnsmasq's DNS services are required but the network is configured
to use a DHCP relay agent (other than dnsmasq's proxy services) the
configuration generated for dnsmasq should not enable DHCP services.

Signed-off-by: TJ <linux at iam.tj>
---
 src/network/bridge_driver.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index c02d3de..a4cd727 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -951,11 +951,12 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
 
     ipv4def = ipv6def = NULL;
     ipdef = network->def->ipv4_dhcp;
-    if (ipdef && (ipdef->nranges || ipdef->nhosts))
+    if (ipdef && ipdef->dhcp_enabled && !ipdef->dhcp_relay &&
+        (ipdef->nranges || ipdef->nhosts))
         ipv4def = ipdef;
 
     ipdef = network->def->ipv6_dhcp;
-    if (ipdef) {
+    if (ipdef && ipdef->dhcp_enabled && !ipdef->dhcp_relay) {
         if (ipdef->nranges || ipdef->nhosts) {
             ipv6def = ipdef;
 
@@ -1266,8 +1267,8 @@ static int
 networkRefreshDhcpDaemon(struct network_driver *driver,
                          virNetworkObjPtr network)
 {
-    int ret = -1, ii;
-    virNetworkIpDefPtr ipdef, ipv4def, ipv6def;
+    int ret = -1;
+    virNetworkIpDefPtr ipv4def, ipv6def;
     dnsmasqContext *dctx = NULL;
 
     /* if no IP addresses specified, nothing to do */
-- 
1.8.1.2.433.g9808ce0.dirty


>From e8dfe2a0b5945dbd71e3a7d6fdbbf9457fae9063 Mon Sep 17 00:00:00 2001
In-Reply-To: <512E724A.10805 at iam.tj>
References: <512E724A.10805 at iam.tj>
From: "TJ" <libvirt at iam.tj>
Date: Tue, 26 Feb 2013 21:35:05 +0000
Subject: [PATCH 08/10] configure: Add DHCPRELAY to the set of external program
 definitions
To: libvir-list at redhat.com

This variable should name the path to the system's DHCP relay daemon.

At this time the expected daemon is "dhcp-helper", a DHCP relay agent
from Simon Kelly, author of dnsmasq.

The supporting code, however, has been designed to work with any
suitable DHCP relay agent. Later patches could allow configuration
of the agent's command-line arguments.

Currently the chosen agent must support:

-b <bridge_interface> (the virtual network to listen on)
-i <physical_interface> (the interface to broadcast on)
-r </path/to/pid.file> (the PID file of the daemon)

Signed-off-by: TJ <linux at iam.tj>
---
 configure.ac | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/configure.ac b/configure.ac
index e3a749a..b62170e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -295,6 +295,8 @@ dnl External programs that we can use if they are available.
 dnl We will hard-code paths to these programs unless we cannot
 dnl detect them, in which case we'll search for the program
 dnl along the $PATH at runtime and fail if it's not there.
+AC_PATH_PROG([DHCPRELAY], [dhcp-helper], [dhcp-helper],
+	[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
 AC_PATH_PROG([DNSMASQ], [dnsmasq], [dnsmasq],
 	[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
 AC_PATH_PROG([RADVD], [radvd], [radvd],
@@ -314,6 +316,8 @@ AC_PATH_PROG([OVSVSCTL], [ovs-vsctl], [ovs-vsctl],
 AC_PATH_PROG([SCRUB], [scrub], [scrub],
 	[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
 
+AC_DEFINE_UNQUOTED([DHCPRELAY], ["$DHCPRELAY"],
+	[Location or name of the dhcp relay-agent program])
 AC_DEFINE_UNQUOTED([DNSMASQ],["$DNSMASQ"],
         [Location or name of the dnsmasq program])
 AC_DEFINE_UNQUOTED([RADVD],["$RADVD"],
-- 
1.8.1.2.433.g9808ce0.dirty


>From 69128632689e26cc281288fb556cf76e77f441fb Mon Sep 17 00:00:00 2001
In-Reply-To: <512E724A.10805 at iam.tj>
References: <512E724A.10805 at iam.tj>
From: "TJ" <libvirt at iam.tj>
Date: Wed, 27 Feb 2013 03:51:28 +0000
Subject: [PATCH 09/10] Add copyright attribution for DHCP relay functionality
To: libvir-list at redhat.com

Signed-off-by: TJ <linux at iam.tj>
---
 src/conf/network_conf.c     | 1 +
 src/network/bridge_driver.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index c5eab01..43c277c 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2006-2013 Red Hat, Inc.
  * Copyright (C) 2006-2008 Daniel P. Berrange
+ * Copyright (C) 2013 TJ <linux at iam.tj>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index a4cd727..1667ae6 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -4,6 +4,7 @@
  *
  * Copyright (C) 2006-2013 Red Hat, Inc.
  * Copyright (C) 2006 Daniel P. Berrange
+ * Copyright (C) 2013 TJ <linux at iam.tj>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
-- 
1.8.1.2.433.g9808ce0.dirty


>From c68b5a4aa5d28929e86a3e9227dba6c64df90e71 Mon Sep 17 00:00:00 2001
In-Reply-To: <512E724A.10805 at iam.tj>
References: <512E724A.10805 at iam.tj>
From: "TJ" <libvirt at iam.tj>
Date: Wed, 27 Feb 2013 20:35:06 +0000
Subject: [PATCH 10/10] docs: Describe the <dhcp> 'enable' and 'relay'
 attributes
To: libvir-list at redhat.com

Signed-off-by: TJ <linux at iam.tj>
---
 docs/formatnetwork.html.in | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index 41a83fa..c4c4def 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -650,12 +650,20 @@
           <dt><code>dhcp</code></dt>
           <dd>Also within the <code>ip</code> element there is an
             optional <code>dhcp</code> element. The presence of this element
-            enables DHCP services on the virtual network. It will further
+            enables DHCP services on the virtual network. It can further
             contain one or more <code>range</code> elements. The
             <code>dhcp</code> element supported for both
             IPv4 <span class="since">Since 0.3.0</span>
             and IPv6 <span class="since">Since 1.0.1</span>, but
             only for one IP address of each type per network.
+            Since $TODO.$FIXME it can optionally contain a boolean <code>enable</code> attribute
+            ('yes' or 'no') where the value defaults to 'yes', and a boolean
+            <code>relay</code> attribute where the value defaults to 'no'.
+            When <code>relay='yes'</code> any settings within the <code>dhcp</code> block
+            are ignored and a DHCP relay agent is started instead of a local DHCP server.
+            The DHCP relay daemon will listen on the network's bridge interface for
+            DHCP/BOOTP traffic and relay it via broadcast from the first interface declared
+            in the <code>forward</code> element.
             <dl>
               <dt><code>range</code></dt>
               <dd>The <code>start</code> and <code>end</code> attributes on the
@@ -779,6 +787,18 @@
         <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" />
       </network></pre>
 
+    <p>Here is the same configuration using a DHCP relay agent instead of a local DHCP server.</p>
+    <pre>
+      <network>
+        <name>local</name>
+        <bridge name="virbr1" />
+        <forward mode="route" dev="eth1"/>
+        <ip address="192.168.122.1" netmask="255.255.255.0">
+          <dhcp relay='yes'/>
+        </ip>
+        <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" />
+      </network></pre>
+ 
     <p>
       Below is another IPv6 varition.  Instead of a dhcp range being
       specified, this example has a couple of IPv6 host definitions.
-- 
1.8.1.2.433.g9808ce0.dirty




More information about the libvir-list mailing list