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