Skip to content

Commit 966e505

Browse files
kuba-mooSaeed Mahameed
authored andcommitted
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 <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent b206490 commit 966e505

File tree

4 files changed

+76
-8
lines changed

4 files changed

+76
-8
lines changed

Documentation/networking/ethtool-netlink.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,9 @@ Kernel response contents:
12631263
| | | | ``ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE`` | u32 | tunnel type |
12641264
+-+-+-+---------------------------------------+--------+---------------------+
12651265

1266+
For UDP tunnel table empty ``ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES`` indicates that
1267+
the table contains static entries, hard-coded by the NIC.
1268+
12661269
Request translation
12671270
===================
12681271

include/net/udp_tunnel.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ enum udp_tunnel_nic_info_flags {
193193
UDP_TUNNEL_NIC_INFO_OPEN_ONLY = BIT(1),
194194
/* Device supports only IPv4 tunnels */
195195
UDP_TUNNEL_NIC_INFO_IPV4_ONLY = BIT(2),
196+
/* Device has hard-coded the IANA VXLAN port (4789) as VXLAN.
197+
* This port must not be counted towards n_entries of any table.
198+
* Driver will not receive any callback associated with port 4789.
199+
*/
200+
UDP_TUNNEL_NIC_INFO_STATIC_IANA_VXLAN = BIT(3),
196201
};
197202

198203
/**

net/ethtool/tunnels.c

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <linux/ethtool_netlink.h>
44
#include <net/udp_tunnel.h>
5+
#include <net/vxlan.h>
56

67
#include "bitset.h"
78
#include "common.h"
@@ -18,15 +19,29 @@ static_assert(ETHTOOL_UDP_TUNNEL_TYPE_GENEVE == ilog2(UDP_TUNNEL_TYPE_GENEVE));
1819
static_assert(ETHTOOL_UDP_TUNNEL_TYPE_VXLAN_GPE ==
1920
ilog2(UDP_TUNNEL_TYPE_VXLAN_GPE));
2021

22+
static ssize_t ethnl_udp_table_reply_size(unsigned int types, bool compact)
23+
{
24+
ssize_t size;
25+
26+
size = ethnl_bitset32_size(&types, NULL, __ETHTOOL_UDP_TUNNEL_TYPE_CNT,
27+
udp_tunnel_type_names, compact);
28+
if (size < 0)
29+
return size;
30+
31+
return size +
32+
nla_total_size(0) + /* _UDP_TABLE */
33+
nla_total_size(sizeof(u32)); /* _UDP_TABLE_SIZE */
34+
}
35+
2136
static ssize_t
2237
ethnl_tunnel_info_reply_size(const struct ethnl_req_info *req_base,
2338
struct netlink_ext_ack *extack)
2439
{
2540
bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
2641
const struct udp_tunnel_nic_info *info;
2742
unsigned int i;
43+
ssize_t ret;
2844
size_t size;
29-
int ret;
3045

3146
info = req_base->dev->udp_tunnel_nic_info;
3247
if (!info) {
@@ -39,20 +54,28 @@ ethnl_tunnel_info_reply_size(const struct ethnl_req_info *req_base,
3954

4055
for (i = 0; i < UDP_TUNNEL_NIC_MAX_TABLES; i++) {
4156
if (!info->tables[i].n_entries)
42-
return size;
57+
break;
4358

44-
size += nla_total_size(0); /* _UDP_TABLE */
45-
size += nla_total_size(sizeof(u32)); /* _UDP_TABLE_SIZE */
46-
ret = ethnl_bitset32_size(&info->tables[i].tunnel_types, NULL,
47-
__ETHTOOL_UDP_TUNNEL_TYPE_CNT,
48-
udp_tunnel_type_names, compact);
59+
ret = ethnl_udp_table_reply_size(info->tables[i].tunnel_types,
60+
compact);
4961
if (ret < 0)
5062
return ret;
5163
size += ret;
5264

5365
size += udp_tunnel_nic_dump_size(req_base->dev, i);
5466
}
5567

68+
if (info->flags & UDP_TUNNEL_NIC_INFO_STATIC_IANA_VXLAN) {
69+
ret = ethnl_udp_table_reply_size(0, compact);
70+
if (ret < 0)
71+
return ret;
72+
size += ret;
73+
74+
size += nla_total_size(0) + /* _TABLE_ENTRY */
75+
nla_total_size(sizeof(__be16)) + /* _ENTRY_PORT */
76+
nla_total_size(sizeof(u32)); /* _ENTRY_TYPE */
77+
}
78+
5679
return size;
5780
}
5881

@@ -62,7 +85,7 @@ ethnl_tunnel_info_fill_reply(const struct ethnl_req_info *req_base,
6285
{
6386
bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
6487
const struct udp_tunnel_nic_info *info;
65-
struct nlattr *ports, *table;
88+
struct nlattr *ports, *table, *entry;
6689
unsigned int i;
6790

6891
info = req_base->dev->udp_tunnel_nic_info;
@@ -97,10 +120,40 @@ ethnl_tunnel_info_fill_reply(const struct ethnl_req_info *req_base,
97120
nla_nest_end(skb, table);
98121
}
99122

123+
if (info->flags & UDP_TUNNEL_NIC_INFO_STATIC_IANA_VXLAN) {
124+
u32 zero = 0;
125+
126+
table = nla_nest_start(skb, ETHTOOL_A_TUNNEL_UDP_TABLE);
127+
if (!table)
128+
goto err_cancel_ports;
129+
130+
if (nla_put_u32(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE, 1))
131+
goto err_cancel_table;
132+
133+
if (ethnl_put_bitset32(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES,
134+
&zero, NULL,
135+
__ETHTOOL_UDP_TUNNEL_TYPE_CNT,
136+
udp_tunnel_type_names, compact))
137+
goto err_cancel_table;
138+
139+
entry = nla_nest_start(skb, ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY);
140+
141+
if (nla_put_be16(skb, ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT,
142+
htons(IANA_VXLAN_UDP_PORT)) ||
143+
nla_put_u32(skb, ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE,
144+
ilog2(UDP_TUNNEL_TYPE_VXLAN)))
145+
goto err_cancel_entry;
146+
147+
nla_nest_end(skb, entry);
148+
nla_nest_end(skb, table);
149+
}
150+
100151
nla_nest_end(skb, ports);
101152

102153
return 0;
103154

155+
err_cancel_entry:
156+
nla_nest_cancel(skb, entry);
104157
err_cancel_table:
105158
nla_nest_cancel(skb, table);
106159
err_cancel_ports:

net/ipv4/udp_tunnel_nic.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linux/types.h>
88
#include <linux/workqueue.h>
99
#include <net/udp_tunnel.h>
10+
#include <net/vxlan.h>
1011

1112
enum udp_tunnel_nic_table_entry_flags {
1213
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)
504505
return;
505506
if (!netif_running(dev) && info->flags & UDP_TUNNEL_NIC_INFO_OPEN_ONLY)
506507
return;
508+
if (info->flags & UDP_TUNNEL_NIC_INFO_STATIC_IANA_VXLAN &&
509+
ti->port == htons(IANA_VXLAN_UDP_PORT)) {
510+
if (ti->type != UDP_TUNNEL_TYPE_VXLAN)
511+
netdev_warn(dev, "device assumes port 4789 will be used by vxlan tunnels\n");
512+
return;
513+
}
507514

508515
if (!udp_tunnel_nic_is_capable(dev, utn, ti))
509516
return;

0 commit comments

Comments
 (0)