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