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='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 | 56 +++++++++++++++++++++++++++++++++ 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, 267 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_IP_LEARNING "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" @@ -11205,7 +11206,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); @@ -11346,9 +11348,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); } @@ -12632,7 +12640,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++) @@ -14885,7 +14893,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 @@ -3272,7 +3272,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 @@ -1839,6 +1839,55 @@ 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[INET_ADDRSTRLEN]; + + 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 (!inet_ntop(AF_INET, &ipl->ipAddress, ipbuf, sizeof(ipbuf))) { + virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, + _("%s: inet_ntop failed " + " (0x%08X)"), + __func__, ipl->ipAddress); + continue; + } + + virBufferAsprintf(buf, + "<parameter name='" + NWFILTER_VARNAME_IP_LEASE + "' value='%s,%u'/>\n", + ipbuf, + (unsigned int)(ipl->timeout - now)); + } + + virNWFilterSnoopReqUnlock(req); + + virNWFilterSnoopReqPut(req); + } +} + +/* * Wait until all threads have ended. */ static void @@ -2024,6 +2073,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_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='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> 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> -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list