diff options
-rw-r--r-- | man/systemd.netdev.xml | 19 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-message.c | 13 | ||||
-rw-r--r-- | src/network/networkd-netdev-gperf.gperf | 2 | ||||
-rw-r--r-- | src/network/networkd-netdev-vxlan.c | 100 | ||||
-rw-r--r-- | src/network/networkd-netdev-vxlan.h | 25 | ||||
-rw-r--r-- | src/systemd/sd-netlink.h | 1 |
6 files changed, 160 insertions, 0 deletions
diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index 16e41e05b3..b697d0c9a6 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -493,6 +493,25 @@ VXLAN Group Policy </ulink> document. Defaults to false.</para> </listitem> </varlistentry> + <varlistentry> + <term><varname>DestinationPort=</varname></term> + <listitem> + <para>Configures the default destination UDP port on a per-device basis. + If destination port is not specified then Linux kernel default will be used. + Set destination port 4789 to get the IANA assigned value, + and destination port 0 to get default values.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><varname>PortRange=</varname></term> + <listitem> + <para>Configures VXLAN port range. VXLAN bases source + UDP port based on flow to help the receiver to be able + to load balance based on outer header flow. It + restricts the port range to the normal UDP local + ports, and allows overriding via configuration.</para> + </listitem> + </varlistentry> </variablelist> </refsect1> <refsect1> diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c index 50792bc4a3..b1b3bccc44 100644 --- a/src/libsystemd/sd-netlink/netlink-message.c +++ b/src/libsystemd/sd-netlink/netlink-message.c @@ -342,6 +342,19 @@ int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, ui return 0; } +int sd_netlink_message_append_data(sd_netlink_message *m, unsigned short type, const void *data, size_t len) { + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + + r = add_rtattr(m, type, &data, len); + if (r < 0) + return r; + + return 0; +} + int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data) { int r; diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf index 4a4b400e41..8f506af092 100644 --- a/src/network/networkd-netdev-gperf.gperf +++ b/src/network/networkd-netdev-gperf.gperf @@ -57,6 +57,8 @@ VXLAN.UDP6ZeroCheckSumTx, config_parse_bool, 0, VXLAN.FDBAgeingSec, config_parse_sec, 0, offsetof(VxLan, fdb_ageing) VXLAN.GroupPolicyExtension, config_parse_bool, 0, offsetof(VxLan, group_policy) VXLAN.MaximumFDBEntries, config_parse_unsigned, 0, offsetof(VxLan, max_fdb) +VXLAN.PortRange, config_parse_port_range, 0, 0 +VXLAN.DestinationPort, config_parse_destination_port, 0, offsetof(VxLan, dest_port) Tun.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue) Tun.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue) Tun.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info) diff --git a/src/network/networkd-netdev-vxlan.c b/src/network/networkd-netdev-vxlan.c index 7932b93335..531f2c300e 100644 --- a/src/network/networkd-netdev-vxlan.c +++ b/src/network/networkd-netdev-vxlan.c @@ -24,6 +24,8 @@ #include "sd-netlink.h" #include "conf-parser.h" +#include "alloc-util.h" +#include "parse-util.h" #include "missing.h" #include "networkd-link.h" #include "networkd-netdev-vxlan.h" @@ -110,6 +112,21 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netli if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX attribute: %m"); + r = sd_netlink_message_append_u16(m, IFLA_VXLAN_PORT, htobe16(v->dest_port)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PORT attribute: %m"); + + if (v->port_range.low || v->port_range.high) { + struct ifla_vxlan_port_range port_range; + + port_range.low = htobe16(v->port_range.low); + port_range.high = htobe16(v->port_range.high); + + r = sd_netlink_message_append_data(m, IFLA_VXLAN_PORT_RANGE, &port_range, sizeof(port_range)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PORT_RANGE attribute: %m"); + } + if (v->group_policy) { r = sd_netlink_message_append_flag(m, IFLA_VXLAN_GBP); if (r < 0) @@ -155,6 +172,89 @@ int config_parse_vxlan_group_address(const char *unit, return 0; } +int config_parse_port_range(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) { + _cleanup_free_ char *word = NULL; + VxLan *v = userdata; + unsigned low, high; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = extract_first_word(&rvalue, &word, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract VXLAN port range, ignoring: %s", rvalue); + return 0; + } + + if (r == 0) + return 0; + + r = parse_range(word, &low, &high); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN port range '%s'", word); + return 0; + } + + if (low <= 0 || low > 65535 || high <= 0 || high > 65535) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse VXLAN port range '%s'. Port should be greater than 0 and less than 65535.", word); + return 0; + } + + if (high < low) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse VXLAN port range '%s'. Port range %u .. %u not valid", word, low, high); + return 0; + } + + v->port_range.low = low; + v->port_range.high = high; + + return 0; +} + +int config_parse_destination_port(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) { + VxLan *v = userdata; + uint16_t port; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou16(rvalue, &port); + if (r < 0 || port <= 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN destination port '%s'.", rvalue); + return 0; + } + + v->dest_port = port; + + return 0; +} + static int netdev_vxlan_verify(NetDev *netdev, const char *filename) { VxLan *v = VXLAN(netdev); diff --git a/src/network/networkd-netdev-vxlan.h b/src/network/networkd-netdev-vxlan.h index 16977ea6a9..00142968ae 100644 --- a/src/network/networkd-netdev-vxlan.h +++ b/src/network/networkd-netdev-vxlan.h @@ -40,6 +40,8 @@ struct VxLan { unsigned ttl; unsigned max_fdb; + uint16_t dest_port; + usec_t fdb_ageing; bool learning; @@ -51,6 +53,8 @@ struct VxLan { bool udp6zerocsumtx; bool udp6zerocsumrx; bool group_policy; + + struct ifla_vxlan_port_range port_range; }; extern const NetDevVTable vxlan_vtable; @@ -65,3 +69,24 @@ int config_parse_vxlan_group_address(const char *unit, const char *rvalue, void *data, void *userdata); +int config_parse_port_range(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); + +int config_parse_destination_port(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); diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h index 98088f1204..5d0d0643e1 100644 --- a/src/systemd/sd-netlink.h +++ b/src/systemd/sd-netlink.h @@ -74,6 +74,7 @@ int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type); int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uint8_t data); int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, uint16_t data); int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, uint32_t data); +int sd_netlink_message_append_data(sd_netlink_message *m, unsigned short type, const void *data, size_t len); int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data); int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short type, const struct in6_addr *data); int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short type, const struct ether_addr *data); |