__ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show,
               nsim_bus_dev_numvfs_store);
 
+static ssize_t
+new_port_store(struct device *dev, struct device_attribute *attr,
+              const char *buf, size_t count)
+{
+       struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
+       unsigned int port_index;
+       int ret;
+
+       ret = kstrtouint(buf, 0, &port_index);
+       if (ret)
+               return ret;
+       ret = nsim_dev_port_add(nsim_bus_dev, port_index);
+       return ret ? ret : count;
+}
+
+static struct device_attribute nsim_bus_dev_new_port_attr = __ATTR_WO(new_port);
+
+static ssize_t
+del_port_store(struct device *dev, struct device_attribute *attr,
+              const char *buf, size_t count)
+{
+       struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
+       unsigned int port_index;
+       int ret;
+
+       ret = kstrtouint(buf, 0, &port_index);
+       if (ret)
+               return ret;
+       ret = nsim_dev_port_del(nsim_bus_dev, port_index);
+       return ret ? ret : count;
+}
+
+static struct device_attribute nsim_bus_dev_del_port_attr = __ATTR_WO(del_port);
+
 static struct attribute *nsim_bus_dev_attrs[] = {
        &nsim_bus_dev_numvfs_attr.attr,
+       &nsim_bus_dev_new_port_attr.attr,
+       &nsim_bus_dev_del_port_attr.attr,
        NULL,
 };
 
 
 #include <linux/debugfs.h>
 #include <linux/device.h>
 #include <linux/list.h>
+#include <linux/mutex.h>
 #include <linux/random.h>
 #include <linux/rtnetlink.h>
 #include <net/devlink.h>
        nsim_dev->switch_id.id_len = sizeof(nsim_dev->switch_id.id);
        get_random_bytes(nsim_dev->switch_id.id, nsim_dev->switch_id.id_len);
        INIT_LIST_HEAD(&nsim_dev->port_list);
+       mutex_init(&nsim_dev->port_list_lock);
 
        nsim_dev->fib_data = nsim_fib_create();
        if (IS_ERR(nsim_dev->fib_data)) {
        devlink_unregister(devlink);
        devlink_resources_unregister(devlink, NULL);
        nsim_fib_destroy(nsim_dev->fib_data);
+       mutex_destroy(&nsim_dev->port_list_lock);
        devlink_free(devlink);
 }
 
-static int nsim_dev_port_add(struct nsim_dev *nsim_dev, unsigned int port_index)
+static int __nsim_dev_port_add(struct nsim_dev *nsim_dev,
+                              unsigned int port_index)
 {
        struct nsim_dev_port *nsim_dev_port;
        struct devlink_port *devlink_port;
        return err;
 }
 
-static void nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port)
+static void __nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port)
 {
        struct devlink_port *devlink_port = &nsim_dev_port->devlink_port;
 
 
        list_for_each_entry_safe(nsim_dev_port, tmp,
                                 &nsim_dev->port_list, list)
-               nsim_dev_port_del(nsim_dev_port);
+               __nsim_dev_port_del(nsim_dev_port);
 }
 
 int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
        dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev);
 
        for (i = 0; i < nsim_bus_dev->port_count; i++) {
-               err = nsim_dev_port_add(nsim_dev, i);
+               err = __nsim_dev_port_add(nsim_dev, i);
                if (err)
                        goto err_port_del_all;
        }
        nsim_dev_destroy(nsim_dev);
 }
 
+static struct nsim_dev_port *
+__nsim_dev_port_lookup(struct nsim_dev *nsim_dev, unsigned int port_index)
+{
+       struct nsim_dev_port *nsim_dev_port;
+
+       list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list)
+               if (nsim_dev_port->port_index == port_index)
+                       return nsim_dev_port;
+       return NULL;
+}
+
+int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
+                     unsigned int port_index)
+{
+       struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
+       int err;
+
+       mutex_lock(&nsim_dev->port_list_lock);
+       if (__nsim_dev_port_lookup(nsim_dev, port_index))
+               err = -EEXIST;
+       else
+               err = __nsim_dev_port_add(nsim_dev, port_index);
+       mutex_unlock(&nsim_dev->port_list_lock);
+       return err;
+}
+
+int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
+                     unsigned int port_index)
+{
+       struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
+       struct nsim_dev_port *nsim_dev_port;
+       int err = 0;
+
+       mutex_lock(&nsim_dev->port_list_lock);
+       nsim_dev_port = __nsim_dev_port_lookup(nsim_dev, port_index);
+       if (!nsim_dev_port)
+               err = -ENOENT;
+       else
+               __nsim_dev_port_del(nsim_dev_port);
+       mutex_unlock(&nsim_dev->port_list_lock);
+       return err;
+}
+
 int nsim_dev_init(void)
 {
        nsim_dev_ddir = debugfs_create_dir(DRV_NAME, NULL);
 
        struct list_head bpf_bound_maps;
        struct netdev_phys_item_id switch_id;
        struct list_head port_list;
+       struct mutex port_list_lock; /* protects port list */
 };
 
 int nsim_dev_init(void);
 void nsim_dev_exit(void);
 int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev);
 void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev);
+int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
+                     unsigned int port_index);
+int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
+                     unsigned int port_index);
 
 struct nsim_fib_data *nsim_fib_create(void);
 void nsim_fib_destroy(struct nsim_fib_data *fib_data);