diff --git a/docs/schemas/nwfilter.rng b/docs/schemas/nwfilter.rng
index 5fd4860b26..6a9c7bc108 100644
--- a/docs/schemas/nwfilter.rng
+++ b/docs/schemas/nwfilter.rng
@@ -38,6 +38,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -299,6 +309,9 @@
mac[a-zA-Z0-9_\.:-]{0,9}
+
+ stp[a-zA-Z0-9_\.:-]{0,9}
+
vlan[a-zA-Z0-9_\.:-]{0,8}
@@ -382,7 +395,7 @@
-
+
@@ -390,6 +403,12 @@
+
+
+
+
+
+
@@ -588,6 +607,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -852,6 +984,24 @@
+
+
+
+
+ $[a-zA-Z0-9_]+
+
+
+
+ 0x[0-9a-fA-F]{1,8}
+
+
+
+ 0
+ 4294967295
+
+
+
+
yes
diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c
index 1321f8b1c0..9a97dae776 100644
--- a/src/conf/nwfilter_conf.c
+++ b/src/conf/nwfilter_conf.c
@@ -84,6 +84,7 @@ VIR_ENUM_IMPL(virNWFilterChainSuffix, VIR_NWFILTER_CHAINSUFFIX_LAST,
"root",
"mac",
"vlan",
+ "stp",
"arp",
"rarp",
"ipv4",
@@ -93,6 +94,7 @@ VIR_ENUM_IMPL(virNWFilterRuleProtocol, VIR_NWFILTER_RULE_PROTOCOL_LAST,
"none",
"mac",
"vlan",
+ "stp",
"arp",
"rarp",
"ip",
@@ -1047,6 +1049,138 @@ static const virXMLAttr2Struct vlanAttributes[] = {
}
};
+/* STP is documented by IEEE 802.1D; for a synopsis,
+ * see http://www.javvin.com/protocolSTP.html */
+static const virXMLAttr2Struct stpAttributes[] = {
+ /* spanning tree uses a special destination MAC address */
+ {
+ .name = SRCMACADDR,
+ .datatype = DATATYPE_MACADDR,
+ .dataIdx = offsetof(virNWFilterRuleDef,
+ p.stpHdrFilter.ethHdr.dataSrcMACAddr),
+ },
+ {
+ .name = SRCMACMASK,
+ .datatype = DATATYPE_MACMASK,
+ .dataIdx = offsetof(virNWFilterRuleDef,
+ p.stpHdrFilter.ethHdr.dataSrcMACMask),
+ },
+ {
+ .name = "type",
+ .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataType),
+ },
+ {
+ .name = "flags",
+ .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataFlags),
+ },
+ {
+ .name = "root-priority",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataRootPri),
+ },
+ {
+ .name = "root-priority-hi",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataRootPriHi),
+ },
+ {
+ .name = "root-address",
+ .datatype = DATATYPE_MACADDR,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataRootAddr),
+ },
+ {
+ .name = "root-address-mask",
+ .datatype = DATATYPE_MACMASK,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataRootAddrMask),
+ },
+ {
+ .name = "root-cost",
+ .datatype = DATATYPE_UINT32 | DATATYPE_UINT32_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataRootCost),
+ },
+ {
+ .name = "root-cost-hi",
+ .datatype = DATATYPE_UINT32 | DATATYPE_UINT32_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataRootCostHi),
+ },
+ {
+ .name = "sender-priority",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataSndrPrio),
+ },
+ {
+ .name = "sender-priority-hi",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataSndrPrioHi),
+ },
+ {
+ .name = "sender-address",
+ .datatype = DATATYPE_MACADDR,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataSndrAddr),
+ },
+ {
+ .name = "sender-address-mask",
+ .datatype = DATATYPE_MACMASK,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataSndrAddrMask),
+ },
+ {
+ .name = "port",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataPort),
+ },
+ {
+ .name = "port-hi",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataPortHi),
+ },
+ {
+ .name = "age",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataAge),
+ },
+ {
+ .name = "age-hi",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataAgeHi),
+ },
+ {
+ .name = "max-age",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataMaxAge),
+ },
+ {
+ .name = "max-age-hi",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataMaxAgeHi),
+ },
+ {
+ .name = "hello-time",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataHelloTime),
+ },
+ {
+ .name = "hello-time-hi",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataHelloTimeHi),
+ },
+ {
+ .name = "forward-delay",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataFwdDelay),
+ },
+ {
+ .name = "forward-delay-hi",
+ .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.stpHdrFilter.dataFwdDelayHi),
+ },
+ COMMENT_PROP(stpHdrFilter),
+ {
+ .name = NULL,
+ }
+};
+
static const virXMLAttr2Struct arpAttributes[] = {
COMMON_MAC_PROPS(arpHdrFilter),
{
@@ -1505,6 +1639,7 @@ static const virAttributes virAttr[] = {
PROTOCOL_ENTRY("rarp" , arpAttributes , VIR_NWFILTER_RULE_PROTOCOL_RARP),
PROTOCOL_ENTRY("mac" , macAttributes , VIR_NWFILTER_RULE_PROTOCOL_MAC),
PROTOCOL_ENTRY("vlan" , vlanAttributes , VIR_NWFILTER_RULE_PROTOCOL_VLAN),
+ PROTOCOL_ENTRY("stp" , stpAttributes , VIR_NWFILTER_RULE_PROTOCOL_STP),
PROTOCOL_ENTRY("ip" , ipAttributes , VIR_NWFILTER_RULE_PROTOCOL_IP),
PROTOCOL_ENTRY("ipv6" , ipv6Attributes , VIR_NWFILTER_RULE_PROTOCOL_IPV6),
PROTOCOL_ENTRY("tcp" , tcpAttributes , VIR_NWFILTER_RULE_PROTOCOL_TCP),
@@ -1628,6 +1763,18 @@ virNWFilterRuleDetailsParse(xmlNodePtr node,
rc = -1;
break;
+ case DATATYPE_UINT32_HEX:
+ base = 16;
+ /* fallthrough */
+ case DATATYPE_UINT32:
+ if (virStrToLong_ui(prop, NULL, base, &uint_val) >= 0) {
+ item->u.u32 = uint_val;
+ found = 1;
+ data.ui = uint_val;
+ } else
+ rc = -1;
+ break;
+
case DATATYPE_IPADDR:
if (virSocketAddrParseIPv4(&item->u.ipaddr, prop) < 0)
rc = -1;
@@ -1839,6 +1986,31 @@ virNWFilterRuleDefFixup(virNWFilterRuleDefPtr rule)
rule->p.vlanHdrFilter.ethHdr.dataDstMACAddr);
break;
+ case VIR_NWFILTER_RULE_PROTOCOL_STP:
+ COPY_NEG_SIGN(rule->p.stpHdrFilter.ethHdr.dataSrcMACMask,
+ rule->p.stpHdrFilter.ethHdr.dataSrcMACAddr);
+ COPY_NEG_SIGN(rule->p.stpHdrFilter.dataRootPriHi,
+ rule->p.stpHdrFilter.dataRootPri);
+ COPY_NEG_SIGN(rule->p.stpHdrFilter.dataRootAddrMask,
+ rule->p.stpHdrFilter.dataRootAddr);
+ COPY_NEG_SIGN(rule->p.stpHdrFilter.dataRootCostHi,
+ rule->p.stpHdrFilter.dataRootCost);
+ COPY_NEG_SIGN(rule->p.stpHdrFilter.dataSndrPrioHi,
+ rule->p.stpHdrFilter.dataSndrPrio);
+ COPY_NEG_SIGN(rule->p.stpHdrFilter.dataSndrAddrMask,
+ rule->p.stpHdrFilter.dataSndrAddr);
+ COPY_NEG_SIGN(rule->p.stpHdrFilter.dataPortHi,
+ rule->p.stpHdrFilter.dataPort);
+ COPY_NEG_SIGN(rule->p.stpHdrFilter.dataAgeHi,
+ rule->p.stpHdrFilter.dataAge);
+ COPY_NEG_SIGN(rule->p.stpHdrFilter.dataMaxAgeHi,
+ rule->p.stpHdrFilter.dataMaxAge);
+ COPY_NEG_SIGN(rule->p.stpHdrFilter.dataHelloTimeHi,
+ rule->p.stpHdrFilter.dataHelloTime);
+ COPY_NEG_SIGN(rule->p.stpHdrFilter.dataFwdDelayHi,
+ rule->p.stpHdrFilter.dataFwdDelay);
+ break;
+
case VIR_NWFILTER_RULE_PROTOCOL_IP:
COPY_NEG_SIGN(rule->p.ipHdrFilter.ipHdr.dataSrcIPMask,
rule->p.ipHdrFilter.ipHdr.dataSrcIPAddr);
@@ -2921,6 +3093,14 @@ virNWFilterRuleDefDetailsFormat(virBufferPtr buf,
item->u.u16);
break;
+ case DATATYPE_UINT32_HEX:
+ asHex = true;
+ /* fallthrough */
+ case DATATYPE_UINT32:
+ virBufferAsprintf(buf, asHex ? "0x%x" : "%u",
+ item->u.u32);
+ break;
+
case DATATYPE_IPADDR:
case DATATYPE_IPV6ADDR:
virNWIPAddressFormat(buf,
diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
index a7e7a13dc2..61923aa5a4 100644
--- a/src/conf/nwfilter_conf.h
+++ b/src/conf/nwfilter_conf.h
@@ -101,10 +101,14 @@ enum attrDatatype {
DATATYPE_IPV6MASK = (1 << 10),
DATATYPE_STRINGCOPY = (1 << 11),
DATATYPE_BOOLEAN = (1 << 12),
+ DATATYPE_UINT32 = (1 << 13),
+ DATATYPE_UINT32_HEX = (1 << 14),
- DATATYPE_LAST = (1 << 13),
+ DATATYPE_LAST = (1 << 15),
};
+# define NWFILTER_MAC_BGA "01:80:c2:00:00:00"
+
typedef struct _nwMACAddress nwMACAddress;
typedef nwMACAddress *nwMACAddressPtr;
@@ -125,6 +129,7 @@ struct _nwItemDesc {
bool boolean;
uint8_t u8;
uint16_t u16;
+ uint32_t u32;
char protocolID[10];
char *string;
struct {
@@ -164,6 +169,36 @@ struct _vlanHdrFilterDef {
};
+typedef struct _stpHdrFilterDef stpHdrFilterDef;
+typedef stpHdrFilterDef *stpHdrFilterDefPtr;
+struct _stpHdrFilterDef {
+ ethHdrDataDef ethHdr;
+ nwItemDesc dataType;
+ nwItemDesc dataFlags;
+ nwItemDesc dataRootPri;
+ nwItemDesc dataRootPriHi;
+ nwItemDesc dataRootAddr;
+ nwItemDesc dataRootAddrMask;
+ nwItemDesc dataRootCost;
+ nwItemDesc dataRootCostHi;
+ nwItemDesc dataSndrPrio;
+ nwItemDesc dataSndrPrioHi;
+ nwItemDesc dataSndrAddr;
+ nwItemDesc dataSndrAddrMask;
+ nwItemDesc dataPort;
+ nwItemDesc dataPortHi;
+ nwItemDesc dataAge;
+ nwItemDesc dataAgeHi;
+ nwItemDesc dataMaxAge;
+ nwItemDesc dataMaxAgeHi;
+ nwItemDesc dataHelloTime;
+ nwItemDesc dataHelloTimeHi;
+ nwItemDesc dataFwdDelay;
+ nwItemDesc dataFwdDelayHi;
+ nwItemDesc dataComment;
+};
+
+
typedef struct _arpHdrFilterDef arpHdrFilterDef;
typedef arpHdrFilterDef *arpHdrFilterDefPtr;
struct _arpHdrFilterDef {
@@ -337,6 +372,7 @@ enum virNWFilterRuleProtocolType {
VIR_NWFILTER_RULE_PROTOCOL_NONE = 0,
VIR_NWFILTER_RULE_PROTOCOL_MAC,
VIR_NWFILTER_RULE_PROTOCOL_VLAN,
+ VIR_NWFILTER_RULE_PROTOCOL_STP,
VIR_NWFILTER_RULE_PROTOCOL_ARP,
VIR_NWFILTER_RULE_PROTOCOL_RARP,
VIR_NWFILTER_RULE_PROTOCOL_IP,
@@ -378,6 +414,7 @@ enum virNWFilterEbtablesTableType {
# define NWFILTER_MAX_FILTER_PRIORITY MAX_RULE_PRIORITY
# define NWFILTER_ROOT_FILTER_PRI 0
+# define NWFILTER_STP_FILTER_PRI -810
# define NWFILTER_MAC_FILTER_PRI -800
# define NWFILTER_VLAN_FILTER_PRI -750
# define NWFILTER_IPV4_FILTER_PRI -700
@@ -418,6 +455,7 @@ struct _virNWFilterRuleDef {
union {
ethHdrFilterDef ethHdrFilter;
vlanHdrFilterDef vlanHdrFilter;
+ stpHdrFilterDef stpHdrFilter;
arpHdrFilterDef arpHdrFilter; /* also used for rarp */
ipHdrFilterDef ipHdrFilter;
ipv6HdrFilterDef ipv6HdrFilter;
@@ -459,6 +497,7 @@ enum virNWFilterChainSuffixType {
VIR_NWFILTER_CHAINSUFFIX_ROOT = 0,
VIR_NWFILTER_CHAINSUFFIX_MAC,
VIR_NWFILTER_CHAINSUFFIX_VLAN,
+ VIR_NWFILTER_CHAINSUFFIX_STP,
VIR_NWFILTER_CHAINSUFFIX_ARP,
VIR_NWFILTER_CHAINSUFFIX_RARP,
VIR_NWFILTER_CHAINSUFFIX_IPv4,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 2cf50d30b0..1c64311e55 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -830,6 +830,7 @@ virNWFilterPrintStateMatchFlags;
virNWFilterPrintTCPFlags;
virNWFilterRegisterCallbackDriver;
virNWFilterRuleActionTypeToString;
+virNWFilterRuleDirectionTypeToString;
virNWFilterRuleProtocolTypeToString;
virNWFilterTestUnassignDef;
virNWFilterUnlockFilterUpdates;
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c
index 73b62f43e1..54f76562ad 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -41,6 +41,7 @@
#include "virfile.h"
#include "command.h"
#include "configmake.h"
+#include "intprops.h"
#define VIR_FROM_THIS VIR_FROM_NWFILTER
@@ -190,6 +191,7 @@ enum l3_proto_idx {
L3_PROTO_RARP_IDX,
L2_PROTO_MAC_IDX,
L2_PROTO_VLAN_IDX,
+ L2_PROTO_STP_IDX,
L3_PROTO_LAST_IDX
};
@@ -206,6 +208,7 @@ static const struct ushort_map l3_protocols[] = {
USHORTMAP_ENTRY_IDX(L3_PROTO_ARP_IDX , ETHERTYPE_ARP , "arp"),
USHORTMAP_ENTRY_IDX(L3_PROTO_RARP_IDX, ETHERTYPE_REVARP, "rarp"),
USHORTMAP_ENTRY_IDX(L2_PROTO_VLAN_IDX, ETHERTYPE_VLAN , "vlan"),
+ USHORTMAP_ENTRY_IDX(L2_PROTO_STP_IDX, 0 , "stp"),
USHORTMAP_ENTRY_IDX(L2_PROTO_MAC_IDX, 0 , "mac"),
USHORTMAP_ENTRY_IDX(L3_PROTO_LAST_IDX, 0 , NULL),
};
@@ -306,6 +309,16 @@ _printDataType(virNWFilterVarCombIterPtr vars,
}
break;
+ case DATATYPE_UINT32:
+ case DATATYPE_UINT32_HEX:
+ if (snprintf(buf, bufsize, asHex ? "0x%x" : "%u",
+ item->u.u32) >= bufsize) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Buffer too small for uint32 type"));
+ return 1;
+ }
+ break;
+
case DATATYPE_UINT16:
case DATATYPE_UINT16_HEX:
if (snprintf(buf, bufsize, asHex ? "0x%x" : "%d",
@@ -937,7 +950,8 @@ iptablesHandleIpHdr(virBufferPtr buf,
virBufferPtr prefix)
{
char ipaddr[INET6_ADDRSTRLEN],
- number[20];
+ number[MAX(INT_BUFSIZE_BOUND(uint32_t),
+ INT_BUFSIZE_BOUND(int))];
const char *src = "--source";
const char *dst = "--destination";
const char *srcrange = "--src-range";
@@ -1218,7 +1232,8 @@ _iptablesCreateRuleInstance(int directionIn,
bool maySkipICMP)
{
char chain[MAX_CHAINNAME_LENGTH];
- char number[20];
+ char number[MAX(INT_BUFSIZE_BOUND(uint32_t),
+ INT_BUFSIZE_BOUND(int))];
virBuffer prefix = VIR_BUFFER_INITIALIZER;
virBuffer buf = VIR_BUFFER_INITIALIZER;
virBuffer afterStateMatch = VIR_BUFFER_INITIALIZER;
@@ -1953,7 +1968,9 @@ ebtablesCreateRuleInstance(char chainPrefix,
char macaddr[VIR_MAC_STRING_BUFLEN],
ipaddr[INET_ADDRSTRLEN],
ipv6addr[INET6_ADDRSTRLEN],
- number[20];
+ number[MAX(INT_BUFSIZE_BOUND(uint32_t),
+ INT_BUFSIZE_BOUND(int))],
+ field[MAX(VIR_MAC_STRING_BUFLEN, INET6_ADDRSTRLEN)];
char chain[MAX_CHAINNAME_LENGTH];
virBuffer buf = VIR_BUFFER_INITIALIZER;
const char *target;
@@ -2019,19 +2036,91 @@ ebtablesCreateRuleInstance(char chainPrefix,
#define INST_ITEM(STRUCT, ITEM, CLI) \
if (HAS_ENTRY_ITEM(&rule->p.STRUCT.ITEM)) { \
if (printDataType(vars, \
- number, sizeof(number), \
+ field, sizeof(field), \
&rule->p.STRUCT.ITEM)) \
goto err_exit; \
virBufferAsprintf(&buf, \
" " CLI " %s %s", \
ENTRY_GET_NEG_SIGN(&rule->p.STRUCT.ITEM), \
- number); \
+ field); \
}
+#define INST_ITEM_2PARMS(STRUCT, ITEM, ITEM_HI, CLI, SEP) \
+ if (HAS_ENTRY_ITEM(&rule->p.STRUCT.ITEM)) { \
+ if (printDataType(vars, \
+ field, sizeof(field), \
+ &rule->p.STRUCT.ITEM)) \
+ goto err_exit; \
+ virBufferAsprintf(&buf, \
+ " " CLI " %s %s", \
+ ENTRY_GET_NEG_SIGN(&rule->p.STRUCT.ITEM), \
+ field); \
+ if (HAS_ENTRY_ITEM(&rule->p.STRUCT.ITEM_HI)) { \
+ if (printDataType(vars, \
+ field, sizeof(field), \
+ &rule->p.STRUCT.ITEM_HI)) \
+ goto err_exit; \
+ virBufferAsprintf(&buf, SEP "%s", field); \
+ } \
+ }
+#define INST_ITEM_RANGE(S, I, I_HI, C) \
+ INST_ITEM_2PARMS(S, I, I_HI, C, ":")
+#define INST_ITEM_MASK(S, I, MASK, C) \
+ INST_ITEM_2PARMS(S, I, MASK, C, "/")
+
INST_ITEM(vlanHdrFilter, dataVlanID, "--vlan-id")
INST_ITEM(vlanHdrFilter, dataVlanEncap, "--vlan-encap")
break;
+ case VIR_NWFILTER_RULE_PROTOCOL_STP:
+
+ /* cannot handle inout direction with srcmask set in reverse dir.
+ since this clashes with -d below... */
+ if (reverse &&
+ HAS_ENTRY_ITEM(&rule->p.stpHdrFilter.ethHdr.dataSrcMACAddr)) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("STP filtering in %s direction with "
+ "source MAC address set is not supported"),
+ virNWFilterRuleDirectionTypeToString(
+ VIR_NWFILTER_RULE_DIRECTION_INOUT));
+ return -1;
+ }
+
+ virBufferAsprintf(&buf,
+ CMD_DEF_PRE "%s -t %s -%%c %s %%s",
+ ebtables_cmd_path, EBTABLES_DEFAULT_TABLE, chain);
+
+
+ if (ebtablesHandleEthHdr(&buf,
+ vars,
+ &rule->p.stpHdrFilter.ethHdr,
+ reverse))
+ goto err_exit;
+
+ virBufferAddLit(&buf, " -d " NWFILTER_MAC_BGA);
+
+ INST_ITEM(stpHdrFilter, dataType, "--stp-type")
+ INST_ITEM(stpHdrFilter, dataFlags, "--stp-flags")
+ INST_ITEM_RANGE(stpHdrFilter, dataRootPri, dataRootPriHi,
+ "--stp-root-pri");
+ INST_ITEM_MASK( stpHdrFilter, dataRootAddr, dataRootAddrMask,
+ "--stp-root-addr");
+ INST_ITEM_RANGE(stpHdrFilter, dataRootCost, dataRootCostHi,
+ "--stp-root-cost");
+ INST_ITEM_RANGE(stpHdrFilter, dataSndrPrio, dataSndrPrioHi,
+ "--stp-sender-prio");
+ INST_ITEM_MASK( stpHdrFilter, dataSndrAddr, dataSndrAddrMask,
+ "--stp-sender-addr");
+ INST_ITEM_RANGE(stpHdrFilter, dataPort, dataPortHi, "--stp-port");
+ INST_ITEM_RANGE(stpHdrFilter, dataAge, dataAgeHi, "--stp-msg-age");
+ INST_ITEM_RANGE(stpHdrFilter, dataMaxAge, dataMaxAgeHi,
+ "--stp-max-age");
+ INST_ITEM_RANGE(stpHdrFilter, dataHelloTime, dataHelloTimeHi,
+ "--stp-hello-time");
+ INST_ITEM_RANGE(stpHdrFilter, dataFwdDelay, dataFwdDelayHi,
+ "--stp-forward-delay");
+ break;
+
case VIR_NWFILTER_RULE_PROTOCOL_ARP:
case VIR_NWFILTER_RULE_PROTOCOL_RARP:
@@ -2480,6 +2569,7 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
case VIR_NWFILTER_RULE_PROTOCOL_IP:
case VIR_NWFILTER_RULE_PROTOCOL_MAC:
case VIR_NWFILTER_RULE_PROTOCOL_VLAN:
+ case VIR_NWFILTER_RULE_PROTOCOL_STP:
case VIR_NWFILTER_RULE_PROTOCOL_ARP:
case VIR_NWFILTER_RULE_PROTOCOL_RARP:
case VIR_NWFILTER_RULE_PROTOCOL_NONE:
@@ -2818,6 +2908,9 @@ ebtablesCreateTmpSubChain(ebiptablesRuleInstPtr *inst,
case L2_PROTO_MAC_IDX:
protostr = strdup("");
break;
+ case L2_PROTO_STP_IDX:
+ virAsprintf(&protostr, "-d " NWFILTER_MAC_BGA " ");
+ break;
default:
virAsprintf(&protostr, "-p 0x%04x ", l3_protocols[protoidx].attr);
break;