{"id":819027,"url":"http://patchwork.ozlabs.org/api/patches/819027/?format=json","web_url":"http://patchwork.ozlabs.org/project/netdev/patch/1506500637-13881-2-git-send-email-jasowang@redhat.com/","project":{"id":7,"url":"http://patchwork.ozlabs.org/api/projects/7/?format=json","name":"Linux network development","link_name":"netdev","list_id":"netdev.vger.kernel.org","list_email":"netdev@vger.kernel.org","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<1506500637-13881-2-git-send-email-jasowang@redhat.com>","list_archive_url":null,"date":"2017-09-27T08:23:55","name":"[net-next,1/3] tun: abstract flow steering logic","commit_ref":null,"pull_url":null,"state":"changes-requested","archived":true,"hash":"8e28a802a9a3b8687664e474030a5245862870e2","submitter":{"id":5225,"url":"http://patchwork.ozlabs.org/api/people/5225/?format=json","name":"Jason Wang","email":"jasowang@redhat.com"},"delegate":{"id":34,"url":"http://patchwork.ozlabs.org/api/users/34/?format=json","username":"davem","first_name":"David","last_name":"Miller","email":"davem@davemloft.net"},"mbox":"http://patchwork.ozlabs.org/project/netdev/patch/1506500637-13881-2-git-send-email-jasowang@redhat.com/mbox/","series":[{"id":5306,"url":"http://patchwork.ozlabs.org/api/series/5306/?format=json","web_url":"http://patchwork.ozlabs.org/project/netdev/list/?series=5306","date":"2017-09-27T08:23:56","name":"support changing steering policies in tuntap","version":1,"mbox":"http://patchwork.ozlabs.org/series/5306/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/819027/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/819027/checks/","tags":{},"related":[],"headers":{"Return-Path":"<netdev-owner@vger.kernel.org>","X-Original-To":"patchwork-incoming@ozlabs.org","Delivered-To":"patchwork-incoming@ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)","ext-mx09.extmail.prod.ext.phx2.redhat.com;\n\tdmarc=none (p=none dis=none) header.from=redhat.com","ext-mx09.extmail.prod.ext.phx2.redhat.com;\n\tspf=fail smtp.mailfrom=jasowang@redhat.com"],"Received":["from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3y29qT4Ts7z9t3x\n\tfor <patchwork-incoming@ozlabs.org>;\n\tWed, 27 Sep 2017 18:25:09 +1000 (AEST)","(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1752490AbdI0IY3 (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tWed, 27 Sep 2017 04:24:29 -0400","from mx1.redhat.com ([209.132.183.28]:41116 \"EHLO mx1.redhat.com\"\n\trhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP\n\tid S1751887AbdI0IYI (ORCPT <rfc822;netdev@vger.kernel.org>);\n\tWed, 27 Sep 2017 04:24:08 -0400","from smtp.corp.redhat.com\n\t(int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby mx1.redhat.com (Postfix) with ESMTPS id 4D9B14E909;\n\tWed, 27 Sep 2017 08:24:08 +0000 (UTC)","from jason-ThinkPad-T450s.redhat.com (ovpn-12-60.pek2.redhat.com\n\t[10.72.12.60])\n\tby smtp.corp.redhat.com (Postfix) with ESMTP id 7C71E77C8E;\n\tWed, 27 Sep 2017 08:24:05 +0000 (UTC)"],"DMARC-Filter":"OpenDMARC Filter v1.3.2 mx1.redhat.com 4D9B14E909","From":"Jason Wang <jasowang@redhat.com>","To":"netdev@vger.kernel.org, linux-kernel@vger.kernel.org","Cc":"mst@redhat.com, Jason Wang <jasowang@redhat.com>","Subject":"[PATCH net-next 1/3] tun: abstract flow steering logic","Date":"Wed, 27 Sep 2017 16:23:55 +0800","Message-Id":"<1506500637-13881-2-git-send-email-jasowang@redhat.com>","In-Reply-To":"<1506500637-13881-1-git-send-email-jasowang@redhat.com>","References":"<1506500637-13881-1-git-send-email-jasowang@redhat.com>","X-Scanned-By":"MIMEDefang 2.79 on 10.5.11.15","X-Greylist":"Sender IP whitelisted, not delayed by milter-greylist-4.5.16\n\t(mx1.redhat.com [10.5.110.38]);\n\tWed, 27 Sep 2017 08:24:08 +0000 (UTC)","Sender":"netdev-owner@vger.kernel.org","Precedence":"bulk","List-ID":"<netdev.vger.kernel.org>","X-Mailing-List":"netdev@vger.kernel.org"},"content":"tun now use flow caches based automatic queue steering method. This\nmay not suffice all user cases. To extend it to be able to use more\nflow steering policy, this patch abstracts flow steering logic into\ntun_steering_ops, then we can declare and use different methods in\nthe future.\n\nSigned-off-by: Jason Wang <jasowang@redhat.com>\n---\n drivers/net/tun.c | 85 +++++++++++++++++++++++++++++++++++++++++--------------\n 1 file changed, 63 insertions(+), 22 deletions(-)","diff":"diff --git a/drivers/net/tun.c b/drivers/net/tun.c\nindex 2c36f6e..de83e72 100644\n--- a/drivers/net/tun.c\n+++ b/drivers/net/tun.c\n@@ -181,6 +181,14 @@ struct tun_file {\n \tstruct skb_array tx_array;\n };\n \n+struct tun_steering_ops {\n+\tu16 (*select_queue) (struct tun_struct *tun, struct sk_buff *skb);\n+\tvoid (*xmit) (struct tun_struct *tun, struct sk_buff *skb);\n+\tu32 (*pre_rx) (struct tun_struct *tun, struct sk_buff *skb);\n+\tvoid (*post_rx) (struct tun_struct *tun, struct tun_file *tfile,\n+\t\t\t u32 data);\n+};\n+\n struct tun_flow_entry {\n \tstruct hlist_node hash_link;\n \tstruct rcu_head rcu;\n@@ -231,6 +239,7 @@ struct tun_struct {\n \tu32 rx_batched;\n \tstruct tun_pcpu_stats __percpu *pcpu_stats;\n \tstruct bpf_prog __rcu *xdp_prog;\n+\tstruct tun_steering_ops *steering_ops;\n };\n \n static int tun_napi_receive(struct napi_struct *napi, int budget)\n@@ -532,10 +541,8 @@ static inline void tun_flow_save_rps_rxhash(struct tun_flow_entry *e, u32 hash)\n  * different rxq no. here. If we could not get rxhash, then we would\n  * hope the rxq no. may help here.\n  */\n-static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,\n-\t\t\t    void *accel_priv, select_queue_fallback_t fallback)\n+static u16 tun_automq_select_queue(struct tun_struct *tun, struct sk_buff *skb)\n {\n-\tstruct tun_struct *tun = netdev_priv(dev);\n \tstruct tun_flow_entry *e;\n \tu32 txq = 0;\n \tu32 numqueues = 0;\n@@ -559,9 +566,18 @@ static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,\n \t}\n \n \trcu_read_unlock();\n+\n \treturn txq;\n }\n \n+static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,\n+\t\t\t    void *accel_priv, select_queue_fallback_t fallback)\n+{\n+\tstruct tun_struct *tun = netdev_priv(dev);\n+\n+\treturn tun->steering_ops->select_queue(tun, skb);\n+}\n+\n static inline bool tun_not_capable(struct tun_struct *tun)\n {\n \tconst struct cred *cred = current_cred();\n@@ -931,24 +947,10 @@ static int tun_net_close(struct net_device *dev)\n \treturn 0;\n }\n \n-/* Net device start xmit */\n-static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)\n+static void tun_automq_xmit(struct tun_struct *tun, struct sk_buff *skb)\n {\n-\tstruct tun_struct *tun = netdev_priv(dev);\n-\tint txq = skb->queue_mapping;\n-\tstruct tun_file *tfile;\n-\tu32 numqueues = 0;\n-\n-\trcu_read_lock();\n-\ttfile = rcu_dereference(tun->tfiles[txq]);\n-\tnumqueues = ACCESS_ONCE(tun->numqueues);\n-\n-\t/* Drop packet if interface is not attached */\n-\tif (txq >= numqueues)\n-\t\tgoto drop;\n-\n #ifdef CONFIG_RPS\n-\tif (numqueues == 1 && static_key_false(&rps_needed)) {\n+\tif (ACCESS_ONCE(tun->numqueues) == 1 && static_key_false(&rps_needed)) {\n \t\t/* Select queue was not called for the skbuff, so we extract the\n \t\t * RPS hash and save it into the flow_table here.\n \t\t */\n@@ -964,6 +966,25 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)\n \t\t}\n \t}\n #endif\n+}\n+\n+/* Net device start xmit */\n+static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)\n+{\n+\tstruct tun_struct *tun = netdev_priv(dev);\n+\tint txq = skb->queue_mapping;\n+\tstruct tun_file *tfile;\n+\tu32 numqueues = 0;\n+\n+\trcu_read_lock();\n+\ttfile = rcu_dereference(tun->tfiles[txq]);\n+\tnumqueues = ACCESS_ONCE(tun->numqueues);\n+\n+\t/* Drop packet if interface is not attached */\n+\tif (txq >= numqueues)\n+\t\tgoto drop;\n+\n+\ttun->steering_ops->xmit(tun, skb);\n \n \ttun_debug(KERN_INFO, tun, \"tun_net_xmit %d\\n\", skb->len);\n \n@@ -1527,6 +1548,17 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,\n \treturn NULL;\n }\n \n+u32 tun_automq_pre_rx(struct tun_struct *tun, struct sk_buff *skb)\n+{\n+\treturn __skb_get_hash_symmetric(skb);\n+}\n+\n+void tun_automq_post_rx(struct tun_struct *tun, struct tun_file *tfile,\n+\t\t\tu32 rxhash)\n+{\n+\ttun_flow_update(tun, rxhash, tfile);\n+}\n+\n /* Get packet from user space buffer */\n static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,\n \t\t\t    void *msg_control, struct iov_iter *from,\n@@ -1542,7 +1574,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,\n \tint copylen;\n \tbool zerocopy = false;\n \tint err;\n-\tu32 rxhash;\n+\tu32 data;\n \tint skb_xdp = 1;\n \tbool frags = tun_napi_frags_enabled(tun);\n \n@@ -1728,7 +1760,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,\n \t\trcu_read_unlock();\n \t}\n \n-\trxhash = __skb_get_hash_symmetric(skb);\n+\tdata = tun->steering_ops->pre_rx(tun, skb);\n \n \tif (frags) {\n \t\t/* Exercise flow dissector code path. */\n@@ -1772,7 +1804,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,\n \tu64_stats_update_end(&stats->syncp);\n \tput_cpu_ptr(stats);\n \n-\ttun_flow_update(tun, rxhash, tfile);\n+\ttun->steering_ops->post_rx(tun, tfile, data);\n \treturn total_len;\n }\n \n@@ -2112,6 +2144,13 @@ static struct proto tun_proto = {\n \t.obj_size\t= sizeof(struct tun_file),\n };\n \n+static struct tun_steering_ops tun_automq_ops = {\n+\t.select_queue = tun_automq_select_queue,\n+\t.xmit = tun_automq_xmit,\n+\t.pre_rx = tun_automq_pre_rx,\n+\t.post_rx = tun_automq_post_rx,\n+};\n+\n static int tun_flags(struct tun_struct *tun)\n {\n \treturn tun->flags & (TUN_FEATURES | IFF_PERSIST | IFF_TUN | IFF_TAP);\n@@ -2268,6 +2307,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)\n \t\t\tgoto err_free_dev;\n \t\t}\n \n+\t\ttun->steering_ops = &tun_automq_ops;\n+\n \t\tspin_lock_init(&tun->lock);\n \n \t\terr = security_tun_dev_alloc_security(&tun->security);\n","prefixes":["net-next","1/3"]}