[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH V3 1/4] Rework value part of name-value pairs



NWFilters can be provided name-value pairs using the following
XML notiation:

      <filterref filter='xyz'>
        <parameter name='PORT' value='80'/>
        <parameter name='VAL' value='abc'/>
      </filterref>

The internal representation currently is so that a name is stored as a
string and the value as well. This patch now addresses the value part of it
and introduces a data structure for storing a value either as a simple
value or as an array for later support of lists (provided in python-like
notation ( [a,b,c] ).

This patch adjusts all code that was handling the values in hash tables
and makes it use the new data type.

Signed-off-by: Stefan Berger <stefanb linux vnet ibm com>

---
 src/conf/domain_conf.c                    |    2 
 src/conf/nwfilter_params.c                |  288 ++++++++++++++++++++++++++++--
 src/conf/nwfilter_params.h                |   38 +++
 src/libvirt_private.syms                  |    3 
 src/nwfilter/nwfilter_ebiptables_driver.c |   15 +
 src/nwfilter/nwfilter_gentech_driver.c    |   27 ++
 src/nwfilter/nwfilter_learnipaddr.c       |   13 +
 7 files changed, 365 insertions(+), 21 deletions(-)

Index: libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_ebiptables_driver.c
+++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -200,14 +200,25 @@ printVar(virNWFilterHashTablePtr vars,
     *done = 0;
 
     if ((item->flags & NWFILTER_ENTRY_ITEM_FLAG_HAS_VAR)) {
-        char *val = (char *)virHashLookup(vars->hashTable, item->var);
-        if (!val) {
+        virNWFilterVarValuePtr varval;
+        const char *val;
+
+        varval = virHashLookup(vars->hashTable, item->var);
+        if (!varval) {
             virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
                                    _("cannot find value for '%s'"),
                                    item->var);
             return 1;
         }
 
+        val = virNWFilterVarValueGetSimple(varval);
+        if (!val) {
+            virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+                                   _("cannot get simple value of '%s'"),
+                                   item->var);
+            return 1;
+        }
+
         if (!virStrcpy(buf, val, bufsize)) {
             virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
                                    _("Buffer to small to print MAC address "
Index: libvirt-acl/src/conf/nwfilter_params.c
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_params.c
+++ libvirt-acl/src/conf/nwfilter_params.c
@@ -30,14 +30,268 @@
 #include "datatypes.h"
 #include "nwfilter_params.h"
 #include "domain_conf.h"
+#include "c-ctype.h"
 
 
 #define VIR_FROM_THIS VIR_FROM_NWFILTER
 
+static bool isValidVarValue(const char *value);
+
+
+static void
+virNWFilterVarValueFree(virNWFilterVarValuePtr val)
+{
+    unsigned i;
+
+    if (!val)
+        return;
+
+    switch (val->valType) {
+    case NWFILTER_VALUE_TYPE_SIMPLE:
+        VIR_FREE(val->u.simple.value);
+        break;
+    case NWFILTER_VALUE_TYPE_ARRAY:
+        for (i = 0; i < val->u.array.nValues; i++)
+            VIR_FREE(val->u.array.values[i]);
+        VIR_FREE(val->u.array.values);
+        break;
+    case NWFILTER_VALUE_TYPE_LAST:
+        break;
+    }
+    VIR_FREE(val);
+}
+
+static virNWFilterVarValuePtr
+virNWFilterVarValueCopy(const virNWFilterVarValuePtr val)
+{
+    virNWFilterVarValuePtr res;
+    unsigned i;
+    char *str;
+
+    if (VIR_ALLOC(res) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+    res->valType = val->valType;
+
+    switch (res->valType) {
+    case NWFILTER_VALUE_TYPE_SIMPLE:
+        if (val->u.simple.value) {
+            res->u.simple.value = strdup(val->u.simple.value);
+            if (!res->u.simple.value)
+                goto err_exit;
+        }
+        break;
+    case NWFILTER_VALUE_TYPE_ARRAY:
+        if (VIR_ALLOC_N(res->u.array.values, val->u.array.nValues))
+            goto err_exit;
+        res->u.array.nValues = val->u.array.nValues;
+        for (i = 0; i < val->u.array.nValues; i++) {
+            str = strdup(val->u.array.values[i]);
+            if (!str)
+                goto err_exit;
+            res->u.array.values[i] = str;
+        }
+        break;
+    case NWFILTER_VALUE_TYPE_LAST:
+        break;
+    }
+
+    return res;
+
+err_exit:
+    virReportOOMError();
+    virNWFilterVarValueFree(res);
+    return NULL;
+}
+
+void
+virNWFilterVarValuePrint(virNWFilterVarValuePtr val, virBufferPtr buf)
+{
+    unsigned i;
+    char *item;
+
+    switch (val->valType) {
+    case NWFILTER_VALUE_TYPE_SIMPLE:
+        virBufferAdd(buf, val->u.simple.value, -1);
+        break;
+    case NWFILTER_VALUE_TYPE_ARRAY:
+        virBufferAddLit(buf, "[");
+        for (i = 0; i < val->u.array.nValues; i++) {
+            if (i > 0)
+                virBufferAddLit(buf, ", ");
+            item = val->u.array.values[i];
+            if (item) {
+                bool quote = false;
+                if (c_isspace(item[0]) || c_isspace(item[strlen(item)- 1 ]))
+                    quote = true;
+                if (quote)
+                    virBufferEscapeString(buf, "%s", "'");
+                virBufferAdd(buf, val->u.array.values[i], -1);
+                if (quote)
+                    virBufferEscapeString(buf, "%s", "'");
+            }
+        }
+        virBufferAddLit(buf, "]");
+        break;
+    case NWFILTER_VALUE_TYPE_LAST:
+        break;
+    }
+}
+
+virNWFilterVarValuePtr
+virNWFilterVarValueCreateSimple(const char *value, bool copy_value)
+{
+    virNWFilterVarValuePtr val;
+
+    if (!isValidVarValue(value))
+        return NULL;
+
+    if (VIR_ALLOC(val) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    val->valType = NWFILTER_VALUE_TYPE_SIMPLE;
+    if (copy_value) {
+        val->u.simple.value = strdup(value);
+        if (!val->u.simple.value) {
+            VIR_FREE(val);
+            virReportOOMError();
+            return NULL;
+        }
+    } else
+        val->u.simple.value = (char *)value;
+
+    return val;
+}
+
+const char *
+virNWFilterVarValueGetSimple(virNWFilterVarValuePtr val)
+{
+    if (val->valType == NWFILTER_VALUE_TYPE_SIMPLE)
+        return val->u.simple.value;
+    return NULL;
+}
+
+const char *
+virNWFilterVarValueGetNthValue(virNWFilterVarValuePtr val, unsigned int idx)
+{
+    const char *res = NULL;
+
+    switch (val->valType) {
+    case NWFILTER_VALUE_TYPE_SIMPLE:
+        if (idx == 0)
+            res = val->u.simple.value;
+        break;
+    case NWFILTER_VALUE_TYPE_ARRAY:
+        if (idx < val->u.array.nValues)
+            res = val->u.array.values[idx];
+        break;
+    case NWFILTER_VALUE_TYPE_LAST:
+        break;
+    }
+
+    return res;
+}
+
+unsigned int
+virNWFilterVarValueGetCardinality(virNWFilterVarValuePtr val)
+{
+    switch (val->valType) {
+    case NWFILTER_VALUE_TYPE_SIMPLE:
+        return 1;
+        break;
+    case NWFILTER_VALUE_TYPE_ARRAY:
+        return val->u.array.nValues;
+        break;
+    case NWFILTER_VALUE_TYPE_LAST:
+        return 0;
+    }
+    return 0;
+}
+
+bool
+virNWFilterVarValueDelValue(virNWFilterVarValuePtr val, const char *value)
+{
+    unsigned int i;
+
+    switch (val->valType) {
+    case NWFILTER_VALUE_TYPE_SIMPLE:
+        return false;
+
+    case NWFILTER_VALUE_TYPE_ARRAY:
+        for (i = 0; i < val->u.array.nValues; i++) {
+            if (STREQ(value, val->u.array.values[i])) {
+                VIR_FREE(val->u.array.values[i]);
+                val->u.array.nValues--;
+                val->u.array.values[i] =
+                                val->u.array.values[val->u.array.nValues];
+                return true;
+            }
+        }
+        break;
+
+    case NWFILTER_VALUE_TYPE_LAST:
+        break;
+    }
+
+    return false;
+}
+
+bool
+virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, const char *value,
+                            bool make_copy)
+{
+    char *tmp;
+    bool rc = false;
+
+    if (make_copy) {
+        value = strdup(value);
+        if (!value) {
+            virReportOOMError();
+            return false;
+        }
+    }
+
+    switch (val->valType) {
+    case NWFILTER_VALUE_TYPE_SIMPLE:
+        /* switch to array */
+        tmp = val->u.simple.value;
+        if (VIR_ALLOC_N(val->u.array.values, 2) < 0) {
+            val->u.simple.value = tmp;
+            virReportOOMError();
+            return false;
+        }
+        val->valType = NWFILTER_VALUE_TYPE_ARRAY;
+        val->u.array.nValues = 2;
+        val->u.array.values[0] = tmp;
+        val->u.array.values[1] = (char *)value;
+        rc  = true;
+        break;
+
+    case NWFILTER_VALUE_TYPE_ARRAY:
+        if (VIR_REALLOC_N(val->u.array.values,
+                          val->u.array.nValues + 1) < 0) {
+            virReportOOMError();
+            return false;
+        }
+        val->u.array.values[val->u.array.nValues] = (char *)value;
+        val->u.array.nValues += 1;
+        rc = true;
+        break;
+
+    case NWFILTER_VALUE_TYPE_LAST:
+        break;
+    }
+
+    return rc;
+}
+
 static void
 hashDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)
 {
-    VIR_FREE(payload);
+    virNWFilterVarValueFree(payload);
 }
 
 
@@ -56,7 +310,7 @@ hashDataFree(void *payload, const void *
 int
 virNWFilterHashTablePut(virNWFilterHashTablePtr table,
                         const char *name,
-                        char *val,
+                        virNWFilterVarValuePtr val,
                         int copyName)
 {
     if (!virHashLookup(table->hashTable, name)) {
@@ -160,12 +414,12 @@ static void
 addToTable(void *payload, const void *name, void *data)
 {
     struct addToTableStruct *atts = (struct addToTableStruct *)data;
-    char *val;
+    virNWFilterVarValuePtr val;
 
     if (atts->errOccurred)
         return;
 
-    val = strdup((char *)payload);
+    val = virNWFilterVarValueCopy((virNWFilterVarValuePtr)payload);
     if (!val) {
         virReportOOMError();
         atts->errOccurred = 1;
@@ -177,7 +431,7 @@ addToTable(void *payload, const void *na
                                _("Could not put variable '%s' into hashmap"),
                                (const char *)name);
         atts->errOccurred = 1;
-        VIR_FREE(val);
+        virNWFilterVarValueFree(val);
     }
 }
 
@@ -215,11 +469,17 @@ isValidVarValue(const char *value)
     return value[strspn(value, VALID_VARVALUE)] == 0;
 }
 
+static virNWFilterVarValuePtr
+virNWFilterParseVarValue(const char *val)
+{
+    return virNWFilterVarValueCreateSimple(val, true);
+}
 
 virNWFilterHashTablePtr
 virNWFilterParseParamAttributes(xmlNodePtr cur)
 {
     char *nam, *val;
+    virNWFilterVarValuePtr value;
 
     virNWFilterHashTablePtr table = virNWFilterHashTableCreate(0);
     if (!table) {
@@ -234,20 +494,24 @@ virNWFilterParseParamAttributes(xmlNodeP
             if (xmlStrEqual(cur->name, BAD_CAST "parameter")) {
                 nam = virXMLPropString(cur, "name");
                 val = virXMLPropString(cur, "value");
+                value = NULL;
                 if (nam != NULL && val != NULL) {
                     if (!isValidVarName(nam))
                         goto skip_entry;
-                    if (!isValidVarValue(nam))
+                    value = virNWFilterParseVarValue(val);
+                    if (!value)
                         goto skip_entry;
-                    if (virNWFilterHashTablePut(table, nam, val, 1)) {
+                    if (virNWFilterHashTablePut(table, nam, value, 1)) {
                         VIR_FREE(nam);
                         VIR_FREE(val);
+                        virNWFilterVarValueFree(value);
                         virNWFilterHashTableFree(table);
                         return NULL;
                     }
-                    val = NULL;
+                    value = NULL;
                 }
 skip_entry:
+                virNWFilterVarValueFree(value);
                 VIR_FREE(nam);
                 VIR_FREE(val);
             }
@@ -268,11 +532,13 @@ static void
 _formatParameterAttrs(void *payload, const void *name, void *data)
 {
     struct formatterParam *fp = (struct formatterParam *)data;
+    virNWFilterVarValuePtr value = payload;
 
-    virBufferAsprintf(fp->buf, "%s<parameter name='%s' value='%s'/>\n",
+    virBufferAsprintf(fp->buf, "%s<parameter name='%s' value='",
                       fp->indent,
-                      (const char *)name,
-                      (char *)payload);
+                      (const char *)name);
+    virNWFilterVarValuePrint(value, fp->buf);
+    virBufferAddLit(fp->buf, "'/>\n");
 }
 
 
Index: libvirt-acl/src/conf/nwfilter_params.h
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_params.h
+++ libvirt-acl/src/conf/nwfilter_params.h
@@ -23,6 +23,42 @@
 # define NWFILTER_PARAMS_H
 
 # include "hash.h"
+# include "buf.h"
+
+enum virNWFilterVarValueType {
+    NWFILTER_VALUE_TYPE_SIMPLE,
+    NWFILTER_VALUE_TYPE_ARRAY,
+
+    NWFILTER_VALUE_TYPE_LAST
+};
+
+typedef struct _virNWFilterVarValue virNWFilterVarValue;
+typedef virNWFilterVarValue *virNWFilterVarValuePtr;
+struct _virNWFilterVarValue {
+    enum virNWFilterVarValueType valType;
+    union {
+        struct {
+            char *value;
+        } simple;
+        struct {
+            char **values;
+            unsigned nValues;
+        } array;
+    } u;
+};
+
+virNWFilterVarValuePtr virNWFilterVarValueCreateSimple(const char *,
+                                                       bool copy_value);
+const char *virNWFilterVarValueGetSimple(virNWFilterVarValuePtr val);
+const char *virNWFilterVarValueGetNthValue(virNWFilterVarValuePtr val,
+                                           unsigned int idx);
+unsigned int virNWFilterVarValueGetCardinality(virNWFilterVarValuePtr val);
+bool virNWFilterVarValueDelValue(virNWFilterVarValuePtr val,
+                                 const char *value);
+bool virNWFilterVarValueAddValue(virNWFilterVarValuePtr val,
+                                 const char *value,
+                                 bool make_copy);
+void virNWFilterVarValuePrint(virNWFilterVarValuePtr val, virBufferPtr buf);
 
 typedef struct _virNWFilterHashTable virNWFilterHashTable;
 typedef virNWFilterHashTable *virNWFilterHashTablePtr;
@@ -42,7 +78,7 @@ virNWFilterHashTablePtr virNWFilterHashT
 void virNWFilterHashTableFree(virNWFilterHashTablePtr table);
 int virNWFilterHashTablePut(virNWFilterHashTablePtr table,
                             const char *name,
-                            char *val,
+                            virNWFilterVarValuePtr val,
                             int freeName);
 int virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr table,
                                     const char *name);
Index: libvirt-acl/src/conf/domain_conf.c
===================================================================
--- libvirt-acl.orig/src/conf/domain_conf.c
+++ libvirt-acl/src/conf/domain_conf.c
@@ -3152,7 +3152,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
                 event_idx = virXMLPropString(cur, "event_idx");
             } else if (xmlStrEqual (cur->name, BAD_CAST "filterref")) {
                 filter = virXMLPropString(cur, "filter");
-                VIR_FREE(filterparams);
+                virNWFilterHashTableFree(filterparams);
                 filterparams = virNWFilterParseParamAttributes(cur);
             } else if ((flags & VIR_DOMAIN_XML_INTERNAL_STATUS) &&
                        xmlStrEqual(cur->name, BAD_CAST "state")) {
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
@@ -147,10 +147,17 @@ virNWFilterVarHashmapAddStdValues(virNWF
                                   char *macaddr,
                                   char *ipaddr)
 {
+    virNWFilterVarValue *val;
+
     if (macaddr) {
+        val = virNWFilterVarValueCreateSimple(macaddr, false);
+        if (!val) {
+            virReportOOMError();
+            return 1;
+        }
         if (virHashAddEntry(table->hashTable,
                             NWFILTER_STD_VAR_MAC,
-                            macaddr) < 0) {
+                            val) < 0) {
             virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
                                    "%s", _("Could not add variable 'MAC' to hashmap"));
             return 1;
@@ -158,9 +165,14 @@ virNWFilterVarHashmapAddStdValues(virNWF
     }
 
     if (ipaddr) {
+        val = virNWFilterVarValueCreateSimple(ipaddr, false);
+        if (!val) {
+            virReportOOMError();
+            return 1;
+        }
         if (virHashAddEntry(table->hashTable,
                             NWFILTER_STD_VAR_IP,
-                            ipaddr) < 0) {
+                            val) < 0) {
             virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
                                    "%s", _("Could not add variable 'IP' to hashmap"));
             return 1;
@@ -491,6 +503,7 @@ virNWFilterDetermineMissingVarsRec(virCo
     int rc = 0;
     int i, j;
     virNWFilterDefPtr next_filter;
+    virNWFilterVarValuePtr val;
 
     for (i = 0; i < filter->nentries; i++) {
         virNWFilterRuleDefPtr    rule = filter->filterEntries[i]->rule;
@@ -499,10 +512,18 @@ virNWFilterDetermineMissingVarsRec(virCo
             /* check all variables of this rule */
             for (j = 0; j < rule->nvars; j++) {
                 if (!virHashLookup(vars->hashTable, rule->vars[j])) {
+                    val = virNWFilterVarValueCreateSimple("1", true);
+                    if (!val) {
+                        virReportOOMError();
+                        rc = 1;
+                        break;
+                    }
                     virNWFilterHashTablePut(missing_vars, rule->vars[j],
-                                            strdup("1"), 1);
+                                            val, 1);
                 }
             }
+            if (rc)
+                break;
         } else if (inc) {
             VIR_DEBUG("Following filter %s\n", inc->filterref);
             obj = virNWFilterObjFindByName(&driver->nwfilters, inc->filterref);
Index: libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_learnipaddr.c
+++ libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c
@@ -313,10 +313,14 @@ virNWFilterDeregisterLearnReq(int ifinde
 static int
 virNWFilterAddIpAddrForIfname(const char *ifname, char *addr) {
     int ret;
+    virNWFilterVarValuePtr val = virNWFilterVarValueCreateSimple(addr, false);
+
+    if (!val)
+        return 1;
 
     virMutexLock(&ipAddressMapLock);
 
-    ret = virNWFilterHashTablePut(ipAddressMap, ifname, addr, 1);
+    ret = virNWFilterHashTablePut(ipAddressMap, ifname, val, 1);
 
     virMutexUnlock(&ipAddressMapLock);
 
@@ -339,7 +343,7 @@ virNWFilterDelIpAddrForIfname(const char
 
 const char *
 virNWFilterGetIpAddrForIfname(const char *ifname) {
-    const char *res;
+    virNWFilterVarValuePtr res;
 
     virMutexLock(&ipAddressMapLock);
 
@@ -347,7 +351,10 @@ virNWFilterGetIpAddrForIfname(const char
 
     virMutexUnlock(&ipAddressMapLock);
 
-    return res;
+    if (res)
+        return virNWFilterVarValueGetSimple(res);
+
+    return NULL;
 }
 
 
Index: libvirt-acl/src/libvirt_private.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_private.syms
+++ libvirt-acl/src/libvirt_private.syms
@@ -881,6 +881,9 @@ virNWFilterHashTableFree;
 virNWFilterHashTablePut;
 virNWFilterHashTablePutAll;
 virNWFilterHashTableRemoveEntry;
+virNWFilterVarValueCreateSimple;
+virNWFilterVarValueGetSimple;
+virNWFilterVarValuePrint;
 
 
 # pci.h


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]