Re: [libvirt] [libvirt PATCHv3 09/10] add leasefile support

2011-10-17 Thread Stefan Berger

On 10/12/2011 03:50 PM, David L Stevens wrote:

This patch adds support for saving DHCP snooping leases to an on-disk
file and restoring saved leases that are still active on restart.

Signed-off-by: David L Stevensdlstev...@us.ibm.com
---
  src/nwfilter/nwfilter_dhcpsnoop.c |  370 +++--
  1 files changed, 353 insertions(+), 17 deletions(-)

diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c 
b/src/nwfilter/nwfilter_dhcpsnoop.c
index f784a29..eedf550 100644
--- a/src/nwfilter/nwfilter_dhcpsnoop.c
+++ b/src/nwfilter/nwfilter_dhcpsnoop.c
@@ -56,10 +56,21 @@
  #include nwfilter_gentech_driver.h
  #include nwfilter_ebiptables_driver.h
  #include nwfilter_dhcpsnoop.h
+#include configmake.h

  #define VIR_FROM_THIS VIR_FROM_NWFILTER

+#define LEASEFILE LOCALSTATEDIR /run/libvirt/network/nwfilter.leases
+#define TMPLEASEFILE LOCALSTATEDIR /run/libvirt/network/nwfilter.ltmp
+static int lease_fd = -1;
+static int nleases = 0; /* number of active leases */
+static int wleases = 0; /* number of written leases */
+
  static virHashTablePtr SnoopReqs;
+static pthread_mutex_t SnoopLock;
+
+#define snoop_lock(){ pthread_mutex_lock(SnoopLock); }
+#define snoop_unlock()  { pthread_mutex_unlock(SnoopLock); }

  struct virNWFilterSnoopReq {
  virConnectPtr conn;
@@ -90,7 +101,14 @@ struct iplease {

  static struct iplease *ipl_getbyip(struct iplease *start, uint32_t ipaddr);
  static void ipl_update(struct iplease *pl, uint32_t timeout);
-
+
+static struct iflease *getiflease(const char *ifname);
+static void lease_open(void);
+static void lease_close(void);
+static void lease_load(void);
+static void lease_save(struct iplease *ipl);
+static void lease_refresh(void);
+static void lease_restore(struct virNWFilterSnoopReq *req);

  /*
   * ipl_ladd - add an IP lease to a list
@@ -150,6 +168,7 @@ ipl_add(struct iplease *plnew)
  ipl_update(pl, plnew-ipl_timeout);
  return;
  }
+nleases++;
  if (VIR_ALLOC(pl)  0) {
  virReportOOMError();
  return;
@@ -184,6 +203,7 @@ ipl_add(struct iplease *plnew)
  return;
  }
  ipl_tadd(pl);
+lease_save(pl);
  }

  /*
@@ -231,6 +251,7 @@ ipl_del(struct iplease *ipl)
  req = ipl-ipl_req;

  ipl_tdel(ipl);
+lease_save(ipl);

  if (inet_ntop(AF_INET,ipl-ipl_ipaddr, ipbuf, sizeof(ipbuf))) {
  ipstr = strdup(ipbuf);
@@ -248,6 +269,7 @@ ipl_del(struct iplease *ipl)
 _(ipl_del inet_ntop  failed (0x%08X)),
 ipl-ipl_ipaddr);
  VIR_FREE(ipl);
+nleases--;
  }

  /*
@@ -259,6 +281,7 @@ ipl_update(struct iplease *ipl, uint32_t timeout)
  ipl_tdel(ipl);
  ipl-ipl_timeout = timeout;
  ipl_tadd(ipl);
+lease_save(ipl);
  return;
  }

@@ -275,8 +298,6 @@ ipl_getbyip(struct iplease *start, uint32_t ipaddr)
  return pl;
  }

-#define GRACE   5
-
  /*
   * ipl_trun - run the IP lease timeout list
   */
@@ -465,6 +486,19 @@ dhcpopen(const char *intf)
  return handle;
  }

+/*
+ * snoopReqFree - release a snoop Req
+ */
+static void
+snoopReqFree(struct virNWFilterSnoopReq *req)
+{
+if (req-ifname)
+VIR_FREE(req-ifname);
+if (req-vars)
+virNWFilterHashTableFree(req-vars);
+VIR_FREE(req);
+}
+
  static void *
  virNWFilterDHCPSnoop(void *req0)
  {
@@ -479,12 +513,19 @@ virNWFilterDHCPSnoop(void *req0)
  if (!handle)
  return 0;

+/* restore any saved leases for this interface */
+snoop_lock();
+lease_restore(req);
+snoop_unlock();
+
  ifindex = if_nametoindex(req-ifname);

  while (1) {
  if (req-die)
  break;
+snoop_lock();
  ipl_trun(req);
+snoop_unlock();

  packet = (struct eth *) pcap_next(handle,hdr);

@@ -494,16 +535,18 @@ virNWFilterDHCPSnoop(void *req0)
  continue;
  }

+snoop_lock();
  dhcpdecode(req, packet, hdr.caplen);
+snoop_unlock();
  }
+
+snoop_lock();
  /* free all leases */
  for (ipl = req-start; ipl; ipl = req-start)
  ipl_del(ipl);
+snoop_unlock();

-/* free all req data */
-VIR_FREE(req-ifname);
-virNWFilterHashTableFree(req-vars);
-VIR_FREE(req);
+snoopReqFree(req);
  return 0;
  }

