[libvirt] [PATCH] nwfilter: Display detected IP address in domain XML

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 address>,<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> This patch now also offers a better (libvirt-internal) API for accessing the detected IP addresses. The function virDomainConfNWFilterGetLeases can be used to retrieve a list of IP leases associated with a given interface. This function will then either retrieve the data from the DHCP snooping or IP learning subsystems, depending on which detection algorithm has been activated. If none is active, a NULL pointer for the array of leases will be returned. --- PS: This is the last remaining patch of the DHCP snooping series. I am submitting it now as a stand-alone patch restarting the version counting. --- docs/formatnwfilter.html.in | 27 +++++++++++ src/conf/domain_conf.c | 16 +++++-- src/conf/domain_nwfilter.c | 13 +++++ src/conf/domain_nwfilter.h | 15 ++++++ src/conf/nwfilter_conf.c | 3 - src/conf/nwfilter_ipaddrmap.c | 51 ++++++++++++++++++++++ src/conf/nwfilter_ipaddrmap.h | 5 ++ src/conf/nwfilter_params.c | 75 ++++++++++++++++++++++++++++++++- src/conf/nwfilter_params.h | 9 +++ src/libvirt_private.syms | 5 +- src/nwfilter/nwfilter_dhcpsnoop.c | 59 +++++++++++++++++++++++++ src/nwfilter/nwfilter_dhcpsnoop.h | 4 + src/nwfilter/nwfilter_driver.c | 10 ++++ src/nwfilter/nwfilter_gentech_driver.c | 26 +++++++++++ src/nwfilter/nwfilter_gentech_driver.h | 8 +++ src/nwfilter/nwfilter_learnipaddr.c | 9 +++ src/nwfilter/nwfilter_learnipaddr.h | 2 src/util/viriplease.h | 18 +++++++ 18 files changed, 345 insertions(+), 10 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" @@ -11500,7 +11501,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); @@ -11641,9 +11643,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); } @@ -12969,7 +12977,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++) @@ -15222,7 +15230,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 @@ -552,6 +552,7 @@ virDomainLockLeaseDetach; # domain_nwfilter.h +virDomainConfNWFiltetGetLeases; virDomainConfNWFilterInstantiate; virDomainConfNWFilterRegister; virDomainConfNWFilterTeardown; @@ -873,15 +874,17 @@ virNWFilterTestUnassignDef; virNWFilterUnlockFilterUpdates; -# nwfilter_ipaddrmap +# nwfilter_ipaddrmap.h virNWFilterIPAddrMapAddIPAddr; virNWFilterIPAddrMapDelIPAddr; virNWFilterIPAddrMapGetIPAddr; +virNWFilterIPAddrMapGetIPLeases; virNWFilterIPAddrMapInit; virNWFilterIPAddrMapShutdown; # nwfilter_params.h +virNWFilterFormatParamAttributes; virNWFilterHashTableCreate; virNWFilterHashTableFree; virNWFilterHashTablePut; Index: libvirt-acl/src/conf/nwfilter_params.c =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_params.c +++ libvirt-acl/src/conf/nwfilter_params.c @@ -31,9 +31,16 @@ #include "nwfilter_params.h" #include "domain_conf.h" #include "logging.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); @@ -784,6 +791,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) { @@ -834,6 +854,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: @@ -855,10 +884,16 @@ 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; + virIPLeasePtr leases = NULL; + size_t nLeases = 0; int i, j, card, numKeys; + int ret = 0; numKeys = virHashSize(table->hashTable); @@ -889,14 +924,50 @@ virNWFilterFormatParamAttributes(virBuff virNWFilterVarValueGetNthValue(value, j)); } + if (ifname) { + time_t now = time(0); + /* also display the IP addresses being used */ + if (virDomainConfNWFilterGetLeases(&leases, &nLeases, + table, + ifname, + vmuuid, + mac) < 0) { + ret = -1; + goto cleanup; + } + + for (i = 0; i < nLeases; i++) { + int64_t to; + char *ipbuf = virSocketAddrFormat(&leases[i].addr); + + if (!ipbuf) { + virReportOOMError(); + ret = -1; + goto cleanup; + } + + to = (leases[i].timeout != VIR_IPLEASE_TIMEOUT_NONE) + ? (int64_t)(leases[i].timeout - now) + : -1; + + virBufferAsprintf(buf, + " <parameter name='" + NWFILTER_VARNAME_IP_LEASE + "' value='%s,%ld'/>\n", + ipbuf, to); + VIR_FREE(ipbuf); + } + } virBufferAddLit(buf, "</filterref>\n"); } else { virBufferAddLit(buf, "/>\n"); } +cleanup: VIR_FREE(items); + VIR_FREE(leases); - return 0; + return ret; } void Index: libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_dhcpsnoop.c +++ libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.c @@ -1987,6 +1987,57 @@ virNWFilterSnoopLeaseFileLoad(void) } /* + * Get the detected IP addresses along with their absolute lease timeout. + */ +int +virNWFilterSnoopGetLeases(virIPLeasePtr *leases, size_t *nLeases, + const unsigned char *vmuuid, + const unsigned char *macaddr) +{ + int ret = 0; + char ifkey[VIR_IFKEY_LEN]; + virNWFilterSnoopReqPtr req; + virNWFilterSnoopIPLeasePtr ipl; + size_t ctr = 0; + virIPLeasePtr myleases = NULL; + + *leases = NULL; + + 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; + + if (VIR_EXPAND_N(myleases, ctr, 1) < 0) { + VIR_FREE(myleases); + ret = -1; + goto cleanup; + } + + myleases[ctr-1].addr = ipl->ipAddress; + myleases[ctr-1].timeout = ipl->timeout; + } + + *leases = myleases; + *nLeases = ctr; + +cleanup: + virNWFilterSnoopReqUnlock(req); + + virNWFilterSnoopReqPut(req); + } + return ret; +} + +/* * Wait until all threads have ended. */ static void @@ -2174,6 +2225,14 @@ virNWFilterDHCPSnoopShutdown(void) #else /* HAVE_LIBPCAP */ int +virNWFilterSnoopGetLeases(virIPLeasePtr *leases ATTRIBUTE_UNUSED, + size_t *nLeases ATTRIBUTE_UNUSED, + const unsigned char *vmuuid ATTRIBUTE_UNUSED, + const unsigned char *macaddr ATTRIBUTE_UNUSED) +{ +} + +int virNWFilterDHCPSnoopInit(void) { return -1; 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); +int virNWFilterSnoopGetLeases(virIPLeasePtr *leases, size_t *nLeases, + 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,16 @@ virDomainConfVMNWFilterTeardown(virDomai virDomainConfNWFilterTeardown(vm->def->nets[i]); } } + +int +virDomainConfNWFilterGetLeases(virIPLeasePtr *leases, size_t *nLeases, + virNWFilterHashTablePtr table, + const char *ifname, + const unsigned char *vmuuid, + const unsigned char *mac) +{ + if (nwfilterDriver != NULL) + return nwfilterDriver->getLeases(leases, nLeases, table, ifname, + vmuuid, mac); + return 0; +} Index: libvirt-acl/src/conf/domain_nwfilter.h =================================================================== --- libvirt-acl.orig/src/conf/domain_nwfilter.h +++ libvirt-acl/src/conf/domain_nwfilter.h @@ -23,14 +23,24 @@ #ifndef DOMAIN_NWFILTER_H # define DOMAIN_NWFILTER_H +# include "viriplease.h" + typedef int (*virDomainConfInstantiateNWFilter)(virConnectPtr conn, const unsigned char *vmuuid, virDomainNetDefPtr net); typedef void (*virDomainConfTeardownNWFilter)(virDomainNetDefPtr net); +typedef int (*virDomainConfGetLeases)(virIPLeasePtr *leases, + size_t *nLeases, + virNWFilterHashTablePtr table, + const char *ifname, + const unsigned char *vmuuid, + const unsigned char *mac); + typedef struct { virDomainConfInstantiateNWFilter instantiateFilter; virDomainConfTeardownNWFilter teardownFilter; + virDomainConfGetLeases getLeases; } virDomainConfNWFilterDriver; typedef virDomainConfNWFilterDriver *virDomainConfNWFilterDriverPtr; @@ -41,5 +51,10 @@ int virDomainConfNWFilterInstantiate(vir virDomainNetDefPtr net); void virDomainConfNWFilterTeardown(virDomainNetDefPtr net); void virDomainConfVMNWFilterTeardown(virDomainObjPtr vm); +int virDomainConfNWFilterGetLeases(virIPLeasePtr *leases, size_t *nLeases, + 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,29 @@ virNWFilterDomainFWUpdateCB(void *payloa virDomainObjUnlock(obj); } + +int +virNWFilterGetLeases(virIPLeasePtr *leases, size_t *nLeases, + virNWFilterHashTablePtr vars, + const char *ifname, + const unsigned char *vmuuid, + const unsigned char *mac) +{ + virNWFilterVarValuePtr lv; + const char *learning = NULL; + int ret = 0; + + if (!vars) + return 0; + + lv = virHashLookup(vars->hashTable, NWFILTER_VARNAME_CTRL_IP_LEARNING); + if (lv) + learning = virNWFilterVarValueGetNthValue(lv, 0); + + if (!learning || STRCASEEQ(learning, "any")) { + ret = virNWFilterLearnGetLeases(leases, nLeases, ifname); + } else if (STRCASEEQ(learning, "dhcp")) { + ret = virNWFilterSnoopGetLeases(leases, nLeases, vmuuid, mac); + } + return ret; +} 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 @@ -23,6 +23,8 @@ #ifndef __NWFILTER_GENTECH_DRIVER_H # define __NWFILTER_GENTECH_DRIVER_H +# include "viriplease.h" + virNWFilterTechDriverPtr virNWFilterTechDriverForName(const char *name); int virNWFilterRuleInstAddData(virNWFilterRuleInstPtr res, @@ -64,4 +66,10 @@ void virNWFilterDomainFWUpdateCB(void *p const void *name, void *data); +int virNWFilterGetLeases(virIPLeasePtr *leases, size_t *nLeases, + 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 @@ -463,6 +463,15 @@ nwfilterTeardownFilter(virDomainNetDefPt virNWFilterTeardownFilter(net); } +static int +nwfilterGetLeases(virIPLeasePtr *leases, size_t *nLeases, + virNWFilterHashTablePtr vars, + const char *ifname, + const unsigned char *vmuuid, + const unsigned char *mac) +{ + return virNWFilterGetLeases(leases, nLeases, vars, ifname, vmuuid, mac); +} static virNWFilterDriver nwfilterDriver = { .name = "nwfilter", @@ -490,6 +499,7 @@ static virStateDriver stateDriver = { static virDomainConfNWFilterDriver domainNWFilterDriver = { .instantiateFilter = nwfilterInstantiateFilter, .teardownFilter = nwfilterTeardownFilter, + .getLeases = nwfilterGetLeases, }; 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,9 @@ #ifndef __VIR_NWFILTER_IPADDRMAP_H # define __VIR_NWFILTER_IPADDRMAP_H +# include "buf.h" +# include "viriplease.h" + int virNWFilterIPAddrMapInit(void); void virNWFilterIPAddrMapShutdown(void); @@ -33,5 +36,7 @@ int virNWFilterIPAddrMapAddIPAddr(const int virNWFilterIPAddrMapDelIPAddr(const char *ifname, const char *ipaddr); virNWFilterVarValuePtr virNWFilterIPAddrMapGetIPAddr(const char *ifname); +int virNWFilterIPAddrMapGetIPLeases(const char *ifname, + virIPLeasePtr *leases, size_t *nLeases); #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,15 @@ virNWFilterLearnIPAddress(virNWFilterTec } #endif /* HAVE_LIBPCAP */ +/* + * Get the detected IP addresses along with their absolute lease timeout + */ +int +virNWFilterLearnGetLeases(virIPLeasePtr *leases, size_t *nLeases, + const char *ifname) +{ + return virNWFilterIPAddrMapGetIPLeases(ifname, leases, nLeases); +} /** * 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); +int virNWFilterLearnGetLeases(virIPLeasePtr *leases, size_t *nLeases, + 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 (<span class="since">Since 0.9.13</span>)</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> Index: libvirt-acl/src/util/viriplease.h =================================================================== --- /dev/null +++ libvirt-acl/src/util/viriplease.h @@ -0,0 +1,18 @@ +#ifndef __VIR_IPLEASE_H__ +# define __VIR_IPLEASE_H__ + +# include <time.h> + +# include "virsocketaddr.h" + +typedef struct _virIPLease virIPLease; +typedef virIPLease *virIPLeasePtr; + +struct _virIPLease { + virSocketAddr addr; + time_t timeout; +}; + +#define VIR_IPLEASE_TIMEOUT_NONE (-1) + +#endif /* __VIR_IP_LEASE_H__ */ Index: libvirt-acl/src/conf/nwfilter_ipaddrmap.c =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_ipaddrmap.c +++ libvirt-acl/src/conf/nwfilter_ipaddrmap.c @@ -28,6 +28,7 @@ #include "virterror_internal.h" #include "datatypes.h" +#include "memory.h" #include "nwfilter_params.h" #include "nwfilter_ipaddrmap.h" @@ -142,6 +143,56 @@ virNWFilterIPAddrMapGetIPAddr(const char return res; } +/* + * Get the IP addresses associated with the interface as an array + * of virIPLease. Since we don't know about lease timeouts here, we + * set the lease timeout to VIR_IPLEASE_TIMEOUT_NONE. + */ +int +virNWFilterIPAddrMapGetIPLeases(const char *ifname, + virIPLeasePtr *leases, size_t *nLeases) +{ + int ret = 0; + virNWFilterVarValuePtr val; + virIPLeasePtr myleases = NULL; + + *leases = NULL; + + virMutexLock(&ipAddressMapLock); + + val = virHashLookup(ipAddressMap->hashTable, ifname); + + if (val) { + size_t card = virNWFilterVarValueGetCardinality(val); + unsigned int i; + + if (VIR_ALLOC_N(myleases, card) < 0) { + virReportOOMError(); + ret = -1; + goto cleanup; + } + + for (i = 0; i < card; i++) { + const char *value = virNWFilterVarValueGetNthValue(val, i); + + if (virSocketAddrParse(&myleases[i].addr, value, AF_UNSPEC) < 0) { + VIR_FREE(myleases); + ret = -1; + goto cleanup; + } + myleases[i].timeout = VIR_IPLEASE_TIMEOUT_NONE; + } + + *leases = myleases; + *nLeases = card; + } + +cleanup: + virMutexUnlock(&ipAddressMapLock); + + return ret; +} + int virNWFilterIPAddrMapInit(void) {

