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