@@ -518,9 +561,12 @@ virNWFilterDHCPSnoopReq(virConnectPtr conn,
  {
  struct virNWFilterSnoopReq *req;

+snoop_lock();
  req = virHashLookup(SnoopReqs, ifname);
-if (req)
+snoop_unlock();
+if (req) {
  return 0;
+}
  if (VIR_ALLOC(req)  0) {
  virReportOOMError();
  return 1;
@@ -533,28 +579,30 @@ virNWFilterDHCPSnoopReq(virConnectPtr conn,
  req-ifname = strdup(ifname);
  req-vars = virNWFilterHashTableCreate(0);
  if (!req-vars) {
+snoopReqFree(req);
Following the lookup into the hashtable above you cannot just free the 
request. I suppose you'd first have to remove it from the hash 

[libvirt] [libvirt PATCHv3 09/10] add leasefile support

2011-10-12 Thread David L Stevens
This patch adds support for saving DHCP snooping leases to an on-disk
file and restoring saved leases that are still active on restart.

Signed-off-by: David L Stevens dlstev...@us.ibm.com
---
 src/nwfilter/nwfilter_dhcpsnoop.c |  370 +++--
 1 files changed, 353 insertions(+), 17 deletions(-)

diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c 
b/src/nwfilter/nwfilter_dhcpsnoop.c
index f784a29..eedf550 100644
--- a/src/nwfilter/nwfilter_dhcpsnoop.c
+++ b/src/nwfilter/nwfilter_dhcpsnoop.c
@@ -56,10 +56,21 @@
 #include nwfilter_gentech_driver.h
 #include nwfilter_ebiptables_driver.h
 #include nwfilter_dhcpsnoop.h
+#include configmake.h
 
 #define VIR_FROM_THIS VIR_FROM_NWFILTER
 
+#define LEASEFILE LOCALSTATEDIR /run/libvirt/network/nwfilter.leases
+#define TMPLEASEFILE LOCALSTATEDIR /run/libvirt/network/nwfilter.ltmp
+static int lease_fd = -1;
+static int nleases = 0; /* number of active leases */
+static int wleases = 0; /* number of written leases */
+
 static virHashTablePtr SnoopReqs;
+static pthread_mutex_t SnoopLock;
+
+#define snoop_lock(){ pthread_mutex_lock(SnoopLock); }
+#define snoop_unlock()  { pthread_mutex_unlock(SnoopLock); }
 
 struct virNWFilterSnoopReq {
 virConnectPtr conn;
@@ -90,7 +101,14 @@ struct iplease {
 
 static struct iplease *ipl_getbyip(struct iplease *start, uint32_t ipaddr);
 static void ipl_update(struct iplease *pl, uint32_t timeout);
-
+ 
+static struct iflease *getiflease(const char *ifname);
+static void lease_open(void);
+static void lease_close(void);
+static void lease_load(void);
+static void lease_save(struct iplease *ipl);
+static void lease_refresh(void);
+static void lease_restore(struct virNWFilterSnoopReq *req);
 
 /*
  * ipl_ladd - add an IP lease to a list
@@ -150,6 +168,7 @@ ipl_add(struct iplease *plnew)
 ipl_update(pl, plnew-ipl_timeout);
 return;
 }
+nleases++;
 if (VIR_ALLOC(pl)  0) {
 virReportOOMError();
 return;
@@ -184,6 +203,7 @@ ipl_add(struct iplease *plnew)
 return;
 }
 ipl_tadd(pl);
+lease_save(pl);
 }
 
 /*
@@ -231,6 +251,7 @@ ipl_del(struct iplease *ipl)
 req = ipl-ipl_req;
 
 ipl_tdel(ipl);
+lease_save(ipl);
 
 if (inet_ntop(AF_INET, ipl-ipl_ipaddr, ipbuf, sizeof(ipbuf))) {
 ipstr = strdup(ipbuf);
@@ -248,6 +269,7 @@ ipl_del(struct iplease *ipl)
_(ipl_del inet_ntop  failed (0x%08X)),
ipl-ipl_ipaddr);
 VIR_FREE(ipl);
+nleases--;
 }
 
 /*
@@ -259,6 +281,7 @@ ipl_update(struct iplease *ipl, uint32_t timeout)
 ipl_tdel(ipl);
 ipl-ipl_timeout = timeout;
 ipl_tadd(ipl);
+lease_save(ipl);
 return;
 }
 
@@ -275,8 +298,6 @@ ipl_getbyip(struct iplease *start, uint32_t ipaddr)
 return pl;
 }
 
-#define GRACE   5
-
 /*
  * ipl_trun - run the IP lease timeout list
  */
@@ -465,6 +486,19 @@ dhcpopen(const char *intf)
 return handle;
 }
 
+/*
+ * snoopReqFree - release a snoop Req
+ */
+static void
+snoopReqFree(struct virNWFilterSnoopReq *req)
+{
+if (req-ifname)
+VIR_FREE(req-ifname);
+if (req-vars)
+virNWFilterHashTableFree(req-vars);
+VIR_FREE(req);
+}
+
 static void *
 virNWFilterDHCPSnoop(void *req0)
 {
@@ -479,12 +513,19 @@ virNWFilterDHCPSnoop(void *req0)
 if (!handle)
 return 0;
 
+/* restore any saved leases for this interface */
+snoop_lock();
+lease_restore(req);
+snoop_unlock();
+
 ifindex = if_nametoindex(req-ifname);
 
 while (1) {
 if (req-die)
 break;
+snoop_lock();
 ipl_trun(req);
+snoop_unlock();
 
 packet = (struct eth *) pcap_next(handle, hdr);
 
@@ -494,16 +535,18 @@ virNWFilterDHCPSnoop(void *req0)
 continue;
 }
 
+snoop_lock();
 dhcpdecode(req, packet, hdr.caplen);
+snoop_unlock();
 }
+
+snoop_lock();
 /* free all leases */
 for (ipl = req-start; ipl; ipl = req-start)
 ipl_del(ipl);
+snoop_unlock();
 
-/* free all req data */
-VIR_FREE(req-ifname);
-virNWFilterHashTableFree(req-vars);
-VIR_FREE(req);
+snoopReqFree(req);
 return 0;
 }
 
@@ -518,9 +561,12 @@ virNWFilterDHCPSnoopReq(virConnectPtr conn,
 {
 struct virNWFilterSnoopReq *req;
 
+snoop_lock();
 req = virHashLookup(SnoopReqs, ifname);
-if (req)
+snoop_unlock();
+if (req) {
 return 0;
+}
 if (VIR_ALLOC(req)  0) {
 virReportOOMError();
 return 1;
@@ -533,28 +579,30 @@ virNWFilterDHCPSnoopReq(virConnectPtr conn,
 req-ifname = strdup(ifname);
 req-vars = virNWFilterHashTableCreate(0);
 if (!req-vars) {
+snoopReqFree(req);
 virReportOOMError();
 return 1;
 }
 if (virNWFilterHashTablePutAll(vars, req-vars)) {
 virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
-   _(virNWFilterDHCPSnoopReq: can't copy