Networking under KVM works best if we allocate a per-vCPU rx and tx
queue in a virtual NIC. This requires a per-vCPU queue on the host side.
Modern physical NICs have multiqueue support for large number of queues.
To scale vNIC to run multiple queues parallel to maximum number of vCPU's
we need to increase number of queues support in tuntap.
This series is to increase the limit of tuntap queues. Original work is being
done by 'jasowang@redhat.com'. I am taking this 'https://lkml.org/lkml/2013/6/19/29'
patch series as a reference. As per discussion in the patch series:
There were two reasons which prevented us from increasing number of tun queues:
- The netdev_queue array in netdevice were allocated through kmalloc, which may
cause a high order memory allocation too when we have several queues.
E.g. sizeof(netdev_queue) is 320, which means a high order allocation would
happens when the device has more than 16 queues.
- We store the hash buckets in tun_struct which results a very large size of
tun_struct, this high order memory allocation fail easily when the memory is
fragmented.
The patch 60877a32bce00041528576e6b8df5abe9251fa73 increases the number of tx
queues. Memory allocation fallback to vzalloc() when kmalloc() fails.
This series tries to address following issues:
- Increase the number of netdev_queue queues for rx similarly its done for tx
queues by falling back to vzalloc() when memory allocation with kmalloc() fails.
- Switches to use flex array to implement the flow caches to avoid higher order
allocations.
- Publish maximum number of queues as read only module_param so that user space
application like libvirt can use this value to limit number of queues. Also
Administrators can specify number of queues at module load time.
- Increase number of queues to 256, maximum number is equal to maximum number
of vCPUS allowed in a guest.
I have done some testing to find out any regression and with sample program
which creates tun/tap for single queue / multiqueue device and it seems to be
working fine.
tuntap: Increase the number of queues in tun
tuntap: Reduce the size of tun_struct by using flex array
tuntap: Publish tuntap max queue length as module_param
net: allow large number of rx queues
drivers/net/tun.c | 71 ++++++++++++++++++++++++++++++++++++++++--------------
net/core/dev.c | 20 +++++++++------
2 files changed, 66 insertions(+), 25 deletions(-)
netif_alloc_rx_queues() uses kcalloc() to allocate memory
for "struct netdev_queue *_rx" array.
If we are doing large rx queue allocation kcalloc() might
fail, so this patch does a fallback to vzalloc().
Similar implementation is done for tx queue allocation in
netif_alloc_netdev_queues().
We avoid failure of high order memory allocation
with the help of vzalloc(), this allows us to do large
rx and tx queue allocation which in turn helps us to
increase the number of queues in tun.
As vmalloc() adds overhead on a critical network path,
__GFP_REPEAT flag is used with kzalloc() to do this fallback
only when really needed.
Signed-off-by: Pankaj Gupta <redacted>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: David Gibson <redacted>
---
net/core/dev.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
This patch publishes maximum number of tun/tap queues allocated as a
read_only module parameter which a user space application like libvirt
can make use of to limit maximum number of queues. Value of read_only
module parameter can be writable only at module load time. If no value is set
at module load time a default value 256 is used which is equal to maximum number
of vCPUS allowed by KVM.
Administrator can specify maximum number of queues only at the driver
module load time.
Signed-off-by: Pankaj Gupta <redacted>
---
drivers/net/tun.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
@@ -119,6 +119,9 @@ struct tap_filter {#define TUN_FLOW_EXPIRE (3 * HZ)+staticintmax_tap_queues=MAX_TAP_QUEUES;+module_param(max_tap_queues,int,S_IRUGO);+/* A tun_file connects an open character device to a tuntap netdevice. It*alsocontainsallsocketrelatedstructures(exceptsock_fprogandtap_filter)*toserveasonetransmitqueuefortuntapdevice.Thesock_fprogand
@@ -1609,7 +1612,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)char*name;unsignedlongflags=0;intqueues=ifr->ifr_flags&IFF_MULTI_QUEUE?-MAX_TAP_QUEUES:1;+max_tap_queues:1;if(!ns_capable(net->user_ns,CAP_NET_ADMIN))return-EPERM;
@@ -2327,6 +2330,12 @@ static int __init tun_init(void)pr_info("%s, %s\n",DRV_DESCRIPTION,DRV_VERSION);pr_info("%s\n",DRV_COPYRIGHT);+if(max_tap_queues>MAX_TAP_QUEUES||max_tap_queues<=0){+printk(KERN_WARNING"max_tap_queues parameter value either too large"+" or too small forcing default value: %d\n",MAX_TAP_QUEUES);+max_tap_queues=MAX_TAP_QUEUES;+}+ret=rtnl_link_register(&tun_link_ops);if(ret){pr_err("Can't register link_ops\n");
This patch switches to flex array to implement the flow caches, it brings
several advantages:
- Reduce the size of the tun_struct structure, which allows us to increase the
upper limit of queues in future.
- Avoid higher order memory allocation. It will be useful when switching to
pure hashing in flow cache which may demand a larger size array in future.
After this patch, the size of tun_struct on x86_64 reduced from 8512 to
328
Signed-off-by: Jason Wang <redacted>
Signed-off-by: Pankaj Gupta <redacted>
---
drivers/net/tun.c | 49 +++++++++++++++++++++++++++++++++++++------------
1 files changed, 37 insertions(+), 12 deletions(-)
Networking under kvm works best if we allocate a per-vCPU RX and TX
queue in a virtual NIC. This requires a per-vCPU queue on the host side.
It is now safe to increase the maximum number of queues.
Preceding patches:
net: allow large number of rx queues
tuntap: Reduce the size of tun_struct by using flex array
tuntap: Publish tuntap max queue length as module_param
made sure this won't cause failures due to high order memory
allocations. Increase it to 256: this is the max number of vCPUs
KVM supports.
Signed-off-by: Pankaj Gupta <redacted>
---
drivers/net/tun.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
@@ -111,10 +111,11 @@ struct tap_filter {unsignedcharaddr[FLT_EXACT_COUNT][ETH_ALEN];};-/* DEFAULT_MAX_NUM_RSS_QUEUES were chosen to let the rx/tx queues allocated for-*thenetdevicetobefitinonepage.Sowecanmakesurethesuccessof-*memoryallocation.TODO:increasethelimit.*/-#define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES+/* MAX_TAP_QUEUES 256 is chosen to allow rx/tx queues to be equal+*tomaxnumberofvCPUSinguest.Also,wearemakingsurehere+*queuememoryallocationdonotfail.+*/+#define MAX_TAP_QUEUES 256#define MAX_TAP_FLOWS 4096#define TUN_FLOW_EXPIRE (3 * HZ)
From: Sergei Shtylyov <hidden> Date: 2014-08-18 17:43:46
Hello.
On 08/18/2014 05:37 PM, Pankaj Gupta wrote:
netif_alloc_rx_queues() uses kcalloc() to allocate memory
for "struct netdev_queue *_rx" array.
If we are doing large rx queue allocation kcalloc() might
fail, so this patch does a fallback to vzalloc().
Similar implementation is done for tx queue allocation in
netif_alloc_netdev_queues().
We avoid failure of high order memory allocation
with the help of vzalloc(), this allows us to do large
rx and tx queue allocation which in turn helps us to
increase the number of queues in tun.
As vmalloc() adds overhead on a critical network path,
__GFP_REPEAT flag is used with kzalloc() to do this fallback
only when really needed.
Signed-off-by: Pankaj Gupta <redacted>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: David Gibson <redacted>
---
net/core/dev.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
Hello.
On 08/18/2014 05:37 PM, Pankaj Gupta wrote:
quoted
netif_alloc_rx_queues() uses kcalloc() to allocate memory
for "struct netdev_queue *_rx" array.
If we are doing large rx queue allocation kcalloc() might
fail, so this patch does a fallback to vzalloc().
Similar implementation is done for tx queue allocation in
netif_alloc_netdev_queues().
quoted
We avoid failure of high order memory allocation
with the help of vzalloc(), this allows us to do large
rx and tx queue allocation which in turn helps us to
increase the number of queues in tun.
quoted
As vmalloc() adds overhead on a critical network path,
__GFP_REPEAT flag is used with kzalloc() to do this fallback
only when really needed.
quoted
Signed-off-by: Pankaj Gupta <redacted>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: David Gibson <redacted>
---
net/core/dev.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
Mon, Aug 18, 2014 at 03:37:18PM CEST, pagupta@redhat.com wrote:
quoted hunk
This patch publishes maximum number of tun/tap queues allocated as a
read_only module parameter which a user space application like libvirt
can make use of to limit maximum number of queues. Value of read_only
module parameter can be writable only at module load time. If no value is set
at module load time a default value 256 is used which is equal to maximum number
of vCPUS allowed by KVM.
Administrator can specify maximum number of queues only at the driver
module load time.
Signed-off-by: Pankaj Gupta <redacted>
---
drivers/net/tun.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2014-08-20 11:17:10
On Wed, Aug 20, 2014 at 12:58:17PM +0200, Jiri Pirko wrote:
Mon, Aug 18, 2014 at 03:37:18PM CEST, pagupta@redhat.com wrote:
quoted
This patch publishes maximum number of tun/tap queues allocated as a
read_only module parameter which a user space application like libvirt
can make use of to limit maximum number of queues. Value of read_only
module parameter can be writable only at module load time. If no value is set
at module load time a default value 256 is used which is equal to maximum number
of vCPUS allowed by KVM.
Administrator can specify maximum number of queues only at the driver
module load time.
Signed-off-by: Pankaj Gupta <redacted>
---
drivers/net/tun.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
Please do not introduce new module paramaters. Please other ways to
interchange values with userspace.
I suggested this initially, but thinking more about it, I agree.
It's a global limit (necessary to limit memory utilization by
userspace), but it should be possible to change it
after module load.
Additionally, userspace that has the FD should be able to
retrieve the value without guessing that the FD is
for the tun device (and not e.g. macvtap).
To retrieve the value, an ioctl is probably the
cleanest approach.
To set it, how about a sysctl? I think the limit can also apply to
all devices, not just tun.
--
MST
Wed, Aug 20, 2014 at 01:17:24PM CEST, mst@redhat.com wrote:
On Wed, Aug 20, 2014 at 12:58:17PM +0200, Jiri Pirko wrote:
quoted
Mon, Aug 18, 2014 at 03:37:18PM CEST, pagupta@redhat.com wrote:
quoted
This patch publishes maximum number of tun/tap queues allocated as a
read_only module parameter which a user space application like libvirt
can make use of to limit maximum number of queues. Value of read_only
module parameter can be writable only at module load time. If no value is set
at module load time a default value 256 is used which is equal to maximum number
of vCPUS allowed by KVM.
Administrator can specify maximum number of queues only at the driver
module load time.
Signed-off-by: Pankaj Gupta <redacted>
---
drivers/net/tun.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
Please do not introduce new module paramaters. Please other ways to
interchange values with userspace.
I suggested this initially, but thinking more about it, I agree.
It's a global limit (necessary to limit memory utilization by
userspace), but it should be possible to change it
after module load.
Additionally, userspace that has the FD should be able to
retrieve the value without guessing that the FD is
for the tun device (and not e.g. macvtap).
To retrieve the value, an ioctl is probably the
cleanest approach.
To set it, how about a sysctl? I think the limit can also apply to
all devices, not just tun.
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2014-08-20 11:48:51
On Wed, Aug 20, 2014 at 01:46:20PM +0200, Jiri Pirko wrote:
Wed, Aug 20, 2014 at 01:17:24PM CEST, mst@redhat.com wrote:
quoted
On Wed, Aug 20, 2014 at 12:58:17PM +0200, Jiri Pirko wrote:
quoted
Mon, Aug 18, 2014 at 03:37:18PM CEST, pagupta@redhat.com wrote:
quoted
This patch publishes maximum number of tun/tap queues allocated as a
read_only module parameter which a user space application like libvirt
can make use of to limit maximum number of queues. Value of read_only
module parameter can be writable only at module load time. If no value is set
at module load time a default value 256 is used which is equal to maximum number
of vCPUS allowed by KVM.
Administrator can specify maximum number of queues only at the driver
module load time.
Signed-off-by: Pankaj Gupta <redacted>
---
drivers/net/tun.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
Please do not introduce new module paramaters. Please other ways to
interchange values with userspace.
I suggested this initially, but thinking more about it, I agree.
It's a global limit (necessary to limit memory utilization by
userspace), but it should be possible to change it
after module load.
Additionally, userspace that has the FD should be able to
retrieve the value without guessing that the FD is
for the tun device (and not e.g. macvtap).
To retrieve the value, an ioctl is probably the
cleanest approach.
To set it, how about a sysctl? I think the limit can also apply to
all devices, not just tun.
Or netlink?
Are there examples of netlink being used to set global defaults
as opposed to per-device parameters?
Wed, Aug 20, 2014 at 01:49:07PM CEST, mst@redhat.com wrote:
On Wed, Aug 20, 2014 at 01:46:20PM +0200, Jiri Pirko wrote:
quoted
Wed, Aug 20, 2014 at 01:17:24PM CEST, mst@redhat.com wrote:
quoted
On Wed, Aug 20, 2014 at 12:58:17PM +0200, Jiri Pirko wrote:
quoted
Mon, Aug 18, 2014 at 03:37:18PM CEST, pagupta@redhat.com wrote:
quoted
This patch publishes maximum number of tun/tap queues allocated as a
read_only module parameter which a user space application like libvirt
can make use of to limit maximum number of queues. Value of read_only
module parameter can be writable only at module load time. If no value is set
at module load time a default value 256 is used which is equal to maximum number
of vCPUS allowed by KVM.
Administrator can specify maximum number of queues only at the driver
module load time.
Signed-off-by: Pankaj Gupta <redacted>
---
drivers/net/tun.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
Please do not introduce new module paramaters. Please other ways to
interchange values with userspace.
I suggested this initially, but thinking more about it, I agree.
It's a global limit (necessary to limit memory utilization by
userspace), but it should be possible to change it
after module load.
Additionally, userspace that has the FD should be able to
retrieve the value without guessing that the FD is
for the tun device (and not e.g. macvtap).
To retrieve the value, an ioctl is probably the
cleanest approach.
To set it, how about a sysctl? I think the limit can also apply to
all devices, not just tun.
Or netlink?
Are there examples of netlink being used to set global defaults
as opposed to per-device parameters?
That is so far not possible. But I believe that it can be implemented.
I'm just thinking out loud.
From: Jason Wang <hidden> Date: 2014-08-21 04:31:22
On 08/20/2014 07:17 PM, Michael S. Tsirkin wrote:
On Wed, Aug 20, 2014 at 12:58:17PM +0200, Jiri Pirko wrote:
quoted
quoted
Mon, Aug 18, 2014 at 03:37:18PM CEST, pagupta@redhat.com wrote:
quoted
quoted
This patch publishes maximum number of tun/tap queues allocated as a
read_only module parameter which a user space application like libvirt
can make use of to limit maximum number of queues. Value of read_only
module parameter can be writable only at module load time. If no value is set
at module load time a default value 256 is used which is equal to maximum number
of vCPUS allowed by KVM.
Administrator can specify maximum number of queues only at the driver
module load time.
Signed-off-by: Pankaj Gupta <redacted>
---
drivers/net/tun.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
Please do not introduce new module paramaters. Please other ways to
interchange values with userspace.
I suggested this initially, but thinking more about it, I agree.
It's a global limit (necessary to limit memory utilization by
userspace), but it should be possible to change it
after module load.
How about pass this limit through ifr during TUNSETIFF, then
alloc_netdev_mq() can use this limit.
On Wed, Aug 20, 2014 at 12:58:17PM +0200, Jiri Pirko wrote:
quoted
quoted
Mon, Aug 18, 2014 at 03:37:18PM CEST, pagupta@redhat.com wrote:
quoted
quoted
This patch publishes maximum number of tun/tap queues allocated as a
read_only module parameter which a user space application like
libvirt
can make use of to limit maximum number of queues. Value of read_only
module parameter can be writable only at module load time. If no
value is set
at module load time a default value 256 is used which is equal to
maximum number
of vCPUS allowed by KVM.
Administrator can specify maximum number of queues only at the driver
module load time.
Signed-off-by: Pankaj Gupta <redacted>
---
drivers/net/tun.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
Please do not introduce new module paramaters. Please other ways to
interchange values with userspace.
I suggested this initially, but thinking more about it, I agree.
It's a global limit (necessary to limit memory utilization by
userspace), but it should be possible to change it
after module load.
How about pass this limit through ifr during TUNSETIFF, then
alloc_netdev_mq() can use this limit.
Any other ideas/comments from the experts. Or shall I re-repost other patches
in the series except this patch until we agree on one.
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2014-08-24 11:14:09
On Fri, Aug 22, 2014 at 07:52:22AM -0400, Pankaj Gupta wrote:
quoted
On 08/20/2014 07:17 PM, Michael S. Tsirkin wrote:
quoted
On Wed, Aug 20, 2014 at 12:58:17PM +0200, Jiri Pirko wrote:
quoted
quoted
Mon, Aug 18, 2014 at 03:37:18PM CEST, pagupta@redhat.com wrote:
quoted
quoted
This patch publishes maximum number of tun/tap queues allocated as a
read_only module parameter which a user space application like
libvirt
can make use of to limit maximum number of queues. Value of read_only
module parameter can be writable only at module load time. If no
value is set
at module load time a default value 256 is used which is equal to
maximum number
of vCPUS allowed by KVM.
Administrator can specify maximum number of queues only at the driver
module load time.
Signed-off-by: Pankaj Gupta <redacted>
---
drivers/net/tun.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
Please do not introduce new module paramaters. Please other ways to
interchange values with userspace.
I suggested this initially, but thinking more about it, I agree.
It's a global limit (necessary to limit memory utilization by
userspace), but it should be possible to change it
after module load.
How about pass this limit through ifr during TUNSETIFF, then
alloc_netdev_mq() can use this limit.
Any other ideas/comments from the experts. Or shall I re-repost other patches
in the series except this patch until we agree on one.
quoted
It's kind of useless without a way for userspace to discover
how many queues it can create, no?
From: David Gibson <hidden> Date: 2014-08-25 01:35:07
On Mon, 18 Aug 2014 19:07:19 +0530
Pankaj Gupta [off-list ref] wrote:
This patch switches to flex array to implement the flow caches, it brings
several advantages:
- Reduce the size of the tun_struct structure, which allows us to increase the
upper limit of queues in future.
- Avoid higher order memory allocation. It will be useful when switching to
pure hashing in flow cache which may demand a larger size array in future.
After this patch, the size of tun_struct on x86_64 reduced from 8512 to
328
Signed-off-by: Jason Wang <redacted>
Signed-off-by: Pankaj Gupta <redacted>
Reviewed-by: David Gibson <redacted>
--
David Gibson [off-list ref]
From: David Gibson <hidden> Date: 2014-08-25 01:37:36
On Mon, 18 Aug 2014 19:07:20 +0530
Pankaj Gupta [off-list ref] wrote:
Networking under kvm works best if we allocate a per-vCPU RX and TX
queue in a virtual NIC. This requires a per-vCPU queue on the host side.
It is now safe to increase the maximum number of queues.
Preceding patches:
net: allow large number of rx queues
tuntap: Reduce the size of tun_struct by using flex array
tuntap: Publish tuntap max queue length as module_param
made sure this won't cause failures due to high order memory
allocations. Increase it to 256: this is the max number of vCPUs
KVM supports.
Signed-off-by: Pankaj Gupta <redacted>
Reviewed-by: David Gibson <redacted>
--
David Gibson [off-list ref]
From: Jason Wang <hidden> Date: 2014-08-25 02:57:39
On 08/24/2014 07:14 PM, Michael S. Tsirkin wrote:
On Fri, Aug 22, 2014 at 07:52:22AM -0400, Pankaj Gupta wrote:
quoted
quoted
On 08/20/2014 07:17 PM, Michael S. Tsirkin wrote:
quoted
On Wed, Aug 20, 2014 at 12:58:17PM +0200, Jiri Pirko wrote:
quoted
quoted
Mon, Aug 18, 2014 at 03:37:18PM CEST, pagupta@redhat.com wrote:
quoted
quoted
This patch publishes maximum number of tun/tap queues allocated as a
read_only module parameter which a user space application like
libvirt
can make use of to limit maximum number of queues. Value of read_only
module parameter can be writable only at module load time. If no
value is set
at module load time a default value 256 is used which is equal to
maximum number
of vCPUS allowed by KVM.
Administrator can specify maximum number of queues only at the driver
module load time.
Signed-off-by: Pankaj Gupta <redacted>
---
drivers/net/tun.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
Please do not introduce new module paramaters. Please other ways to
interchange values with userspace.
I suggested this initially, but thinking more about it, I agree.
It's a global limit (necessary to limit memory utilization by
userspace), but it should be possible to change it
after module load.
How about pass this limit through ifr during TUNSETIFF, then
alloc_netdev_mq() can use this limit.
Any other ideas/comments from the experts. Or shall I re-repost other patches
in the series except this patch until we agree on one.
It's kind of useless without a way for userspace to discover
how many queues it can create, no?
We can implement ethtool_get_channels for tuntap. But I'm still not
clear why this is necessary.
On Fri, Aug 22, 2014 at 07:52:22AM -0400, Pankaj Gupta wrote:
quoted
quoted
On 08/20/2014 07:17 PM, Michael S. Tsirkin wrote:
quoted
On Wed, Aug 20, 2014 at 12:58:17PM +0200, Jiri Pirko wrote:
quoted
quoted
Mon, Aug 18, 2014 at 03:37:18PM CEST, pagupta@redhat.com wrote:
quoted
quoted
This patch publishes maximum number of tun/tap queues allocated as a
read_only module parameter which a user space application like
libvirt
can make use of to limit maximum number of queues. Value of
read_only
module parameter can be writable only at module load time. If no
value is set
at module load time a default value 256 is used which is equal to
maximum number
of vCPUS allowed by KVM.
Administrator can specify maximum number of queues only at the
driver
module load time.
Signed-off-by: Pankaj Gupta <redacted>
---
drivers/net/tun.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
Please do not introduce new module paramaters. Please other ways to
interchange values with userspace.
I suggested this initially, but thinking more about it, I agree.
It's a global limit (necessary to limit memory utilization by
userspace), but it should be possible to change it
after module load.
How about pass this limit through ifr during TUNSETIFF, then
alloc_netdev_mq() can use this limit.
Any other ideas/comments from the experts. Or shall I re-repost other
patches
in the series except this patch until we agree on one.
It's kind of useless without a way for userspace to discover
how many queues it can create, no?
We can implement ethtool_get_channels for tuntap. But I'm still not
clear why this is necessary.
ethtool_get_channels for tuntap sounds good idea to retrieve number of queues
configured.