netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: kan.liang@intel.com
To: davem@davemloft.net, linux-kernel@vger.kernel.org,
	netdev@vger.kernel.org
Cc: mingo@redhat.com, peterz@infradead.org, kuznet@ms2.inr.ac.ru,
	jmorris@namei.org, yoshfuji@linux-ipv6.org, kaber@trash.net,
	akpm@linux-foundation.org, keescook@chromium.org,
	viro@zeniv.linux.org.uk, gorcunov@openvz.org,
	john.stultz@linaro.org, aduyck@mirantis.com, ben@decadent.org.uk,
	decot@googlers.com, fw@strlen.de, alexander.duyck@gmail.com,
	daniel@iogearbox.net, tom@herbertland.com, rdunlap@infradead.org,
	xiyou.wangcong@gmail.com, hannes@stressinduktion.org,
	jesse.brandeburg@intel.com, andi@firstfloor.org,
	Kan Liang <kan.liang@intel.com>
Subject: [RFC V2 PATCH 17/25] net/netpolicy: introduce netpolicy_pick_queue
Date: Thu,  4 Aug 2016 15:36:21 -0400	[thread overview]
Message-ID: <1470339389-8542-18-git-send-email-kan.liang@intel.com> (raw)
In-Reply-To: <1470339389-8542-1-git-send-email-kan.liang@intel.com>

From: Kan Liang <kan.liang@intel.com>

To achieve better network performance, the key step is to distribute the
packets to dedicated queues according to policy and system run time
status.

This patch provides an interface which can return the proper dedicated
queue for socket/task. Then the packets of the socket/task will be
redirect to the dedicated queue for better network performance.

For selecting the proper queue, currently it uses round-robin algorithm
to find the available object from the given policy object list. The
algorithm is good enough for now. But it could be improved by some
adaptive algorithm later.

The selected object will be stored in hashtable. So it does not need to
go through the whole object list every time.

Signed-off-by: Kan Liang <kan.liang@intel.com>
---
 include/linux/netpolicy.h |   5 ++
 net/core/netpolicy.c      | 136 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 141 insertions(+)

diff --git a/include/linux/netpolicy.h b/include/linux/netpolicy.h
index 5900252..a522015 100644
--- a/include/linux/netpolicy.h
+++ b/include/linux/netpolicy.h
@@ -97,6 +97,7 @@ extern void update_netpolicy_sys_map(void);
 extern int netpolicy_register(struct netpolicy_instance *instance,
 			      enum netpolicy_name policy);
 extern void netpolicy_unregister(struct netpolicy_instance *instance);
+extern int netpolicy_pick_queue(struct netpolicy_instance *instance, bool is_rx);
 #else
 static inline void update_netpolicy_sys_map(void)
 {
@@ -111,6 +112,10 @@ static inline void netpolicy_unregister(struct netpolicy_instance *instance)
 {
 }
 
+static inline int netpolicy_pick_queue(struct netpolicy_instance *instance, bool is_rx)
+{
+	return 0;
+}
 #endif
 
 #endif /*__LINUX_NETPOLICY_H*/
diff --git a/net/core/netpolicy.c b/net/core/netpolicy.c
index 3605761..98ca430 100644
--- a/net/core/netpolicy.c
+++ b/net/core/netpolicy.c
@@ -290,6 +290,142 @@ static void netpolicy_record_clear_dev_node(struct net_device *dev)
 	spin_unlock_bh(&np_hashtable_lock);
 }
 
