Display detected IP addresses in the domain XML using the
IP_LEASE variable name. This variable name now becomes
a reserved variable name that can be read only but not set
by the user.
The format of the value is: <ip addresss>,<lease timeout in seconds>
An example of a displayed XML may then be:
<interface type='bridge'>
<mac address='52:54:00:68:e3:90'/>
<source bridge='virbr0'/>
<target dev='vnet1'/>
<model type='virtio'/>
<filterref filter='clean-traffic'>
<parameter name='CTRL_IP_LEARNING' value='dhcp'/>
<parameter name='IP_LEASE' value='192.168.122.210,100'/>
</filterref>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00'
slot='0x04' function='0x0'/>
</interface>
---
docs/formatnwfilter.html.in | 27 ++++++++++++++++
src/conf/domain_conf.c | 16 +++++++--
src/conf/domain_nwfilter.c | 11 ++++++
src/conf/domain_nwfilter.h | 12 +++++++
src/conf/nwfilter_conf.c | 3 +
src/conf/nwfilter_ipaddrmap.c | 29 ++++++++++++++++++
src/conf/nwfilter_ipaddrmap.h | 5 +++
src/conf/nwfilter_params.c | 45 ++++++++++++++++++++++++++--
src/conf/nwfilter_params.h | 9 ++++-
src/libvirt_private.syms | 3 +
src/nwfilter/nwfilter_dhcpsnoop.c | 53 +++++++++++++++++++++++++++++++++
src/nwfilter/nwfilter_dhcpsnoop.h | 4 ++
src/nwfilter/nwfilter_driver.c | 10 ++++++
src/nwfilter/nwfilter_gentech_driver.c | 24 ++++++++++++++
src/nwfilter/nwfilter_gentech_driver.h | 6 +++
src/nwfilter/nwfilter_learnipaddr.c | 14 ++++++++
src/nwfilter/nwfilter_learnipaddr.h | 2 +
17 files changed, 264 insertions(+), 9 deletions(-)
Index: libvirt-acl/src/conf/nwfilter_params.h
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_params.h
+++ libvirt-acl/src/conf/nwfilter_params.h
@@ -72,7 +72,10 @@ struct _virNWFilterHashTable {
virNWFilterHashTablePtr virNWFilterParseParamAttributes(xmlNodePtr cur);
int virNWFilterFormatParamAttributes(virBufferPtr buf,
virNWFilterHashTablePtr table,
- const char *filterref);
+ const char *filterref,
+ const unsigned char *vmuuid,
+ const unsigned char *mac,
+ const char *ifname);
virNWFilterHashTablePtr virNWFilterHashTableCreate(int n);
void virNWFilterHashTableFree(virNWFilterHashTablePtr table);
@@ -89,12 +92,14 @@ int virNWFilterHashTablePutAll(virNWFilt
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
# define VALID_VARVALUE \
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.:"
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.:,"
# define NWFILTER_VARNAME_IP "IP"
# define NWFILTER_VARNAME_MAC "MAC"
# define NWFILTER_VARNAME_CTRL_IP_LEARNING "CTRL_IP_LEARNING"
# define NWFILTER_VARNAME_DHCPSERVER "DHCPSERVER"
+# define NWFILTER_VARNAME_IP_LEASE "IP_LEASE"
+# define NWFILTER_VARNAME_IPV6_LEASE "IPV6_LEASE" /* future */
enum virNWFilterVarAccessType {
VIR_NWFILTER_VAR_ACCESS_ELEMENT = 0,
Index: libvirt-acl/src/conf/domain_conf.c
===================================================================
--- libvirt-acl.orig/src/conf/domain_conf.c
+++ libvirt-acl/src/conf/domain_conf.c
@@ -43,6 +43,7 @@
#include "buf.h"
#include "c-ctype.h"
#include "logging.h"
+#include "nwfilter_params.h"
#include "nwfilter_conf.h"
#include "ignore-value.h"
#include "storage_file.h"
@@ -11258,7 +11259,8 @@ error:
static int
virDomainNetDefFormat(virBufferPtr buf,
virDomainNetDefPtr def,
- unsigned int flags)
+ unsigned int flags,
+ const unsigned char *vmuuid)
{
const char *type = virDomainNetTypeToString(def->type);
@@ -11399,9 +11401,15 @@ virDomainNetDefFormat(virBufferPtr buf,
}
}
if (def->filter) {
+ const char *ifname = NULL;
+
+ if (!(flags & VIR_DOMAIN_XML_INACTIVE))
+ ifname = def->ifname;
+
virBufferAdjustIndent(buf, 6);
if (virNWFilterFormatParamAttributes(buf, def->filterparams,
- def->filter) < 0)
+ def->filter, vmuuid, def->mac,
+ ifname) < 0)
return -1;
virBufferAdjustIndent(buf, -6);
}
@@ -12684,7 +12692,7 @@ virDomainDefFormatInternal(virDomainDefP
for (n = 0 ; n < def->nnets ; n++)
- if (virDomainNetDefFormat(buf, def->nets[n], flags) < 0)
+ if (virDomainNetDefFormat(buf, def->nets[n], flags, def->uuid) < 0)
goto cleanup;
for (n = 0 ; n < def->nsmartcards ; n++)
@@ -14937,7 +14945,7 @@ virDomainDeviceDefCopy(virCapsPtr caps,
rc = virDomainFSDefFormat(&buf, src->data.fs, flags);
break;
case VIR_DOMAIN_DEVICE_NET:
- rc = virDomainNetDefFormat(&buf,
src->data.net, flags);
+ rc = virDomainNetDefFormat(&buf,
src->data.net, flags, def->uuid);
break;
case VIR_DOMAIN_DEVICE_INPUT:
rc = virDomainInputDefFormat(&buf, src->data.input, flags);
Index: libvirt-acl/src/conf/nwfilter_conf.c
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_conf.c
+++ libvirt-acl/src/conf/nwfilter_conf.c
@@ -3406,7 +3406,8 @@ virNWFilterIncludeDefFormat(virNWFilterI
virBufferAdjustIndent(&buf, 2);
if (virNWFilterFormatParamAttributes(&buf, inc->params,
- inc->filterref) < 0) {
+ inc->filterref,
+ NULL, NULL, NULL) < 0) {
virBufferFreeAndReset(&buf);
return NULL;
}
Index: libvirt-acl/src/libvirt_private.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_private.syms
+++ libvirt-acl/src/libvirt_private.syms
@@ -545,6 +545,7 @@ virDomainLockLeaseDetach;
# domain_nwfilter.h
+virDomainConfNWFilterFormatLeases;
virDomainConfNWFilterInstantiate;
virDomainConfNWFilterRegister;
virDomainConfNWFilterTeardown;
@@ -856,6 +857,7 @@ virNWFilterUnlockFilterUpdates;
# nwfilter_ipaddrmap
virNWFilterIPAddrMapAddIPAddr;
virNWFilterIPAddrMapDelIPAddr;
+virNWFilterIPAddrMapFormatIPAddrs;
virNWFilterIPAddrMapGetIPAddr;
virNWFilterIPAddrMapInit;
virNWFilterIPAddrMapShutdown;
@@ -883,6 +885,7 @@ virNWFilterVarValueFree;
virNWFilterVarValueGetCardinality;
virNWFilterVarValueGetNthValue;
virNWFilterVarValueGetSimple;
+virNWFilterFormatParamAttributes;
# pci.h
Index: libvirt-acl/src/conf/nwfilter_params.c
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_params.c
+++ libvirt-acl/src/conf/nwfilter_params.c
@@ -30,10 +30,17 @@
#include "datatypes.h"
#include "nwfilter_params.h"
#include "domain_conf.h"
+#include "domain_nwfilter.h"
+#include "nwfilter_ipaddrmap.h"
#define VIR_FROM_THIS VIR_FROM_NWFILTER
+static const char *virNWFilterReservedVarnames[] = {
+ NWFILTER_VARNAME_IP_LEASE,
+ NWFILTER_VARNAME_IPV6_LEASE,
+};
+
static bool isValidVarValue(const char *value);
static void virNWFilterVarAccessSetIntIterId(virNWFilterVarAccessPtr,
unsigned int);
@@ -747,7 +754,6 @@ err_exit:
return -1;
}
-
static bool
isValidVarName(const char *var)
{
@@ -767,6 +773,19 @@ virNWFilterParseVarValue(const char *val
return virNWFilterVarValueCreateSimpleCopyValue(val);
}
+static void
+virNWFilterDelReservedVarnames(virNWFilterHashTablePtr ht)
+{
+ unsigned int i;
+ virNWFilterVarValuePtr val;
+
+ for (i = 0; i < ARRAY_CARDINALITY(virNWFilterReservedVarnames); i++) {
+ val = virNWFilterHashTableRemoveEntry(ht,
+ virNWFilterReservedVarnames[i]);
+ virNWFilterVarValueFree(val);
+ }
+}
+
virNWFilterHashTablePtr
virNWFilterParseParamAttributes(xmlNodePtr cur)
{
@@ -817,6 +836,15 @@ skip_entry:
}
cur = cur->next;
}
+
+ /*
+ * read-only variables that may be usable in an incoming
+ * migration could be wired up here.
+ */
+
+ /* remove all reserved varnames from the table */
+ virNWFilterDelReservedVarnames(table);
+
return table;
err_exit:
@@ -838,7 +866,10 @@ virNWFilterFormatParameterNameSorter(con
int
virNWFilterFormatParamAttributes(virBufferPtr buf,
virNWFilterHashTablePtr table,
- const char *filterref)
+ const char *filterref,
+ const unsigned char *vmuuid,
+ const unsigned char *mac,
+ const char *ifname)
{
virHashKeyValuePairPtr items;
int i, j, card, numKeys;
@@ -872,6 +903,16 @@ virNWFilterFormatParamAttributes(virBuff
virNWFilterVarValueGetNthValue(value, j));
}
+ if (ifname) {
+ virBufferAdjustIndent(buf, 2);
+ /* also display the IP addresses being used */
+ virDomainConfNWFilterFormatLeases(buf,
+ table,
+ ifname,
+ vmuuid,
+ mac);
+ virBufferAdjustIndent(buf, -2);
+ }
virBufferAddLit(buf, "</filterref>\n");
} else {
virBufferAddLit(buf, "/>\n");
Index: libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_dhcpsnoop.c
+++ libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.c
@@ -1990,6 +1990,52 @@ virNWFilterSnoopLeaseFileLoad(void)
}
/*
+ * Format the detected IP addresses for display in the domain's
+ * XML inside a <parameter name=... value=.../> XML node.
+ */
+void
+virNWFilterSnoopFormatLeases(virBufferPtr buf,
+ const unsigned char *vmuuid,
+ const unsigned char *macaddr)
+{
+ char ifkey[VIR_IFKEY_LEN];
+ virNWFilterSnoopReqPtr req;
+ virNWFilterSnoopIPLeasePtr ipl;
+ char *ipbuf;
+
+ virNWFilterSnoopIFKeyFMT(ifkey, vmuuid, macaddr);
+
+ req = virNWFilterSnoopReqGetByIFKey(ifkey);
+ if (req) {
+ time_t now = time(0);
+
+ /* protect req->start */
+ virNWFilterSnoopReqLock(req);
+
+ for (ipl = req->start; ipl; ipl = ipl->next) {
+ if (ipl->timeout <= now)
+ continue;
+
+ ipbuf = virSocketAddrFormat(&ipl->ipAddress);
+ if (!ipbuf)
+ continue;
+
+ virBufferAsprintf(buf,
+ "<parameter name='"
+ NWFILTER_VARNAME_IP_LEASE
+ "' value='%s,%u'/>\n",
+ ipbuf,
+ (unsigned int)(ipl->timeout - now));
+ VIR_FREE(ipbuf);
+ }
+
+ virNWFilterSnoopReqUnlock(req);
+
+ virNWFilterSnoopReqPut(req);
+ }
+}
+
+/*
* Wait until all threads have ended.
*/
static void
@@ -2175,6 +2221,13 @@ virNWFilterDHCPSnoopShutdown(void)
#else /* HAVE_LIBPCAP */
+void
+virNWFilterSnoopFormatLeases(virBufferPtr buf ATTRIBUTE_UNUSED,
+ const unsigned char *vmuuid ATTRIBUTE_UNUSED,
+ const unsigned char *macaddr ATTRIBUTE_UNUSED)
+{
+}
+
int
virNWFilterDHCPSnoopInit(void)
{
Index: libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.h
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_dhcpsnoop.h
+++ libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.h
@@ -36,4 +36,8 @@ int virNWFilterDHCPSnoopReq(virNWFilterT
virNWFilterHashTablePtr filterparams,
virNWFilterDriverStatePtr driver);
void virNWFilterDHCPSnoopEnd(const char *ifname);
+void virNWFilterSnoopFormatLeases(virBufferPtr buf,
+ const unsigned char *vmuuid,
+ const unsigned char *macaddr);
+
#endif /* __NWFILTER_DHCPSNOOP_H */
Index: libvirt-acl/src/conf/domain_nwfilter.c
===================================================================
--- libvirt-acl.orig/src/conf/domain_nwfilter.c
+++ libvirt-acl/src/conf/domain_nwfilter.c
@@ -60,3 +60,14 @@ virDomainConfVMNWFilterTeardown(virDomai
virDomainConfNWFilterTeardown(vm->def->nets[i]);
}
}
+
+void
+virDomainConfNWFilterFormatLeases(virBufferPtr buf,
+ virNWFilterHashTablePtr table,
+ const char *ifname,
+ const unsigned char *vmuuid,
+ const unsigned char *mac)
+{
+ if (nwfilterDriver != NULL)
+ nwfilterDriver->formatLeases(buf, table, ifname, vmuuid, mac);
+}
Index: libvirt-acl/src/conf/domain_nwfilter.h
===================================================================
--- libvirt-acl.orig/src/conf/domain_nwfilter.h
+++ libvirt-acl/src/conf/domain_nwfilter.h
@@ -28,9 +28,16 @@ typedef int (*virDomainConfInstantiateNW
virDomainNetDefPtr net);
typedef void (*virDomainConfTeardownNWFilter)(virDomainNetDefPtr net);
+typedef void (*virDomainConfFormatLeases)(virBufferPtr buf,
+ virNWFilterHashTablePtr table,
+ const char *ifname,
+ const unsigned char *vmuuid,
+ const unsigned char *mac);
+
typedef struct {
virDomainConfInstantiateNWFilter instantiateFilter;
virDomainConfTeardownNWFilter teardownFilter;
+ virDomainConfFormatLeases formatLeases;
} virDomainConfNWFilterDriver;
typedef virDomainConfNWFilterDriver *virDomainConfNWFilterDriverPtr;
@@ -41,5 +48,10 @@ int virDomainConfNWFilterInstantiate(vir
virDomainNetDefPtr net);
void virDomainConfNWFilterTeardown(virDomainNetDefPtr net);
void virDomainConfVMNWFilterTeardown(virDomainObjPtr vm);
+void virDomainConfNWFilterFormatLeases(virBufferPtr buf,
+ virNWFilterHashTablePtr table,
+ const char *ifname,
+ const unsigned char *vmuuid,
+ const unsigned char *mac);
#endif /* DOMAIN_NWFILTER_H */
Index: libvirt-acl/src/nwfilter/nwfilter_gentech_driver.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_gentech_driver.c
+++ libvirt-acl/src/nwfilter/nwfilter_gentech_driver.c
@@ -1209,3 +1209,27 @@ virNWFilterDomainFWUpdateCB(void *payloa
virDomainObjUnlock(obj);
}
+
+void
+virNWFilterFormatLeases(virBufferPtr buf,
+ virNWFilterHashTablePtr vars,
+ const char *ifname,
+ const unsigned char *vmuuid,
+ const unsigned char *mac)
+{
+ virNWFilterVarValuePtr lv;
+ const char *learning = NULL;
+
+ if (!vars)
+ return;
+
+ lv = virHashLookup(vars->hashTable, NWFILTER_VARNAME_CTRL_IP_LEARNING);
+ if (lv)
+ learning = virNWFilterVarValueGetNthValue(lv, 0);
+
+ if (!learning || STRCASEEQ(learning, "any")) {
+ virNWFilterLearnFormatLeases(buf, ifname);
+ } else if (STRCASEEQ(learning, "dhcp")) {
+ virNWFilterSnoopFormatLeases(buf, vmuuid, mac);
+ }
+}
Index: libvirt-acl/src/nwfilter/nwfilter_gentech_driver.h
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_gentech_driver.h
+++ libvirt-acl/src/nwfilter/nwfilter_gentech_driver.h
@@ -64,4 +64,10 @@ void virNWFilterDomainFWUpdateCB(void *p
const void *name,
void *data);
+void virNWFilterFormatLeases(virBufferPtr buf,
+ virNWFilterHashTablePtr vars,
+ const char *ifname,
+ const unsigned char *vmmuid,
+ const unsigned char *mac);
+
#endif
Index: libvirt-acl/src/nwfilter/nwfilter_driver.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_driver.c
+++ libvirt-acl/src/nwfilter/nwfilter_driver.c
@@ -471,6 +471,15 @@ nwfilterTeardownFilter(virDomainNetDefPt
virNWFilterTeardownFilter(net);
}
+static void
+nwfilterFormatLeases(virBufferPtr buf,
+ virNWFilterHashTablePtr vars,
+ const char *ifname,
+ const unsigned char *vmuuid,
+ const unsigned char *mac)
+{
+ virNWFilterFormatLeases(buf, vars, ifname, vmuuid, mac);
+}
static virNWFilterDriver nwfilterDriver = {
.name = "nwfilter",
@@ -498,6 +507,7 @@ static virStateDriver stateDriver = {
static virDomainConfNWFilterDriver domainNWFilterDriver = {
.instantiateFilter = nwfilterInstantiateFilter,
.teardownFilter = nwfilterTeardownFilter,
+ .formatLeases = nwfilterFormatLeases,
};
Index: libvirt-acl/src/conf/nwfilter_ipaddrmap.c
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_ipaddrmap.c
+++ libvirt-acl/src/conf/nwfilter_ipaddrmap.c
@@ -122,6 +122,35 @@ remove_entry:
return ret;
}
+void
+virNWFilterIPAddrMapFormatIPAddrs(virBufferPtr buf,
+ const char *ifname,
+ const char *pre, const char *post)
+{
+ virNWFilterVarValuePtr val = NULL;
+
+ virMutexLock(&ipAddressMapLock);
+
+ val = virHashLookup(ipAddressMap->hashTable, ifname);
+ if (val) {
+ unsigned int card = virNWFilterVarValueGetCardinality(val);
+ unsigned int i;
+
+ for (i = 0; i < card; i++) {
+ const char *ipaddr = virNWFilterVarValueGetNthValue(val, i);
+
+ if (pre)
+ virBufferAdd(buf, pre, -1);
+ virBufferAdd(buf, ipaddr, -1);
+
+ if (post)
+ virBufferAdd(buf, post, -1);
+ }
+ }
+
+ virMutexUnlock(&ipAddressMapLock);
+}
+
/* Get the list of IP addresses known to be in use by an interface
*
* This function returns NULL in case no IP address is known to be
Index: libvirt-acl/src/conf/nwfilter_ipaddrmap.h
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_ipaddrmap.h
+++ libvirt-acl/src/conf/nwfilter_ipaddrmap.h
@@ -26,6 +26,8 @@
#ifndef __VIR_NWFILTER_IPADDRMAP_H
# define __VIR_NWFILTER_IPADDRMAP_H
+# include "buf.h"
+
int virNWFilterIPAddrMapInit(void);
void virNWFilterIPAddrMapShutdown(void);
@@ -33,5 +35,8 @@ int virNWFilterIPAddrMapAddIPAddr(const
int virNWFilterIPAddrMapDelIPAddr(const char *ifname,
const char *ipaddr);
virNWFilterVarValuePtr virNWFilterIPAddrMapGetIPAddr(const char *ifname);
+void virNWFilterIPAddrMapFormatIPAddrs(virBufferPtr buf,
+ const char *ifname,
+ const char *pre, const char *post);
#endif /* __VIR_NWFILTER_IPADDRMAP_H */
Index: libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_learnipaddr.c
+++ libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c
@@ -771,6 +771,20 @@ virNWFilterLearnIPAddress(virNWFilterTec
}
#endif /* HAVE_LIBPCAP */
+/*
+ * Format the detected IP addresses for display in the domain's
+ * XML inside a <parameter name=... value=.../> XML node.
+ */
+void
+virNWFilterLearnFormatLeases(virBufferPtr buf,
+ const char *ifname)
+{
+ virNWFilterIPAddrMapFormatIPAddrs(buf, ifname,
+ "<parameter name='"
+ NWFILTER_VARNAME_IP_LEASE
+ "' value='",
+ ",-1'/>\n");
+}
/**
* virNWFilterLearnInit
Index: libvirt-acl/src/nwfilter/nwfilter_learnipaddr.h
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_learnipaddr.h
+++ libvirt-acl/src/nwfilter/nwfilter_learnipaddr.h
@@ -71,5 +71,7 @@ void virNWFilterUnlockIface(const char *
int virNWFilterLearnInit(void);
void virNWFilterLearnShutdown(void);
void virNWFilterLearnThreadsTerminate(bool allowNewThreads);
+void virNWFilterLearnFormatLeases(virBufferPtr buf,
+ const char *ifname);
#endif /* __NWFILTER_LEARNIPADDR_H */
Index: libvirt-acl/docs/formatnwfilter.html.in
===================================================================
--- libvirt-acl.orig/docs/formatnwfilter.html.in
+++ libvirt-acl/docs/formatnwfilter.html.in
@@ -446,6 +446,22 @@
</interface>
</pre>
+ <p>
+ Once an IP address has been detected, the domain's interface XML
+ will display the detected IP address and its lease expiration time
+ in seconds. Note that the <code>IP_LEASE</code> variable is read-only
+ and cannot be set by the user.
+ </p>
+<pre>
+ <interface type='bridge'>
+ <source bridge='virbr0'/>
+ <filterref filter='clean-traffic'>
+ <parameter name='CTRL_IP_LEARNING' value='dhcp'/>
+ <parameter name='IP_LEASE'
value='192.168.122.100,200'/>
+ </filterref>
+ </interface>
+</pre>
+
<h3><a name="nwfelemsReservedVars">Reserved
Variables</a></h3>
<p>
The following table lists reserved variables in use by libvirt.
@@ -481,6 +497,17 @@
<td> CTRL_IP_LEARNING </td>
<td> The choice of the IP address detection mode </td>
</tr>
+ <tr>
+ <td> IP_LEASE </td>
+ <td> Read-only variable displaying the detected IP lease in the
+ format IP address,lease expiration time in seconds </td>
+ </tr>
+ <tr>
+ <td> IPV6_LEASE </td>
+ <td> Not currently implemented:
+ Read-only variable displaying the detected IPV6 lease in the
+ format IPV6 address,lease expiration time in seconds </td>
+ </tr>
</table>
<h2><a name="nwfelems">Element and attribute
overview</a></h2>