xref: /linux/drivers/net/netdevsim/dev.c (revision faee676944dab731c9b2b91cf86c769d291a2237)
1 /*
2  * Copyright (c) 2018 Cumulus Networks. All rights reserved.
3  * Copyright (c) 2018 David Ahern <dsa@cumulusnetworks.com>
4  * Copyright (c) 2019 Mellanox Technologies. All rights reserved.
5  *
6  * This software is licensed under the GNU General License Version 2,
7  * June 1991 as shown in the file COPYING in the top-level directory of this
8  * source tree.
9  *
10  * THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
11  * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
12  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13  * FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
14  * OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
15  * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16  */
17 
18 #include <linux/debugfs.h>
19 #include <linux/device.h>
20 #include <linux/etherdevice.h>
21 #include <linux/inet.h>
22 #include <linux/jiffies.h>
23 #include <linux/kernel.h>
24 #include <linux/list.h>
25 #include <linux/mutex.h>
26 #include <linux/random.h>
27 #include <linux/rtnetlink.h>
28 #include <linux/workqueue.h>
29 #include <net/devlink.h>
30 #include <net/ip.h>
31 #include <net/flow_offload.h>
32 #include <uapi/linux/devlink.h>
33 #include <uapi/linux/ip.h>
34 #include <uapi/linux/udp.h>
35 
36 #include "netdevsim.h"
37 
38 static struct dentry *nsim_dev_ddir;
39 
40 #define NSIM_DEV_DUMMY_REGION_SIZE (1024 * 32)
41 
42 static int
43 nsim_dev_take_snapshot(struct devlink *devlink, struct netlink_ext_ack *extack,
44 		       u8 **data)
45 {
46 	void *dummy_data;
47 
48 	dummy_data = kmalloc(NSIM_DEV_DUMMY_REGION_SIZE, GFP_KERNEL);
49 	if (!dummy_data)
50 		return -ENOMEM;
51 
52 	get_random_bytes(dummy_data, NSIM_DEV_DUMMY_REGION_SIZE);
53 
54 	*data = dummy_data;
55 
56 	return 0;
57 }
58 
59 static ssize_t nsim_dev_take_snapshot_write(struct file *file,
60 					    const char __user *data,
61 					    size_t count, loff_t *ppos)
62 {
63 	struct nsim_dev *nsim_dev = file->private_data;
64 	struct devlink *devlink;
65 	u8 *dummy_data;
66 	int err;
67 	u32 id;
68 
69 	devlink = priv_to_devlink(nsim_dev);
70 
71 	err = nsim_dev_take_snapshot(devlink, NULL, &dummy_data);
72 	if (err)
73 		return err;
74 
75 	err = devlink_region_snapshot_id_get(devlink, &id);
76 	if (err) {
77 		pr_err("Failed to get snapshot id\n");
78 		return err;
79 	}
80 	err = devlink_region_snapshot_create(nsim_dev->dummy_region,
81 					     dummy_data, id);
82 	devlink_region_snapshot_id_put(devlink, id);
83 	if (err) {
84 		pr_err("Failed to create region snapshot\n");
85 		kfree(dummy_data);
86 		return err;
87 	}
88 
89 	return count;
90 }
91 
92 static const struct file_operations nsim_dev_take_snapshot_fops = {
93 	.open = simple_open,
94 	.write = nsim_dev_take_snapshot_write,
95 	.llseek = generic_file_llseek,
96 };
97 
98 static ssize_t nsim_dev_trap_fa_cookie_read(struct file *file,
99 					    char __user *data,
100 					    size_t count, loff_t *ppos)
101 {
102 	struct nsim_dev *nsim_dev = file->private_data;
103 	struct flow_action_cookie *fa_cookie;
104 	unsigned int buf_len;
105 	ssize_t ret;
106 	char *buf;
107 
108 	spin_lock(&nsim_dev->fa_cookie_lock);
109 	fa_cookie = nsim_dev->fa_cookie;
110 	if (!fa_cookie) {
111 		ret = -EINVAL;
112 		goto errout;
113 	}
114 	buf_len = fa_cookie->cookie_len * 2;
115 	buf = kmalloc(buf_len, GFP_ATOMIC);
116 	if (!buf) {
117 		ret = -ENOMEM;
118 		goto errout;
119 	}
120 	bin2hex(buf, fa_cookie->cookie, fa_cookie->cookie_len);
121 	spin_unlock(&nsim_dev->fa_cookie_lock);
122 
123 	ret = simple_read_from_buffer(data, count, ppos, buf, buf_len);
124 
125 	kfree(buf);
126 	return ret;
127 
128 errout:
129 	spin_unlock(&nsim_dev->fa_cookie_lock);
130 	return ret;
131 }
132 
133 static ssize_t nsim_dev_trap_fa_cookie_write(struct file *file,
134 					     const char __user *data,
135 					     size_t count, loff_t *ppos)
136 {
137 	struct nsim_dev *nsim_dev = file->private_data;
138 	struct flow_action_cookie *fa_cookie;
139 	size_t cookie_len;
140 	ssize_t ret;
141 	char *buf;
142 
143 	if (*ppos != 0)
144 		return -EINVAL;
145 	cookie_len = (count - 1) / 2;
146 	if ((count - 1) % 2)
147 		return -EINVAL;
148 	buf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN);
149 	if (!buf)
150 		return -ENOMEM;
151 
152 	ret = simple_write_to_buffer(buf, count, ppos, data, count);
153 	if (ret < 0)
154 		goto free_buf;
155 
156 	fa_cookie = kmalloc(sizeof(*fa_cookie) + cookie_len,
157 			    GFP_KERNEL | __GFP_NOWARN);
158 	if (!fa_cookie) {
159 		ret = -ENOMEM;
160 		goto free_buf;
161 	}
162 
163 	fa_cookie->cookie_len = cookie_len;
164 	ret = hex2bin(fa_cookie->cookie, buf, cookie_len);
165 	if (ret)
166 		goto free_fa_cookie;
167 	kfree(buf);
168 
169 	spin_lock(&nsim_dev->fa_cookie_lock);
170 	kfree(nsim_dev->fa_cookie);
171 	nsim_dev->fa_cookie = fa_cookie;
172 	spin_unlock(&nsim_dev->fa_cookie_lock);
173 
174 	return count;
175 
176 free_fa_cookie:
177 	kfree(fa_cookie);
178 free_buf:
179 	kfree(buf);
180 	return ret;
181 }
182 
183 static const struct file_operations nsim_dev_trap_fa_cookie_fops = {
184 	.open = simple_open,
185 	.read = nsim_dev_trap_fa_cookie_read,
186 	.write = nsim_dev_trap_fa_cookie_write,
187 	.llseek = generic_file_llseek,
188 };
189 
190 static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
191 {
192 	char dev_ddir_name[sizeof(DRV_NAME) + 10];
193 
194 	sprintf(dev_ddir_name, DRV_NAME "%u", nsim_dev->nsim_bus_dev->dev.id);
195 	nsim_dev->ddir = debugfs_create_dir(dev_ddir_name, nsim_dev_ddir);
196 	if (IS_ERR(nsim_dev->ddir))
197 		return PTR_ERR(nsim_dev->ddir);
198 	nsim_dev->ports_ddir = debugfs_create_dir("ports", nsim_dev->ddir);
199 	if (IS_ERR(nsim_dev->ports_ddir))
200 		return PTR_ERR(nsim_dev->ports_ddir);
201 	debugfs_create_bool("fw_update_status", 0600, nsim_dev->ddir,
202 			    &nsim_dev->fw_update_status);
203 	debugfs_create_u32("max_macs", 0600, nsim_dev->ddir,
204 			   &nsim_dev->max_macs);
205 	debugfs_create_bool("test1", 0600, nsim_dev->ddir,
206 			    &nsim_dev->test1);
207 	nsim_dev->take_snapshot = debugfs_create_file("take_snapshot",
208 						      0200,
209 						      nsim_dev->ddir,
210 						      nsim_dev,
211 						&nsim_dev_take_snapshot_fops);
212 	debugfs_create_bool("dont_allow_reload", 0600, nsim_dev->ddir,
213 			    &nsim_dev->dont_allow_reload);
214 	debugfs_create_bool("fail_reload", 0600, nsim_dev->ddir,
215 			    &nsim_dev->fail_reload);
216 	debugfs_create_file("trap_flow_action_cookie", 0600, nsim_dev->ddir,
217 			    nsim_dev, &nsim_dev_trap_fa_cookie_fops);
218 	return 0;
219 }
220 
221 static void nsim_dev_debugfs_exit(struct nsim_dev *nsim_dev)
222 {
223 	debugfs_remove_recursive(nsim_dev->ports_ddir);
224 	debugfs_remove_recursive(nsim_dev->ddir);
225 }
226 
227 static int nsim_dev_port_debugfs_init(struct nsim_dev *nsim_dev,
228 				      struct nsim_dev_port *nsim_dev_port)
229 {
230 	char port_ddir_name[16];
231 	char dev_link_name[32];
232 
233 	sprintf(port_ddir_name, "%u", nsim_dev_port->port_index);
234 	nsim_dev_port->ddir = debugfs_create_dir(port_ddir_name,
235 						 nsim_dev->ports_ddir);
236 	if (IS_ERR(nsim_dev_port->ddir))
237 		return PTR_ERR(nsim_dev_port->ddir);
238 
239 	sprintf(dev_link_name, "../../../" DRV_NAME "%u",
240 		nsim_dev->nsim_bus_dev->dev.id);
241 	debugfs_create_symlink("dev", nsim_dev_port->ddir, dev_link_name);
242 
243 	return 0;
244 }
245 
246 static void nsim_dev_port_debugfs_exit(struct nsim_dev_port *nsim_dev_port)
247 {
248 	debugfs_remove_recursive(nsim_dev_port->ddir);
249 }
250 
251 static int nsim_dev_resources_register(struct devlink *devlink)
252 {
253 	struct devlink_resource_size_params params = {
254 		.size_max = (u64)-1,
255 		.size_granularity = 1,
256 		.unit = DEVLINK_RESOURCE_UNIT_ENTRY
257 	};
258 	int err;
259 
260 	/* Resources for IPv4 */
261 	err = devlink_resource_register(devlink, "IPv4", (u64)-1,
262 					NSIM_RESOURCE_IPV4,
263 					DEVLINK_RESOURCE_ID_PARENT_TOP,
264 					&params);
265 	if (err) {
266 		pr_err("Failed to register IPv4 top resource\n");
267 		goto out;
268 	}
269 
270 	err = devlink_resource_register(devlink, "fib", (u64)-1,
271 					NSIM_RESOURCE_IPV4_FIB,
272 					NSIM_RESOURCE_IPV4, &params);
273 	if (err) {
274 		pr_err("Failed to register IPv4 FIB resource\n");
275 		return err;
276 	}
277 
278 	err = devlink_resource_register(devlink, "fib-rules", (u64)-1,
279 					NSIM_RESOURCE_IPV4_FIB_RULES,
280 					NSIM_RESOURCE_IPV4, &params);
281 	if (err) {
282 		pr_err("Failed to register IPv4 FIB rules resource\n");
283 		return err;
284 	}
285 
286 	/* Resources for IPv6 */
287 	err = devlink_resource_register(devlink, "IPv6", (u64)-1,
288 					NSIM_RESOURCE_IPV6,
289 					DEVLINK_RESOURCE_ID_PARENT_TOP,
290 					&params);
291 	if (err) {
292 		pr_err("Failed to register IPv6 top resource\n");
293 		goto out;
294 	}
295 
296 	err = devlink_resource_register(devlink, "fib", (u64)-1,
297 					NSIM_RESOURCE_IPV6_FIB,
298 					NSIM_RESOURCE_IPV6, &params);
299 	if (err) {
300 		pr_err("Failed to register IPv6 FIB resource\n");
301 		return err;
302 	}
303 
304 	err = devlink_resource_register(devlink, "fib-rules", (u64)-1,
305 					NSIM_RESOURCE_IPV6_FIB_RULES,
306 					NSIM_RESOURCE_IPV6, &params);
307 	if (err) {
308 		pr_err("Failed to register IPv6 FIB rules resource\n");
309 		return err;
310 	}
311 
312 out:
313 	return err;
314 }
315 
316 enum nsim_devlink_param_id {
317 	NSIM_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
318 	NSIM_DEVLINK_PARAM_ID_TEST1,
319 };
320 
321 static const struct devlink_param nsim_devlink_params[] = {
322 	DEVLINK_PARAM_GENERIC(MAX_MACS,
323 			      BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
324 			      NULL, NULL, NULL),
325 	DEVLINK_PARAM_DRIVER(NSIM_DEVLINK_PARAM_ID_TEST1,
326 			     "test1", DEVLINK_PARAM_TYPE_BOOL,
327 			     BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
328 			     NULL, NULL, NULL),
329 };
330 
331 static void nsim_devlink_set_params_init_values(struct nsim_dev *nsim_dev,
332 						struct devlink *devlink)
333 {
334 	union devlink_param_value value;
335 
336 	value.vu32 = nsim_dev->max_macs;
337 	devlink_param_driverinit_value_set(devlink,
338 					   DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
339 					   value);
340 	value.vbool = nsim_dev->test1;
341 	devlink_param_driverinit_value_set(devlink,
342 					   NSIM_DEVLINK_PARAM_ID_TEST1,
343 					   value);
344 }
345 
346 static void nsim_devlink_param_load_driverinit_values(struct devlink *devlink)
347 {
348 	struct nsim_dev *nsim_dev = devlink_priv(devlink);
349 	union devlink_param_value saved_value;
350 	int err;
351 
352 	err = devlink_param_driverinit_value_get(devlink,
353 						 DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
354 						 &saved_value);
355 	if (!err)
356 		nsim_dev->max_macs = saved_value.vu32;
357 	err = devlink_param_driverinit_value_get(devlink,
358 						 NSIM_DEVLINK_PARAM_ID_TEST1,
359 						 &saved_value);
360 	if (!err)
361 		nsim_dev->test1 = saved_value.vbool;
362 }
363 
364 #define NSIM_DEV_DUMMY_REGION_SNAPSHOT_MAX 16
365 
366 static const struct devlink_region_ops dummy_region_ops = {
367 	.name = "dummy",
368 	.destructor = &kfree,
369 	.snapshot = nsim_dev_take_snapshot,
370 };
371 
372 static int nsim_dev_dummy_region_init(struct nsim_dev *nsim_dev,
373 				      struct devlink *devlink)
374 {
375 	nsim_dev->dummy_region =
376 		devlink_region_create(devlink, &dummy_region_ops,
377 				      NSIM_DEV_DUMMY_REGION_SNAPSHOT_MAX,
378 				      NSIM_DEV_DUMMY_REGION_SIZE);
379 	return PTR_ERR_OR_ZERO(nsim_dev->dummy_region);
380 }
381 
382 static void nsim_dev_dummy_region_exit(struct nsim_dev *nsim_dev)
383 {
384 	devlink_region_destroy(nsim_dev->dummy_region);
385 }
386 
387 struct nsim_trap_item {
388 	void *trap_ctx;
389 	enum devlink_trap_action action;
390 };
391 
392 struct nsim_trap_data {
393 	struct delayed_work trap_report_dw;
394 	struct nsim_trap_item *trap_items_arr;
395 	struct nsim_dev *nsim_dev;
396 	spinlock_t trap_lock;	/* Protects trap_items_arr */
397 };
398 
399 /* All driver-specific traps must be documented in
400  * Documentation/networking/devlink/netdevsim.rst
401  */
402 enum {
403 	NSIM_TRAP_ID_BASE = DEVLINK_TRAP_GENERIC_ID_MAX,
404 	NSIM_TRAP_ID_FID_MISS,
405 };
406 
407 #define NSIM_TRAP_NAME_FID_MISS "fid_miss"
408 
409 #define NSIM_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT
410 
411 #define NSIM_TRAP_DROP(_id, _group_id)					      \
412 	DEVLINK_TRAP_GENERIC(DROP, DROP, _id,				      \
413 			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
414 			     NSIM_TRAP_METADATA)
415 #define NSIM_TRAP_DROP_EXT(_id, _group_id, _metadata)			      \
416 	DEVLINK_TRAP_GENERIC(DROP, DROP, _id,				      \
417 			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
418 			     NSIM_TRAP_METADATA | (_metadata))
419 #define NSIM_TRAP_EXCEPTION(_id, _group_id)				      \
420 	DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id,			      \
421 			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
422 			     NSIM_TRAP_METADATA)
423 #define NSIM_TRAP_DRIVER_EXCEPTION(_id, _group_id)			      \
424 	DEVLINK_TRAP_DRIVER(EXCEPTION, TRAP, NSIM_TRAP_ID_##_id,	      \
425 			    NSIM_TRAP_NAME_##_id,			      \
426 			    DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
427 			    NSIM_TRAP_METADATA)
428 
429 static const struct devlink_trap_group nsim_trap_groups_arr[] = {
430 	DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS),
431 	DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS),
432 	DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS),
433 	DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS),
434 };
435 
436 static const struct devlink_trap nsim_traps_arr[] = {
437 	NSIM_TRAP_DROP(SMAC_MC, L2_DROPS),
438 	NSIM_TRAP_DROP(VLAN_TAG_MISMATCH, L2_DROPS),
439 	NSIM_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS),
440 	NSIM_TRAP_DROP(INGRESS_STP_FILTER, L2_DROPS),
441 	NSIM_TRAP_DROP(EMPTY_TX_LIST, L2_DROPS),
442 	NSIM_TRAP_DROP(PORT_LOOPBACK_FILTER, L2_DROPS),
443 	NSIM_TRAP_DRIVER_EXCEPTION(FID_MISS, L2_DROPS),
444 	NSIM_TRAP_DROP(BLACKHOLE_ROUTE, L3_DROPS),
445 	NSIM_TRAP_EXCEPTION(TTL_ERROR, L3_DROPS),
446 	NSIM_TRAP_DROP(TAIL_DROP, BUFFER_DROPS),
447 	NSIM_TRAP_DROP_EXT(INGRESS_FLOW_ACTION_DROP, ACL_DROPS,
448 			   DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE),
449 	NSIM_TRAP_DROP_EXT(EGRESS_FLOW_ACTION_DROP, ACL_DROPS,
450 			   DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE),
451 };
452 
453 #define NSIM_TRAP_L4_DATA_LEN 100
454 
455 static struct sk_buff *nsim_dev_trap_skb_build(void)
456 {
457 	int tot_len, data_len = NSIM_TRAP_L4_DATA_LEN;
458 	struct sk_buff *skb;
459 	struct udphdr *udph;
460 	struct ethhdr *eth;
461 	struct iphdr *iph;
462 
463 	skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
464 	if (!skb)
465 		return NULL;
466 	tot_len = sizeof(struct iphdr) + sizeof(struct udphdr) + data_len;
467 
468 	skb_reset_mac_header(skb);
469 	eth = skb_put(skb, sizeof(struct ethhdr));
470 	eth_random_addr(eth->h_dest);
471 	eth_random_addr(eth->h_source);
472 	eth->h_proto = htons(ETH_P_IP);
473 	skb->protocol = htons(ETH_P_IP);
474 
475 	skb_set_network_header(skb, skb->len);
476 	iph = skb_put(skb, sizeof(struct iphdr));
477 	iph->protocol = IPPROTO_UDP;
478 	iph->saddr = in_aton("192.0.2.1");
479 	iph->daddr = in_aton("198.51.100.1");
480 	iph->version = 0x4;
481 	iph->frag_off = 0;
482 	iph->ihl = 0x5;
483 	iph->tot_len = htons(tot_len);
484 	iph->ttl = 100;
485 	iph->check = 0;
486 	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
487 
488 	skb_set_transport_header(skb, skb->len);
489 	udph = skb_put_zero(skb, sizeof(struct udphdr) + data_len);
490 	get_random_bytes(&udph->source, sizeof(u16));
491 	get_random_bytes(&udph->dest, sizeof(u16));
492 	udph->len = htons(sizeof(struct udphdr) + data_len);
493 
494 	return skb;
495 }
496 
497 static void nsim_dev_trap_report(struct nsim_dev_port *nsim_dev_port)
498 {
499 	struct nsim_dev *nsim_dev = nsim_dev_port->ns->nsim_dev;
500 	struct devlink *devlink = priv_to_devlink(nsim_dev);
501 	struct nsim_trap_data *nsim_trap_data;
502 	int i;
503 
504 	nsim_trap_data = nsim_dev->trap_data;
505 
506 	spin_lock(&nsim_trap_data->trap_lock);
507 	for (i = 0; i < ARRAY_SIZE(nsim_traps_arr); i++) {
508 		struct flow_action_cookie *fa_cookie = NULL;
509 		struct nsim_trap_item *nsim_trap_item;
510 		struct sk_buff *skb;
511 		bool has_fa_cookie;
512 
513 		has_fa_cookie = nsim_traps_arr[i].metadata_cap &
514 				DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE;
515 
516 		nsim_trap_item = &nsim_trap_data->trap_items_arr[i];
517 		if (nsim_trap_item->action == DEVLINK_TRAP_ACTION_DROP)
518 			continue;
519 
520 		skb = nsim_dev_trap_skb_build();
521 		if (!skb)
522 			continue;
523 		skb->dev = nsim_dev_port->ns->netdev;
524 
525 		/* Trapped packets are usually passed to devlink in softIRQ,
526 		 * but in this case they are generated in a workqueue. Disable
527 		 * softIRQs to prevent lockdep from complaining about
528 		 * "incosistent lock state".
529 		 */
530 
531 		spin_lock_bh(&nsim_dev->fa_cookie_lock);
532 		fa_cookie = has_fa_cookie ? nsim_dev->fa_cookie : NULL;
533 		devlink_trap_report(devlink, skb, nsim_trap_item->trap_ctx,
534 				    &nsim_dev_port->devlink_port, fa_cookie);
535 		spin_unlock_bh(&nsim_dev->fa_cookie_lock);
536 		consume_skb(skb);
537 	}
538 	spin_unlock(&nsim_trap_data->trap_lock);
539 }
540 
541 #define NSIM_TRAP_REPORT_INTERVAL_MS	100
542 
543 static void nsim_dev_trap_report_work(struct work_struct *work)
544 {
545 	struct nsim_trap_data *nsim_trap_data;
546 	struct nsim_dev_port *nsim_dev_port;
547 	struct nsim_dev *nsim_dev;
548 
549 	nsim_trap_data = container_of(work, struct nsim_trap_data,
550 				      trap_report_dw.work);
551 	nsim_dev = nsim_trap_data->nsim_dev;
552 
553 	/* For each running port and enabled packet trap, generate a UDP
554 	 * packet with a random 5-tuple and report it.
555 	 */
556 	mutex_lock(&nsim_dev->port_list_lock);
557 	list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list) {
558 		if (!netif_running(nsim_dev_port->ns->netdev))
559 			continue;
560 
561 		nsim_dev_trap_report(nsim_dev_port);
562 	}
563 	mutex_unlock(&nsim_dev->port_list_lock);
564 
565 	schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw,
566 			      msecs_to_jiffies(NSIM_TRAP_REPORT_INTERVAL_MS));
567 }
568 
569 static int nsim_dev_traps_init(struct devlink *devlink)
570 {
571 	struct nsim_dev *nsim_dev = devlink_priv(devlink);
572 	struct nsim_trap_data *nsim_trap_data;
573 	int err;
574 
575 	nsim_trap_data = kzalloc(sizeof(*nsim_trap_data), GFP_KERNEL);
576 	if (!nsim_trap_data)
577 		return -ENOMEM;
578 
579 	nsim_trap_data->trap_items_arr = kcalloc(ARRAY_SIZE(nsim_traps_arr),
580 						 sizeof(struct nsim_trap_item),
581 						 GFP_KERNEL);
582 	if (!nsim_trap_data->trap_items_arr) {
583 		err = -ENOMEM;
584 		goto err_trap_data_free;
585 	}
586 
587 	/* The lock is used to protect the action state of the registered
588 	 * traps. The value is written by user and read in delayed work when
589 	 * iterating over all the traps.
590 	 */
591 	spin_lock_init(&nsim_trap_data->trap_lock);
592 	nsim_trap_data->nsim_dev = nsim_dev;
593 	nsim_dev->trap_data = nsim_trap_data;
594 
595 	err = devlink_trap_groups_register(devlink, nsim_trap_groups_arr,
596 					   ARRAY_SIZE(nsim_trap_groups_arr));
597 	if (err)
598 		goto err_trap_items_free;
599 
600 	err = devlink_traps_register(devlink, nsim_traps_arr,
601 				     ARRAY_SIZE(nsim_traps_arr), NULL);
602 	if (err)
603 		goto err_trap_groups_unregister;
604 
605 	INIT_DELAYED_WORK(&nsim_dev->trap_data->trap_report_dw,
606 			  nsim_dev_trap_report_work);
607 	schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw,
608 			      msecs_to_jiffies(NSIM_TRAP_REPORT_INTERVAL_MS));
609 
610 	return 0;
611 
612 err_trap_groups_unregister:
613 	devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr,
614 				       ARRAY_SIZE(nsim_trap_groups_arr));
615 err_trap_items_free:
616 	kfree(nsim_trap_data->trap_items_arr);
617 err_trap_data_free:
618 	kfree(nsim_trap_data);
619 	return err;
620 }
621 
622 static void nsim_dev_traps_exit(struct devlink *devlink)
623 {
624 	struct nsim_dev *nsim_dev = devlink_priv(devlink);
625 
626 	cancel_delayed_work_sync(&nsim_dev->trap_data->trap_report_dw);
627 	devlink_traps_unregister(devlink, nsim_traps_arr,
628 				 ARRAY_SIZE(nsim_traps_arr));
629 	devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr,
630 				       ARRAY_SIZE(nsim_trap_groups_arr));
631 	kfree(nsim_dev->trap_data->trap_items_arr);
632 	kfree(nsim_dev->trap_data);
633 }
634 
635 static int nsim_dev_reload_create(struct nsim_dev *nsim_dev,
636 				  struct netlink_ext_ack *extack);
637 static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev);
638 
639 static int nsim_dev_reload_down(struct devlink *devlink, bool netns_change,
640 				struct netlink_ext_ack *extack)
641 {
642 	struct nsim_dev *nsim_dev = devlink_priv(devlink);
643 
644 	if (nsim_dev->dont_allow_reload) {
645 		/* For testing purposes, user set debugfs dont_allow_reload
646 		 * value to true. So forbid it.
647 		 */
648 		NL_SET_ERR_MSG_MOD(extack, "User forbid the reload for testing purposes");
649 		return -EOPNOTSUPP;
650 	}
651 
652 	nsim_dev_reload_destroy(nsim_dev);
653 	return 0;
654 }
655 
656 static int nsim_dev_reload_up(struct devlink *devlink,
657 			      struct netlink_ext_ack *extack)
658 {
659 	struct nsim_dev *nsim_dev = devlink_priv(devlink);
660 
661 	if (nsim_dev->fail_reload) {
662 		/* For testing purposes, user set debugfs fail_reload
663 		 * value to true. Fail right away.
664 		 */
665 		NL_SET_ERR_MSG_MOD(extack, "User setup the reload to fail for testing purposes");
666 		return -EINVAL;
667 	}
668 
669 	return nsim_dev_reload_create(nsim_dev, extack);
670 }
671 
672 static int nsim_dev_info_get(struct devlink *devlink,
673 			     struct devlink_info_req *req,
674 			     struct netlink_ext_ack *extack)
675 {
676 	return devlink_info_driver_name_put(req, DRV_NAME);
677 }
678 
679 #define NSIM_DEV_FLASH_SIZE 500000
680 #define NSIM_DEV_FLASH_CHUNK_SIZE 1000
681 #define NSIM_DEV_FLASH_CHUNK_TIME_MS 10
682 
683 static int nsim_dev_flash_update(struct devlink *devlink, const char *file_name,
684 				 const char *component,
685 				 struct netlink_ext_ack *extack)
686 {
687 	struct nsim_dev *nsim_dev = devlink_priv(devlink);
688 	int i;
689 
690 	if (nsim_dev->fw_update_status) {
691 		devlink_flash_update_begin_notify(devlink);
692 		devlink_flash_update_status_notify(devlink,
693 						   "Preparing to flash",
694 						   component, 0, 0);
695 	}
696 
697 	for (i = 0; i < NSIM_DEV_FLASH_SIZE / NSIM_DEV_FLASH_CHUNK_SIZE; i++) {
698 		if (nsim_dev->fw_update_status)
699 			devlink_flash_update_status_notify(devlink, "Flashing",
700 							   component,
701 							   i * NSIM_DEV_FLASH_CHUNK_SIZE,
702 							   NSIM_DEV_FLASH_SIZE);
703 		msleep(NSIM_DEV_FLASH_CHUNK_TIME_MS);
704 	}
705 
706 	if (nsim_dev->fw_update_status) {
707 		devlink_flash_update_status_notify(devlink, "Flashing",
708 						   component,
709 						   NSIM_DEV_FLASH_SIZE,
710 						   NSIM_DEV_FLASH_SIZE);
711 		devlink_flash_update_status_notify(devlink, "Flashing done",
712 						   component, 0, 0);
713 		devlink_flash_update_end_notify(devlink);
714 	}
715 
716 	return 0;
717 }
718 
719 static struct nsim_trap_item *
720 nsim_dev_trap_item_lookup(struct nsim_dev *nsim_dev, u16 trap_id)
721 {
722 	struct nsim_trap_data *nsim_trap_data = nsim_dev->trap_data;
723 	int i;
724 
725 	for (i = 0; i < ARRAY_SIZE(nsim_traps_arr); i++) {
726 		if (nsim_traps_arr[i].id == trap_id)
727 			return &nsim_trap_data->trap_items_arr[i];
728 	}
729 
730 	return NULL;
731 }
732 
733 static int nsim_dev_devlink_trap_init(struct devlink *devlink,
734 				      const struct devlink_trap *trap,
735 				      void *trap_ctx)
736 {
737 	struct nsim_dev *nsim_dev = devlink_priv(devlink);
738 	struct nsim_trap_item *nsim_trap_item;
739 
740 	nsim_trap_item = nsim_dev_trap_item_lookup(nsim_dev, trap->id);
741 	if (WARN_ON(!nsim_trap_item))
742 		return -ENOENT;
743 
744 	nsim_trap_item->trap_ctx = trap_ctx;
745 	nsim_trap_item->action = trap->init_action;
746 
747 	return 0;
748 }
749 
750 static int
751 nsim_dev_devlink_trap_action_set(struct devlink *devlink,
752 				 const struct devlink_trap *trap,
753 				 enum devlink_trap_action action)
754 {
755 	struct nsim_dev *nsim_dev = devlink_priv(devlink);
756 	struct nsim_trap_item *nsim_trap_item;
757 
758 	nsim_trap_item = nsim_dev_trap_item_lookup(nsim_dev, trap->id);
759 	if (WARN_ON(!nsim_trap_item))
760 		return -ENOENT;
761 
762 	spin_lock(&nsim_dev->trap_data->trap_lock);
763 	nsim_trap_item->action = action;
764 	spin_unlock(&nsim_dev->trap_data->trap_lock);
765 
766 	return 0;
767 }
768 
769 static const struct devlink_ops nsim_dev_devlink_ops = {
770 	.reload_down = nsim_dev_reload_down,
771 	.reload_up = nsim_dev_reload_up,
772 	.info_get = nsim_dev_info_get,
773 	.flash_update = nsim_dev_flash_update,
774 	.trap_init = nsim_dev_devlink_trap_init,
775 	.trap_action_set = nsim_dev_devlink_trap_action_set,
776 };
777 
778 #define NSIM_DEV_MAX_MACS_DEFAULT 32
779 #define NSIM_DEV_TEST1_DEFAULT true
780 
781 static int __nsim_dev_port_add(struct nsim_dev *nsim_dev,
782 			       unsigned int port_index)
783 {
784 	struct nsim_dev_port *nsim_dev_port;
785 	struct devlink_port *devlink_port;
786 	int err;
787 
788 	nsim_dev_port = kzalloc(sizeof(*nsim_dev_port), GFP_KERNEL);
789 	if (!nsim_dev_port)
790 		return -ENOMEM;
791 	nsim_dev_port->port_index = port_index;
792 
793 	devlink_port = &nsim_dev_port->devlink_port;
794 	devlink_port_attrs_set(devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
795 			       port_index + 1, 0, 0,
796 			       nsim_dev->switch_id.id,
797 			       nsim_dev->switch_id.id_len);
798 	err = devlink_port_register(priv_to_devlink(nsim_dev), devlink_port,
799 				    port_index);
800 	if (err)
801 		goto err_port_free;
802 
803 	err = nsim_dev_port_debugfs_init(nsim_dev, nsim_dev_port);
804 	if (err)
805 		goto err_dl_port_unregister;
806 
807 	nsim_dev_port->ns = nsim_create(nsim_dev, nsim_dev_port);
808 	if (IS_ERR(nsim_dev_port->ns)) {
809 		err = PTR_ERR(nsim_dev_port->ns);
810 		goto err_port_debugfs_exit;
811 	}
812 
813 	devlink_port_type_eth_set(devlink_port, nsim_dev_port->ns->netdev);
814 	list_add(&nsim_dev_port->list, &nsim_dev->port_list);
815 
816 	return 0;
817 
818 err_port_debugfs_exit:
819 	nsim_dev_port_debugfs_exit(nsim_dev_port);
820 err_dl_port_unregister:
821 	devlink_port_unregister(devlink_port);
822 err_port_free:
823 	kfree(nsim_dev_port);
824 	return err;
825 }
826 
827 static void __nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port)
828 {
829 	struct devlink_port *devlink_port = &nsim_dev_port->devlink_port;
830 
831 	list_del(&nsim_dev_port->list);
832 	devlink_port_type_clear(devlink_port);
833 	nsim_destroy(nsim_dev_port->ns);
834 	nsim_dev_port_debugfs_exit(nsim_dev_port);
835 	devlink_port_unregister(devlink_port);
836 	kfree(nsim_dev_port);
837 }
838 
839 static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev)
840 {
841 	struct nsim_dev_port *nsim_dev_port, *tmp;
842 
843 	mutex_lock(&nsim_dev->port_list_lock);
844 	list_for_each_entry_safe(nsim_dev_port, tmp,
845 				 &nsim_dev->port_list, list)
846 		__nsim_dev_port_del(nsim_dev_port);
847 	mutex_unlock(&nsim_dev->port_list_lock);
848 }
849 
850 static int nsim_dev_port_add_all(struct nsim_dev *nsim_dev,
851 				 unsigned int port_count)
852 {
853 	int i, err;
854 
855 	for (i = 0; i < port_count; i++) {
856 		err = __nsim_dev_port_add(nsim_dev, i);
857 		if (err)
858 			goto err_port_del_all;
859 	}
860 	return 0;
861 
862 err_port_del_all:
863 	nsim_dev_port_del_all(nsim_dev);
864 	return err;
865 }
866 
867 static int nsim_dev_reload_create(struct nsim_dev *nsim_dev,
868 				  struct netlink_ext_ack *extack)
869 {
870 	struct nsim_bus_dev *nsim_bus_dev = nsim_dev->nsim_bus_dev;
871 	struct devlink *devlink;
872 	int err;
873 
874 	devlink = priv_to_devlink(nsim_dev);
875 	nsim_dev = devlink_priv(devlink);
876 	INIT_LIST_HEAD(&nsim_dev->port_list);
877 	mutex_init(&nsim_dev->port_list_lock);
878 	nsim_dev->fw_update_status = true;
879 
880 	nsim_dev->fib_data = nsim_fib_create(devlink, extack);
881 	if (IS_ERR(nsim_dev->fib_data))
882 		return PTR_ERR(nsim_dev->fib_data);
883 
884 	nsim_devlink_param_load_driverinit_values(devlink);
885 
886 	err = nsim_dev_dummy_region_init(nsim_dev, devlink);
887 	if (err)
888 		goto err_fib_destroy;
889 
890 	err = nsim_dev_traps_init(devlink);
891 	if (err)
892 		goto err_dummy_region_exit;
893 
894 	err = nsim_dev_health_init(nsim_dev, devlink);
895 	if (err)
896 		goto err_traps_exit;
897 
898 	err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);
899 	if (err)
900 		goto err_health_exit;
901 
902 	nsim_dev->take_snapshot = debugfs_create_file("take_snapshot",
903 						      0200,
904 						      nsim_dev->ddir,
905 						      nsim_dev,
906 						&nsim_dev_take_snapshot_fops);
907 	return 0;
908 
909 err_health_exit:
910 	nsim_dev_health_exit(nsim_dev);
911 err_traps_exit:
912 	nsim_dev_traps_exit(devlink);
913 err_dummy_region_exit:
914 	nsim_dev_dummy_region_exit(nsim_dev);
915 err_fib_destroy:
916 	nsim_fib_destroy(devlink, nsim_dev->fib_data);
917 	return err;
918 }
919 
920 int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
921 {
922 	struct nsim_dev *nsim_dev;
923 	struct devlink *devlink;
924 	int err;
925 
926 	devlink = devlink_alloc(&nsim_dev_devlink_ops, sizeof(*nsim_dev));
927 	if (!devlink)
928 		return -ENOMEM;
929 	devlink_net_set(devlink, nsim_bus_dev->initial_net);
930 	nsim_dev = devlink_priv(devlink);
931 	nsim_dev->nsim_bus_dev = nsim_bus_dev;
932 	nsim_dev->switch_id.id_len = sizeof(nsim_dev->switch_id.id);
933 	get_random_bytes(nsim_dev->switch_id.id, nsim_dev->switch_id.id_len);
934 	INIT_LIST_HEAD(&nsim_dev->port_list);
935 	mutex_init(&nsim_dev->port_list_lock);
936 	nsim_dev->fw_update_status = true;
937 	nsim_dev->max_macs = NSIM_DEV_MAX_MACS_DEFAULT;
938 	nsim_dev->test1 = NSIM_DEV_TEST1_DEFAULT;
939 	spin_lock_init(&nsim_dev->fa_cookie_lock);
940 
941 	dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev);
942 
943 	err = nsim_dev_resources_register(devlink);
944 	if (err)
945 		goto err_devlink_free;
946 
947 	nsim_dev->fib_data = nsim_fib_create(devlink, NULL);
948 	if (IS_ERR(nsim_dev->fib_data)) {
949 		err = PTR_ERR(nsim_dev->fib_data);
950 		goto err_resources_unregister;
951 	}
952 
953 	err = devlink_register(devlink, &nsim_bus_dev->dev);
954 	if (err)
955 		goto err_fib_destroy;
956 
957 	err = devlink_params_register(devlink, nsim_devlink_params,
958 				      ARRAY_SIZE(nsim_devlink_params));
959 	if (err)
960 		goto err_dl_unregister;
961 	nsim_devlink_set_params_init_values(nsim_dev, devlink);
962 
963 	err = nsim_dev_dummy_region_init(nsim_dev, devlink);
964 	if (err)
965 		goto err_params_unregister;
966 
967 	err = nsim_dev_traps_init(devlink);
968 	if (err)
969 		goto err_dummy_region_exit;
970 
971 	err = nsim_dev_debugfs_init(nsim_dev);
972 	if (err)
973 		goto err_traps_exit;
974 
975 	err = nsim_dev_health_init(nsim_dev, devlink);
976 	if (err)
977 		goto err_debugfs_exit;
978 
979 	err = nsim_bpf_dev_init(nsim_dev);
980 	if (err)
981 		goto err_health_exit;
982 
983 	err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);
984 	if (err)
985 		goto err_bpf_dev_exit;
986 
987 	devlink_params_publish(devlink);
988 	devlink_reload_enable(devlink);
989 	return 0;
990 
991 err_bpf_dev_exit:
992 	nsim_bpf_dev_exit(nsim_dev);
993 err_health_exit:
994 	nsim_dev_health_exit(nsim_dev);
995 err_debugfs_exit:
996 	nsim_dev_debugfs_exit(nsim_dev);
997 err_traps_exit:
998 	nsim_dev_traps_exit(devlink);
999 err_dummy_region_exit:
1000 	nsim_dev_dummy_region_exit(nsim_dev);
1001 err_params_unregister:
1002 	devlink_params_unregister(devlink, nsim_devlink_params,
1003 				  ARRAY_SIZE(nsim_devlink_params));
1004 err_dl_unregister:
1005 	devlink_unregister(devlink);
1006 err_fib_destroy:
1007 	nsim_fib_destroy(devlink, nsim_dev->fib_data);
1008 err_resources_unregister:
1009 	devlink_resources_unregister(devlink, NULL);
1010 err_devlink_free:
1011 	devlink_free(devlink);
1012 	return err;
1013 }
1014 
1015 static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev)
1016 {
1017 	struct devlink *devlink = priv_to_devlink(nsim_dev);
1018 
1019 	if (devlink_is_reload_failed(devlink))
1020 		return;
1021 	debugfs_remove(nsim_dev->take_snapshot);
1022 	nsim_dev_port_del_all(nsim_dev);
1023 	nsim_dev_health_exit(nsim_dev);
1024 	nsim_dev_traps_exit(devlink);
1025 	nsim_dev_dummy_region_exit(nsim_dev);
1026 	mutex_destroy(&nsim_dev->port_list_lock);
1027 	nsim_fib_destroy(devlink, nsim_dev->fib_data);
1028 }
1029 
1030 void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev)
1031 {
1032 	struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
1033 	struct devlink *devlink = priv_to_devlink(nsim_dev);
1034 
1035 	devlink_reload_disable(devlink);
1036 
1037 	nsim_dev_reload_destroy(nsim_dev);
1038 
1039 	nsim_bpf_dev_exit(nsim_dev);
1040 	nsim_dev_debugfs_exit(nsim_dev);
1041 	devlink_params_unregister(devlink, nsim_devlink_params,
1042 				  ARRAY_SIZE(nsim_devlink_params));
1043 	devlink_unregister(devlink);
1044 	devlink_resources_unregister(devlink, NULL);
1045 	devlink_free(devlink);
1046 }
1047 
1048 static struct nsim_dev_port *
1049 __nsim_dev_port_lookup(struct nsim_dev *nsim_dev, unsigned int port_index)
1050 {
1051 	struct nsim_dev_port *nsim_dev_port;
1052 
1053 	list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list)
1054 		if (nsim_dev_port->port_index == port_index)
1055 			return nsim_dev_port;
1056 	return NULL;
1057 }
1058 
1059 int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
1060 		      unsigned int port_index)
1061 {
1062 	struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
1063 	int err;
1064 
1065 	mutex_lock(&nsim_dev->port_list_lock);
1066 	if (__nsim_dev_port_lookup(nsim_dev, port_index))
1067 		err = -EEXIST;
1068 	else
1069 		err = __nsim_dev_port_add(nsim_dev, port_index);
1070 	mutex_unlock(&nsim_dev->port_list_lock);
1071 	return err;
1072 }
1073 
1074 int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
1075 		      unsigned int port_index)
1076 {
1077 	struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
1078 	struct nsim_dev_port *nsim_dev_port;
1079 	int err = 0;
1080 
1081 	mutex_lock(&nsim_dev->port_list_lock);
1082 	nsim_dev_port = __nsim_dev_port_lookup(nsim_dev, port_index);
1083 	if (!nsim_dev_port)
1084 		err = -ENOENT;
1085 	else
1086 		__nsim_dev_port_del(nsim_dev_port);
1087 	mutex_unlock(&nsim_dev->port_list_lock);
1088 	return err;
1089 }
1090 
1091 int nsim_dev_init(void)
1092 {
1093 	nsim_dev_ddir = debugfs_create_dir(DRV_NAME, NULL);
1094 	return PTR_ERR_OR_ZERO(nsim_dev_ddir);
1095 }
1096 
1097 void nsim_dev_exit(void)
1098 {
1099 	debugfs_remove_recursive(nsim_dev_ddir);
1100 }
1101