+static struct netpolicy_object *get_avail_object(struct net_device *dev,
+						 enum netpolicy_name policy,
+						 bool is_rx)
+{
+	int dir = is_rx ? NETPOLICY_RX : NETPOLICY_TX;
+	struct netpolicy_object *tmp, *obj = NULL;
+	int val = -1;
+
+	/* Check if net policy is supported */
+	if (!dev || !dev->netpolicy)
+		return NULL;
+
+	/* The system should have queues which support the request policy. */
+	if ((policy != dev->netpolicy->cur_policy) &&
+	    (dev->netpolicy->cur_policy != NET_POLICY_MIX))
+		return NULL;
+
+	spin_lock_bh(&dev->np_ob_list_lock);
+	list_for_each_entry(tmp, &dev->netpolicy->obj_list[dir][policy], list) {
+		if ((val > atomic_read(&tmp->refcnt)) ||
+		    (val == -1)) {
+			val = atomic_read(&tmp->refcnt);
+			obj = tmp;
+		}
+	}
+
+	if (WARN_ON(!obj)) {
+		spin_unlock_bh(&dev->np_ob_list_lock);
+		return NULL;
+	}
+	atomic_inc(&obj->refcnt);
+	spin_unlock_bh(&dev->np_ob_list_lock);
+
+	return obj;
+}
+
+static int get_avail_queue(struct netpolicy_instance *instance, bool is_rx)
+{
+	struct netpolicy_record *old_record, *new_record;
+	struct net_device *dev = instance->dev;
+	unsigned long ptr_id = (uintptr_t)instance->ptr;
+	int queue = -1;
+
+	spin_lock_bh(&np_hashtable_lock);
+	old_record = netpolicy_record_search(ptr_id);
+	if (!old_record) {
+		pr_warn("NETPOLICY: doesn't registered. Remove net policy settings!\n");
+		instance->policy = NET_POLICY_INVALID;
+		goto err;
+	}
+
+	if (is_rx && old_record->rx_obj) {
+		queue = old_record->rx_obj->queue;
+	} else if (!is_rx && old_record->tx_obj) {
+		queue = old_record->tx_obj->queue;
+	} else {
+		new_record = kzalloc(sizeof(*new_record), GFP_KERNEL);
+		if (!new_record)
+			goto err;
+		memcpy(new_record, old_record, sizeof(*new_record));
+
+		if (is_rx) {
+			new_record->rx_obj = get_avail_object(dev, new_record->policy, is_rx);
+			if (!new_record->dev)
+				new_record->dev = dev;
+			if (!new_record->rx_obj) {
+				kfree(new_record);
+				goto err;
+			}
+			queue = new_record->rx_obj->queue;
+		} else {
+			new_record->tx_obj = get_avail_object(dev, new_record->policy, is_rx);
+			if (!new_record->dev)
+				new_record->dev = dev;
+			if (!new_record->tx_obj) {
+				kfree(new_record);
+				goto err;
+			}
+			queue = new_record->tx_obj->queue;
+		}
+		/* update record */
+		hlist_replace_rcu(&old_record->hash_node, &new_record->hash_node);
+		kfree(old_record);
+	}
+err:
+	spin_unlock_bh(&np_hashtable_lock);
+	return queue;
+}
+
+static inline bool policy_validate(struct netpolicy_instance *instance)
+{
+	struct net_device *dev = instance->dev;
+	enum netpolicy_name cur_policy;
+
+	cur_policy = dev->netpolicy->cur_policy;
+	if ((instance->policy == NET_POLICY_NONE) ||
+	    (cur_policy == NET_POLICY_NONE))
+		return false;
+
+	if (((cur_policy != NET_POLICY_MIX) && (cur_policy != instance->policy)) ||
+	    ((cur_policy == NET_POLICY_MIX) && (instance->policy == NET_POLICY_CPU))) {
+		pr_warn("NETPOLICY: %s current device policy %s doesn't support required policy %s! Remove net policy settings!\n",
+			dev->name, policy_name[cur_policy],
+			policy_name[instance->policy]);
+		return false;
+	}
+	return true;
+}
+
+/**
+ * netpolicy_pick_queue() - Find proper queue
+ * @instance:	NET policy per socket/task instance info
+ * @is_rx:	RX queue or TX queue
+ *
+ * This function intends to find the proper queue according to policy.
+ * For selecting the proper queue, currently it uses round-robin algorithm
+ * to find the available object from the given policy object list.
+ * The selected object will be stored in hashtable. So it does not need to
+ * go through the whole object list every time.
+ *
+ * Return: negative on failure, otherwise on the assigned queue
+ */
+int netpolicy_pick_queue(struct netpolicy_instance *instance, bool is_rx)
+{
+	struct net_device *dev = instance->dev;
+
+	if (!dev || !dev->netpolicy)
+		return -EINVAL;
+
+	if (!policy_validate(instance))
+		return -EINVAL;
+
+	return get_avail_queue(instance, is_rx);
+}
+EXPORT_SYMBOL(netpolicy_pick_queue);
+
 /**
  * netpolicy_register() - Register per socket/task policy request
  * @instance:	NET policy per socket/task instance info
-- 
2.5.5

  parent reply	other threads:[~2016-08-04 19:36 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-04 19:36 [RFC V2 PATCH 00/25] Kernel NET policy kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 01/25] net: introduce " kan.liang
2016-08-04 20:09   ` Randy Dunlap
2016-08-04 19:36 ` [RFC V2 PATCH 02/25] net/netpolicy: init " kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 03/25] net/netpolicy: get device queue irq information kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 04/25] net/netpolicy: get CPU information kan.liang
2016-08-05 11:00   ` Sergei Shtylyov
2016-08-04 19:36 ` [RFC V2 PATCH 05/25] net/netpolicy: create CPU and queue mapping kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 06/25] net/netpolicy: set and remove IRQ affinity kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 07/25] net/netpolicy: enable and disable NET policy kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 08/25] net/netpolicy: introduce NET policy object kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 09/25] net/netpolicy: set NET policy by policy name kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 10/25] net/netpolicy: add three new NET policies kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 11/25] net/netpolicy: add MIX policy kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 12/25] net/netpolicy: NET device hotplug kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 13/25] net/netpolicy: support CPU hotplug kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 14/25] net/netpolicy: handle channel changes kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 15/25] net/netpolicy: implement netpolicy register kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 16/25] net/netpolicy: introduce per socket netpolicy kan.liang
2016-08-04 19:36 ` kan.liang [this message]
2016-08-04 20:21   ` [RFC V2 PATCH 17/25] net/netpolicy: introduce netpolicy_pick_queue John Fastabend
2016-08-04 22:39     ` Daniel Borkmann
2016-08-04 22:54       ` Andi Kleen
2016-08-05  0:17         ` Daniel Borkmann
2016-08-05 14:41           ` Tom Herbert
2016-08-05  3:51   ` Tom Herbert
2016-08-05 13:55     ` Liang, Kan
2016-08-05 14:38       ` Tom Herbert
2016-08-04 19:36 ` [RFC V2 PATCH 18/25] net/netpolicy: set Tx queues according to policy kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 19/25] net/netpolicy: set Rx " kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 20/25] net/netpolicy: introduce per task net policy kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 21/25] net/netpolicy: set per task policy by proc kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 22/25] net/netpolicy: fast path for finding the queues kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 23/25] net/netpolicy: optimize for queue pair kan.liang
2016-08-04 19:36 ` [RFC V2 PATCH 24/25] net/netpolicy: limit the total record number kan.liang
2016-08-17  1:43   ` [lkp] [net/netpolicy] 19e7d15d66: EIP: [<c735077b>] netpolicy_unregister+0x23a/0x28a SS:ESP 0068:ceb19d94 kernel test robot
2016-08-04 19:36 ` [RFC V2 PATCH 25/25] Documentation/networking: Document NET policy kan.liang
  -- strict thread matches above, loose matches on Subject: below --
2015-01-01  1:38 [RFC V2 PATCH 00/25] Kernel " kan.liang
2015-01-01  1:39 ` [RFC V2 PATCH 17/25] net/netpolicy: introduce netpolicy_pick_queue kan.liang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1470339389-8542-18-git-send-email-kan.liang@intel.com \
    --to=kan.liang@intel.com \
    --cc=aduyck@mirantis.com \
    --cc=akpm@linux-foundation.org \
    --cc=alexander.duyck@gmail.com \
    --cc=andi@firstfloor.org \
    --cc=ben@decadent.org.uk \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=decot@googlers.com \
    --cc=fw@strlen.de \
    --cc=gorcunov@openvz.org \
    --cc=hannes@stressinduktion.org \
    --cc=jesse.brandeburg@intel.com \
    --cc=jmorris@namei.org \
    --cc=john.stultz@linaro.org \
    --cc=kaber@trash.net \
    --cc=keescook@chromium.org \
    --cc=kuznet@ms2.inr.ac.ru \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=peterz@infradead.org \
    --cc=rdunlap@infradead.org \
    --cc=tom@herbertland.com \
    --cc=viro@zeniv.linux.org.uk \
    --cc=xiyou.wangcong@gmail.com \
    --cc=yoshfuji@linux-ipv6.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).