This patch introduces the capability to use a different iterator per
variable.
The currently supported notation of variables in a filtering rule like
<rule action='accept' direction='out'>
<tcp srcipaddr='$A' srcportstart='$B'/>
</rule>
processes the two lists 'A' and 'B' in parallel. This means that A and B
must have the same number of 'N' elements and that 'N' rules will be
instantiated (assuming all tuples from A and B are unique).
In this patch we now introduce the assignment of variables to different
iterators. Therefore a rule like
<rule action='accept' direction='out'>
<tcp srcipaddr='$A[@1]' srcportstart='$B[@2]'/>
</rule>
will now create every combination of elements in A with elements in B since
A has been assigned to an iterator with Id '1' and B has been assigned to an
iterator with Id '2', thus processing their value independently.
The first rule has an equivalent notation of
<rule action='accept' direction='out'>
<tcp srcipaddr='$A[@0]' srcportstart='$B[@0]'/>
</rule>
---
docs/schemas/nwfilter.rng | 71 ++------
src/conf/nwfilter_conf.c | 35 ++--
src/conf/nwfilter_conf.h | 6
src/conf/nwfilter_params.c | 240 +++++++++++++++++++++++++++---
src/conf/nwfilter_params.h | 38 ++++
src/libvirt_private.syms | 1
src/nwfilter/nwfilter_ebiptables_driver.c | 13 +
src/nwfilter/nwfilter_gentech_driver.c | 8 -
8 files changed, 308 insertions(+), 104 deletions(-)
Index: libvirt-iterator/src/conf/nwfilter_conf.h
===================================================================
--- libvirt-iterator.orig/src/conf/nwfilter_conf.h
+++ libvirt-iterator/src/conf/nwfilter_conf.h
@@ -121,7 +121,7 @@ typedef struct _nwItemDesc nwItemDesc;
typedef nwItemDesc *nwItemDescPtr;
struct _nwItemDesc {
enum virNWFilterEntryItemFlags flags;
- char *var;
+ virNWFilterVarAccessPtr varAccess;
enum attrDatatype datatype;
union {
nwMACAddress macaddr;
@@ -470,8 +470,8 @@ struct _virNWFilterRuleDef {
sctpHdrFilterDef sctpHdrFilter;
} p;
- int nvars;
- char **vars;
+ size_t nVarAccess;
+ virNWFilterVarAccessPtr *varAccess;
int nstrings;
char **strings;
Index: libvirt-iterator/src/conf/nwfilter_conf.c
===================================================================
--- libvirt-iterator.orig/src/conf/nwfilter_conf.c
+++ libvirt-iterator/src/conf/nwfilter_conf.c
@@ -272,13 +272,13 @@ virNWFilterRuleDefFree(virNWFilterRuleDe
if (!def)
return;
- for (i = 0; i < def->nvars; i++)
- VIR_FREE(def->vars[i]);
+ for (i = 0; i < def->nVarAccess; i++)
+ virNWFilterVarAccessFree(def->varAccess[i]);
for (i = 0; i < def->nstrings; i++)
VIR_FREE(def->strings[i]);
- VIR_FREE(def->vars);
+ VIR_FREE(def->varAccess);
VIR_FREE(def->strings);
VIR_FREE(def);
@@ -358,28 +358,28 @@ virNWFilterRuleDefAddVar(virNWFilterRule
const char *var)
{
int i = 0;
+ virNWFilterVarAccessPtr varAccess;
- if (nwf->vars) {
- for (i = 0; i < nwf->nvars; i++)
- if (STREQ(nwf->vars[i], var)) {
- item->var = nwf->vars[i];
+ varAccess = virNWFilterVarAccessParse(var);
+ if (varAccess == NULL)
+ return -1;
+
+ if (nwf->varAccess) {
+ for (i = 0; i < nwf->nVarAccess; i++)
+ if (virNWFilterVarAccessEqual(nwf->varAccess[i], varAccess)) {
+ virNWFilterVarAccessFree(varAccess);
+ item->varAccess = nwf->varAccess[i];
return 0;
}
}
- if (VIR_REALLOC_N(nwf->vars, nwf->nvars+1) < 0) {
- virReportOOMError();
- return -1;
- }
-
- nwf->vars[nwf->nvars] = strdup(var);
-
- if (!nwf->vars[nwf->nvars]) {
+ if (VIR_EXPAND_N(nwf->varAccess, nwf->nVarAccess, 1) < 0) {
virReportOOMError();
return -1;
}
- item->var = nwf->vars[nwf->nvars++];
+ nwf->varAccess[nwf->nVarAccess - 1] = varAccess;
+ item->varAccess = varAccess;
return 0;
}
@@ -3069,7 +3069,8 @@ virNWFilterRuleDefDetailsFormat(virBuffe
goto err_exit;
}
} else if ((flags & NWFILTER_ENTRY_ITEM_FLAG_HAS_VAR)) {
- virBufferAsprintf(buf, "$%s", item->var);
+ virBufferAddChar(buf, '$');
+ virNWFilterVarAccessPrint(item->varAccess, buf);
} else {
asHex = false;
Index: libvirt-iterator/src/conf/nwfilter_params.c
===================================================================
--- libvirt-iterator.orig/src/conf/nwfilter_params.c
+++ libvirt-iterator/src/conf/nwfilter_params.c
@@ -310,10 +310,11 @@ virNWFilterVarCombIterEntryInit(virNWFil
static int
virNWFilterVarCombIterAddVariable(virNWFilterVarCombIterEntryPtr cie,
virNWFilterHashTablePtr hash,
- const char *varName)
+ const virNWFilterVarAccessPtr varAccess)
{
virNWFilterVarValuePtr varValue;
unsigned int cardinality;
+ const char *varName = virNWFilterVarAccessGetVarName(varAccess);
varValue = virHashLookup(hash->hashTable, varName);
if (varValue == NULL) {
@@ -409,13 +410,14 @@ virNWFilterVarCombIterEntryAreUniqueEntr
*/
virNWFilterVarCombIterPtr
virNWFilterVarCombIterCreate(virNWFilterHashTablePtr hash,
- char * const *vars, unsigned int nVars)
+ const virNWFilterVarAccessPtr *varAccess,
+ size_t nVarAccess)
{
virNWFilterVarCombIterPtr res;
unsigned int i, iterId;
- int iterIndex;
+ int iterIndex = -1;
- if (VIR_ALLOC_VAR(res, virNWFilterVarCombIterEntry, 1) < 0) {
+ if (VIR_ALLOC_VAR(res, virNWFilterVarCombIterEntry, 1 + nVarAccess) < 0) {
virReportOOMError();
return NULL;
}
@@ -428,22 +430,24 @@ virNWFilterVarCombIterCreate(virNWFilter
res->nIter = 1;
virNWFilterVarCombIterEntryInit(&res->iter[0], iterId);
- for (i = 0; i < nVars; i++) {
-
- /* currently always access @0 */
- iterId = 0;
-
- iterIndex = virNWFilterVarCombIterGetIndexByIterId(res, iterId);
- if (iterIndex < 0) {
- /* future: create new iterator. for now it's a bug */
- virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
- _("Could not find iterator with id %u"),
- iterId);
- goto err_exit;
+ for (i = 0; i < nVarAccess; i++) {
+ switch (virNWFilterVarAccessGetType(varAccess[i])) {
+ case VIR_NWFILTER_VAR_ACCESS_ITERATOR:
+ iterId = virNWFilterVarAccessGetIterId(varAccess[i]);
+ iterIndex = virNWFilterVarCombIterGetIndexByIterId(res, iterId);
+ if (iterIndex < 0) {
+ iterIndex = res->nIter;
+ virNWFilterVarCombIterEntryInit(&res->iter[iterIndex], iterId);
+ res->nIter++;
+ }
+ break;
+ case VIR_NWFILTER_VAR_ACCESS_ELEMENT:
+ case VIR_NWFILTER_VAR_ACCESS_LAST:
+ break;
}
if (virNWFilterVarCombIterAddVariable(&res->iter[iterIndex],
- hash, vars[i]) < 0)
+ hash, varAccess[i]) < 0)
goto err_exit;
}
@@ -482,16 +486,33 @@ next:
const char *
virNWFilterVarCombIterGetVarValue(virNWFilterVarCombIterPtr ci,
- const char *varName)
+ const virNWFilterVarAccessPtr vap)
{
- unsigned int i;
+ unsigned int i, iterId;
bool found = false;
const char *res = NULL;
virNWFilterVarValuePtr value;
- unsigned int iterIndex;
+ int iterIndex = -1;
+ const char *varName = virNWFilterVarAccessGetVarName(vap);
- /* currently always accessing iter @0 */
- iterIndex = 0;
+ switch (virNWFilterVarAccessGetType(vap)) {
+ case VIR_NWFILTER_VAR_ACCESS_ITERATOR:
+ iterId = virNWFilterVarAccessGetIterId(vap);
+ iterIndex = virNWFilterVarCombIterGetIndexByIterId(ci, iterId);
+ if (iterIndex < 0) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get iterator index for "
+ "iterator ID %u"), iterId);
+ return NULL;
+ }
+ break;
+ case VIR_NWFILTER_VAR_ACCESS_ELEMENT:
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Element access via index is not possible"));
+ return NULL;
+ case VIR_NWFILTER_VAR_ACCESS_LAST:
+ return NULL;
+ }
for (i = 0; i < ci->iter[iterIndex].nVarNames; i++) {
if (STREQ(ci->iter[iterIndex].varNames[i], varName)) {
@@ -830,3 +851,178 @@ virNWFilterFormatParamAttributes(virBuff
return 0;
}
+
+void
+virNWFilterVarAccessFree(virNWFilterVarAccessPtr varAccess)
+{
+ if (!varAccess)
+ return;
+
+ VIR_FREE(varAccess->varName);
+ VIR_FREE(varAccess);
+}
+
+bool
+virNWFilterVarAccessEqual(const virNWFilterVarAccessPtr a,
+ const virNWFilterVarAccessPtr b)
+{
+ if (a->accessType != b->accessType)
+ return false;
+
+ if (STRNEQ(a->varName, b->varName))
+ return false;
+
+ switch (a->accessType) {
+ case VIR_NWFILTER_VAR_ACCESS_ELEMENT:
+ return (a->u.index == b->u.index);
+ break;
+ case VIR_NWFILTER_VAR_ACCESS_ITERATOR:
+ return (a->u.iterId == b->u.iterId);
+ break;
+ case VIR_NWFILTER_VAR_ACCESS_LAST:
+ break;
+ }
+ return false;
+}
+
+/*
+ * Parse a variable access like
+ * IP, IP[@2], IP[3]
+ */
+virNWFilterVarAccessPtr
+virNWFilterVarAccessParse(const char *varAccess)
+{
+ size_t idx, varNameLen;
+ virNWFilterVarAccessPtr dest;
+ const char *input = varAccess;
+
+ if (VIR_ALLOC(dest) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ idx = strspn(input, VALID_VARNAME);
+
+ if (input[idx] == '\0') {
+ /* in the form 'IP', which is equivalent to IP[@0] */
+ dest->varName = strndup(input, idx);
+ if (!dest->varName) {
+ virReportOOMError();
+ goto err_exit;
+ }
+ dest->accessType = VIR_NWFILTER_VAR_ACCESS_ITERATOR;
+ dest->u.iterId = 0;
+ return dest;
+ }
+
+ if (input[idx] == '[') {
+ char *end_ptr;
+ unsigned int result;
+ bool parseError = false;
+
+ varNameLen = idx;
+
+ dest->varName = strndup(input, varNameLen);
+ if (!dest->varName) {
+ virReportOOMError();
+ goto err_exit;
+ }
+
+ input += idx + 1;
+ virSkipSpaces(&input);
+
+ if (*input == '@') {
+ /* in the form 'IP[@<number>] -> iterator */
+ dest->accessType = VIR_NWFILTER_VAR_ACCESS_ITERATOR;
+ input++;
+ } else {
+ /* in the form 'IP[<number>] -> element */
+ dest->accessType = VIR_NWFILTER_VAR_ACCESS_ELEMENT;
+ /* not supported (yet) */
+ virNWFilterReportError(VIR_ERR_INVALID_ARG,
+ _("Variable access in the form "
+ "var[<index>] is not supported"));
+ goto err_exit;
+ }
+
+ if (virStrToLong_ui(input, &end_ptr, 10, &result) < 0)
+ parseError = true;
+ if (!parseError) {
+ input = end_ptr;
+ virSkipSpaces(&input);
+ if (*input != ']')
+ parseError = true;
+ }
+ if (parseError) {
+ if (dest->accessType == VIR_NWFILTER_VAR_ACCESS_ELEMENT)
+ virNWFilterReportError(VIR_ERR_INVALID_ARG,
+ _("Malformatted array index"));
+ else
+ virNWFilterReportError(VIR_ERR_INVALID_ARG,
+ _("Malformatted iterator id"));
+ goto err_exit;
+ }
+
+ switch (dest->accessType) {
+ case VIR_NWFILTER_VAR_ACCESS_ELEMENT:
+ dest->u.index = result;
+ break;
+ case VIR_NWFILTER_VAR_ACCESS_ITERATOR:
+ if (result > VIR_NWFILTER_MAX_ITERID) {
+ virNWFilterReportError(VIR_ERR_INVALID_ARG,
+ _("Iterator ID exceeds maximum ID "
+ "of %u"), VIR_NWFILTER_MAX_ITERID);
+ goto err_exit;
+ }
+ dest->u.iterId = result;
+ break;
+ case VIR_NWFILTER_VAR_ACCESS_LAST:
+ goto err_exit;
+ }
+
+ return dest;
+ } else {
+ virNWFilterReportError(VIR_ERR_INVALID_ARG,
+ _("Malformatted variable"));
+ }
+
+err_exit:
+ virNWFilterVarAccessFree(dest);
+
+ return NULL;
+}
+
+void
+virNWFilterVarAccessPrint(virNWFilterVarAccessPtr vap, virBufferPtr buf)
+{
+ virBufferAdd(buf, vap->varName, -1);
+ switch (vap->accessType) {
+ case VIR_NWFILTER_VAR_ACCESS_ELEMENT:
+ virBufferAsprintf(buf, "[%u]", vap->u.index);
+ break;
+ case VIR_NWFILTER_VAR_ACCESS_ITERATOR:
+ if (vap->u.iterId != 0)
+ virBufferAsprintf(buf, "[@%u]", vap->u.iterId);
+ break;
+ case VIR_NWFILTER_VAR_ACCESS_LAST:
+ break;
+ }
+}
+
+const char *
+virNWFilterVarAccessGetVarName(const virNWFilterVarAccessPtr vap)
+{
+ return vap->varName;
+}
+
+enum virNWFilterVarAccessType
+virNWFilterVarAccessGetType(const virNWFilterVarAccessPtr vap)
+{
+ return vap->accessType;
+}
+
+unsigned int
+virNWFilterVarAccessGetIterId(const virNWFilterVarAccessPtr vap)
+{
+ return vap->u.iterId;
+}
Index: libvirt-iterator/src/conf/nwfilter_params.h
===================================================================
--- libvirt-iterator.orig/src/conf/nwfilter_params.h
+++ libvirt-iterator/src/conf/nwfilter_params.h
@@ -91,6 +91,38 @@ int virNWFilterHashTablePutAll(virNWFilt
# define VALID_VARVALUE \
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.:"
+enum virNWFilterVarAccessType {
+ VIR_NWFILTER_VAR_ACCESS_ELEMENT = 0,
+ VIR_NWFILTER_VAR_ACCESS_ITERATOR = 1,
+
+ VIR_NWFILTER_VAR_ACCESS_LAST,
+};
+
+typedef struct _virNWFilterVarAccess virNWFilterVarAccess;
+typedef virNWFilterVarAccess *virNWFilterVarAccessPtr;
+struct _virNWFilterVarAccess {
+ enum virNWFilterVarAccessType accessType;
+ union {
+ unsigned int index;
+ unsigned int iterId;
+ } u;
+ char *varName;
+};
+
+# define VIR_NWFILTER_MAX_ITERID 1000
+
+void virNWFilterVarAccessFree(virNWFilterVarAccessPtr varAccess);
+bool virNWFilterVarAccessEqual(const virNWFilterVarAccessPtr a,
+ const virNWFilterVarAccessPtr b);
+virNWFilterVarAccessPtr virNWFilterVarAccessParse(const char *varAccess);
+void virNWFilterVarAccessPrint(virNWFilterVarAccessPtr vap,
+ virBufferPtr buf);
+const char *virNWFilterVarAccessGetVarName(const virNWFilterVarAccessPtr vap);
+enum virNWFilterVarAccessType virNWFilterVarAccessGetType(
+ const virNWFilterVarAccessPtr vap);
+unsigned int virNWFilterVarAccessGetIterId(const virNWFilterVarAccessPtr vap);
+
+
typedef struct _virNWFilterVarCombIterEntry virNWFilterVarCombIterEntry;
typedef virNWFilterVarCombIterEntry *virNWFilterVarCombIterEntryPtr;
struct _virNWFilterVarCombIterEntry {
@@ -110,12 +142,14 @@ struct _virNWFilterVarCombIter {
};
virNWFilterVarCombIterPtr virNWFilterVarCombIterCreate(
virNWFilterHashTablePtr hash,
- char * const *vars, unsigned int nVars);
+ const virNWFilterVarAccessPtr *vars,
+ size_t nVars);
void virNWFilterVarCombIterFree(virNWFilterVarCombIterPtr ci);
virNWFilterVarCombIterPtr virNWFilterVarCombIterNext(
virNWFilterVarCombIterPtr ci);
const char *virNWFilterVarCombIterGetVarValue(virNWFilterVarCombIterPtr ci,
- const char *varname);
+ const virNWFilterVarAccessPtr);
+
#endif /* NWFILTER_PARAMS_H */
Index: libvirt-iterator/src/libvirt_private.syms
===================================================================
--- libvirt-iterator.orig/src/libvirt_private.syms
+++ libvirt-iterator/src/libvirt_private.syms
@@ -832,6 +832,7 @@ virNWFilterHashTableFree;
virNWFilterHashTablePut;
virNWFilterHashTablePutAll;
virNWFilterHashTableRemoveEntry;
+virNWFilterVarAccessGetVarName;
virNWFilterVarCombIterCreate;
virNWFilterVarCombIterFree;
virNWFilterVarCombIterGetVarValue;
Index: libvirt-iterator/src/nwfilter/nwfilter_ebiptables_driver.c
===================================================================
--- libvirt-iterator.orig/src/nwfilter/nwfilter_ebiptables_driver.c
+++ libvirt-iterator/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -230,17 +230,19 @@ printVar(virNWFilterVarCombIterPtr vars,
if ((item->flags & NWFILTER_ENTRY_ITEM_FLAG_HAS_VAR)) {
const char *val;
- val = virNWFilterVarCombIterGetVarValue(vars, item->var);
+ val = virNWFilterVarCombIterGetVarValue(vars, item->varAccess);
if (!val) {
/* error has been reported */
return -1;
}
if (!virStrcpy(buf, val, bufsize)) {
+ const char *varName;
+
+ varName = virNWFilterVarAccessGetVarName(item->varAccess);
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
- _("Buffer too small to print MAC address "
- "'%s' into"),
- item->var);
+ _("Buffer too small to print variable "
+ "'%s' into"), varName);
return -1;
}
@@ -2631,7 +2633,8 @@ ebiptablesCreateRuleInstanceIterate(
* iterate over all combinations of the variables' values and instantiate
* the filtering rule with each combination.
*/
- vciter = virNWFilterVarCombIterCreate(vars, rule->vars, rule->nvars);
+ vciter = virNWFilterVarCombIterCreate(vars,
+ rule->varAccess, rule->nVarAccess);
if (!vciter)
return -1;
Index: libvirt-iterator/src/nwfilter/nwfilter_gentech_driver.c
===================================================================
--- libvirt-iterator.orig/src/nwfilter/nwfilter_gentech_driver.c
+++ libvirt-iterator/src/nwfilter/nwfilter_gentech_driver.c
@@ -500,14 +500,16 @@ virNWFilterDetermineMissingVarsRec(virNW
virNWFilterIncludeDefPtr inc = filter->filterEntries[i]->include;
if (rule) {
/* check all variables of this rule */
- for (j = 0; j < rule->nvars; j++) {
- if (!virHashLookup(vars->hashTable, rule->vars[j])) {
+ for (j = 0; j < rule->nVarAccess; j++) {
+ const char *varName;
+ varName = virNWFilterVarAccessGetVarName(rule->varAccess[j]);
+ if (!virHashLookup(vars->hashTable, varName)) {
val = virNWFilterVarValueCreateSimpleCopyValue("1");
if (!val) {
rc = -1;
break;
}
- virNWFilterHashTablePut(missing_vars, rule->vars[j],
+ virNWFilterHashTablePut(missing_vars, varName,
val, 1);
}
}
Index: libvirt-iterator/docs/schemas/nwfilter.rng
===================================================================
--- libvirt-iterator.orig/docs/schemas/nwfilter.rng
+++ libvirt-iterator/docs/schemas/nwfilter.rng
@@ -811,12 +811,15 @@
</choice>
</define>
+ <define name="variable-name-type">
+ <data type="string">
+ <param name="pattern">$[a-zA-Z0-9_]+(\[[ ]*[@]?[0-9]+[
]*\])?</param>
+ </data>
+ </define>
+
<define name="addrMAC">
<choice>
- <!-- variable -->
- <data type="string">
- <param name="pattern">$[a-zA-Z0-9_]+</param>
- </data>
+ <ref name="variable-name-type"/>
<data type="string">
<param
name="pattern">([a-fA-F0-9]{1,2}:){5}[a-fA-F0-9]{1,2}</param>
@@ -826,10 +829,7 @@
<define name="addrIP">
<choice>
- <!-- variable -->
- <data type="string">
- <param name="pattern">$[a-zA-Z0-9_]+</param>
- </data>
+ <ref name="variable-name-type"/>
<data type="string">
<param
name="pattern">([0-2]?[0-9]?[0-9]\.){3}[0-2]?[0-9]?[0-9]</param>
@@ -839,10 +839,7 @@
<define name="addrIPv6">
<choice>
- <!-- variable -->
- <data type="string">
- <param name="pattern">$[a-zA-Z0-9_]+</param>
- </data>
+ <ref name="variable-name-type"/>
<data type="string">
<param
name="pattern">([a-fA-F0-9]{0,4}:){2,7}([a-fA-F0-9]*)(([0-2]?[0-9]?[0-9]\.){3}[0-2]?[0-9]?[0-9])?</param>
@@ -852,10 +849,7 @@
<define name="addrMask">
<choice>
- <!-- variable -->
- <data type="string">
- <param name="pattern">$[a-zA-Z0-9_]+</param>
- </data>
+ <ref name="variable-name-type"/>
<data type="int">
<param name="minInclusive">0</param>
@@ -870,10 +864,7 @@
<define name="addrMaskv6">
<choice>
- <!-- variable -->
- <data type="string">
- <param name="pattern">$[a-zA-Z0-9_]+</param>
- </data>
+ <ref name="variable-name-type"/>
<data type="int">
<param name="minInclusive">0</param>
@@ -892,10 +883,7 @@
<param
name="pattern">0x([0-3][0-9a-fA-F]|[0-9a-fA-F])</param>
</data>
- <!-- variable -->
- <data type="string">
- <param name="pattern">$[a-zA-Z0-9_]+</param>
- </data>
+ <ref name="variable-name-type"/>
<data type="int">
<param name="minInclusive">0</param>
@@ -906,10 +894,7 @@
<define name="mac-protocolid">
<choice>
- <!-- variable -->
- <data type="string">
- <param name="pattern">$[a-zA-Z0-9_]+</param>
- </data>
+ <ref name="variable-name-type"/>
<data type="string">
<param
name="pattern">0x([6-9a-fA-F][0-9a-fA-F]{2}|[0-9a-fA-F]{4})</param>
@@ -932,10 +917,7 @@
<define name="vlan-vlanid">
<choice>
- <!-- variable -->
- <data type="string">
- <param name="pattern">$[a-zA-Z0-9_]+</param>
- </data>
+ <ref name="variable-name-type"/>
<data type="string">
<param name="pattern">0x([0-9a-fA-F]{1,3})</param>
@@ -950,10 +932,7 @@
<define name="uint8range">
<choice>
- <!-- variable -->
- <data type="string">
- <param name="pattern">$[a-zA-Z0-9_]+</param>
- </data>
+ <ref name="variable-name-type"/>
<data type="string">
<param name="pattern">0x[0-9a-fA-F]{1,2}</param>
@@ -968,10 +947,7 @@
<define name="uint16range">
<choice>
- <!-- variable -->
- <data type="string">
- <param name="pattern">$[a-zA-Z0-9_]+</param>
- </data>
+ <ref name="variable-name-type"/>
<data type="string">
<param name="pattern">0x[0-9a-fA-F]{1,4}</param>
@@ -986,10 +962,7 @@
<define name="uint32range">
<choice>
- <!-- variable -->
- <data type="string">
- <param name="pattern">$[a-zA-Z0-9_]+</param>
- </data>
+ <ref name="variable-name-type"/>
<data type="string">
<param name="pattern">0x[0-9a-fA-F]{1,8}</param>
@@ -1015,10 +988,7 @@
<define name="arpOpcodeType">
<choice>
- <!-- variable -->
- <data type="string">
- <param name="pattern">$[a-zA-Z0-9_]+</param>
- </data>
+ <ref name="variable-name-type"/>
<data type="int">
<param name="minInclusive">0</param>
@@ -1034,10 +1004,7 @@
<define name="ipProtocolType">
<choice>
- <!-- variable -->
- <data type="string">
- <param name="pattern">$[a-zA-Z0-9_]+</param>
- </data>
+ <ref name="variable-name-type"/>
<data type="string">
<param name="pattern">0x[0-9a-fA-F]{1,2}</param>