.. | .. |
---|
13 | 13 | * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. |
---|
14 | 14 | */ |
---|
15 | 15 | |
---|
| 16 | +#include <linux/debugfs.h> |
---|
16 | 17 | #include <linux/device.h> |
---|
17 | 18 | #include <linux/kernel.h> |
---|
18 | 19 | #include <linux/list.h> |
---|
19 | 20 | #include <linux/netdevice.h> |
---|
20 | 21 | #include <linux/u64_stats_sync.h> |
---|
| 22 | +#include <net/devlink.h> |
---|
| 23 | +#include <net/udp_tunnel.h> |
---|
21 | 24 | #include <net/xdp.h> |
---|
22 | 25 | |
---|
23 | 26 | #define DRV_NAME "netdevsim" |
---|
.. | .. |
---|
26 | 29 | |
---|
27 | 30 | #define NSIM_EA(extack, msg) NL_SET_ERR_MSG_MOD((extack), msg) |
---|
28 | 31 | |
---|
29 | | -struct bpf_prog; |
---|
30 | | -struct bpf_offload_dev; |
---|
31 | | -struct dentry; |
---|
32 | | -struct nsim_vf_config; |
---|
33 | | - |
---|
34 | | -struct netdevsim_shared_dev { |
---|
35 | | - unsigned int refcnt; |
---|
36 | | - u32 switch_id; |
---|
37 | | - |
---|
38 | | - struct dentry *ddir; |
---|
39 | | - |
---|
40 | | - struct bpf_offload_dev *bpf_dev; |
---|
41 | | - |
---|
42 | | - struct dentry *ddir_bpf_bound_progs; |
---|
43 | | - u32 prog_id_gen; |
---|
44 | | - |
---|
45 | | - struct list_head bpf_bound_progs; |
---|
46 | | - struct list_head bpf_bound_maps; |
---|
47 | | -}; |
---|
48 | | - |
---|
49 | 32 | #define NSIM_IPSEC_MAX_SA_COUNT 33 |
---|
50 | 33 | #define NSIM_IPSEC_VALID BIT(31) |
---|
| 34 | +#define NSIM_UDP_TUNNEL_N_PORTS 4 |
---|
51 | 35 | |
---|
52 | 36 | struct nsim_sa { |
---|
53 | 37 | struct xfrm_state *xs; |
---|
.. | .. |
---|
67 | 51 | u32 ok; |
---|
68 | 52 | }; |
---|
69 | 53 | |
---|
| 54 | +struct nsim_ethtool { |
---|
| 55 | + bool rx; |
---|
| 56 | + bool tx; |
---|
| 57 | + bool report_stats_rx; |
---|
| 58 | + bool report_stats_tx; |
---|
| 59 | +}; |
---|
| 60 | + |
---|
70 | 61 | struct netdevsim { |
---|
71 | 62 | struct net_device *netdev; |
---|
| 63 | + struct nsim_dev *nsim_dev; |
---|
| 64 | + struct nsim_dev_port *nsim_dev_port; |
---|
72 | 65 | |
---|
73 | 66 | u64 tx_packets; |
---|
74 | 67 | u64 tx_bytes; |
---|
75 | 68 | struct u64_stats_sync syncp; |
---|
76 | 69 | |
---|
77 | | - struct device dev; |
---|
78 | | - struct netdevsim_shared_dev *sdev; |
---|
79 | | - |
---|
80 | | - struct dentry *ddir; |
---|
81 | | - |
---|
82 | | - unsigned int num_vfs; |
---|
83 | | - struct nsim_vf_config *vfconfigs; |
---|
| 70 | + struct nsim_bus_dev *nsim_bus_dev; |
---|
84 | 71 | |
---|
85 | 72 | struct bpf_prog *bpf_offloaded; |
---|
86 | 73 | u32 bpf_offloaded_id; |
---|
.. | .. |
---|
88 | 75 | struct xdp_attachment_info xdp; |
---|
89 | 76 | struct xdp_attachment_info xdp_hw; |
---|
90 | 77 | |
---|
91 | | - bool bpf_bind_accept; |
---|
92 | | - u32 bpf_bind_verifier_delay; |
---|
93 | | - |
---|
94 | 78 | bool bpf_tc_accept; |
---|
95 | 79 | bool bpf_tc_non_bound_accept; |
---|
96 | 80 | bool bpf_xdpdrv_accept; |
---|
97 | 81 | bool bpf_xdpoffload_accept; |
---|
98 | 82 | |
---|
99 | 83 | bool bpf_map_accept; |
---|
100 | | -#if IS_ENABLED(CONFIG_NET_DEVLINK) |
---|
101 | | - struct devlink *devlink; |
---|
102 | | -#endif |
---|
103 | 84 | struct nsim_ipsec ipsec; |
---|
| 85 | + struct { |
---|
| 86 | + u32 inject_error; |
---|
| 87 | + u32 sleep; |
---|
| 88 | + u32 __ports[2][NSIM_UDP_TUNNEL_N_PORTS]; |
---|
| 89 | + u32 (*ports)[NSIM_UDP_TUNNEL_N_PORTS]; |
---|
| 90 | + struct debugfs_u32_array dfs_ports[2]; |
---|
| 91 | + } udp_ports; |
---|
| 92 | + |
---|
| 93 | + struct nsim_ethtool ethtool; |
---|
104 | 94 | }; |
---|
105 | 95 | |
---|
| 96 | +struct netdevsim * |
---|
| 97 | +nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port); |
---|
| 98 | +void nsim_destroy(struct netdevsim *ns); |
---|
| 99 | + |
---|
| 100 | +void nsim_ethtool_init(struct netdevsim *ns); |
---|
| 101 | + |
---|
| 102 | +void nsim_udp_tunnels_debugfs_create(struct nsim_dev *nsim_dev); |
---|
| 103 | +int nsim_udp_tunnels_info_create(struct nsim_dev *nsim_dev, |
---|
| 104 | + struct net_device *dev); |
---|
| 105 | +void nsim_udp_tunnels_info_destroy(struct net_device *dev); |
---|
| 106 | + |
---|
106 | 107 | #ifdef CONFIG_BPF_SYSCALL |
---|
| 108 | +int nsim_bpf_dev_init(struct nsim_dev *nsim_dev); |
---|
| 109 | +void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev); |
---|
107 | 110 | int nsim_bpf_init(struct netdevsim *ns); |
---|
108 | 111 | void nsim_bpf_uninit(struct netdevsim *ns); |
---|
109 | 112 | int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf); |
---|
.. | .. |
---|
111 | 114 | int nsim_bpf_setup_tc_block_cb(enum tc_setup_type type, |
---|
112 | 115 | void *type_data, void *cb_priv); |
---|
113 | 116 | #else |
---|
| 117 | + |
---|
| 118 | +static inline int nsim_bpf_dev_init(struct nsim_dev *nsim_dev) |
---|
| 119 | +{ |
---|
| 120 | + return 0; |
---|
| 121 | +} |
---|
| 122 | + |
---|
| 123 | +static inline void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev) |
---|
| 124 | +{ |
---|
| 125 | +} |
---|
114 | 126 | static inline int nsim_bpf_init(struct netdevsim *ns) |
---|
115 | 127 | { |
---|
116 | 128 | return 0; |
---|
.. | .. |
---|
122 | 134 | |
---|
123 | 135 | static inline int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf) |
---|
124 | 136 | { |
---|
125 | | - return bpf->command == XDP_QUERY_PROG ? 0 : -EOPNOTSUPP; |
---|
| 137 | + return -EOPNOTSUPP; |
---|
126 | 138 | } |
---|
127 | 139 | |
---|
128 | 140 | static inline int nsim_bpf_disable_tc(struct netdevsim *ns) |
---|
.. | .. |
---|
138 | 150 | } |
---|
139 | 151 | #endif |
---|
140 | 152 | |
---|
141 | | -#if IS_ENABLED(CONFIG_NET_DEVLINK) |
---|
142 | 153 | enum nsim_resource_id { |
---|
143 | 154 | NSIM_RESOURCE_NONE, /* DEVLINK_RESOURCE_ID_PARENT_TOP */ |
---|
144 | 155 | NSIM_RESOURCE_IPV4, |
---|
.. | .. |
---|
149 | 160 | NSIM_RESOURCE_IPV6_FIB_RULES, |
---|
150 | 161 | }; |
---|
151 | 162 | |
---|
152 | | -int nsim_devlink_setup(struct netdevsim *ns); |
---|
153 | | -void nsim_devlink_teardown(struct netdevsim *ns); |
---|
| 163 | +struct nsim_dev_health { |
---|
| 164 | + struct devlink_health_reporter *empty_reporter; |
---|
| 165 | + struct devlink_health_reporter *dummy_reporter; |
---|
| 166 | + struct dentry *ddir; |
---|
| 167 | + char *recovered_break_msg; |
---|
| 168 | + u32 binary_len; |
---|
| 169 | + bool fail_recover; |
---|
| 170 | +}; |
---|
154 | 171 | |
---|
155 | | -int nsim_devlink_init(void); |
---|
156 | | -void nsim_devlink_exit(void); |
---|
| 172 | +int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink); |
---|
| 173 | +void nsim_dev_health_exit(struct nsim_dev *nsim_dev); |
---|
157 | 174 | |
---|
158 | | -int nsim_fib_init(void); |
---|
159 | | -void nsim_fib_exit(void); |
---|
160 | | -u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max); |
---|
161 | | -int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val, |
---|
162 | | - struct netlink_ext_ack *extack); |
---|
163 | | -#else |
---|
164 | | -static inline int nsim_devlink_setup(struct netdevsim *ns) |
---|
| 175 | +struct nsim_dev_port { |
---|
| 176 | + struct list_head list; |
---|
| 177 | + struct devlink_port devlink_port; |
---|
| 178 | + unsigned int port_index; |
---|
| 179 | + struct dentry *ddir; |
---|
| 180 | + struct netdevsim *ns; |
---|
| 181 | +}; |
---|
| 182 | + |
---|
| 183 | +struct nsim_dev { |
---|
| 184 | + struct nsim_bus_dev *nsim_bus_dev; |
---|
| 185 | + struct nsim_fib_data *fib_data; |
---|
| 186 | + struct nsim_trap_data *trap_data; |
---|
| 187 | + struct dentry *ddir; |
---|
| 188 | + struct dentry *ports_ddir; |
---|
| 189 | + struct dentry *take_snapshot; |
---|
| 190 | + struct bpf_offload_dev *bpf_dev; |
---|
| 191 | + bool bpf_bind_accept; |
---|
| 192 | + bool bpf_bind_verifier_accept; |
---|
| 193 | + u32 bpf_bind_verifier_delay; |
---|
| 194 | + struct dentry *ddir_bpf_bound_progs; |
---|
| 195 | + u32 prog_id_gen; |
---|
| 196 | + struct list_head bpf_bound_progs; |
---|
| 197 | + struct list_head bpf_bound_maps; |
---|
| 198 | + struct netdev_phys_item_id switch_id; |
---|
| 199 | + struct list_head port_list; |
---|
| 200 | + struct mutex port_list_lock; /* protects port list */ |
---|
| 201 | + bool fw_update_status; |
---|
| 202 | + u32 fw_update_overwrite_mask; |
---|
| 203 | + u32 max_macs; |
---|
| 204 | + bool test1; |
---|
| 205 | + bool dont_allow_reload; |
---|
| 206 | + bool fail_reload; |
---|
| 207 | + struct devlink_region *dummy_region; |
---|
| 208 | + struct nsim_dev_health health; |
---|
| 209 | + struct flow_action_cookie *fa_cookie; |
---|
| 210 | + spinlock_t fa_cookie_lock; /* protects fa_cookie */ |
---|
| 211 | + bool fail_trap_group_set; |
---|
| 212 | + bool fail_trap_policer_set; |
---|
| 213 | + bool fail_trap_policer_counter_get; |
---|
| 214 | + struct { |
---|
| 215 | + struct udp_tunnel_nic_shared utn_shared; |
---|
| 216 | + u32 __ports[2][NSIM_UDP_TUNNEL_N_PORTS]; |
---|
| 217 | + bool sync_all; |
---|
| 218 | + bool open_only; |
---|
| 219 | + bool ipv4_only; |
---|
| 220 | + bool shared; |
---|
| 221 | + bool static_iana_vxlan; |
---|
| 222 | + u32 sleep; |
---|
| 223 | + } udp_ports; |
---|
| 224 | +}; |
---|
| 225 | + |
---|
| 226 | +static inline struct net *nsim_dev_net(struct nsim_dev *nsim_dev) |
---|
165 | 227 | { |
---|
166 | | - return 0; |
---|
| 228 | + return devlink_net(priv_to_devlink(nsim_dev)); |
---|
167 | 229 | } |
---|
168 | 230 | |
---|
169 | | -static inline void nsim_devlink_teardown(struct netdevsim *ns) |
---|
170 | | -{ |
---|
171 | | -} |
---|
| 231 | +int nsim_dev_init(void); |
---|
| 232 | +void nsim_dev_exit(void); |
---|
| 233 | +int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev); |
---|
| 234 | +void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev); |
---|
| 235 | +int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev, |
---|
| 236 | + unsigned int port_index); |
---|
| 237 | +int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev, |
---|
| 238 | + unsigned int port_index); |
---|
172 | 239 | |
---|
173 | | -static inline int nsim_devlink_init(void) |
---|
174 | | -{ |
---|
175 | | - return 0; |
---|
176 | | -} |
---|
177 | | - |
---|
178 | | -static inline void nsim_devlink_exit(void) |
---|
179 | | -{ |
---|
180 | | -} |
---|
181 | | -#endif |
---|
| 240 | +struct nsim_fib_data *nsim_fib_create(struct devlink *devlink, |
---|
| 241 | + struct netlink_ext_ack *extack); |
---|
| 242 | +void nsim_fib_destroy(struct devlink *devlink, struct nsim_fib_data *fib_data); |
---|
| 243 | +u64 nsim_fib_get_val(struct nsim_fib_data *fib_data, |
---|
| 244 | + enum nsim_resource_id res_id, bool max); |
---|
182 | 245 | |
---|
183 | 246 | #if IS_ENABLED(CONFIG_XFRM_OFFLOAD) |
---|
184 | 247 | void nsim_ipsec_init(struct netdevsim *ns); |
---|
.. | .. |
---|
199 | 262 | } |
---|
200 | 263 | #endif |
---|
201 | 264 | |
---|
202 | | -static inline struct netdevsim *to_nsim(struct device *ptr) |
---|
203 | | -{ |
---|
204 | | - return container_of(ptr, struct netdevsim, dev); |
---|
205 | | -} |
---|
| 265 | +struct nsim_vf_config { |
---|
| 266 | + int link_state; |
---|
| 267 | + u16 min_tx_rate; |
---|
| 268 | + u16 max_tx_rate; |
---|
| 269 | + u16 vlan; |
---|
| 270 | + __be16 vlan_proto; |
---|
| 271 | + u16 qos; |
---|
| 272 | + u8 vf_mac[ETH_ALEN]; |
---|
| 273 | + bool spoofchk_enabled; |
---|
| 274 | + bool trusted; |
---|
| 275 | + bool rss_query_enabled; |
---|
| 276 | +}; |
---|
| 277 | + |
---|
| 278 | +struct nsim_bus_dev { |
---|
| 279 | + struct device dev; |
---|
| 280 | + struct list_head list; |
---|
| 281 | + unsigned int port_count; |
---|
| 282 | + struct net *initial_net; /* Purpose of this is to carry net pointer |
---|
| 283 | + * during the probe time only. |
---|
| 284 | + */ |
---|
| 285 | + unsigned int num_vfs; |
---|
| 286 | + struct nsim_vf_config *vfconfigs; |
---|
| 287 | + /* Lock for devlink->reload_enabled in netdevsim module */ |
---|
| 288 | + struct mutex nsim_bus_reload_lock; |
---|
| 289 | + bool init; |
---|
| 290 | +}; |
---|
| 291 | + |
---|
| 292 | +int nsim_bus_init(void); |
---|
| 293 | +void nsim_bus_exit(void); |
---|