Re: [libvirt] [libvirt PATCHv3 09/10] add leasefile support
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
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