[libvirt] [PATCH] nwfilter: skip interfaces on filter update

Stefan Berger stefanb at us.ibm.com
Mon May 3 17:46:24 UTC 2010


When a filter is updated, only those interfaces must have their old
rules cleared that either reference the filter directly or indirectly
through another filter. Remember between the different steps of the
instantiation of the filters which interfaces must be skipped. I am
using a hash map to remember the names of the interfaces and store a
bogus pointer to ~0 into it that need not be freed.

Signed-off-by: Stefan Berger <stefanb at us.ibm.com>

---
 src/conf/nwfilter_conf.c               |    8 ++++
 src/conf/nwfilter_conf.h               |    1 
 src/nwfilter/nwfilter_gentech_driver.c |   66 ++++++++++++++++++++++++---------
 src/nwfilter/nwfilter_gentech_driver.h |    3 +
 4 files changed, 59 insertions(+), 19 deletions(-)

Index: libvirt-acl/src/conf/nwfilter_conf.c
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_conf.c
+++ libvirt-acl/src/conf/nwfilter_conf.c
@@ -2088,8 +2088,14 @@ virNWFilterTriggerVMFilterRebuild(virCon
         .conn = conn,
         .err = 0,
         .step = STEP_APPLY_NEW,
+        .skipInterfaces = virHashCreate(0),
     };
 
+    if (!cb.skipInterfaces) {
+        virReportOOMError();
+        return 1;
+    }
+
     for (i = 0; i < nCallbackDriver; i++) {
         callbackDrvArray[i]->vmFilterRebuild(conn,
                                              virNWFilterDomainFWUpdateCB,
@@ -2115,6 +2121,8 @@ virNWFilterTriggerVMFilterRebuild(virCon
                                                  &cb);
     }
 
+    virHashFree(cb.skipInterfaces, NULL);
+
     return err;
 }
 
