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