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