[libvirt] [PATCH 2/2] nwfilter: Add multiple IP address support to DHCP snooping

Stefan Berger stefanb at linux.vnet.ibm.com
Mon Apr 9 11:31:35 UTC 2012


With support for multiple IP addresses per interface in place, this patch
now adds support for multiple IP addresses per interface to the DHCP
snooping code.

---

This patch applies to David Stevens's DHCP snooping patch v8 plus the
patch I applied on top of v8.

Testing:

Since the infrastructure I tested this with does not provide multiple IP
addresses per MAC address (anymore), I either had to plug the VM's interface
from the virtual bride connected directly to the infrastructure to virbr0
to get a 2nd IP address from dnsmasq (kill and run dhclient inside the VM)
or changed the lease file  (/var/run/libvirt/network/nwfilter.leases) and
restart libvirtd to have a 2nd IP address on an existing interface.
Note that dnsmasq can take a lease timeout parameter as part of the 
--dhcp-range
command line parameter, so that timeouts can be tested that way
(--dhcp-range 192.168.122.2,192.168.122.254,120). So, terminating and 
restarting
dnsmasq with that parameter is another choice to watch an IP address 
disappear
after 120 seconds.

Regards,
    Stefan

---
  src/nwfilter/nwfilter_dhcpsnoop.c |   54 
+++++++++++++++++++++++---------------
  1 file changed, 34 insertions(+), 20 deletions(-)

Index: libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_dhcpsnoop.c
+++ libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.c
@@ -43,6 +43,7 @@
  #include "conf/domain_conf.h"
  #include "nwfilter_gentech_driver.h"
  #include "nwfilter_dhcpsnoop.h"
+#include "nwfilter_ipaddrmap.h"
  #include "virnetdev.h"
  #include "virfile.h"
  #include "configmake.h"
@@ -222,7 +223,7 @@ virNWFilterSnoopInstallRule(struct virNW
  {
      char                     ipbuf[INET_ADDRSTRLEN];
      int                      rc;
-    virNWFilterVarValuePtr   ipVar;
+    char *ipaddr;

      if (!inet_ntop(AF_INET, &ipl->IPAddress, ipbuf, sizeof(ipbuf))) {
          virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
@@ -230,17 +231,19 @@ virNWFilterSnoopInstallRule(struct virNW
                                   " (0x%08X)"), ipl->IPAddress);
          return -1;
      }
-    ipVar = virNWFilterVarValueCreateSimpleCopyValue(ipbuf);
-    if (!ipVar) {
+
+    ipaddr = strdup(ipbuf);
+    if (ipaddr == NULL) {
          virReportOOMError();
          return -1;
      }
-    if (virNWFilterHashTablePut(ipl->SnoopReq->vars, "IP", ipVar, 1)) {
-        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Could not add variable \"IP\" to 
hashmap"));
-        virNWFilterVarValueFree(ipVar);
+
+    if (virNWFilterIPAddrMapAddIPAddrForIfname(ipl->SnoopReq->ifname,
+                                               ipaddr) < 0) {
+        VIR_FREE(ipaddr);
          return -1;
      }
+
      rc = virNWFilterInstantiateFilterLate(NULL,
                                            ipl->SnoopReq->ifname,
                                            ipl->SnoopReq->ifindex,
@@ -272,14 +275,6 @@ virNWFilterSnoopLeaseAdd(struct virNWFil
              virNWFilterSnoopLeaseFileSave(pl);
          return;
      }
-    /* support for multiple addresses requires the ability to add filters
-     * to existing chains, or to instantiate address lists via
-     * virNWFilterInstantiateFilterLate(). Until one of those capabilities
-     * is added, don't allow a new address when one is already assigned to
-     * this interface.
-     */
-    if (req->start)
-         return;    /* silently ignore multiple addresses */

      if (VIR_ALLOC(pl) < 0) {
          virReportOOMError();
@@ -336,20 +331,39 @@ virNWFilterSnoopLeaseDel(struct virNWFil
                           uint32_t ipaddr, bool update_leasefile)
  {
      struct virNWFilterSnoopIPLease *ipl;
+    char ipstr[INET_ADDRSTRLEN];
+    int ipAddrLeft;

      ipl = virNWFilterSnoopGetByIP(req->start, ipaddr);
      if (ipl == NULL)
          return;

+    if (!inet_ntop(AF_INET, &ipl->IPAddress, ipstr, sizeof(ipstr))) {
+        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("%s: inet_ntop failed (0x%08X)"),
+                               __func__, ipl->IPAddress);
+        return;
+    }
+
      virNWFilterSnoopTimerDel(ipl);

-    if (update_leasefile) {
+    if (update_leasefile)
          virNWFilterSnoopLeaseFileSave(ipl);

-        /*
-         * for multiple address support, this needs to remove those rules
-         * referencing "IP" with ipl's ip value.
-         */
+    ipAddrLeft = 
virNWFilterIPAddrMapDelIPAddrForIfname(ipl->SnoopReq->ifname,
+                                                        ipstr);
+
+    if (ipAddrLeft > 0) {
+        virNWFilterInstantiateFilterLate(NULL,
+                                         ipl->SnoopReq->ifname,
+                                         ipl->SnoopReq->ifindex,
+                                         ipl->SnoopReq->linkdev,
+                                         ipl->SnoopReq->nettype,
+                                         ipl->SnoopReq->macaddr,
+                                         ipl->SnoopReq->filtername,
+                                         ipl->SnoopReq->vars,
+                                         ipl->SnoopReq->driver);
+    } else {
          if (req->techdriver->applyDHCPOnlyRules(req->ifname, req->macaddr,
                                                  NULL, false))
              virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,




More information about the libvir-list mailing list