On 06/11/2012 07:54 AM, Stefan Berger wrote:
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 address>,<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'/>
I still think we're wrong in doing it with something that the user has to reparse instead of being able to get at it via XPath queries. Are we any better off having: <parameter name='IP_LEASE_ADDRESS' value='192.168.122.210'/> <parameter name='IP_LEASE_TIMEOUT' value='100'/> Or maybe feeding off of Laine's idea for keeping just one <parameter>, but adding additional attributes (the redundant value= attribute would remain, with redundant information, for back-compat), so that the XPath query is still possible by using the new attributes: <parameter name='IP_LEASE_ADDRESS' value='192.168.122.210,100' address='192.168.122.210' timeout='100'/> -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On Mon, Jun 11, 2012 at 09:27:15AM -0600, Eric Blake wrote:
On 06/11/2012 07:54 AM, Stefan Berger wrote:
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 address>,<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'/>
I still think we're wrong in doing it with something that the user has to reparse instead of being able to get at it via XPath queries. Are we any better off having:
<parameter name='IP_LEASE_ADDRESS' value='192.168.122.210'/> <parameter name='IP_LEASE_TIMEOUT' value='100'/>
Or maybe feeding off of Laine's idea for keeping just one <parameter>, but adding additional attributes (the redundant value= attribute would remain, with redundant information, for back-compat), so that the XPath query is still possible by using the new attributes:
<parameter name='IP_LEASE_ADDRESS' value='192.168.122.210,100' address='192.168.122.210' timeout='100'/>
The <parameter> element handling is supposed to be agnostic to the type of data present, so I'd be loathe to add specific address/timeout attributes to it. I think I'd prefer the idea of separate IP_LEASE_ADDRESS/TIMEOUT parameters, or even just not show the timeout data at all. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 06/11/2012 11:31 AM, Daniel P. Berrange wrote:
On Mon, Jun 11, 2012 at 09:27:15AM -0600, Eric Blake wrote:
On 06/11/2012 07:54 AM, Stefan Berger wrote:
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 address>,<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'/> I still think we're wrong in doing it with something that the user has to reparse instead of being able to get at it via XPath queries. Are we any better off having:
<parameter name='IP_LEASE_ADDRESS' value='192.168.122.210'/> <parameter name='IP_LEASE_TIMEOUT' value='100'/>
Or maybe feeding off of Laine's idea for keeping just one<parameter>, but adding additional attributes (the redundant value= attribute would remain, with redundant information, for back-compat), so that the XPath query is still possible by using the new attributes:
<parameter name='IP_LEASE_ADDRESS' value='192.168.122.210,100' address='192.168.122.210' timeout='100'/> The<parameter> element handling is supposed to be agnostic to the type of data present, so I'd be loathe to add specific address/timeout attributes to it.
I think I'd prefer the idea of separate IP_LEASE_ADDRESS/TIMEOUT parameters, or even just not show the timeout data at all.
Displaying the IP address is useful in any way, either in the XML or through another virsh command. So we keep that. I thought displaying the timeout value could also be useful (in the future) if we were to use this during migration on the target system to re-instantiate the filters without having to kick the dhclient inside the VM to do another DHCP request. This would require libvirt's XML parser to know the reason why it is parsing the XML and in case of migration feed the parsed lease (IP address + timeout) into the nwfilter subsystem and that way migration at least could be seamless. Stefan
participants (3)
-
Daniel P. Berrange
-
Eric Blake
-
Stefan Berger