0001
0002
0003
0004 #include <linux/debugfs.h>
0005 #include <linux/netdevice.h>
0006 #include <linux/slab.h>
0007 #include <net/udp_tunnel.h>
0008
0009 #include "netdevsim.h"
0010
0011 static int
0012 nsim_udp_tunnel_set_port(struct net_device *dev, unsigned int table,
0013 unsigned int entry, struct udp_tunnel_info *ti)
0014 {
0015 struct netdevsim *ns = netdev_priv(dev);
0016 int ret;
0017
0018 ret = -ns->udp_ports.inject_error;
0019 ns->udp_ports.inject_error = 0;
0020
0021 if (ns->udp_ports.sleep)
0022 msleep(ns->udp_ports.sleep);
0023
0024 if (!ret) {
0025 if (ns->udp_ports.ports[table][entry]) {
0026 WARN(1, "entry already in use\n");
0027 ret = -EBUSY;
0028 } else {
0029 ns->udp_ports.ports[table][entry] =
0030 be16_to_cpu(ti->port) << 16 | ti->type;
0031 }
0032 }
0033
0034 netdev_info(dev, "set [%d, %d] type %d family %d port %d - %d\n",
0035 table, entry, ti->type, ti->sa_family, ntohs(ti->port),
0036 ret);
0037 return ret;
0038 }
0039
0040 static int
0041 nsim_udp_tunnel_unset_port(struct net_device *dev, unsigned int table,
0042 unsigned int entry, struct udp_tunnel_info *ti)
0043 {
0044 struct netdevsim *ns = netdev_priv(dev);
0045 int ret;
0046
0047 ret = -ns->udp_ports.inject_error;
0048 ns->udp_ports.inject_error = 0;
0049
0050 if (ns->udp_ports.sleep)
0051 msleep(ns->udp_ports.sleep);
0052 if (!ret) {
0053 u32 val = be16_to_cpu(ti->port) << 16 | ti->type;
0054
0055 if (val == ns->udp_ports.ports[table][entry]) {
0056 ns->udp_ports.ports[table][entry] = 0;
0057 } else {
0058 WARN(1, "entry not installed %x vs %x\n",
0059 val, ns->udp_ports.ports[table][entry]);
0060 ret = -ENOENT;
0061 }
0062 }
0063
0064 netdev_info(dev, "unset [%d, %d] type %d family %d port %d - %d\n",
0065 table, entry, ti->type, ti->sa_family, ntohs(ti->port),
0066 ret);
0067 return ret;
0068 }
0069
0070 static int
0071 nsim_udp_tunnel_sync_table(struct net_device *dev, unsigned int table)
0072 {
0073 struct netdevsim *ns = netdev_priv(dev);
0074 struct udp_tunnel_info ti;
0075 unsigned int i;
0076 int ret;
0077
0078 ret = -ns->udp_ports.inject_error;
0079 ns->udp_ports.inject_error = 0;
0080
0081 for (i = 0; i < NSIM_UDP_TUNNEL_N_PORTS; i++) {
0082 udp_tunnel_nic_get_port(dev, table, i, &ti);
0083 ns->udp_ports.ports[table][i] =
0084 be16_to_cpu(ti.port) << 16 | ti.type;
0085 }
0086
0087 return ret;
0088 }
0089
0090 static const struct udp_tunnel_nic_info nsim_udp_tunnel_info = {
0091 .set_port = nsim_udp_tunnel_set_port,
0092 .unset_port = nsim_udp_tunnel_unset_port,
0093 .sync_table = nsim_udp_tunnel_sync_table,
0094
0095 .tables = {
0096 {
0097 .n_entries = NSIM_UDP_TUNNEL_N_PORTS,
0098 .tunnel_types = UDP_TUNNEL_TYPE_VXLAN,
0099 },
0100 {
0101 .n_entries = NSIM_UDP_TUNNEL_N_PORTS,
0102 .tunnel_types = UDP_TUNNEL_TYPE_GENEVE |
0103 UDP_TUNNEL_TYPE_VXLAN_GPE,
0104 },
0105 },
0106 };
0107
0108 static ssize_t
0109 nsim_udp_tunnels_info_reset_write(struct file *file, const char __user *data,
0110 size_t count, loff_t *ppos)
0111 {
0112 struct net_device *dev = file->private_data;
0113 struct netdevsim *ns = netdev_priv(dev);
0114
0115 memset(ns->udp_ports.ports, 0, sizeof(ns->udp_ports.__ports));
0116 rtnl_lock();
0117 udp_tunnel_nic_reset_ntf(dev);
0118 rtnl_unlock();
0119
0120 return count;
0121 }
0122
0123 static const struct file_operations nsim_udp_tunnels_info_reset_fops = {
0124 .open = simple_open,
0125 .write = nsim_udp_tunnels_info_reset_write,
0126 .llseek = generic_file_llseek,
0127 .owner = THIS_MODULE,
0128 };
0129
0130 int nsim_udp_tunnels_info_create(struct nsim_dev *nsim_dev,
0131 struct net_device *dev)
0132 {
0133 struct netdevsim *ns = netdev_priv(dev);
0134 struct udp_tunnel_nic_info *info;
0135
0136 if (nsim_dev->udp_ports.shared && nsim_dev->udp_ports.open_only) {
0137 dev_err(&nsim_dev->nsim_bus_dev->dev,
0138 "shared can't be used in conjunction with open_only\n");
0139 return -EINVAL;
0140 }
0141
0142 if (!nsim_dev->udp_ports.shared)
0143 ns->udp_ports.ports = ns->udp_ports.__ports;
0144 else
0145 ns->udp_ports.ports = nsim_dev->udp_ports.__ports;
0146
0147 debugfs_create_u32("udp_ports_inject_error", 0600,
0148 ns->nsim_dev_port->ddir,
0149 &ns->udp_ports.inject_error);
0150
0151 ns->udp_ports.dfs_ports[0].array = ns->udp_ports.ports[0];
0152 ns->udp_ports.dfs_ports[0].n_elements = NSIM_UDP_TUNNEL_N_PORTS;
0153 debugfs_create_u32_array("udp_ports_table0", 0400,
0154 ns->nsim_dev_port->ddir,
0155 &ns->udp_ports.dfs_ports[0]);
0156
0157 ns->udp_ports.dfs_ports[1].array = ns->udp_ports.ports[1];
0158 ns->udp_ports.dfs_ports[1].n_elements = NSIM_UDP_TUNNEL_N_PORTS;
0159 debugfs_create_u32_array("udp_ports_table1", 0400,
0160 ns->nsim_dev_port->ddir,
0161 &ns->udp_ports.dfs_ports[1]);
0162
0163 debugfs_create_file("udp_ports_reset", 0200, ns->nsim_dev_port->ddir,
0164 dev, &nsim_udp_tunnels_info_reset_fops);
0165
0166
0167
0168
0169 info = kmemdup(&nsim_udp_tunnel_info, sizeof(nsim_udp_tunnel_info),
0170 GFP_KERNEL);
0171 if (!info)
0172 return -ENOMEM;
0173 ns->udp_ports.sleep = nsim_dev->udp_ports.sleep;
0174
0175 if (nsim_dev->udp_ports.sync_all) {
0176 info->set_port = NULL;
0177 info->unset_port = NULL;
0178 } else {
0179 info->sync_table = NULL;
0180 }
0181
0182 if (ns->udp_ports.sleep)
0183 info->flags |= UDP_TUNNEL_NIC_INFO_MAY_SLEEP;
0184 if (nsim_dev->udp_ports.open_only)
0185 info->flags |= UDP_TUNNEL_NIC_INFO_OPEN_ONLY;
0186 if (nsim_dev->udp_ports.ipv4_only)
0187 info->flags |= UDP_TUNNEL_NIC_INFO_IPV4_ONLY;
0188 if (nsim_dev->udp_ports.shared)
0189 info->shared = &nsim_dev->udp_ports.utn_shared;
0190 if (nsim_dev->udp_ports.static_iana_vxlan)
0191 info->flags |= UDP_TUNNEL_NIC_INFO_STATIC_IANA_VXLAN;
0192
0193 dev->udp_tunnel_nic_info = info;
0194 return 0;
0195 }
0196
0197 void nsim_udp_tunnels_info_destroy(struct net_device *dev)
0198 {
0199 kfree(dev->udp_tunnel_nic_info);
0200 dev->udp_tunnel_nic_info = NULL;
0201 }
0202
0203 void nsim_udp_tunnels_debugfs_create(struct nsim_dev *nsim_dev)
0204 {
0205 debugfs_create_bool("udp_ports_sync_all", 0600, nsim_dev->ddir,
0206 &nsim_dev->udp_ports.sync_all);
0207 debugfs_create_bool("udp_ports_open_only", 0600, nsim_dev->ddir,
0208 &nsim_dev->udp_ports.open_only);
0209 debugfs_create_bool("udp_ports_ipv4_only", 0600, nsim_dev->ddir,
0210 &nsim_dev->udp_ports.ipv4_only);
0211 debugfs_create_bool("udp_ports_shared", 0600, nsim_dev->ddir,
0212 &nsim_dev->udp_ports.shared);
0213 debugfs_create_bool("udp_ports_static_iana_vxlan", 0600, nsim_dev->ddir,
0214 &nsim_dev->udp_ports.static_iana_vxlan);
0215 debugfs_create_u32("udp_ports_sleep", 0600, nsim_dev->ddir,
0216 &nsim_dev->udp_ports.sleep);
0217 }