Skip to content

Commit 424be63

Browse files
kuba-moodavem330
authored andcommitted
netdevsim: add UDP tunnel port offload support
Add UDP tunnel port handlers to our fake driver so we can test the core infra. Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c7d759e commit 424be63

File tree

5 files changed

+224
-2
lines changed

5 files changed

+224
-2
lines changed

drivers/net/netdevsim/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
obj-$(CONFIG_NETDEVSIM) += netdevsim.o
44

55
netdevsim-objs := \
6-
netdev.o dev.o fib.o bus.o health.o
6+
netdev.o dev.o fib.o bus.o health.o udp_tunnels.o
77

88
ifeq ($(CONFIG_BPF_SYSCALL),y)
99
netdevsim-objs += \

drivers/net/netdevsim/dev.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
225225
debugfs_create_bool("fail_trap_policer_counter_get", 0600,
226226
nsim_dev->ddir,
227227
&nsim_dev->fail_trap_policer_counter_get);
228+
nsim_udp_tunnels_debugfs_create(nsim_dev);
228229
return 0;
229230
}
230231

drivers/net/netdevsim/netdev.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <net/netlink.h>
2323
#include <net/pkt_cls.h>
2424
#include <net/rtnetlink.h>
25+
#include <net/udp_tunnel.h>
2526

2627
#include "netdevsim.h"
2728

@@ -257,6 +258,8 @@ static const struct net_device_ops nsim_netdev_ops = {
257258
.ndo_setup_tc = nsim_setup_tc,
258259
.ndo_set_features = nsim_set_features,
259260
.ndo_bpf = nsim_bpf,
261+
.ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
262+
.ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
260263
.ndo_get_devlink_port = nsim_get_devlink_port,
261264
};
262265

@@ -299,10 +302,14 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port)
299302
SET_NETDEV_DEV(dev, &ns->nsim_bus_dev->dev);
300303
dev->netdev_ops = &nsim_netdev_ops;
301304

305+
err = nsim_udp_tunnels_info_create(nsim_dev, dev);
306+
if (err)
307+
goto err_free_netdev;
308+
302309
rtnl_lock();
303310
err = nsim_bpf_init(ns);
304311
if (err)
305-
goto err_free_netdev;
312+
goto err_utn_destroy;
306313

307314
nsim_ipsec_init(ns);
308315

@@ -317,6 +324,8 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port)
317324
nsim_ipsec_teardown(ns);
318325
nsim_bpf_uninit(ns);
319326
rtnl_unlock();
327+
err_utn_destroy:
328+
nsim_udp_tunnels_info_destroy(dev);
320329
err_free_netdev:
321330
free_netdev(dev);
322331
return ERR_PTR(err);
@@ -331,6 +340,7 @@ void nsim_destroy(struct netdevsim *ns)
331340
nsim_ipsec_teardown(ns);
332341
nsim_bpf_uninit(ns);
333342
rtnl_unlock();
343+
nsim_udp_tunnels_info_destroy(dev);
334344
free_netdev(dev);
335345
}
336346

drivers/net/netdevsim/netdevsim.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
1414
*/
1515

16+
#include <linux/debugfs.h>
1617
#include <linux/device.h>
1718
#include <linux/kernel.h>
1819
#include <linux/list.h>
@@ -29,6 +30,7 @@
2930

3031
#define NSIM_IPSEC_MAX_SA_COUNT 33
3132
#define NSIM_IPSEC_VALID BIT(31)
33+
#define NSIM_UDP_TUNNEL_N_PORTS 4
3234

3335
struct nsim_sa {
3436
struct xfrm_state *xs;
@@ -72,12 +74,23 @@ struct netdevsim {
7274

7375
bool bpf_map_accept;
7476
struct nsim_ipsec ipsec;
77+
struct {
78+
u32 inject_error;
79+
u32 sleep;
80+
u32 ports[2][NSIM_UDP_TUNNEL_N_PORTS];
81+
struct debugfs_u32_array dfs_ports[2];
82+
} udp_ports;
7583
};
7684

7785
struct netdevsim *
7886
nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port);
7987
void nsim_destroy(struct netdevsim *ns);
8088

