summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd.netdev.xml28
-rw-r--r--src/network/netdev/netdev-gperf.gperf5
-rw-r--r--src/network/netdev/tunnel.c170
-rw-r--r--src/network/netdev/tunnel.h10
-rw-r--r--test/fuzz/fuzz-netdev-parser/directives.netdev3
5 files changed, 207 insertions, 9 deletions
diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index 3a776b3f42..0855cf17a8 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -1370,11 +1370,33 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><varname>ERSPANVersion=</varname></term>
+ <listitem>
+ <para>Specifies the ERSPAN version number. Takes 0 for version 0 (a.k.a. type I), 1 for version 1
+ (a.k.a. type II), or 2 for version 2 (a.k.a. type III). Defaults to 1.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>ERSPANIndex=</varname></term>
<listitem>
- <para>Specifies the ERSPAN index field for the interface, an integer in the range 1…1048575 associated with
- the ERSPAN traffic's source port and direction. This field is mandatory.
- </para>
+ <para>Specifies the ERSPAN v1 index field for the interface. Takes an integer in the range
+ 0…1048575, which is associated with the ERSPAN traffic's source port and direction. Only used when
+ <varname>ERSPANVersion=1</varname>. Defaults to 0.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>ERSPANDirection=</varname></term>
+ <listitem>
+ <para>Specifies the ERSPAN v2 mirrored traffic's direction. Takes <literal>ingress</literal> or
+ <literal>egress</literal>. Only used when <varname>ERSPANVersion=2</varname>. Defaults to
+ <literal>ingress</literal>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>ERSPANHardwareId=</varname></term>
+ <listitem>
+ <para>Specifies an unique identifier of the ERSPAN v2 engine. Takes an integer in the range 0…63.
+ Only used when <varname>ERSPANVersion=2</varname>. Defaults to 0.</para>
</listitem>
</varlistentry>
</variablelist>
diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf
index 77140be400..55ad60ddc8 100644
--- a/src/network/netdev/netdev-gperf.gperf
+++ b/src/network/netdev/netdev-gperf.gperf
@@ -89,7 +89,10 @@ Tunnel.FOUDestinationPort, config_parse_ip_port,
Tunnel.FOUSourcePort, config_parse_ip_port, 0, offsetof(Tunnel, encap_src_port)
Tunnel.Encapsulation, config_parse_fou_encap_type, 0, offsetof(Tunnel, fou_encap_type)
Tunnel.IPv6RapidDeploymentPrefix, config_parse_6rd_prefix, 0, 0
-Tunnel.ERSPANIndex, config_parse_uint32, 0, offsetof(Tunnel, erspan_index)
+Tunnel.ERSPANVersion, config_parse_erspan_version, 0, offsetof(Tunnel, erspan_version)
+Tunnel.ERSPANIndex, config_parse_erspan_index, 0, offsetof(Tunnel, erspan_index)
+Tunnel.ERSPANDirection, config_parse_erspan_direction, 0, offsetof(Tunnel, erspan_direction)
+Tunnel.ERSPANHardwareId, config_parse_erspan_hwid, 0, offsetof(Tunnel, erspan_hwid)
Tunnel.SerializeTunneledPackets, config_parse_tristate, 0, offsetof(Tunnel, gre_erspan_sequence)
Tunnel.ISATAP, config_parse_tristate, 0, offsetof(Tunnel, isatap)
Tunnel.External, config_parse_bool, 0, offsetof(Tunnel, external)
diff --git a/src/network/netdev/tunnel.c b/src/network/netdev/tunnel.c
index 747acb1e80..78a8708b21 100644
--- a/src/network/netdev/tunnel.c
+++ b/src/network/netdev/tunnel.c
@@ -335,9 +335,24 @@ static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_
}
if (netdev->kind == NETDEV_KIND_ERSPAN) {
- r = sd_netlink_message_append_u32(m, IFLA_GRE_ERSPAN_INDEX, t->erspan_index);
+ r = sd_netlink_message_append_u8(m, IFLA_GRE_ERSPAN_VER, t->erspan_version);
if (r < 0)
return r;
+
+ if (t->erspan_version == 1) {
+ r = sd_netlink_message_append_u32(m, IFLA_GRE_ERSPAN_INDEX, t->erspan_index);
+ if (r < 0)
+ return r;
+
+ } else if (t->erspan_version == 2) {
+ r = sd_netlink_message_append_u8(m, IFLA_GRE_ERSPAN_DIR, t->erspan_direction);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_append_u16(m, IFLA_GRE_ERSPAN_HWID, t->erspan_hwid);
+ if (r < 0)
+ return r;
+ }
}
r = tunnel_get_local_address(t, link, &local);
@@ -720,9 +735,6 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"FooOverUDP missing port configured in %s. Ignoring", filename);
- if (netdev->kind == NETDEV_KIND_ERSPAN && (t->erspan_index >= (1 << 20) || t->erspan_index == 0))
- return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Invalid erspan index %d. Ignoring", t->erspan_index);
-
/* netlink_message_append_in_addr_union() is used for vti/vti6. So, t->family cannot be AF_UNSPEC. */
if (netdev->kind == NETDEV_KIND_VTI)
t->family = AF_INET;
@@ -1021,6 +1033,155 @@ int config_parse_6rd_prefix(
return 0;
}
+int config_parse_erspan_version(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ uint8_t n, *v = ASSERT_PTR(data);
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ *v = 1; /* defaults to 1 */
+ return 0;
+ }
+
+ r = safe_atou8(rvalue, &n);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse erspan version \"%s\", ignoring: %m", rvalue);
+ return 0;
+ }
+ if (!IN_SET(n, 0, 1, 2)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid erspan version \"%s\", which must be 0, 1 or 2, ignoring.", rvalue);
+ return 0;
+ }
+
+ *v = n;
+ return 0;
+}
+
+int config_parse_erspan_index(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ uint32_t n, *v = ASSERT_PTR(data);
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ *v = 0; /* defaults to 0 */
+ return 0;
+ }
+
+ r = safe_atou32(rvalue, &n);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse erspan index \"%s\", ignoring: %m", rvalue);
+ return 0;
+ }
+ if (n >= 0x100000) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid erspan index \"%s\", which must be less than 0x100000, ignoring.", rvalue);
+ return 0;
+ }
+
+ *v = n;
+ return 0;
+}
+
+int config_parse_erspan_direction(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ uint8_t *v = ASSERT_PTR(data);
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue) || streq(rvalue, "ingress"))
+ *v = 0; /* defaults to ingress */
+ else if (streq(rvalue, "egress"))
+ *v = 1;
+ else
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid erspan direction \"%s\", which must be \"ingress\" or \"egress\", ignoring.", rvalue);
+
+ return 0;
+}
+
+int config_parse_erspan_hwid(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ uint16_t n, *v = ASSERT_PTR(data);
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ *v = 0; /* defaults to 0 */
+ return 0;
+ }
+
+ r = safe_atou16(rvalue, &n);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse erspan hwid \"%s\", ignoring: %m", rvalue);
+ return 0;
+ }
+ if (n >= 64) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid erspan index \"%s\", which must be less than 64, ignoring.", rvalue);
+ return 0;
+ }
+
+ *v = n;
+ return 0;
+}
+
static void netdev_tunnel_init(NetDev *netdev) {
Tunnel *t;
@@ -1039,6 +1200,7 @@ static void netdev_tunnel_init(NetDev *netdev) {
t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID;
t->allow_localremote = -1;
+ t->erspan_version = 1;
if (IN_SET(netdev->kind, NETDEV_KIND_IP6GRE, NETDEV_KIND_IP6GRETAP, NETDEV_KIND_IP6TNL))
t->ttl = DEFAULT_IPV6_TTL;
diff --git a/src/network/netdev/tunnel.h b/src/network/netdev/tunnel.h
index e25dfb215a..7c81f22391 100644
--- a/src/network/netdev/tunnel.h
+++ b/src/network/netdev/tunnel.h
@@ -41,7 +41,11 @@ typedef struct Tunnel {
uint32_t key;
uint32_t ikey;
uint32_t okey;
- uint32_t erspan_index;
+
+ uint8_t erspan_version;
+ uint32_t erspan_index; /* version 1 */
+ uint8_t erspan_direction; /* version 2 */
+ uint16_t erspan_hwid; /* version 2 */
NetDevLocalAddressType local_type;
union in_addr_union local;
@@ -128,3 +132,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_flowlabel);
CONFIG_PARSER_PROTOTYPE(config_parse_encap_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_tunnel_key);
CONFIG_PARSER_PROTOTYPE(config_parse_6rd_prefix);
+CONFIG_PARSER_PROTOTYPE(config_parse_erspan_version);
+CONFIG_PARSER_PROTOTYPE(config_parse_erspan_index);
+CONFIG_PARSER_PROTOTYPE(config_parse_erspan_direction);
+CONFIG_PARSER_PROTOTYPE(config_parse_erspan_hwid);
diff --git a/test/fuzz/fuzz-netdev-parser/directives.netdev b/test/fuzz/fuzz-netdev-parser/directives.netdev
index d6c2e18464..d97f81512b 100644
--- a/test/fuzz/fuzz-netdev-parser/directives.netdev
+++ b/test/fuzz/fuzz-netdev-parser/directives.netdev
@@ -92,7 +92,10 @@ EncapsulationLimit=
TTL=
FOUSourcePort=
IPv6RapidDeploymentPrefix=
+ERSPANVersion=
ERSPANIndex=
+ERSPANDirection=
+ERSPANHardwareId=
SerializeTunneledPackets=
ISATAP=
External=