summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2020-07-29 00:47:58 +0300
committerSaeed Mahameed <saeedm@mellanox.com>2020-08-03 20:13:54 +0300
commit966e50597666d530b69de2abb9c83ff0a9bd3ee6 (patch)
tree64be01ad8586a2d61243ba51f7e93ad34834a971 /net
parentb206490940216542c68563699b279eed3c55107c (diff)
downloadlinux-966e50597666d530b69de2abb9c83ff0a9bd3ee6.tar.xz
udp_tunnel: add the ability to hard-code IANA VXLAN
mlx5 has the IANA VXLAN port (4789) hard coded by the device, instead of being added dynamically when tunnels are created. To support this add a workaround flag to struct udp_tunnel_nic_info. Skipping updates for the port is fairly trivial, dumping the hard coded port via ethtool requires some code duplication. The port is not a part of any real table, we dump it in a special table which has no tunnel types supported and only one entry. This is the last known workaround / hack needed to convert all drivers to the new infra. Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Diffstat (limited to 'net')
-rw-r--r--net/ethtool/tunnels.c69
-rw-r--r--net/ipv4/udp_tunnel_nic.c7
2 files changed, 68 insertions, 8 deletions
diff --git a/net/ethtool/tunnels.c b/net/ethtool/tunnels.c
index 6b89255f1231..84f23289475b 100644
--- a/net/ethtool/tunnels.c
+++ b/net/ethtool/tunnels.c
@@ -2,6 +2,7 @@
#include <linux/ethtool_netlink.h>
#include <net/udp_tunnel.h>
+#include <net/vxlan.h>
#include "bitset.h"
#include "common.h"
@@ -18,6 +19,20 @@ static_assert(ETHTOOL_UDP_TUNNEL_TYPE_GENEVE == ilog2(UDP_TUNNEL_TYPE_GENEVE));
static_assert(ETHTOOL_UDP_TUNNEL_TYPE_VXLAN_GPE ==
ilog2(UDP_TUNNEL_TYPE_VXLAN_GPE));
+static ssize_t ethnl_udp_table_reply_size(unsigned int types, bool compact)
+{
+ ssize_t size;
+
+ size = ethnl_bitset32_size(&types, NULL, __ETHTOOL_UDP_TUNNEL_TYPE_CNT,
+ udp_tunnel_type_names, compact);
+ if (size < 0)
+ return size;
+
+ return size +
+ nla_total_size(0) + /* _UDP_TABLE */
+ nla_total_size(sizeof(u32)); /* _UDP_TABLE_SIZE */
+}
+
static ssize_t
ethnl_tunnel_info_reply_size(const struct ethnl_req_info *req_base,
struct netlink_ext_ack *extack)
@@ -25,8 +40,8 @@ ethnl_tunnel_info_reply_size(const struct ethnl_req_info *req_base,
bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
const struct udp_tunnel_nic_info *info;
unsigned int i;
+ ssize_t ret;
size_t size;
- int ret;
info = req_base->dev->udp_tunnel_nic_info;
if (!info) {
@@ -39,13 +54,10 @@ ethnl_tunnel_info_reply_size(const struct ethnl_req_info *req_base,
for (i = 0; i < UDP_TUNNEL_NIC_MAX_TABLES; i++) {
if (!info->tables[i].n_entries)
- return size;
+ break;
- size += nla_total_size(0); /* _UDP_TABLE */
- size += nla_total_size(sizeof(u32)); /* _UDP_TABLE_SIZE */
- ret = ethnl_bitset32_size(&info->tables[i].tunnel_types, NULL,
- __ETHTOOL_UDP_TUNNEL_TYPE_CNT,
- udp_tunnel_type_names, compact);
+ ret = ethnl_udp_table_reply_size(info->tables[i].tunnel_types,
+ compact);
if (ret < 0)
return ret;
size += ret;
@@ -53,6 +65,17 @@ ethnl_tunnel_info_reply_size(const struct ethnl_req_info *req_base,
size += udp_tunnel_nic_dump_size(req_base->dev, i);
}
+ if (info->flags & UDP_TUNNEL_NIC_INFO_STATIC_IANA_VXLAN) {
+ ret = ethnl_udp_table_reply_size(0, compact);
+ if (ret < 0)
+ return ret;
+ size += ret;
+
+ size += nla_total_size(0) + /* _TABLE_ENTRY */
+ nla_total_size(sizeof(__be16)) + /* _ENTRY_PORT */
+ nla_total_size(sizeof(u32)); /* _ENTRY_TYPE */
+ }
+
return size;
}
@@ -62,7 +85,7 @@ ethnl_tunnel_info_fill_reply(const struct ethnl_req_info *req_base,
{
bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
const struct udp_tunnel_nic_info *info;
- struct nlattr *ports, *table;
+ struct nlattr *ports, *table, *entry;
unsigned int i;
info = req_base->dev->udp_tunnel_nic_info;
@@ -97,10 +120,40 @@ ethnl_tunnel_info_fill_reply(const struct ethnl_req_info *req_base,
nla_nest_end(skb, table);
}
+ if (info->flags & UDP_TUNNEL_NIC_INFO_STATIC_IANA_VXLAN) {
+ u32 zero = 0;
+
+ table = nla_nest_start(skb, ETHTOOL_A_TUNNEL_UDP_TABLE);
+ if (!table)
+ goto err_cancel_ports;
+
+ if (nla_put_u32(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE, 1))
+ goto err_cancel_table;
+
+ if (ethnl_put_bitset32(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES,
+ &zero, NULL,
+ __ETHTOOL_UDP_TUNNEL_TYPE_CNT,
+ udp_tunnel_type_names, compact))
+ goto err_cancel_table;
+
+ entry = nla_nest_start(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY);
+
+ if (nla_put_be16(skb, ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT,
+ htons(IANA_VXLAN_UDP_PORT)) ||
+ nla_put_u32(skb, ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE,
+ ilog2(UDP_TUNNEL_TYPE_VXLAN)))
+ goto err_cancel_entry;
+
+ nla_nest_end(skb, entry);
+ nla_nest_end(skb, table);
+ }
+
nla_nest_end(skb, ports);
return 0;
+err_cancel_entry:
+ nla_nest_cancel(skb, entry);
err_cancel_table:
nla_nest_cancel(skb, table);
err_cancel_ports:
diff --git a/net/ipv4/udp_tunnel_nic.c b/net/ipv4/udp_tunnel_nic.c
index f0dbd9905a53..69962165c0e8 100644
--- a/net/ipv4/udp_tunnel_nic.c
+++ b/net/ipv4/udp_tunnel_nic.c
@@ -7,6 +7,7 @@
#include <linux/types.h>
#include <linux/workqueue.h>
#include <net/udp_tunnel.h>
+#include <net/vxlan.h>
enum udp_tunnel_nic_table_entry_flags {
UDP_TUNNEL_NIC_ENTRY_ADD = BIT(0),
@@ -504,6 +505,12 @@ __udp_tunnel_nic_add_port(struct net_device *dev, struct udp_tunnel_info *ti)
return;
if (!netif_running(dev) && info->flags & UDP_TUNNEL_NIC_INFO_OPEN_ONLY)
return;
+ if (info->flags & UDP_TUNNEL_NIC_INFO_STATIC_IANA_VXLAN &&
+ ti->port == htons(IANA_VXLAN_UDP_PORT)) {
+ if (ti->type != UDP_TUNNEL_TYPE_VXLAN)
+ netdev_warn(dev, "device assumes port 4789 will be used by vxlan tunnels\n");
+ return;
+ }
if (!udp_tunnel_nic_is_capable(dev, utn, ti))
return;