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