89+
void nsim_udp_tunnels_debugfs_create(struct nsim_dev *nsim_dev);
90+
int nsim_udp_tunnels_info_create(struct nsim_dev *nsim_dev,
91+
struct net_device *dev);
92+
void nsim_udp_tunnels_info_destroy(struct net_device *dev);
93+
8194
#ifdef CONFIG_BPF_SYSCALL
8295
int nsim_bpf_dev_init(struct nsim_dev *nsim_dev);
8396
void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev);
@@ -183,6 +196,12 @@ struct nsim_dev {
183196
bool fail_trap_group_set;
184197
bool fail_trap_policer_set;
185198
bool fail_trap_policer_counter_get;
199+
struct {
200+
bool sync_all;
201+
bool open_only;
202+
bool ipv4_only;
203+
u32 sleep;
204+
} udp_ports;
186205
};
187206

188207
static inline struct net *nsim_dev_net(struct nsim_dev *nsim_dev)
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
// Copyright (c) 2020 Facebook Inc.
3+
4+
#include <linux/debugfs.h>
5+
#include <linux/netdevice.h>
6+
#include <linux/slab.h>
7+
#include <net/udp_tunnel.h>
8+
9+
#include "netdevsim.h"
10+
11+
static int
12+
nsim_udp_tunnel_set_port(struct net_device *dev, unsigned int table,
13+
unsigned int entry, struct udp_tunnel_info *ti)
14+
{
15+
struct netdevsim *ns = netdev_priv(dev);
16+
int ret;
17+
18+
ret = -ns->udp_ports.inject_error;
19+
ns->udp_ports.inject_error = 0;
20+
21+
if (ns->udp_ports.sleep)
22+
msleep(ns->udp_ports.sleep);
23+
24+
if (!ret) {
25+
if (ns->udp_ports.ports[table][entry])
26+
ret = -EBUSY;
27+
else
28+
ns->udp_ports.ports[table][entry] =
29+
be16_to_cpu(ti->port) << 16 | ti->type;
30+
}
31+
32+
netdev_info(dev, "set [%d, %d] type %d family %d port %d - %d\n",
33+
table, entry, ti->type, ti->sa_family, ntohs(ti->port),
34+
ret);
35+
return ret;
36+
}
37+
38+
static int
39+
nsim_udp_tunnel_unset_port(struct net_device *dev, unsigned int table,
40+
unsigned int entry, struct udp_tunnel_info *ti)
41+
{
42+
struct netdevsim *ns = netdev_priv(dev);
43+
int ret;
44+
45+
ret = -ns->udp_ports.inject_error;
46+
ns->udp_ports.inject_error = 0;
47+
48+
if (ns->udp_ports.sleep)
49+
msleep(ns->udp_ports.sleep);
50+
if (!ret) {
51+
u32 val = be16_to_cpu(ti->port) << 16 | ti->type;
52+
53+
if (val == ns->udp_ports.ports[table][entry])
54+
ns->udp_ports.ports[table][entry] = 0;
55+
else
56+
ret = -ENOENT;
57+
}
58+
59+
netdev_info(dev, "unset [%d, %d] type %d family %d port %d - %d\n",
60+
table, entry, ti->type, ti->sa_family, ntohs(ti->port),
61+
ret);
62+
return ret;
63+
}
64+
65+
static int
66+
nsim_udp_tunnel_sync_table(struct net_device *dev, unsigned int table)
67+
{
68+
struct netdevsim *ns = netdev_priv(dev);
69+
struct udp_tunnel_info ti;
70+
unsigned int i;
71+
int ret;
72+
73+
ret = -ns->udp_ports.inject_error;
74+
ns->udp_ports.inject_error = 0;
75+
76+
for (i = 0; i < NSIM_UDP_TUNNEL_N_PORTS; i++) {
77+
udp_tunnel_nic_get_port(dev, table, i, &ti);
78+
ns->udp_ports.ports[table][i] =
79+
be16_to_cpu(ti.port) << 16 | ti.type;
80+
}
81+
82+
return ret;
83+
}
84+
85+
static const struct udp_tunnel_nic_info nsim_udp_tunnel_info = {
86+
.set_port = nsim_udp_tunnel_set_port,
87+
.unset_port = nsim_udp_tunnel_unset_port,
88+
.sync_table = nsim_udp_tunnel_sync_table,
89+
90+
.tables = {
91+
{
92+
.n_entries = NSIM_UDP_TUNNEL_N_PORTS,
93+
.tunnel_types = UDP_TUNNEL_TYPE_VXLAN,
94+
},
95+
{
96+
.n_entries = NSIM_UDP_TUNNEL_N_PORTS,
97+
.tunnel_types = UDP_TUNNEL_TYPE_GENEVE |
98+
UDP_TUNNEL_TYPE_VXLAN_GPE,
99+
},
100+
},
101+
};
102+
103+
static ssize_t
104+
nsim_udp_tunnels_info_reset_write(struct file *file, const char __user *data,
105+
size_t count, loff_t *ppos)
106+
{
107+
struct net_device *dev = file->private_data;
108+
struct netdevsim *ns = netdev_priv(dev);
109+
110+
memset(&ns->udp_ports.ports, 0, sizeof(ns->udp_ports.ports));
111+
rtnl_lock();
112+
udp_tunnel_nic_reset_ntf(dev);
113+
rtnl_unlock();
114+
115+
return count;
116+
}
117+
118+
static const struct file_operations nsim_udp_tunnels_info_reset_fops = {
119+
.open = simple_open,
120+
.write = nsim_udp_tunnels_info_reset_write,
121+
.llseek = generic_file_llseek,
122+
};
123+
124+
int nsim_udp_tunnels_info_create(struct nsim_dev *nsim_dev,
125+
struct net_device *dev)
126+
{
127+
struct netdevsim *ns = netdev_priv(dev);
128+
struct udp_tunnel_nic_info *info;
129+
130+
debugfs_create_u32("udp_ports_inject_error", 0600,
131+
ns->nsim_dev_port->ddir,
132+
&ns->udp_ports.inject_error);
133+
134+
ns->udp_ports.dfs_ports[0].array = ns->udp_ports.ports[0];
135+
ns->udp_ports.dfs_ports[0].n_elements = NSIM_UDP_TUNNEL_N_PORTS;
136+
debugfs_create_u32_array("udp_ports_table0", 0400,
137+
ns->nsim_dev_port->ddir,
138+
&ns->udp_ports.dfs_ports[0]);
139+
140+
ns->udp_ports.dfs_ports[1].array = ns->udp_ports.ports[1];
141+
ns->udp_ports.dfs_ports[1].n_elements = NSIM_UDP_TUNNEL_N_PORTS;
142+
debugfs_create_u32_array("udp_ports_table1", 0400,
143+
ns->nsim_dev_port->ddir,
144+
&ns->udp_ports.dfs_ports[1]);
145+
146+
debugfs_create_file("udp_ports_reset", 0200, ns->nsim_dev_port->ddir,
147+
dev, &nsim_udp_tunnels_info_reset_fops);
148+
149+
/* Note: it's not normal to allocate the info struct like this!
150+
* Drivers are expected to use a static const one, here we're testing.
151+
*/
152+
info = kmemdup(&nsim_udp_tunnel_info, sizeof(nsim_udp_tunnel_info),
153+
GFP_KERNEL);
154+
if (!info)
155+
return -ENOMEM;
156+
ns->udp_ports.sleep = nsim_dev->udp_ports.sleep;
157+
158+
if (nsim_dev->udp_ports.sync_all) {
159+
info->set_port = NULL;
160+
info->unset_port = NULL;
161+
} else {
162+
info->sync_table = NULL;
163+
}
164+
165+
if (ns->udp_ports.sleep)
166+
info->flags |= UDP_TUNNEL_NIC_INFO_MAY_SLEEP;
167+
if (nsim_dev->udp_ports.open_only)
168+
info->flags |= UDP_TUNNEL_NIC_INFO_OPEN_ONLY;
169+
if (nsim_dev->udp_ports.ipv4_only)
170+
info->flags |= UDP_TUNNEL_NIC_INFO_IPV4_ONLY;
171+
172+
dev->udp_tunnel_nic_info = info;
173+
return 0;
174+
}
175+
176+
void nsim_udp_tunnels_info_destroy(struct net_device *dev)
177+
{
178+
kfree(dev->udp_tunnel_nic_info);
179+
dev->udp_tunnel_nic_info = NULL;
180+
}
181+
182+
void nsim_udp_tunnels_debugfs_create(struct nsim_dev *nsim_dev)
183+
{
184+
debugfs_create_bool("udp_ports_sync_all", 0600, nsim_dev->ddir,
185+
&nsim_dev->udp_ports.sync_all);
186+
debugfs_create_bool("udp_ports_open_only", 0600, nsim_dev->ddir,
187+
&nsim_dev->udp_ports.open_only);
188+
debugfs_create_bool("udp_ports_ipv4_only", 0600, nsim_dev->ddir,
189+
&nsim_dev->udp_ports.ipv4_only);
190+
debugfs_create_u32("udp_ports_sleep", 0600, nsim_dev->ddir,
191+
&nsim_dev->udp_ports.sleep);
192+
}

0 commit comments

Comments
 (0)