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