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: , An example of a displayed XML may then be:
--- 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, "\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 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, + "\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 XML node. + */ +void +virNWFilterLearnFormatLeases(virBufferPtr buf, + const char *ifname) +{ + virNWFilterIPAddrMapFormatIPAddrs(buf, ifname, + "\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> +

+ 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 IP_LEASE variable is read-only + and cannot be set by the user. +

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

Reserved Variables

The following table lists reserved variables in use by libvirt. @@ -481,6 +497,17 @@ CTRL_IP_LEARNING The choice of the IP address detection mode + + IP_LEASE + Read-only variable displaying the detected IP lease in the + format IP address,lease expiration time in seconds + + + IPV6_LEASE + Not currently implemented: + Read-only variable displaying the detected IPV6 lease in the + format IPV6 address,lease expiration time in seconds +

Element and attribute overview