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 | struct u64_stats_sync syncp; |
102 | |
103 | struct nsim_bus_dev *nsim_bus_dev; |
104 | |
105 | struct bpf_prog *bpf_offloaded; |
106 | u32 bpf_offloaded_id; |
107 | |
108 | struct xdp_attachment_info xdp; |
109 | struct xdp_attachment_info xdp_hw; |
110 | |
111 | bool bpf_tc_accept; |
112 | bool bpf_tc_non_bound_accept; |
113 | bool bpf_xdpdrv_accept; |
114 | bool bpf_xdpoffload_accept; |
115 | |
116 | bool bpf_map_accept; |
117 | struct nsim_ipsec ipsec; |
118 | struct nsim_macsec macsec; |
119 | struct { |
120 | u32 inject_error; |
121 | u32 sleep; |
122 | u32 __ports[2][NSIM_UDP_TUNNEL_N_PORTS]; |
123 | u32 (*ports)[NSIM_UDP_TUNNEL_N_PORTS]; |
124 | struct debugfs_u32_array dfs_ports[2]; |
125 | } udp_ports; |
126 | |
127 | struct nsim_ethtool ethtool; |
128 | }; |
129 | |
130 | struct netdevsim * |
131 | nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port); |
132 | void nsim_destroy(struct netdevsim *ns); |
133 | |
134 | void nsim_ethtool_init(struct netdevsim *ns); |
135 | |
136 | void nsim_udp_tunnels_debugfs_create(struct nsim_dev *nsim_dev); |
137 | int nsim_udp_tunnels_info_create(struct nsim_dev *nsim_dev, |
138 | struct net_device *dev); |
139 | void nsim_udp_tunnels_info_destroy(struct net_device *dev); |
140 | |
141 | #ifdef CONFIG_BPF_SYSCALL |
142 | int nsim_bpf_dev_init(struct nsim_dev *nsim_dev); |
143 | void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev); |
144 | int nsim_bpf_init(struct netdevsim *ns); |
145 | void nsim_bpf_uninit(struct netdevsim *ns); |
146 | int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf); |
147 | int nsim_bpf_disable_tc(struct netdevsim *ns); |
148 | int nsim_bpf_setup_tc_block_cb(enum tc_setup_type type, |
149 | void *type_data, void *cb_priv); |
150 | #else |
151 | |
152 | static inline int nsim_bpf_dev_init(struct nsim_dev *nsim_dev) |
153 | { |
154 | return 0; |
155 | } |
156 | |
157 | static inline void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev) |
158 | { |
159 | } |
160 | static inline int nsim_bpf_init(struct netdevsim *ns) |
161 | { |
162 | return 0; |
163 | } |
164 | |
165 | static inline void nsim_bpf_uninit(struct netdevsim *ns) |
166 | { |
167 | } |
168 | |
169 | static inline int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf) |
170 | { |
171 | return -EOPNOTSUPP; |
172 | } |
173 | |
174 | static inline int nsim_bpf_disable_tc(struct netdevsim *ns) |
175 | { |
176 | return 0; |
177 | } |
178 | |
179 | static inline int |
180 | nsim_bpf_setup_tc_block_cb(enum tc_setup_type type, void *type_data, |
181 | void *cb_priv) |
182 | { |
183 | return -EOPNOTSUPP; |
184 | } |
185 | #endif |
186 | |
187 | enum nsim_resource_id { |
188 | NSIM_RESOURCE_NONE, /* DEVLINK_RESOURCE_ID_PARENT_TOP */ |
189 | NSIM_RESOURCE_IPV4, |
190 | NSIM_RESOURCE_IPV4_FIB, |
191 | NSIM_RESOURCE_IPV4_FIB_RULES, |
192 | NSIM_RESOURCE_IPV6, |
193 | NSIM_RESOURCE_IPV6_FIB, |
194 | NSIM_RESOURCE_IPV6_FIB_RULES, |
195 | NSIM_RESOURCE_NEXTHOPS, |
196 | }; |
197 | |
198 | struct nsim_dev_health { |
199 | struct devlink_health_reporter *empty_reporter; |
200 | struct devlink_health_reporter *dummy_reporter; |
201 | struct dentry *ddir; |
202 | char *recovered_break_msg; |
203 | u32 binary_len; |
204 | bool fail_recover; |
205 | }; |
206 | |
207 | int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink); |
208 | void nsim_dev_health_exit(struct nsim_dev *nsim_dev); |
209 | |
210 | struct nsim_dev_hwstats_netdev { |
211 | struct list_head list; |
212 | struct net_device *netdev; |
213 | struct rtnl_hw_stats64 stats; |
214 | bool enabled; |
215 | bool fail_enable; |
216 | }; |
217 | |
218 | struct nsim_dev_hwstats { |
219 | struct dentry *ddir; |
220 | struct dentry *l3_ddir; |
221 | |
222 | struct mutex hwsdev_list_lock; /* protects hwsdev list(s) */ |
223 | struct list_head l3_list; |
224 | |
225 | struct notifier_block netdevice_nb; |
226 | struct delayed_work traffic_dw; |
227 | }; |
228 | |
229 | int nsim_dev_hwstats_init(struct nsim_dev *nsim_dev); |
230 | void nsim_dev_hwstats_exit(struct nsim_dev *nsim_dev); |
231 | |
232 | #if IS_ENABLED(CONFIG_PSAMPLE) |
233 | int nsim_dev_psample_init(struct nsim_dev *nsim_dev); |
234 | void nsim_dev_psample_exit(struct nsim_dev *nsim_dev); |
235 | #else |
236 | static inline int nsim_dev_psample_init(struct nsim_dev *nsim_dev) |
237 | { |
238 | return 0; |
239 | } |
240 | |
241 | static inline void nsim_dev_psample_exit(struct nsim_dev *nsim_dev) |
242 | { |
243 | } |
244 | #endif |
245 | |
246 | enum nsim_dev_port_type { |
247 | NSIM_DEV_PORT_TYPE_PF, |
248 | NSIM_DEV_PORT_TYPE_VF, |
249 | }; |
250 | |
251 | #define NSIM_DEV_VF_PORT_INDEX_BASE 128 |
252 | #define NSIM_DEV_VF_PORT_INDEX_MAX UINT_MAX |
253 | |
254 | struct nsim_dev_port { |
255 | struct list_head list; |
256 | struct devlink_port devlink_port; |
257 | unsigned int port_index; |
258 | enum nsim_dev_port_type port_type; |
259 | struct dentry *ddir; |
260 | struct dentry *rate_parent; |
261 | char *parent_name; |
262 | struct netdevsim *ns; |
263 | }; |
264 | |
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 ; |
276 | }; |
277 | |
278 | struct nsim_dev { |
279 | struct nsim_bus_dev *nsim_bus_dev; |
280 | struct nsim_fib_data *fib_data; |
281 | struct nsim_trap_data *trap_data; |
282 | struct dentry *ddir; |
283 | struct dentry *ports_ddir; |
284 | struct dentry *take_snapshot; |
285 | struct dentry *nodes_ddir; |
286 | |
287 | struct nsim_vf_config *vfconfigs; |
288 | |
289 | struct bpf_offload_dev *bpf_dev; |
290 | bool bpf_bind_accept; |
291 | bool bpf_bind_verifier_accept; |
292 | u32 bpf_bind_verifier_delay; |
293 | struct dentry *ddir_bpf_bound_progs; |
294 | u32 prog_id_gen; |
295 | struct list_head bpf_bound_progs; |
296 | struct list_head bpf_bound_maps; |
297 | struct netdev_phys_item_id switch_id; |
298 | struct list_head port_list; |
299 | bool fw_update_status; |
300 | u32 fw_update_overwrite_mask; |
301 | u32 max_macs; |
302 | bool test1; |
303 | bool dont_allow_reload; |
304 | bool fail_reload; |
305 | struct devlink_region *dummy_region; |
306 | struct nsim_dev_health health; |
307 | struct nsim_dev_hwstats hwstats; |
308 | struct flow_action_cookie *fa_cookie; |
309 | spinlock_t fa_cookie_lock; /* protects fa_cookie */ |
310 | bool fail_trap_group_set; |
311 | bool fail_trap_policer_set; |
312 | bool fail_trap_policer_counter_get; |
313 | bool fail_trap_drop_counter_get; |
314 | struct { |
315 | struct udp_tunnel_nic_shared utn_shared; |
316 | u32 __ports[2][NSIM_UDP_TUNNEL_N_PORTS]; |
317 | bool sync_all; |
318 | bool open_only; |
319 | bool ipv4_only; |
320 | bool shared; |
321 | bool static_iana_vxlan; |
322 | u32 sleep; |
323 | } udp_ports; |
324 | struct nsim_dev_psample *psample; |
325 | u16 esw_mode; |
326 | }; |
327 | |
328 | static inline bool nsim_esw_mode_is_legacy(struct nsim_dev *nsim_dev) |
329 | { |
330 | return nsim_dev->esw_mode == DEVLINK_ESWITCH_MODE_LEGACY; |
331 | } |
332 | |
333 | static inline bool nsim_esw_mode_is_switchdev(struct nsim_dev *nsim_dev) |
334 | { |
335 | return nsim_dev->esw_mode == DEVLINK_ESWITCH_MODE_SWITCHDEV; |
336 | } |
337 | |
338 | static inline struct net *nsim_dev_net(struct nsim_dev *nsim_dev) |
339 | { |
340 | return devlink_net(devlink: priv_to_devlink(priv: nsim_dev)); |
341 | } |
342 | |
343 | int nsim_dev_init(void); |
344 | void nsim_dev_exit(void); |
345 | int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev); |
346 | void nsim_drv_remove(struct nsim_bus_dev *nsim_bus_dev); |
347 | int nsim_drv_port_add(struct nsim_bus_dev *nsim_bus_dev, |
348 | enum nsim_dev_port_type type, |
349 | unsigned int port_index); |
350 | int nsim_drv_port_del(struct nsim_bus_dev *nsim_bus_dev, |
351 | enum nsim_dev_port_type type, |
352 | unsigned int port_index); |
353 | int nsim_drv_configure_vfs(struct nsim_bus_dev *nsim_bus_dev, |
354 | unsigned int num_vfs); |
355 | |
356 | unsigned int nsim_dev_get_vfs(struct nsim_dev *nsim_dev); |
357 | |
358 | struct nsim_fib_data *nsim_fib_create(struct devlink *devlink, |
359 | struct netlink_ext_ack *extack); |
360 | void nsim_fib_destroy(struct devlink *devlink, struct nsim_fib_data *fib_data); |
361 | u64 nsim_fib_get_val(struct nsim_fib_data *fib_data, |
362 | enum nsim_resource_id res_id, bool max); |
363 | |
364 | static inline bool nsim_dev_port_is_pf(struct nsim_dev_port *nsim_dev_port) |
365 | { |
366 | return nsim_dev_port->port_type == NSIM_DEV_PORT_TYPE_PF; |
367 | } |
368 | |
369 | static inline bool nsim_dev_port_is_vf(struct nsim_dev_port *nsim_dev_port) |
370 | { |
371 | return nsim_dev_port->port_type == NSIM_DEV_PORT_TYPE_VF; |
372 | } |
373 | #if IS_ENABLED(CONFIG_XFRM_OFFLOAD) |
374 | void nsim_ipsec_init(struct netdevsim *ns); |
375 | void nsim_ipsec_teardown(struct netdevsim *ns); |
376 | bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb); |
377 | #else |
378 | static inline void nsim_ipsec_init(struct netdevsim *ns) |
379 | { |
380 | } |
381 | |
382 | static inline void nsim_ipsec_teardown(struct netdevsim *ns) |
383 | { |
384 | } |
385 | |
386 | static inline bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb) |
387 | { |
388 | return true; |
389 | } |
390 | #endif |
391 | |
392 | #if IS_ENABLED(CONFIG_MACSEC) |
393 | void nsim_macsec_init(struct netdevsim *ns); |
394 | void nsim_macsec_teardown(struct netdevsim *ns); |
395 | #else |
396 | static inline void nsim_macsec_init(struct netdevsim *ns) |
397 | { |
398 | } |
399 | |
400 | static inline void nsim_macsec_teardown(struct netdevsim *ns) |
401 | { |
402 | } |
403 | #endif |
404 | |
405 | struct nsim_bus_dev { |
406 | struct device dev; |
407 | struct list_head list; |
408 | unsigned int port_count; |
409 | unsigned int num_queues; /* Number of queues for each port on this bus */ |
410 | struct net *initial_net; /* Purpose of this is to carry net pointer |
411 | * during the probe time only. |
412 | */ |
413 | unsigned int max_vfs; |
414 | unsigned int num_vfs; |
415 | bool init; |
416 | }; |
417 | |
418 | int nsim_bus_init(void); |
419 | void nsim_bus_exit(void); |
420 | |