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