</element>
</zeroOrMore>
</optional>
+ <optional>
+ <zeroOrMore>
+ <element name="stp">
+ <ref name="match-attribute"/>
+ <ref name="srcmacandmask-attributes"/>
+ <ref name="stp-attributes"/>
+ <ref name="comment-attribute"/>
+ </element>
+ </zeroOrMore>
+ </optional>
<optional>
<zeroOrMore>
<element name="arp">
<data type="string">
<param name="pattern">mac[a-zA-Z0-9_\.:-]{0,9}</param>
</data>
+ <data type="string">
+ <param name="pattern">stp[a-zA-Z0-9_\.:-]{0,9}</param>
+ </data>
<data type="string">
<param name="pattern">vlan[a-zA-Z0-9_\.:-]{0,8}</param>
</data>
</interleave>
</define>
- <define name="common-l2-attributes">
+ <define name="srcmacandmask-attributes">
<interleave>
<ref name="srcmac-attribute"/>
<optional>
<ref name="addrMAC"/>
</attribute>
</optional>
+ </interleave>
+ </define>
+
+ <define name="common-l2-attributes">
+ <interleave>
+ <ref name="srcmacandmask-attributes"/>
<optional>
<attribute name="dstmacaddr">
<ref name="addrMAC"/>
</interleave>
</define>
+ <define name="stp-attributes">
+ <optional>
+ <attribute name="type">
+ <ref name="uint8range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="flags">
+ <ref name="uint8range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="root-priority">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="root-priority-hi">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="root-address">
+ <ref name="addrMAC"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="root-address-mask">
+ <ref name="addrMAC"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="root-cost">
+ <ref name="uint32range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="root-cost-hi">
+ <ref name="uint32range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="sender-priority">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="sender-priority-hi">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="sender-address">
+ <ref name="addrMAC"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="sender-address-mask">
+ <ref name="addrMAC"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="port">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="port-hi">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="age">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="age-hi">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="max-age">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="max-age-hi">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="hello-time">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="hello-time-hi">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="forward-delay">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="forward-delay-hi">
+ <ref name="uint16range"/>
+ </attribute>
+ </optional>
+ </define>
+
<define name="arp-attributes">
<interleave>
<optional>
</choice>
</define>
+ <define name="uint32range">
+ <choice>
+ <!-- variable -->
+ <data type="string">
+ <param name="pattern">$[a-zA-Z0-9_]+</param>
+ </data>
+
+ <data type="string">
+ <param name="pattern">0x[0-9a-fA-F]{1,8}</param>
+ </data>
+
+ <data type="int">
+ <param name="minInclusive">0</param>
+ <param name="maxInclusive">4294967295</param>
+ </data>
+ </choice>
+ </define>
+
<define name="boolean">
<choice>
<value>yes</value>
"root",
"mac",
"vlan",
+ "stp",
"arp",
"rarp",
"ipv4",
"none",
"mac",
"vlan",
+ "stp",
"arp",
"rarp",
"ip",
}
};
+/* 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),
{
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),
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;
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);
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,
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;
bool boolean;
uint8_t u8;
uint16_t u16;
+ uint32_t u32;
char protocolID[10];
char *string;
struct {
};
+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 {
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,
# 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
union {
ethHdrFilterDef ethHdrFilter;
vlanHdrFilterDef vlanHdrFilter;
+ stpHdrFilterDef stpHdrFilter;
arpHdrFilterDef arpHdrFilter; /* also used for rarp */
ipHdrFilterDef ipHdrFilter;
ipv6HdrFilterDef ipv6HdrFilter;
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,
virNWFilterPrintTCPFlags;
virNWFilterRegisterCallbackDriver;
virNWFilterRuleActionTypeToString;
+virNWFilterRuleDirectionTypeToString;
virNWFilterRuleProtocolTypeToString;
virNWFilterTestUnassignDef;
virNWFilterUnlockFilterUpdates;
#include "virfile.h"
#include "command.h"
#include "configmake.h"
+#include "intprops.h"
#define VIR_FROM_THIS VIR_FROM_NWFILTER
L3_PROTO_RARP_IDX,
L2_PROTO_MAC_IDX,
L2_PROTO_VLAN_IDX,
+ L2_PROTO_STP_IDX,
L3_PROTO_LAST_IDX
};
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),
};
}
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",
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";
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;
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;
#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), \
+ 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), \
- number); \
+ 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:
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:
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;