get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/8016/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 8016,
    "url": "https://patches.dpdk.org/api/patches/8016/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1445856090-6880-1-git-send-email-dex.chen@ruckuswireless.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1445856090-6880-1-git-send-email-dex.chen@ruckuswireless.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1445856090-6880-1-git-send-email-dex.chen@ruckuswireless.com",
    "date": "2015-10-26T10:41:30",
    "name": "[dpdk-dev,v2] kni: allow per-net instances",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "d793ad980bf0c27b477a34a007f839b5a87904a9",
    "submitter": {
        "id": 275,
        "url": "https://patches.dpdk.org/api/people/275/?format=api",
        "name": "Dex Chen",
        "email": "dex.chen@ruckuswireless.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1445856090-6880-1-git-send-email-dex.chen@ruckuswireless.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/8016/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/8016/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 387565682;\n\tMon, 26 Oct 2015 11:41:55 +0100 (CET)",
            "from anubis (59-124-251-135.HINET-IP.hinet.net [59.124.251.135])\n\tby dpdk.org (Postfix) with ESMTP id 3A603282\n\tfor <dev@dpdk.org>; Mon, 26 Oct 2015 11:41:53 +0100 (CET)",
            "by anubis (Postfix, from userid 1000)\n\tid 36F721480177; Mon, 26 Oct 2015 18:41:51 +0800 (CST)"
        ],
        "From": "Dex Chen <dex.chen@ruckuswireless.com>",
        "To": "dev@dpdk.org",
        "Date": "Mon, 26 Oct 2015 18:41:30 +0800",
        "Message-Id": "<1445856090-6880-1-git-send-email-dex.chen@ruckuswireless.com>",
        "X-Mailer": "git-send-email 2.5.0",
        "In-Reply-To": "<1435831933-13339-1-git-send-email-dex.chen@ruckuswireless.com>",
        "References": "<1435831933-13339-1-git-send-email-dex.chen@ruckuswireless.com>",
        "Subject": "[dpdk-dev] [PATCH v2] kni: allow per-net instances",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "There is a global variable 'device_in_use' which is used to make sure\nonly one instance is using /dev/kni device. If you were using LXC, you\nwill find there is only one instance of KNI example could be run even\ndiffernt namespaces were created.\n\nIn order to have /dev/kni used simultaneously in different namespaces,\nmaking all of global variables as per network namespace variables.\n\nWith regard to single kernel thread mode, there will be one kernel\nthread for each of network namespace.\n\nv2:\n\t> Remove kni_exit_net\n\t> Revise the order of register/unregister of pernet_subsys\n\t> Fix warnings of checkpatch\n\t> Fix NULL nsproxy issue in kni_release()\n\nSigned-off-by: Dex Chen <dex.chen@ruckuswireless.com>\n---\n lib/librte_eal/linuxapp/kni/kni_misc.c | 136 +++++++++++++++++++++------------\n 1 file changed, 87 insertions(+), 49 deletions(-)",
    "diff": "diff --git a/lib/librte_eal/linuxapp/kni/kni_misc.c b/lib/librte_eal/linuxapp/kni/kni_misc.c\nindex 2e9fa89..635e18f 100644\n--- a/lib/librte_eal/linuxapp/kni/kni_misc.c\n+++ b/lib/librte_eal/linuxapp/kni/kni_misc.c\n@@ -28,6 +28,9 @@\n #include <linux/pci.h>\n #include <linux/kthread.h>\n #include <linux/rwsem.h>\n+#include <linux/nsproxy.h>\n+#include <net/net_namespace.h>\n+#include <net/netns/generic.h>\n \n #include <exec-env/rte_kni_common.h>\n #include \"kni_dev.h\"\n@@ -90,18 +93,40 @@ static unsigned multiple_kthread_on = 0;\n \n #define KNI_DEV_IN_USE_BIT_NUM 0 /* Bit number for device in use */\n \n-static volatile unsigned long device_in_use; /* device in use flag */\n-static struct task_struct *kni_kthread;\n+static int kni_net_id;\n \n-/* kni list lock */\n-static DECLARE_RWSEM(kni_list_lock);\n+struct kni_net {\n+\tunsigned long device_in_use; /* device in use flag */\n+\tstruct task_struct *kni_kthread;\n+\tstruct rw_semaphore kni_list_lock;\n+\tstruct list_head kni_list_head;\n+};\n+\n+static __net_init int kni_init_net(struct net *net)\n+{\n+\tstruct kni_net *knet = net_generic(net, kni_net_id);\n \n-/* kni list */\n-static struct list_head kni_list_head = LIST_HEAD_INIT(kni_list_head);\n+\t/* Clear the bit of device in use */\n+\tclear_bit(KNI_DEV_IN_USE_BIT_NUM, &knet->device_in_use);\n+\n+\tinit_rwsem(&knet->kni_list_lock);\n+\tINIT_LIST_HEAD(&knet->kni_list_head);\n+\n+\treturn 0;\n+}\n+\n+static struct pernet_operations kni_net_ops = {\n+\t.init = kni_init_net,\n+\t.exit = NULL,\n+\t.id   = &kni_net_id,\n+\t.size = sizeof(struct kni_net),\n+};\n \n static int __init\n kni_init(void)\n {\n+\tint rc;\n+\n \tKNI_PRINT(\"######## DPDK kni module loading ########\\n\");\n \n \tif (kni_parse_kthread_mode() < 0) {\n@@ -109,13 +134,15 @@ kni_init(void)\n \t\treturn -EINVAL;\n \t}\n \n-\tif (misc_register(&kni_misc) != 0) {\n-\t\tKNI_ERR(\"Misc registration failed\\n\");\n+\trc = register_pernet_subsys(&kni_net_ops);\n+\tif (rc)\n \t\treturn -EPERM;\n-\t}\n \n-\t/* Clear the bit of device in use */\n-\tclear_bit(KNI_DEV_IN_USE_BIT_NUM, &device_in_use);\n+\trc = misc_register(&kni_misc);\n+\tif (rc != 0) {\n+\t\tKNI_ERR(\"Misc registration failed\\n\");\n+\t\tgoto out;\n+\t}\n \n \t/* Configure the lo mode according to the input parameter */\n \tkni_net_config_lo_mode(lo_mode);\n@@ -123,12 +150,17 @@ kni_init(void)\n \tKNI_PRINT(\"######## DPDK kni module loaded  ########\\n\");\n \n \treturn 0;\n+\n+out:\n+\tunregister_pernet_subsys(&kni_net_ops);\n+\treturn rc;\n }\n \n static void __exit\n kni_exit(void)\n {\n \tmisc_deregister(&kni_misc);\n+\tunregister_pernet_subsys(&kni_net_ops);\n \tKNI_PRINT(\"####### DPDK kni module unloaded  #######\\n\");\n }\n \n@@ -151,23 +183,27 @@ kni_parse_kthread_mode(void)\n static int\n kni_open(struct inode *inode, struct file *file)\n {\n-\t/* kni device can be opened by one user only, test and set bit */\n-\tif (test_and_set_bit(KNI_DEV_IN_USE_BIT_NUM, &device_in_use))\n+\tstruct net *net = current->nsproxy->net_ns;\n+\tstruct kni_net *knet = net_generic(net, kni_net_id);\n+\n+\t/* kni device can be opened by one user only per netns */\n+\tif (test_and_set_bit(KNI_DEV_IN_USE_BIT_NUM, &knet->device_in_use))\n \t\treturn -EBUSY;\n \n \t/* Create kernel thread for single mode */\n \tif (multiple_kthread_on == 0) {\n \t\tKNI_PRINT(\"Single kernel thread for all KNI devices\\n\");\n \t\t/* Create kernel thread for RX */\n-\t\tkni_kthread = kthread_run(kni_thread_single, NULL,\n+\t\tknet->kni_kthread = kthread_run(kni_thread_single, (void *)knet,\n \t\t\t\t\t\t\"kni_single\");\n-\t\tif (IS_ERR(kni_kthread)) {\n+\t\tif (IS_ERR(knet->kni_kthread)) {\n \t\t\tKNI_ERR(\"Unable to create kernel threaed\\n\");\n-\t\t\treturn PTR_ERR(kni_kthread);\n+\t\t\treturn PTR_ERR(knet->kni_kthread);\n \t\t}\n \t} else\n \t\tKNI_PRINT(\"Multiple kernel thread mode enabled\\n\");\n \n+\tfile->private_data = get_net(net);\n \tKNI_PRINT(\"/dev/kni opened\\n\");\n \n \treturn 0;\n@@ -176,17 +212,19 @@ kni_open(struct inode *inode, struct file *file)\n static int\n kni_release(struct inode *inode, struct file *file)\n {\n+\tstruct net *net = file->private_data;\n+\tstruct kni_net *knet = net_generic(net, kni_net_id);\n \tstruct kni_dev *dev, *n;\n \n \t/* Stop kernel thread for single mode */\n \tif (multiple_kthread_on == 0) {\n \t\t/* Stop kernel thread */\n-\t\tkthread_stop(kni_kthread);\n-\t\tkni_kthread = NULL;\n+\t\tkthread_stop(knet->kni_kthread);\n+\t\tknet->kni_kthread = NULL;\n \t}\n \n-\tdown_write(&kni_list_lock);\n-\tlist_for_each_entry_safe(dev, n, &kni_list_head, list) {\n+\tdown_write(&knet->kni_list_lock);\n+\tlist_for_each_entry_safe(dev, n, &knet->kni_list_head, list) {\n \t\t/* Stop kernel thread for multiple mode */\n \t\tif (multiple_kthread_on && dev->pthread != NULL) {\n \t\t\tkthread_stop(dev->pthread);\n@@ -199,26 +237,28 @@ kni_release(struct inode *inode, struct file *file)\n \t\tkni_dev_remove(dev);\n \t\tlist_del(&dev->list);\n \t}\n-\tup_write(&kni_list_lock);\n+\tup_write(&knet->kni_list_lock);\n \n \t/* Clear the bit of device in use */\n-\tclear_bit(KNI_DEV_IN_USE_BIT_NUM, &device_in_use);\n+\tclear_bit(KNI_DEV_IN_USE_BIT_NUM, &knet->device_in_use);\n \n+\tput_net(net);\n \tKNI_PRINT(\"/dev/kni closed\\n\");\n \n \treturn 0;\n }\n \n static int\n-kni_thread_single(void *unused)\n+kni_thread_single(void *data)\n {\n+\tstruct kni_net *knet = data;\n \tint j;\n \tstruct kni_dev *dev;\n \n \twhile (!kthread_should_stop()) {\n-\t\tdown_read(&kni_list_lock);\n+\t\tdown_read(&knet->kni_list_lock);\n \t\tfor (j = 0; j < KNI_RX_LOOP_NUM; j++) {\n-\t\t\tlist_for_each_entry(dev, &kni_list_head, list) {\n+\t\t\tlist_for_each_entry(dev, &knet->kni_list_head, list) {\n #ifdef RTE_KNI_VHOST\n \t\t\t\tkni_chk_vhost_rx(dev);\n #else\n@@ -227,7 +267,7 @@ kni_thread_single(void *unused)\n \t\t\t\tkni_net_poll_resp(dev);\n \t\t\t}\n \t\t}\n-\t\tup_read(&kni_list_lock);\n+\t\tup_read(&knet->kni_list_lock);\n #ifdef RTE_KNI_PREEMPT_DEFAULT\n \t\t/* reschedule out for a while */\n \t\tschedule_timeout_interruptible(usecs_to_jiffies( \\\n@@ -305,8 +345,10 @@ kni_check_param(struct kni_dev *kni, struct rte_kni_device_info *dev)\n }\n \n static int\n-kni_ioctl_create(unsigned int ioctl_num, unsigned long ioctl_param)\n+kni_ioctl_create(struct net *net,\n+\t\tunsigned int ioctl_num, unsigned long ioctl_param)\n {\n+\tstruct kni_net *knet = net_generic(net, kni_net_id);\n \tint ret;\n \tstruct rte_kni_device_info dev_info;\n \tstruct pci_dev *pci = NULL;\n@@ -314,7 +356,6 @@ kni_ioctl_create(unsigned int ioctl_num, unsigned long ioctl_param)\n \tstruct net_device *net_dev = NULL;\n \tstruct net_device *lad_dev = NULL;\n \tstruct kni_dev *kni, *dev, *n;\n-\tstruct net *net;\n \n \tprintk(KERN_INFO \"KNI: Creating kni...\\n\");\n \t/* Check the buffer size, to avoid warning */\n@@ -339,14 +380,14 @@ kni_ioctl_create(unsigned int ioctl_num, unsigned long ioctl_param)\n \t}\n \n \t/* Check if it has been created */\n-\tdown_read(&kni_list_lock);\n-\tlist_for_each_entry_safe(dev, n, &kni_list_head, list) {\n+\tdown_read(&knet->kni_list_lock);\n+\tlist_for_each_entry_safe(dev, n, &knet->kni_list_head, list) {\n \t\tif (kni_check_param(dev, &dev_info) < 0) {\n-\t\t\tup_read(&kni_list_lock);\n+\t\t\tup_read(&knet->kni_list_lock);\n \t\t\treturn -EINVAL;\n \t\t}\n \t}\n-\tup_read(&kni_list_lock);\n+\tup_read(&knet->kni_list_lock);\n \n \tnet_dev = alloc_netdev(sizeof(struct kni_dev), dev_info.name,\n #ifdef NET_NAME_UNKNOWN\n@@ -358,13 +399,7 @@ kni_ioctl_create(unsigned int ioctl_num, unsigned long ioctl_param)\n \t\treturn -EBUSY;\n \t}\n \n-\tnet = get_net_ns_by_pid(task_pid_vnr(current));\n-\tif (IS_ERR(net)) {\n-\t\tfree_netdev(net_dev);\n-\t\treturn PTR_ERR(net);\n-\t}\n \tdev_net_set(net_dev, net);\n-\tput_net(net);\n \n \tkni = netdev_priv(net_dev);\n \n@@ -494,16 +529,18 @@ kni_ioctl_create(unsigned int ioctl_num, unsigned long ioctl_param)\n \t\twake_up_process(kni->pthread);\n \t}\n \n-\tdown_write(&kni_list_lock);\n-\tlist_add(&kni->list, &kni_list_head);\n-\tup_write(&kni_list_lock);\n+\tdown_write(&knet->kni_list_lock);\n+\tlist_add(&kni->list, &knet->kni_list_head);\n+\tup_write(&knet->kni_list_lock);\n \n \treturn 0;\n }\n \n static int\n-kni_ioctl_release(unsigned int ioctl_num, unsigned long ioctl_param)\n+kni_ioctl_release(struct net *net,\n+\t\tunsigned int ioctl_num, unsigned long ioctl_param)\n {\n+\tstruct kni_net *knet = net_generic(net, kni_net_id);\n \tint ret = -EINVAL;\n \tstruct kni_dev *dev, *n;\n \tstruct rte_kni_device_info dev_info;\n@@ -521,8 +558,8 @@ kni_ioctl_release(unsigned int ioctl_num, unsigned long ioctl_param)\n \tif (strlen(dev_info.name) == 0)\n \t\treturn ret;\n \n-\tdown_write(&kni_list_lock);\n-\tlist_for_each_entry_safe(dev, n, &kni_list_head, list) {\n+\tdown_write(&knet->kni_list_lock);\n+\tlist_for_each_entry_safe(dev, n, &knet->kni_list_head, list) {\n \t\tif (strncmp(dev->name, dev_info.name, RTE_KNI_NAMESIZE) != 0)\n \t\t\tcontinue;\n \n@@ -539,7 +576,7 @@ kni_ioctl_release(unsigned int ioctl_num, unsigned long ioctl_param)\n \t\tret = 0;\n \t\tbreak;\n \t}\n-\tup_write(&kni_list_lock);\n+\tup_write(&knet->kni_list_lock);\n \tprintk(KERN_INFO \"KNI: %s release kni named %s\\n\",\n \t\t(ret == 0 ? \"Successfully\" : \"Unsuccessfully\"), dev_info.name);\n \n@@ -552,8 +589,9 @@ kni_ioctl(struct inode *inode,\n \tunsigned long ioctl_param)\n {\n \tint ret = -EINVAL;\n+\tstruct net *net = current->nsproxy->net_ns;\n \n-\tKNI_DBG(\"IOCTL num=0x%0x param=0x%0lx \\n\", ioctl_num, ioctl_param);\n+\tKNI_DBG(\"IOCTL num=0x%0x param=0x%0lx\\n\", ioctl_num, ioctl_param);\n \n \t/*\n \t * Switch according to the ioctl called\n@@ -563,13 +601,13 @@ kni_ioctl(struct inode *inode,\n \t\t/* For test only, not used */\n \t\tbreak;\n \tcase _IOC_NR(RTE_KNI_IOCTL_CREATE):\n-\t\tret = kni_ioctl_create(ioctl_num, ioctl_param);\n+\t\tret = kni_ioctl_create(net, ioctl_num, ioctl_param);\n \t\tbreak;\n \tcase _IOC_NR(RTE_KNI_IOCTL_RELEASE):\n-\t\tret = kni_ioctl_release(ioctl_num, ioctl_param);\n+\t\tret = kni_ioctl_release(net, ioctl_num, ioctl_param);\n \t\tbreak;\n \tdefault:\n-\t\tKNI_DBG(\"IOCTL default \\n\");\n+\t\tKNI_DBG(\"IOCTL default\\n\");\n \t\tbreak;\n \t}\n \n",
    "prefixes": [
        "dpdk-dev",
        "v2"
    ]
}