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

Stefan Berger stefanb at linux.vnet.ibm.com
Mon Jun 11 13:54:21 UTC 2012


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)
 {




More information about the libvir-list mailing list