Index: libvirt-acl/src/conf/nwfilter_conf.h
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_conf.h
+++ libvirt-acl/src/conf/nwfilter_conf.h
@@ -471,6 +471,7 @@ struct domUpdateCBStruct {
     virConnectPtr conn;
     enum UpdateStep step;
     int err;
+    virHashTablePtr skipInterfaces;
 };
 
 
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
@@ -40,7 +40,8 @@ enum instCase {
 int virNWFilterInstantiateFilter(virConnectPtr conn,
                                  const virDomainNetDefPtr net);
 int virNWFilterUpdateInstantiateFilter(virConnectPtr conn,
-                                       const virDomainNetDefPtr net);
+                                       const virDomainNetDefPtr net,
+                                       bool *skipIface);
 int virNWFilterRollbackUpdateFilter(virConnectPtr conn,
                                     const virDomainNetDefPtr net);
 
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
@@ -316,7 +316,7 @@ _virNWFilterInstantiateRec(virConnectPtr
                            virNWFilterHashTablePtr vars,
                            int *nEntries,
                            virNWFilterRuleInstPtr **insts,
-                           enum instCase useNewFilter, int *foundNewFilter,
+                           enum instCase useNewFilter, bool *foundNewFilter,
                            virNWFilterDriverStatePtr driver)
 {
     virNWFilterPoolObjPtr obj;
@@ -381,7 +381,7 @@ _virNWFilterInstantiateRec(virConnectPtr
                 case INSTANTIATE_FOLLOW_NEWFILTER:
                     if (obj->newDef) {
                         next_filter = obj->newDef;
-                        *foundNewFilter = 1;
+                        *foundNewFilter = true;
                     }
                 break;
                 case INSTANTIATE_ALWAYS:
@@ -562,7 +562,7 @@ virNWFilterInstantiate(virConnectPtr con
                        int ifindex,
                        const char *linkdev,
                        virNWFilterHashTablePtr vars,
-                       enum instCase useNewFilter, int *foundNewFilter,
+                       enum instCase useNewFilter, bool *foundNewFilter,
                        bool teardownOld,
                        const unsigned char *macaddr,
                        virNWFilterDriverStatePtr driver,
@@ -693,7 +693,8 @@ __virNWFilterInstantiateFilter(virConnec
                                virNWFilterHashTablePtr filterparams,
                                enum instCase useNewFilter,
                                virNWFilterDriverStatePtr driver,
-                               bool forceWithPendingReq)
+                               bool forceWithPendingReq,
+                               bool *foundNewFilter)
 {
     int rc;
     const char *drvname = EBIPTABLES_DRIVER_ID;
@@ -702,7 +703,6 @@ __virNWFilterInstantiateFilter(virConnec
     virNWFilterHashTablePtr vars, vars1;
     virNWFilterDefPtr filter;
     char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0};
-    int foundNewFilter = 0;
     char *str_macaddr = NULL;
     const char *ipaddr;
     char *str_ipaddr = NULL;
@@ -775,7 +775,7 @@ __virNWFilterInstantiateFilter(virConnec
     case INSTANTIATE_FOLLOW_NEWFILTER:
         if (obj->newDef) {
             filter = obj->newDef;
-            foundNewFilter = 1;
+            *foundNewFilter = true;
         }
     break;
 
@@ -791,7 +791,7 @@ __virNWFilterInstantiateFilter(virConnec
                                 ifindex,
                                 linkdev,
                                 vars,
-                                useNewFilter, &foundNewFilter,
+                                useNewFilter, foundNewFilter,
                                 teardownOld,
                                 macaddr,
                                 driver,
@@ -816,7 +816,8 @@ static int
 _virNWFilterInstantiateFilter(virConnectPtr conn,
                               const virDomainNetDefPtr net,
                               bool teardownOld,
-                              enum instCase useNewFilter)
+                              enum instCase useNewFilter,
+                              bool *foundNewFilter)
 {
     const char *linkdev = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT)
                           ? net->data.direct.linkdev
@@ -837,7 +838,8 @@ _virNWFilterInstantiateFilter(virConnect
                                           net->filterparams,
                                           useNewFilter,
                                           conn->nwfilterPrivateData,
-                                          false);
+                                          false,
+                                          foundNewFilter);
 }
 
 
@@ -853,6 +855,8 @@ virNWFilterInstantiateFilterLate(virConn
                                  virNWFilterDriverStatePtr driver)
 {
     int rc;
+    bool foundNewFilter = false;
+
     rc = __virNWFilterInstantiateFilter(conn,
                                         1,
                                         ifname,
@@ -864,7 +868,8 @@ virNWFilterInstantiateFilterLate(virConn
                                         filterparams,
                                         INSTANTIATE_ALWAYS,
                                         driver,
-                                        true);
+                                        true,
+                                        &foundNewFilter);
     if (rc) {
         //something went wrong... 'DOWN' the interface
         if (ifaceCheck(false, ifname, NULL, ifindex) != 0 ||
@@ -881,19 +886,29 @@ int
 virNWFilterInstantiateFilter(virConnectPtr conn,
                              const virDomainNetDefPtr net)
 {
+    bool foundNewFilter = false;
+
     return _virNWFilterInstantiateFilter(conn, net,
                                          1,
-                                         INSTANTIATE_ALWAYS);
+                                         INSTANTIATE_ALWAYS,
+                                         &foundNewFilter);
 }
 
 
 int
 virNWFilterUpdateInstantiateFilter(virConnectPtr conn,
-                                   const virDomainNetDefPtr net)
+                                   const virDomainNetDefPtr net,
+                                   bool *skipIface)
 {
-    return _virNWFilterInstantiateFilter(conn, net,
-                                         0,
-                                         INSTANTIATE_FOLLOW_NEWFILTER);
+    bool foundNewFilter = false;
+
+    int rc = _virNWFilterInstantiateFilter(conn, net,
+                                           0,
+                                           INSTANTIATE_FOLLOW_NEWFILTER,
+                                           &foundNewFilter);
+
+    *skipIface = !foundNewFilter;
+    return rc;
 }
 
 int virNWFilterRollbackUpdateFilter(virConnectPtr conn,
@@ -993,6 +1008,7 @@ virNWFilterDomainFWUpdateCB(void *payloa
     virDomainDefPtr vm = obj->def;
     struct domUpdateCBStruct *cb = data;
     int i;
+    bool skipIface;
 
     virDomainObjLock(obj);
 
@@ -1003,15 +1019,29 @@ virNWFilterDomainFWUpdateCB(void *payloa
                 switch (cb->step) {
                 case STEP_APPLY_NEW:
                     cb->err = virNWFilterUpdateInstantiateFilter(cb->conn,
-                                                                 net);
+                                                                 net,
+                                                                 &skipIface);
+                    if (cb->err == 0 && skipIface == true) {
+                        // filter tree unchanged -- no update needed
+                        cb->err = virHashAddEntry(cb->skipInterfaces,
+                                                  net->ifname,
+                                                  (void *)~0);
+                        if (cb->err)
+                            virReportOOMError();
+                    }
                     break;
 
                 case STEP_TEAR_NEW:
-                    cb->err = virNWFilterRollbackUpdateFilter(cb->conn, net);
+                    if ( !virHashLookup(cb->skipInterfaces, net->ifname)) {
+                        cb->err = virNWFilterRollbackUpdateFilter(cb->conn,
+                                                                  net);
+                    }
                     break;
 
                 case STEP_TEAR_OLD:
-                    cb->err = virNWFilterTearOldFilter(cb->conn, net);
+                    if ( !virHashLookup(cb->skipInterfaces, net->ifname)) {
+                        cb->err = virNWFilterTearOldFilter(cb->conn, net);
+                    }
                     break;
                 }
                 if (cb->err)




More information about the libvir-list mailing list