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.
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
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.
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>
31 #include <uapi/linux/devlink.h>
32 #include <uapi/linux/ip.h>
33 #include <uapi/linux/udp.h>
35 #include "netdevsim.h"
37 static struct dentry *nsim_dev_ddir;
39 #define NSIM_DEV_DUMMY_REGION_SIZE (1024 * 32)
41 static ssize_t nsim_dev_take_snapshot_write(struct file *file,
42 const char __user *data,
43 size_t count, loff_t *ppos)
45 struct nsim_dev *nsim_dev = file->private_data;
50 dummy_data = kmalloc(NSIM_DEV_DUMMY_REGION_SIZE, GFP_KERNEL);
54 get_random_bytes(dummy_data, NSIM_DEV_DUMMY_REGION_SIZE);
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);
60 pr_err("Failed to create region snapshot\n");
68 static const struct file_operations nsim_dev_take_snapshot_fops = {
70 .write = nsim_dev_take_snapshot_write,
71 .llseek = generic_file_llseek,
74 static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
76 char dev_ddir_name[16];
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,
89 debugfs_create_bool("test1", 0600, nsim_dev->ddir,
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);
100 static void nsim_dev_debugfs_exit(struct nsim_dev *nsim_dev)
102 debugfs_remove_recursive(nsim_dev->ports_ddir);
103 debugfs_remove_recursive(nsim_dev->ddir);
106 static int nsim_dev_port_debugfs_init(struct nsim_dev *nsim_dev,
107 struct nsim_dev_port *nsim_dev_port)
109 char port_ddir_name[16];
110 char dev_link_name[32];
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))
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);
125 static void nsim_dev_port_debugfs_exit(struct nsim_dev_port *nsim_dev_port)
127 debugfs_remove_recursive(nsim_dev_port->ddir);
130 static int nsim_dev_resources_register(struct devlink *devlink)
132 struct devlink_resource_size_params params = {
134 .size_granularity = 1,
135 .unit = DEVLINK_RESOURCE_UNIT_ENTRY
139 /* Resources for IPv4 */
140 err = devlink_resource_register(devlink, "IPv4", (u64)-1,
142 DEVLINK_RESOURCE_ID_PARENT_TOP,
145 pr_err("Failed to register IPv4 top resource\n");
149 err = devlink_resource_register(devlink, "fib", (u64)-1,
150 NSIM_RESOURCE_IPV4_FIB,
151 NSIM_RESOURCE_IPV4, ¶ms);
153 pr_err("Failed to register IPv4 FIB resource\n");
157 err = devlink_resource_register(devlink, "fib-rules", (u64)-1,
158 NSIM_RESOURCE_IPV4_FIB_RULES,
159 NSIM_RESOURCE_IPV4, ¶ms);
161 pr_err("Failed to register IPv4 FIB rules resource\n");
165 /* Resources for IPv6 */
166 err = devlink_resource_register(devlink, "IPv6", (u64)-1,
168 DEVLINK_RESOURCE_ID_PARENT_TOP,
171 pr_err("Failed to register IPv6 top resource\n");
175 err = devlink_resource_register(devlink, "fib", (u64)-1,
176 NSIM_RESOURCE_IPV6_FIB,
177 NSIM_RESOURCE_IPV6, ¶ms);
179 pr_err("Failed to register IPv6 FIB resource\n");
183 err = devlink_resource_register(devlink, "fib-rules", (u64)-1,
184 NSIM_RESOURCE_IPV6_FIB_RULES,
185 NSIM_RESOURCE_IPV6, ¶ms);
187 pr_err("Failed to register IPv6 FIB rules resource\n");
195 enum nsim_devlink_param_id {
196 NSIM_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
197 NSIM_DEVLINK_PARAM_ID_TEST1,
200 static const struct devlink_param nsim_devlink_params[] = {
201 DEVLINK_PARAM_GENERIC(MAX_MACS,
202 BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
204 DEVLINK_PARAM_DRIVER(NSIM_DEVLINK_PARAM_ID_TEST1,
205 "test1", DEVLINK_PARAM_TYPE_BOOL,
206 BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
210 static void nsim_devlink_set_params_init_values(struct nsim_dev *nsim_dev,
211 struct devlink *devlink)
213 union devlink_param_value value;
215 value.vu32 = nsim_dev->max_macs;
216 devlink_param_driverinit_value_set(devlink,
217 DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
219 value.vbool = nsim_dev->test1;
220 devlink_param_driverinit_value_set(devlink,
221 NSIM_DEVLINK_PARAM_ID_TEST1,
225 static void nsim_devlink_param_load_driverinit_values(struct devlink *devlink)
227 struct nsim_dev *nsim_dev = devlink_priv(devlink);
228 union devlink_param_value saved_value;
231 err = devlink_param_driverinit_value_get(devlink,
232 DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
235 nsim_dev->max_macs = saved_value.vu32;
236 err = devlink_param_driverinit_value_get(devlink,
237 NSIM_DEVLINK_PARAM_ID_TEST1,
240 nsim_dev->test1 = saved_value.vbool;
243 #define NSIM_DEV_DUMMY_REGION_SNAPSHOT_MAX 16
245 static int nsim_dev_dummy_region_init(struct nsim_dev *nsim_dev,
246 struct devlink *devlink)
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);
255 static void nsim_dev_dummy_region_exit(struct nsim_dev *nsim_dev)
257 devlink_region_destroy(nsim_dev->dummy_region);
260 struct nsim_trap_item {
262 enum devlink_trap_action action;
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 */
272 /* All driver-specific traps must be documented in
273 * Documentation/networking/devlink-trap-netdevsim.rst
276 NSIM_TRAP_ID_BASE = DEVLINK_TRAP_GENERIC_ID_MAX,
277 NSIM_TRAP_ID_FID_MISS,
280 #define NSIM_TRAP_NAME_FID_MISS "fid_miss"
282 #define NSIM_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT
284 #define NSIM_TRAP_DROP(_id, _group_id) \
285 DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \
286 DEVLINK_TRAP_GROUP_GENERIC(_group_id), \
288 #define NSIM_TRAP_EXCEPTION(_id, _group_id) \
289 DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id, \
290 DEVLINK_TRAP_GROUP_GENERIC(_group_id), \
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), \
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),
311 #define NSIM_TRAP_L4_DATA_LEN 100
313 static struct sk_buff *nsim_dev_trap_skb_build(void)
315 int tot_len, data_len = NSIM_TRAP_L4_DATA_LEN;
321 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
324 tot_len = sizeof(struct iphdr) + sizeof(struct udphdr) + data_len;
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);
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");
341 iph->tot_len = htons(tot_len);
344 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
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);
355 static void nsim_dev_trap_report(struct nsim_dev_port *nsim_dev_port)
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;
362 nsim_trap_data = nsim_dev->trap_data;
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;
369 nsim_trap_item = &nsim_trap_data->trap_items_arr[i];
370 if (nsim_trap_item->action == DEVLINK_TRAP_ACTION_DROP)
373 skb = nsim_dev_trap_skb_build();
376 skb->dev = nsim_dev_port->ns->netdev;
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".
384 devlink_trap_report(devlink, skb, nsim_trap_item->trap_ctx,
385 &nsim_dev_port->devlink_port);
389 spin_unlock(&nsim_trap_data->trap_lock);
392 #define NSIM_TRAP_REPORT_INTERVAL_MS 100
394 static void nsim_dev_trap_report_work(struct work_struct *work)
396 struct nsim_trap_data *nsim_trap_data;
397 struct nsim_dev_port *nsim_dev_port;
398 struct nsim_dev *nsim_dev;
400 nsim_trap_data = container_of(work, struct nsim_trap_data,
401 trap_report_dw.work);
402 nsim_dev = nsim_trap_data->nsim_dev;
404 /* For each running port and enabled packet trap, generate a UDP
405 * packet with a random 5-tuple and report it.
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))
412 nsim_dev_trap_report(nsim_dev_port);
414 mutex_unlock(&nsim_dev->port_list_lock);
416 schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw,
417 msecs_to_jiffies(NSIM_TRAP_REPORT_INTERVAL_MS));
420 static int nsim_dev_traps_init(struct devlink *devlink)
422 struct nsim_dev *nsim_dev = devlink_priv(devlink);
423 struct nsim_trap_data *nsim_trap_data;
426 nsim_trap_data = kzalloc(sizeof(*nsim_trap_data), GFP_KERNEL);
430 nsim_trap_data->trap_items_arr = kcalloc(ARRAY_SIZE(nsim_traps_arr),
431 sizeof(struct nsim_trap_item),
433 if (!nsim_trap_data->trap_items_arr) {
435 goto err_trap_data_free;
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.
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;
446 err = devlink_traps_register(devlink, nsim_traps_arr,
447 ARRAY_SIZE(nsim_traps_arr), NULL);
449 goto err_trap_items_free;
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));
459 kfree(nsim_trap_data->trap_items_arr);
461 kfree(nsim_trap_data);
465 static void nsim_dev_traps_exit(struct devlink *devlink)
467 struct nsim_dev *nsim_dev = devlink_priv(devlink);
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);
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);
480 static int nsim_dev_reload_down(struct devlink *devlink, bool netns_change,
481 struct netlink_ext_ack *extack)
483 struct nsim_dev *nsim_dev = devlink_priv(devlink);
485 if (nsim_dev->dont_allow_reload) {
486 /* For testing purposes, user set debugfs dont_allow_reload
487 * value to true. So forbid it.
489 NL_SET_ERR_MSG_MOD(extack, "User forbid the reload for testing purposes");
493 nsim_dev_reload_destroy(nsim_dev);
497 static int nsim_dev_reload_up(struct devlink *devlink,
498 struct netlink_ext_ack *extack)
500 struct nsim_dev *nsim_dev = devlink_priv(devlink);
502 if (nsim_dev->fail_reload) {
503 /* For testing purposes, user set debugfs fail_reload
504 * value to true. Fail right away.
506 NL_SET_ERR_MSG_MOD(extack, "User setup the reload to fail for testing purposes");
510 return nsim_dev_reload_create(nsim_dev, extack);
513 static int nsim_dev_info_get(struct devlink *devlink,
514 struct devlink_info_req *req,
515 struct netlink_ext_ack *extack)
517 return devlink_info_driver_name_put(req, DRV_NAME);
520 #define NSIM_DEV_FLASH_SIZE 500000
521 #define NSIM_DEV_FLASH_CHUNK_SIZE 1000
522 #define NSIM_DEV_FLASH_CHUNK_TIME_MS 10
524 static int nsim_dev_flash_update(struct devlink *devlink, const char *file_name,
525 const char *component,
526 struct netlink_ext_ack *extack)
528 struct nsim_dev *nsim_dev = devlink_priv(devlink);
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",
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",
542 i * NSIM_DEV_FLASH_CHUNK_SIZE,
543 NSIM_DEV_FLASH_SIZE);
544 msleep(NSIM_DEV_FLASH_CHUNK_TIME_MS);
547 if (nsim_dev->fw_update_status) {
548 devlink_flash_update_status_notify(devlink, "Flashing",
551 NSIM_DEV_FLASH_SIZE);
552 devlink_flash_update_status_notify(devlink, "Flashing done",
554 devlink_flash_update_end_notify(devlink);
560 static struct nsim_trap_item *
561 nsim_dev_trap_item_lookup(struct nsim_dev *nsim_dev, u16 trap_id)
563 struct nsim_trap_data *nsim_trap_data = nsim_dev->trap_data;
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];
574 static int nsim_dev_devlink_trap_init(struct devlink *devlink,
575 const struct devlink_trap *trap,
578 struct nsim_dev *nsim_dev = devlink_priv(devlink);
579 struct nsim_trap_item *nsim_trap_item;
581 nsim_trap_item = nsim_dev_trap_item_lookup(nsim_dev, trap->id);
582 if (WARN_ON(!nsim_trap_item))
585 nsim_trap_item->trap_ctx = trap_ctx;
586 nsim_trap_item->action = trap->init_action;
592 nsim_dev_devlink_trap_action_set(struct devlink *devlink,
593 const struct devlink_trap *trap,
594 enum devlink_trap_action action)
596 struct nsim_dev *nsim_dev = devlink_priv(devlink);
597 struct nsim_trap_item *nsim_trap_item;
599 nsim_trap_item = nsim_dev_trap_item_lookup(nsim_dev, trap->id);
600 if (WARN_ON(!nsim_trap_item))
603 spin_lock(&nsim_dev->trap_data->trap_lock);
604 nsim_trap_item->action = action;
605 spin_unlock(&nsim_dev->trap_data->trap_lock);
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,
619 #define NSIM_DEV_MAX_MACS_DEFAULT 32
620 #define NSIM_DEV_TEST1_DEFAULT true
622 static int __nsim_dev_port_add(struct nsim_dev *nsim_dev,
623 unsigned int port_index)
625 struct nsim_dev_port *nsim_dev_port;
626 struct devlink_port *devlink_port;
629 nsim_dev_port = kzalloc(sizeof(*nsim_dev_port), GFP_KERNEL);
632 nsim_dev_port->port_index = port_index;
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,
644 err = nsim_dev_port_debugfs_init(nsim_dev, nsim_dev_port);
646 goto err_dl_port_unregister;
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;
654 devlink_port_type_eth_set(devlink_port, nsim_dev_port->ns->netdev);
655 list_add(&nsim_dev_port->list, &nsim_dev->port_list);
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);
664 kfree(nsim_dev_port);
668 static void __nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port)
670 struct devlink_port *devlink_port = &nsim_dev_port->devlink_port;
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);
680 static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev)
682 struct nsim_dev_port *nsim_dev_port, *tmp;
684 list_for_each_entry_safe(nsim_dev_port, tmp,
685 &nsim_dev->port_list, list)
686 __nsim_dev_port_del(nsim_dev_port);
689 static int nsim_dev_port_add_all(struct nsim_dev *nsim_dev,
690 unsigned int port_count)
694 for (i = 0; i < port_count; i++) {
695 err = __nsim_dev_port_add(nsim_dev, i);
697 goto err_port_del_all;
702 nsim_dev_port_del_all(nsim_dev);
706 static int nsim_dev_reload_create(struct nsim_dev *nsim_dev,
707 struct netlink_ext_ack *extack)
709 struct nsim_bus_dev *nsim_bus_dev = nsim_dev->nsim_bus_dev;
710 struct devlink *devlink;
713 devlink = priv_to_devlink(nsim_dev);
714 nsim_dev = devlink_priv(devlink);
715 INIT_LIST_HEAD(&nsim_dev->port_list);
716 mutex_init(&nsim_dev->port_list_lock);
717 nsim_dev->fw_update_status = true;
719 nsim_dev->fib_data = nsim_fib_create(devlink, extack);
720 if (IS_ERR(nsim_dev->fib_data))
721 return PTR_ERR(nsim_dev->fib_data);
723 nsim_devlink_param_load_driverinit_values(devlink);
725 err = nsim_dev_dummy_region_init(nsim_dev, devlink);
727 goto err_fib_destroy;
729 err = nsim_dev_traps_init(devlink);
731 goto err_dummy_region_exit;
733 err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);
740 nsim_dev_traps_exit(devlink);
741 err_dummy_region_exit:
742 nsim_dev_dummy_region_exit(nsim_dev);
744 nsim_fib_destroy(devlink, nsim_dev->fib_data);
748 static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev)
750 struct nsim_dev *nsim_dev;
751 struct devlink *devlink;
754 devlink = devlink_alloc(&nsim_dev_devlink_ops, sizeof(*nsim_dev));
756 return ERR_PTR(-ENOMEM);
757 devlink_net_set(devlink, nsim_bus_dev->initial_net);
758 nsim_dev = devlink_priv(devlink);
759 nsim_dev->nsim_bus_dev = nsim_bus_dev;
760 nsim_dev->switch_id.id_len = sizeof(nsim_dev->switch_id.id);
761 get_random_bytes(nsim_dev->switch_id.id, nsim_dev->switch_id.id_len);
762 INIT_LIST_HEAD(&nsim_dev->port_list);
763 mutex_init(&nsim_dev->port_list_lock);
764 nsim_dev->fw_update_status = true;
765 nsim_dev->max_macs = NSIM_DEV_MAX_MACS_DEFAULT;
766 nsim_dev->test1 = NSIM_DEV_TEST1_DEFAULT;
768 err = nsim_dev_resources_register(devlink);
770 goto err_devlink_free;
772 nsim_dev->fib_data = nsim_fib_create(devlink, NULL);
773 if (IS_ERR(nsim_dev->fib_data)) {
774 err = PTR_ERR(nsim_dev->fib_data);
775 goto err_resources_unregister;
778 err = devlink_register(devlink, &nsim_bus_dev->dev);
780 goto err_fib_destroy;
782 err = devlink_params_register(devlink, nsim_devlink_params,
783 ARRAY_SIZE(nsim_devlink_params));
785 goto err_dl_unregister;
786 nsim_devlink_set_params_init_values(nsim_dev, devlink);
788 err = nsim_dev_dummy_region_init(nsim_dev, devlink);
790 goto err_params_unregister;
792 err = nsim_dev_traps_init(devlink);
794 goto err_dummy_region_exit;
796 err = nsim_dev_debugfs_init(nsim_dev);
800 err = nsim_bpf_dev_init(nsim_dev);
802 goto err_debugfs_exit;
804 err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);
806 goto err_bpf_dev_exit;
808 devlink_params_publish(devlink);
812 nsim_bpf_dev_exit(nsim_dev);
814 nsim_dev_debugfs_exit(nsim_dev);
816 nsim_dev_traps_exit(devlink);
817 err_dummy_region_exit:
818 nsim_dev_dummy_region_exit(nsim_dev);
819 err_params_unregister:
820 devlink_params_unregister(devlink, nsim_devlink_params,
821 ARRAY_SIZE(nsim_devlink_params));
823 devlink_unregister(devlink);
825 nsim_fib_destroy(devlink, nsim_dev->fib_data);
826 err_resources_unregister:
827 devlink_resources_unregister(devlink, NULL);
829 devlink_free(devlink);
833 static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev)
835 struct devlink *devlink = priv_to_devlink(nsim_dev);
837 if (devlink_is_reload_failed(devlink))
839 nsim_dev_port_del_all(nsim_dev);
840 nsim_dev_traps_exit(devlink);
841 nsim_dev_dummy_region_exit(nsim_dev);
842 mutex_destroy(&nsim_dev->port_list_lock);
843 nsim_fib_destroy(devlink, nsim_dev->fib_data);
846 static void nsim_dev_destroy(struct nsim_dev *nsim_dev)
848 struct devlink *devlink = priv_to_devlink(nsim_dev);
850 nsim_dev_reload_destroy(nsim_dev);
852 nsim_bpf_dev_exit(nsim_dev);
853 nsim_dev_debugfs_exit(nsim_dev);
854 devlink_params_unregister(devlink, nsim_devlink_params,
855 ARRAY_SIZE(nsim_devlink_params));
856 devlink_unregister(devlink);
857 devlink_resources_unregister(devlink, NULL);
858 devlink_free(devlink);
861 int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
863 struct nsim_dev *nsim_dev;
865 nsim_dev = nsim_dev_create(nsim_bus_dev);
866 if (IS_ERR(nsim_dev))
867 return PTR_ERR(nsim_dev);
868 dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev);
873 void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev)
875 struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
877 nsim_dev_destroy(nsim_dev);
880 static struct nsim_dev_port *
881 __nsim_dev_port_lookup(struct nsim_dev *nsim_dev, unsigned int port_index)
883 struct nsim_dev_port *nsim_dev_port;
885 list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list)
886 if (nsim_dev_port->port_index == port_index)
887 return nsim_dev_port;
891 int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
892 unsigned int port_index)
894 struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
897 mutex_lock(&nsim_dev->port_list_lock);
898 if (__nsim_dev_port_lookup(nsim_dev, port_index))
901 err = __nsim_dev_port_add(nsim_dev, port_index);
902 mutex_unlock(&nsim_dev->port_list_lock);
906 int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
907 unsigned int port_index)
909 struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
910 struct nsim_dev_port *nsim_dev_port;
913 mutex_lock(&nsim_dev->port_list_lock);
914 nsim_dev_port = __nsim_dev_port_lookup(nsim_dev, port_index);
918 __nsim_dev_port_del(nsim_dev_port);
919 mutex_unlock(&nsim_dev->port_list_lock);
923 int nsim_dev_init(void)
925 nsim_dev_ddir = debugfs_create_dir(DRV_NAME, NULL);
926 if (IS_ERR_OR_NULL(nsim_dev_ddir))
931 void nsim_dev_exit(void)
933 debugfs_remove_recursive(nsim_dev_ddir);