1 | /* |
2 | * Copyright (C) 2017 Netronome Systems, Inc. |
3 | * |
4 | * This software is licensed under the GNU General License Version 2, |
5 | * June 1991 as shown in the file COPYING in the top-level directory of this |
6 | * source tree. |
7 | * |
8 | * THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" |
9 | * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, |
10 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
11 | * FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE |
12 | * OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME |
13 | * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. |
14 | */ |
15 | |
16 | #include <linux/debugfs.h> |
17 | #include <linux/device.h> |
18 | #include <linux/ethtool.h> |
19 | #include <linux/kernel.h> |
20 | #include <linux/list.h> |
21 | #include <linux/netdevice.h> |
22 | #include <linux/ptp_mock.h> |
23 | #include <linux/u64_stats_sync.h> |
24 | #include <net/devlink.h> |
25 | #include <net/udp_tunnel.h> |
26 | #include <net/xdp.h> |
27 | #include <net/macsec.h> |
28 | |
29 | #define DRV_NAME "netdevsim" |
30 | |
31 | #define NSIM_XDP_MAX_MTU 4000 |
32 | |
33 | #define NSIM_EA(extack, msg) NL_SET_ERR_MSG_MOD((extack), msg) |
34 | |
35 | #define NSIM_IPSEC_MAX_SA_COUNT 33 |
36 | #define NSIM_IPSEC_VALID BIT(31) |
37 | #define NSIM_UDP_TUNNEL_N_PORTS 4 |
38 | |
39 | struct nsim_sa { |
40 | struct xfrm_state *xs; |
41 | __be32 ipaddr[4]; |
42 | u32 key[4]; |
43 | u32 salt; |
44 | bool used; |
45 | bool crypt; |
46 | bool rx; |
47 | }; |
48 | |
49 | struct nsim_ipsec { |
50 | struct nsim_sa sa[NSIM_IPSEC_MAX_SA_COUNT]; |
51 | struct dentry *pfile; |
52 | u32 count; |
53 | u32 tx; |
54 | u32 ok; |
55 | }; |
56 | |
57 | #define NSIM_MACSEC_MAX_SECY_COUNT 3 |
58 | #define NSIM_MACSEC_MAX_RXSC_COUNT 1 |
59 | struct nsim_rxsc { |
60 | sci_t sci; |
61 | bool used; |
62 | }; |
63 | |
64 | struct nsim_secy { |
65 | sci_t sci; |
66 | struct nsim_rxsc nsim_rxsc[NSIM_MACSEC_MAX_RXSC_COUNT]; |
67 | u8 nsim_rxsc_count; |
68 | bool used; |
69 | }; |
70 | |
71 | struct nsim_macsec { |
72 | struct nsim_secy nsim_secy[NSIM_MACSEC_MAX_SECY_COUNT]; |
73 | u8 nsim_secy_count; |
74 | }; |
75 | |
76 | struct nsim_ethtool_pauseparam { |
77 | bool rx; |
78 | bool tx; |
79 | bool report_stats_rx; |
80 | bool report_stats_tx; |
81 | }; |
82 | |
83 | struct nsim_ethtool { |
84 | u32 get_err; |
85 | u32 set_err; |
86 | u32 channels; |
87 | struct nsim_ethtool_pauseparam pauseparam; |
88 | struct ethtool_coalesce coalesce; |
89 | struct ethtool_ringparam ring; |
90 | struct ethtool_fecparam fec; |
91 | }; |
92 | |
93 | struct netdevsim { |
94 | struct net_device *netdev; |
95 | struct nsim_dev *nsim_dev; |
96 | struct nsim_dev_port *nsim_dev_port; |
97 | struct mock_phc *phc; |
98 | |
99 | u64 tx_packets; |
100 | u64 tx_bytes; |
101 | u64 tx_dropped; |
102 | struct u64_stats_sync syncp; |
103 | |
104 | struct nsim_bus_dev *nsim_bus_dev; |
105 | |
106 | struct bpf_prog *bpf_offloaded; |
107 | u32 bpf_offloaded_id; |
108 | |
109 | struct xdp_attachment_info xdp; |
110 | struct xdp_attachment_info xdp_hw; |
111 | |
112 | bool bpf_tc_accept; |
113 | bool bpf_tc_non_bound_accept; |
114 | bool bpf_xdpdrv_accept; |
115 | bool bpf_xdpoffload_accept; |
116 | |
117 | bool bpf_map_accept; |
118 | struct nsim_ipsec ipsec; |
119 | struct nsim_macsec macsec; |
120 | struct { |
121 | u32 inject_error; |
122 | u32 sleep; |
123 | u32 __ports[2][NSIM_UDP_TUNNEL_N_PORTS]; |
124 | u32 (*ports)[NSIM_UDP_TUNNEL_N_PORTS]; |
125 | struct debugfs_u32_array dfs_ports[2]; |
126 | } udp_ports; |
127 | |
128 | struct nsim_ethtool ethtool; |
129 | struct netdevsim __rcu *peer; |
130 | }; |
131 | |
132 | struct netdevsim * |
133 | nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port); |
134 | void nsim_destroy(struct netdevsim *ns); |
135 | bool netdev_is_nsim(struct net_device *dev); |
136 | |
137 | void nsim_ethtool_init(struct netdevsim *ns); |
138 | |
139 | void nsim_udp_tunnels_debugfs_create(struct nsim_dev *nsim_dev); |
140 | int nsim_udp_tunnels_info_create(struct nsim_dev *nsim_dev, |
141 | struct net_device *dev); |
142 | void nsim_udp_tunnels_info_destroy(struct net_device *dev); |
143 | |
144 | #ifdef CONFIG_BPF_SYSCALL |
145 | int nsim_bpf_dev_init(struct nsim_dev *nsim_dev); |
146 | void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev); |
147 | int nsim_bpf_init(struct netdevsim *ns); |
148 | void nsim_bpf_uninit(struct netdevsim *ns); |
149 | int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf); |
150 | int nsim_bpf_disable_tc(struct netdevsim *ns); |
151 | int nsim_bpf_setup_tc_block_cb(enum tc_setup_type type, |
152 | void *type_data, void *cb_priv); |
153 | #else |
154 | |
155 | static inline int nsim_bpf_dev_init(struct nsim_dev *nsim_dev) |
156 | { |
157 | return 0; |
158 | } |
159 | |
160 | static inline void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev) |
161 | { |
162 | } |
163 | static inline int nsim_bpf_init(struct netdevsim *ns) |
164 | { |
165 | return 0; |
166 | } |
167 | |
168 | static inline void nsim_bpf_uninit(struct netdevsim *ns) |
169 | { |
170 | } |
171 | |
172 | static inline int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf) |
173 | { |
174 | return -EOPNOTSUPP; |
175 | } |
176 | |
177 | static inline int nsim_bpf_disable_tc(struct netdevsim *ns) |
178 | { |
179 | return 0; |
180 | } |
181 | |
182 | static inline int |
183 | nsim_bpf_setup_tc_block_cb(enum tc_setup_type type, void *type_data, |
184 | void *cb_priv) |
185 | { |
186 | return -EOPNOTSUPP; |
187 | } |
188 | #endif |
189 | |
190 | enum nsim_resource_id { |
191 | NSIM_RESOURCE_NONE, /* DEVLINK_RESOURCE_ID_PARENT_TOP */ |
192 | NSIM_RESOURCE_IPV4, |
193 | NSIM_RESOURCE_IPV4_FIB, |
194 | NSIM_RESOURCE_IPV4_FIB_RULES, |
195 | NSIM_RESOURCE_IPV6, |
196 | NSIM_RESOURCE_IPV6_FIB, |
197 | NSIM_RESOURCE_IPV6_FIB_RULES, |
198 | NSIM_RESOURCE_NEXTHOPS, |
199 | }; |
200 | |
201 | struct nsim_dev_health { |
202 | struct devlink_health_reporter *empty_reporter; |
203 | struct devlink_health_reporter *dummy_reporter; |
204 | struct dentry *ddir; |
205 | char *recovered_break_msg; |
206 | u32 binary_len; |
207 | bool fail_recover; |
208 | }; |
209 | |
210 | int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink); |
211 | void nsim_dev_health_exit(struct nsim_dev *nsim_dev); |
212 | |
213 | struct nsim_dev_hwstats_netdev { |
214 | struct list_head list; |
215 | struct net_device *netdev; |
216 | struct rtnl_hw_stats64 stats; |
217 | bool enabled; |
218 | bool fail_enable; |
219 | }; |
220 | |
221 | struct nsim_dev_hwstats { |
222 | struct dentry *ddir; |
223 | struct dentry *l3_ddir; |
224 | |
225 | struct mutex hwsdev_list_lock; /* protects hwsdev list(s) */ |
226 | struct list_head l3_list; |
227 | |
228 | struct notifier_block netdevice_nb; |
229 | struct delayed_work traffic_dw; |
230 | }; |
231 | |
232 | int nsim_dev_hwstats_init(struct nsim_dev *nsim_dev); |
233 | void nsim_dev_hwstats_exit(struct nsim_dev *nsim_dev); |
234 | |
235 | #if IS_ENABLED(CONFIG_PSAMPLE) |
236 | int nsim_dev_psample_init(struct nsim_dev *nsim_dev); |
237 | void nsim_dev_psample_exit(struct nsim_dev *nsim_dev); |
238 | #else |
239 | static inline int nsim_dev_psample_init(struct nsim_dev *nsim_dev) |
240 | { |
241 | return 0; |
242 | } |
243 | |
244 | static inline void nsim_dev_psample_exit(struct nsim_dev *nsim_dev) |
245 | { |
246 | } |
247 | #endif |
248 | |
249 | enum nsim_dev_port_type { |
250 | NSIM_DEV_PORT_TYPE_PF, |
251 | NSIM_DEV_PORT_TYPE_VF, |
252 | }; |
253 | |
254 | #define NSIM_DEV_VF_PORT_INDEX_BASE 128 |
255 | #define NSIM_DEV_VF_PORT_INDEX_MAX UINT_MAX |
256 | |
257 | struct nsim_dev_port { |
258 | struct list_head list; |
259 | struct devlink_port devlink_port; |
260 | unsigned int port_index; |
261 | enum nsim_dev_port_type port_type; |
262 | struct dentry *ddir; |
263 | struct dentry *rate_parent; |
264 | char *parent_name; |
265 | struct netdevsim *ns; |
266 | }; |
267 | |
268 | struct nsim_vf_config { |
269 | int link_state; |
270 | u16 min_tx_rate; |
271 | u16 max_tx_rate; |
272 | u16 vlan; |
273 | __be16 vlan_proto; |
274 | u16 qos; |
275 | u8 vf_mac[ETH_ALEN]; |
276 | bool spoofchk_enabled; |
277 | bool trusted; |
278 | bool ; |
279 | }; |
280 | |
281 | struct nsim_dev { |
282 | struct nsim_bus_dev *nsim_bus_dev; |
283 | struct nsim_fib_data *fib_data; |
284 | struct nsim_trap_data *trap_data; |
285 | struct dentry *ddir; |
286 | struct dentry *ports_ddir; |
287 | struct dentry *take_snapshot; |
288 | struct dentry *nodes_ddir; |
289 | |
290 | struct nsim_vf_config *vfconfigs; |
291 | |
292 | struct bpf_offload_dev *bpf_dev; |
293 | bool bpf_bind_accept; |
294 | bool bpf_bind_verifier_accept; |
295 | u32 bpf_bind_verifier_delay; |
296 | struct dentry *ddir_bpf_bound_progs; |
297 | u32 prog_id_gen; |
298 | struct list_head bpf_bound_progs; |
299 | struct list_head bpf_bound_maps; |
300 | struct netdev_phys_item_id switch_id; |
301 | struct list_head port_list; |
302 | bool fw_update_status; |
303 | u32 fw_update_overwrite_mask; |
304 | u32 max_macs; |
305 | bool test1; |
306 | bool dont_allow_reload; |
307 | bool fail_reload; |
308 | struct devlink_region *dummy_region; |
309 | struct nsim_dev_health health; |
310 | struct nsim_dev_hwstats hwstats; |
311 | struct flow_action_cookie *fa_cookie; |
312 | spinlock_t fa_cookie_lock; /* protects fa_cookie */ |
313 | bool fail_trap_group_set; |
314 | bool fail_trap_policer_set; |
315 | bool fail_trap_policer_counter_get; |
316 | bool fail_trap_drop_counter_get; |
317 | struct { |
318 | struct udp_tunnel_nic_shared utn_shared; |
319 | u32 __ports[2][NSIM_UDP_TUNNEL_N_PORTS]; |
320 | bool sync_all; |
321 | bool open_only; |
322 | bool ipv4_only; |
323 | bool shared; |
324 | bool static_iana_vxlan; |
325 | u32 sleep; |
326 | } udp_ports; |
327 | struct nsim_dev_psample *psample; |
328 | u16 esw_mode; |
329 | }; |
330 | |
331 | static inline bool nsim_esw_mode_is_legacy(struct nsim_dev *nsim_dev) |
332 | { |
333 | return nsim_dev->esw_mode == DEVLINK_ESWITCH_MODE_LEGACY; |
334 | } |
335 | |
336 | static inline bool nsim_esw_mode_is_switchdev(struct nsim_dev *nsim_dev) |
337 | { |
338 | return nsim_dev->esw_mode == DEVLINK_ESWITCH_MODE_SWITCHDEV; |
339 | } |
340 | |
341 | static inline struct net *nsim_dev_net(struct nsim_dev *nsim_dev) |
342 | { |
343 | return devlink_net(devlink: priv_to_devlink(priv: nsim_dev)); |
344 | } |
345 | |
346 | int nsim_dev_init(void); |
347 | void nsim_dev_exit(void); |
348 | int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev); |
349 | void nsim_drv_remove(struct nsim_bus_dev *nsim_bus_dev); |
350 | int nsim_drv_port_add(struct nsim_bus_dev *nsim_bus_dev, |
351 | enum nsim_dev_port_type type, |
352 | unsigned int port_index); |
353 | int nsim_drv_port_del(struct nsim_bus_dev *nsim_bus_dev, |
354 | enum nsim_dev_port_type type, |
355 | unsigned int port_index); |
356 | int nsim_drv_configure_vfs(struct nsim_bus_dev *nsim_bus_dev, |
357 | unsigned int num_vfs); |
358 | |
359 | unsigned int nsim_dev_get_vfs(struct nsim_dev *nsim_dev); |
360 | |
361 | struct nsim_fib_data *nsim_fib_create(struct devlink *devlink, |
362 | struct netlink_ext_ack *extack); |
363 | void nsim_fib_destroy(struct devlink *devlink, struct nsim_fib_data *fib_data); |
364 | u64 nsim_fib_get_val(struct nsim_fib_data *fib_data, |
365 | enum nsim_resource_id res_id, bool max); |
366 | |
367 | static inline bool nsim_dev_port_is_pf(struct nsim_dev_port *nsim_dev_port) |
368 | { |
369 | return nsim_dev_port->port_type == NSIM_DEV_PORT_TYPE_PF; |
370 | } |
371 | |
372 | static inline bool nsim_dev_port_is_vf(struct nsim_dev_port *nsim_dev_port) |
373 | { |
374 | return nsim_dev_port->port_type == NSIM_DEV_PORT_TYPE_VF; |
375 | } |
376 | #if IS_ENABLED(CONFIG_XFRM_OFFLOAD) |
377 | void nsim_ipsec_init(struct netdevsim *ns); |
378 | void nsim_ipsec_teardown(struct netdevsim *ns); |
379 | bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb); |
380 | #else |
381 | static inline void nsim_ipsec_init(struct netdevsim *ns) |
382 | { |
383 | } |
384 | |
385 | static inline void nsim_ipsec_teardown(struct netdevsim *ns) |
386 | { |
387 | } |
388 | |
389 | static inline bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb) |
390 | { |
391 | return true; |
392 | } |
393 | #endif |
394 | |
395 | #if IS_ENABLED(CONFIG_MACSEC) |
396 | void nsim_macsec_init(struct netdevsim *ns); |
397 | void nsim_macsec_teardown(struct netdevsim *ns); |
398 | #else |
399 | static inline void nsim_macsec_init(struct netdevsim *ns) |
400 | { |
401 | } |
402 | |
403 | static inline void nsim_macsec_teardown(struct netdevsim *ns) |
404 | { |
405 | } |
406 | #endif |
407 | |
408 | struct nsim_bus_dev { |
409 | struct device dev; |
410 | struct list_head list; |
411 | unsigned int port_count; |
412 | unsigned int num_queues; /* Number of queues for each port on this bus */ |
413 | struct net *initial_net; /* Purpose of this is to carry net pointer |
414 | * during the probe time only. |
415 | */ |
416 | unsigned int max_vfs; |
417 | unsigned int num_vfs; |
418 | bool init; |
419 | }; |
420 | |
421 | int nsim_bus_init(void); |
422 | void nsim_bus_exit(void); |
423 | |