* Network hangs when communicating with host
@ 2015-10-15 20:20 Dmitry Vyukov
2015-10-16 17:25 ` Sasha Levin
0 siblings, 1 reply; 8+ messages in thread
From: Dmitry Vyukov @ 2015-10-15 20:20 UTC (permalink / raw)
To: levinsasha928, Pekka Enberg, asias.hejun, penberg, gorcunov,
Will Deacon, andre.przywara, matt, michael, prasadjoshi124,
Sasha Levin, marc.zyngier, Aneesh Kumar K.V, mingo, gorcunov
Cc: kvm, Kostya Serebryany, Evgenii Stepanov, Alexey Samsonov,
Alexander Potapenko, syzkaller
[-- Attachment #1: Type: text/plain, Size: 995 bytes --]
Hello,
I am trying to run a program in lkvm sandbox so that it communicates
with a program on host. I run lkvm as:
./lkvm sandbox --disk sandbox-test --mem=2048 --cpus=4 --kernel
/arch/x86/boot/bzImage --network mode=user -- /my_prog
/my_prog then connects to a program on host over a tcp socket.
I see that host receives some data, sends some data back, but then
my_prog hangs on network read.
To localize this I wrote 2 programs (attached). ping is run on host
and pong is run from lkvm sandbox. They successfully establish tcp
connection, but after some iterations both hang on read.
Networking code in Go runtime is there for more than 3 years, widely
used in production and does not have any known bugs. However, it uses
epoll edge-triggered readiness notifications that known to be tricky.
Is it possible that lkvm contains some networking bug? Can it be
related to the data races in lkvm I reported earlier today?
I am on commit 3695adeb227813d96d9c41850703fb53a23845eb.
Thank you
[-- Attachment #2: pong.go --]
[-- Type: text/x-go, Size: 462 bytes --]
package main
import (
"log"
"net"
)
func main() {
c, err := net.Dial("tcp", "192.168.33.1:39921")
if err != nil {
log.Fatalf("failed to dial: %v", err)
}
log.Printf("connected")
for {
var buf [1]byte
n, err := c.Write(buf[:])
if err != nil || n != 1 {
log.Fatalf("failed to write: %v", err)
}
log.Printf("write")
n, err = c.Read(buf[:])
if err != nil || n != 1 {
log.Fatalf("failed to read: %v", err)
}
log.Printf("read")
}
}
[-- Attachment #3: ping.go --]
[-- Type: text/x-go, Size: 574 bytes --]
package main
import (
"log"
"net"
)
func main() {
ln, err := net.Listen("tcp", "127.0.0.1:39921")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
log.Printf("listening")
c, err := ln.Accept()
if err != nil {
log.Fatalf("failed to accept: %v", err)
}
log.Printf("connected")
for {
var buf [1]byte
n, err := c.Read(buf[:])
if err != nil || n != 1 {
log.Fatalf("failed to read: %v", err)
}
log.Printf("read")
n, err = c.Write(buf[:])
if err != nil || n != 1 {
log.Fatalf("failed to write: %v", err)
}
log.Printf("write")
}
}
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Network hangs when communicating with host
2015-10-15 20:20 Network hangs when communicating with host Dmitry Vyukov
@ 2015-10-16 17:25 ` Sasha Levin
[not found] ` <CACT4Y+bG3gZv7eBUg5hv=5CEasdGUHwYEe6Bae6OVMK3bZe1Rw@mail.gmail.com>
0 siblings, 1 reply; 8+ messages in thread
From: Sasha Levin @ 2015-10-16 17:25 UTC (permalink / raw)
To: Dmitry Vyukov, levinsasha928, Pekka Enberg, asias.hejun, penberg,
gorcunov, Will Deacon, andre.przywara, matt, michael,
prasadjoshi124, marc.zyngier, Aneesh Kumar K.V, mingo, gorcunov
Cc: kvm, Kostya Serebryany, Evgenii Stepanov, Alexey Samsonov,
Alexander Potapenko, syzkaller
On 10/15/2015 04:20 PM, Dmitry Vyukov wrote:
> Hello,
>
> I am trying to run a program in lkvm sandbox so that it communicates
> with a program on host. I run lkvm as:
>
> ./lkvm sandbox --disk sandbox-test --mem=2048 --cpus=4 --kernel
> /arch/x86/boot/bzImage --network mode=user -- /my_prog
>
> /my_prog then connects to a program on host over a tcp socket.
> I see that host receives some data, sends some data back, but then
> my_prog hangs on network read.
>
> To localize this I wrote 2 programs (attached). ping is run on host
> and pong is run from lkvm sandbox. They successfully establish tcp
> connection, but after some iterations both hang on read.
>
> Networking code in Go runtime is there for more than 3 years, widely
> used in production and does not have any known bugs. However, it uses
> epoll edge-triggered readiness notifications that known to be tricky.
> Is it possible that lkvm contains some networking bug? Can it be
> related to the data races in lkvm I reported earlier today?
>
> I am on commit 3695adeb227813d96d9c41850703fb53a23845eb.
Hey Dmitry,
How long does it take to reproduce? I've been running ping/pong as you've
described and it looks like it doesn't get stuck (read/writes keep going
on both sides).
Can you share your guest kernel config maybe?
Thanks,
Sasha
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Network hangs when communicating with host
[not found] ` <CACT4Y+bG3gZv7eBUg5hv=5CEasdGUHwYEe6Bae6OVMK3bZe1Rw@mail.gmail.com>
@ 2015-10-19 9:22 ` Andre Przywara
2015-10-19 9:28 ` Dmitry Vyukov
0 siblings, 1 reply; 8+ messages in thread
From: Andre Przywara @ 2015-10-19 9:22 UTC (permalink / raw)
To: Dmitry Vyukov, Sasha Levin
Cc: Sasha Levin, Pekka Enberg, Asias He, penberg, Cyrill Gorcunov,
Will Deacon, matt, Michael Ellerman, Prasad Joshi, marc.zyngier,
Aneesh Kumar K.V, mingo, gorcunov, kvm, Kostya Serebryany,
Evgenii Stepanov, Alexey Samsonov, Alexander Potapenko, syzkaller
Hi Dmitry,
On 19/10/15 10:05, Dmitry Vyukov wrote:
> On Fri, Oct 16, 2015 at 7:25 PM, Sasha Levin <sasha.levin@oracle.com> wrote:
>> On 10/15/2015 04:20 PM, Dmitry Vyukov wrote:
>>> Hello,
>>>
>>> I am trying to run a program in lkvm sandbox so that it communicates
>>> with a program on host. I run lkvm as:
>>>
>>> ./lkvm sandbox --disk sandbox-test --mem=2048 --cpus=4 --kernel
>>> /arch/x86/boot/bzImage --network mode=user -- /my_prog
>>>
>>> /my_prog then connects to a program on host over a tcp socket.
>>> I see that host receives some data, sends some data back, but then
>>> my_prog hangs on network read.
>>>
>>> To localize this I wrote 2 programs (attached). ping is run on host
>>> and pong is run from lkvm sandbox. They successfully establish tcp
>>> connection, but after some iterations both hang on read.
>>>
>>> Networking code in Go runtime is there for more than 3 years, widely
>>> used in production and does not have any known bugs. However, it uses
>>> epoll edge-triggered readiness notifications that known to be tricky.
>>> Is it possible that lkvm contains some networking bug? Can it be
>>> related to the data races in lkvm I reported earlier today?
Just to let you know:
I think we have seen networking issues in the past - root over NFS had
issues IIRC. Will spent some time on debugging this and it looked like a
race condition in kvmtool's virtio implementation. I think pinning
kvmtool's virtio threads to one host core made this go away. However
although he tried hard (even by Will's standards!) he couldn't find a
the real root cause or a fix at the time he looked at it and we found
other ways to work around the issues (using virtio-blk or initrd's).
So it's quite possible that there are issues. I haven't had time yet to
look at your sanitizer reports, but it looks like a promising approach
to find the root cause.
Cheers,
Andre.
>>>
>>> I am on commit 3695adeb227813d96d9c41850703fb53a23845eb.
>>
>> Hey Dmitry,
>>
>> How long does it take to reproduce? I've been running ping/pong as you've
>> described and it looks like it doesn't get stuck (read/writes keep going
>> on both sides).
>>
>> Can you share your guest kernel config maybe?
>
>
> Humm.... it my setup it happens within a minute or so.
>
> My kernel is not completely standard, but it works with qemu without
> any problems.
> It is not trivial to reproduce, but FWIW I on commit
> f9fbf6b72ffaaca8612979116c872c9d5d9cc1f5 of
> https://github.com/dvyukov/linux/commits/coverage branch. Config file
> is attached. Then, I build it with custom gcc: revision 228818 +
> https://codereview.appspot.com/267910043 patch. This is all per
> https://github.com/google/syzkaller instructions.
>
> I run lkvm as:
> ./lkvm sandbox --disk sandbox-test --mem=2048 --cpus=4 --kernel
> /arch/x86/boot/bzImage --network mode=user -- /pong
>
> kvmtool is on 3695adeb227813d96d9c41850703fb53a23845eb.
>
> Just tried to do the same with qemu, it does not hang.
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Network hangs when communicating with host
2015-10-19 9:22 ` Andre Przywara
@ 2015-10-19 9:28 ` Dmitry Vyukov
2015-10-19 14:20 ` Sasha Levin
0 siblings, 1 reply; 8+ messages in thread
From: Dmitry Vyukov @ 2015-10-19 9:28 UTC (permalink / raw)
To: syzkaller
Cc: Sasha Levin, Sasha Levin, Pekka Enberg, Asias He, penberg,
Cyrill Gorcunov, Will Deacon, matt, Michael Ellerman,
Prasad Joshi, marc.zyngier, Aneesh Kumar K.V, mingo, gorcunov,
kvm, Kostya Serebryany, Evgenii Stepanov, Alexey Samsonov,
Alexander Potapenko
On Mon, Oct 19, 2015 at 11:22 AM, Andre Przywara <andre.przywara@arm.com> wrote:
> Hi Dmitry,
>
> On 19/10/15 10:05, Dmitry Vyukov wrote:
>> On Fri, Oct 16, 2015 at 7:25 PM, Sasha Levin <sasha.levin@oracle.com> wrote:
>>> On 10/15/2015 04:20 PM, Dmitry Vyukov wrote:
>>>> Hello,
>>>>
>>>> I am trying to run a program in lkvm sandbox so that it communicates
>>>> with a program on host. I run lkvm as:
>>>>
>>>> ./lkvm sandbox --disk sandbox-test --mem=2048 --cpus=4 --kernel
>>>> /arch/x86/boot/bzImage --network mode=user -- /my_prog
>>>>
>>>> /my_prog then connects to a program on host over a tcp socket.
>>>> I see that host receives some data, sends some data back, but then
>>>> my_prog hangs on network read.
>>>>
>>>> To localize this I wrote 2 programs (attached). ping is run on host
>>>> and pong is run from lkvm sandbox. They successfully establish tcp
>>>> connection, but after some iterations both hang on read.
>>>>
>>>> Networking code in Go runtime is there for more than 3 years, widely
>>>> used in production and does not have any known bugs. However, it uses
>>>> epoll edge-triggered readiness notifications that known to be tricky.
>>>> Is it possible that lkvm contains some networking bug? Can it be
>>>> related to the data races in lkvm I reported earlier today?
>
> Just to let you know:
> I think we have seen networking issues in the past - root over NFS had
> issues IIRC. Will spent some time on debugging this and it looked like a
> race condition in kvmtool's virtio implementation. I think pinning
> kvmtool's virtio threads to one host core made this go away. However
> although he tried hard (even by Will's standards!) he couldn't find a
> the real root cause or a fix at the time he looked at it and we found
> other ways to work around the issues (using virtio-blk or initrd's).
>
> So it's quite possible that there are issues. I haven't had time yet to
> look at your sanitizer reports, but it looks like a promising approach
> to find the root cause.
Thanks, Andre!
ping/pong does not hang within at least 5 minutes when I run lkvm
under taskset 1.
And, yeah, this pretty strongly suggests a data race. ThreadSanitizer
can point you to the bug within a minute, so you just need to say
"aha! it is here". Or maybe not. There are no guarantees. But if you
already spent significant time on this, then checking the reports
definitely looks like a good idea.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Network hangs when communicating with host
2015-10-19 9:28 ` Dmitry Vyukov
@ 2015-10-19 14:20 ` Sasha Levin
2015-10-20 13:42 ` Dmitry Vyukov
0 siblings, 1 reply; 8+ messages in thread
From: Sasha Levin @ 2015-10-19 14:20 UTC (permalink / raw)
To: Dmitry Vyukov, syzkaller
Cc: Sasha Levin, Pekka Enberg, Asias He, penberg, Cyrill Gorcunov,
Will Deacon, matt, Michael Ellerman, Prasad Joshi, marc.zyngier,
Aneesh Kumar K.V, mingo, gorcunov, kvm, Kostya Serebryany,
Evgenii Stepanov, Alexey Samsonov, Alexander Potapenko
On 10/19/2015 05:28 AM, Dmitry Vyukov wrote:
> On Mon, Oct 19, 2015 at 11:22 AM, Andre Przywara <andre.przywara@arm.com> wrote:
>> Hi Dmitry,
>>
>> On 19/10/15 10:05, Dmitry Vyukov wrote:
>>> On Fri, Oct 16, 2015 at 7:25 PM, Sasha Levin <sasha.levin@oracle.com> wrote:
>>>> On 10/15/2015 04:20 PM, Dmitry Vyukov wrote:
>>>>> Hello,
>>>>>
>>>>> I am trying to run a program in lkvm sandbox so that it communicates
>>>>> with a program on host. I run lkvm as:
>>>>>
>>>>> ./lkvm sandbox --disk sandbox-test --mem=2048 --cpus=4 --kernel
>>>>> /arch/x86/boot/bzImage --network mode=user -- /my_prog
>>>>>
>>>>> /my_prog then connects to a program on host over a tcp socket.
>>>>> I see that host receives some data, sends some data back, but then
>>>>> my_prog hangs on network read.
>>>>>
>>>>> To localize this I wrote 2 programs (attached). ping is run on host
>>>>> and pong is run from lkvm sandbox. They successfully establish tcp
>>>>> connection, but after some iterations both hang on read.
>>>>>
>>>>> Networking code in Go runtime is there for more than 3 years, widely
>>>>> used in production and does not have any known bugs. However, it uses
>>>>> epoll edge-triggered readiness notifications that known to be tricky.
>>>>> Is it possible that lkvm contains some networking bug? Can it be
>>>>> related to the data races in lkvm I reported earlier today?
>>
>> Just to let you know:
>> I think we have seen networking issues in the past - root over NFS had
>> issues IIRC. Will spent some time on debugging this and it looked like a
>> race condition in kvmtool's virtio implementation. I think pinning
>> kvmtool's virtio threads to one host core made this go away. However
>> although he tried hard (even by Will's standards!) he couldn't find a
>> the real root cause or a fix at the time he looked at it and we found
>> other ways to work around the issues (using virtio-blk or initrd's).
>>
>> So it's quite possible that there are issues. I haven't had time yet to
>> look at your sanitizer reports, but it looks like a promising approach
>> to find the root cause.
>
>
> Thanks, Andre!
>
> ping/pong does not hang within at least 5 minutes when I run lkvm
> under taskset 1.
>
> And, yeah, this pretty strongly suggests a data race. ThreadSanitizer
> can point you to the bug within a minute, so you just need to say
> "aha! it is here". Or maybe not. There are no guarantees. But if you
> already spent significant time on this, then checking the reports
> definitely looks like a good idea.
Okay, that's good to know.
I have a few busy days, but I'll definitely try to clear up these reports
as they seem to be pointing to real issues.
Thanks,
Sasha
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Network hangs when communicating with host
2015-10-19 14:20 ` Sasha Levin
@ 2015-10-20 13:42 ` Dmitry Vyukov
2015-10-20 13:58 ` Sasha Levin
0 siblings, 1 reply; 8+ messages in thread
From: Dmitry Vyukov @ 2015-10-20 13:42 UTC (permalink / raw)
To: Sasha Levin
Cc: syzkaller, Sasha Levin, Pekka Enberg, Asias He, penberg,
Cyrill Gorcunov, Will Deacon, matt, Michael Ellerman,
Prasad Joshi, marc.zyngier, Aneesh Kumar K.V, mingo, gorcunov,
kvm, Kostya Serebryany, Evgenii Stepanov, Alexey Samsonov,
Alexander Potapenko
I now have another issue. My binary fails to mmap a file within lkvm
sandbox. The same binary works fine on host and in qemu. I've added
strace into sandbox script, and here is the output:
[pid 837] openat(AT_FDCWD, "syzkaller-shm048878722", O_RDWR|O_CLOEXEC) = 5
[pid 837] mmap(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_SHARED, 5,
0) = -1 EINVAL (Invalid argument)
I don't see anything that can potentially cause EINVAL here. Is it
possible that lkvm somehow affects kernel behavior here?
I run lkvm as:
$ taskset 1 /kvmtool/lkvm sandbox --disk syz-0 --mem=2048 --cpus=2
--kernel /arch/x86/boot/bzImage --network mode=user --sandbox
/workdir/kvm/syz-0.sh
On Mon, Oct 19, 2015 at 4:20 PM, Sasha Levin <sasha.levin@oracle.com> wrote:
> On 10/19/2015 05:28 AM, Dmitry Vyukov wrote:
>> On Mon, Oct 19, 2015 at 11:22 AM, Andre Przywara <andre.przywara@arm.com> wrote:
>>> Hi Dmitry,
>>>
>>> On 19/10/15 10:05, Dmitry Vyukov wrote:
>>>> On Fri, Oct 16, 2015 at 7:25 PM, Sasha Levin <sasha.levin@oracle.com> wrote:
>>>>> On 10/15/2015 04:20 PM, Dmitry Vyukov wrote:
>>>>>> Hello,
>>>>>>
>>>>>> I am trying to run a program in lkvm sandbox so that it communicates
>>>>>> with a program on host. I run lkvm as:
>>>>>>
>>>>>> ./lkvm sandbox --disk sandbox-test --mem=2048 --cpus=4 --kernel
>>>>>> /arch/x86/boot/bzImage --network mode=user -- /my_prog
>>>>>>
>>>>>> /my_prog then connects to a program on host over a tcp socket.
>>>>>> I see that host receives some data, sends some data back, but then
>>>>>> my_prog hangs on network read.
>>>>>>
>>>>>> To localize this I wrote 2 programs (attached). ping is run on host
>>>>>> and pong is run from lkvm sandbox. They successfully establish tcp
>>>>>> connection, but after some iterations both hang on read.
>>>>>>
>>>>>> Networking code in Go runtime is there for more than 3 years, widely
>>>>>> used in production and does not have any known bugs. However, it uses
>>>>>> epoll edge-triggered readiness notifications that known to be tricky.
>>>>>> Is it possible that lkvm contains some networking bug? Can it be
>>>>>> related to the data races in lkvm I reported earlier today?
>>>
>>> Just to let you know:
>>> I think we have seen networking issues in the past - root over NFS had
>>> issues IIRC. Will spent some time on debugging this and it looked like a
>>> race condition in kvmtool's virtio implementation. I think pinning
>>> kvmtool's virtio threads to one host core made this go away. However
>>> although he tried hard (even by Will's standards!) he couldn't find a
>>> the real root cause or a fix at the time he looked at it and we found
>>> other ways to work around the issues (using virtio-blk or initrd's).
>>>
>>> So it's quite possible that there are issues. I haven't had time yet to
>>> look at your sanitizer reports, but it looks like a promising approach
>>> to find the root cause.
>>
>>
>> Thanks, Andre!
>>
>> ping/pong does not hang within at least 5 minutes when I run lkvm
>> under taskset 1.
>>
>> And, yeah, this pretty strongly suggests a data race. ThreadSanitizer
>> can point you to the bug within a minute, so you just need to say
>> "aha! it is here". Or maybe not. There are no guarantees. But if you
>> already spent significant time on this, then checking the reports
>> definitely looks like a good idea.
>
> Okay, that's good to know.
>
> I have a few busy days, but I'll definitely try to clear up these reports
> as they seem to be pointing to real issues.
>
>
> Thanks,
> Sasha
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Network hangs when communicating with host
2015-10-20 13:42 ` Dmitry Vyukov
@ 2015-10-20 13:58 ` Sasha Levin
2015-10-27 9:31 ` Will Deacon
0 siblings, 1 reply; 8+ messages in thread
From: Sasha Levin @ 2015-10-20 13:58 UTC (permalink / raw)
To: Dmitry Vyukov
Cc: syzkaller, Sasha Levin, Pekka Enberg, Asias He, penberg,
Cyrill Gorcunov, Will Deacon, matt, Michael Ellerman,
Prasad Joshi, marc.zyngier, Aneesh Kumar K.V, mingo, gorcunov,
kvm, Kostya Serebryany, Evgenii Stepanov, Alexey Samsonov,
Alexander Potapenko
On 10/20/2015 09:42 AM, Dmitry Vyukov wrote:
> I now have another issue. My binary fails to mmap a file within lkvm
> sandbox. The same binary works fine on host and in qemu. I've added
> strace into sandbox script, and here is the output:
>
> [pid 837] openat(AT_FDCWD, "syzkaller-shm048878722", O_RDWR|O_CLOEXEC) = 5
> [pid 837] mmap(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_SHARED, 5,
> 0) = -1 EINVAL (Invalid argument)
>
> I don't see anything that can potentially cause EINVAL here. Is it
> possible that lkvm somehow affects kernel behavior here?
>
> I run lkvm as:
>
> $ taskset 1 /kvmtool/lkvm sandbox --disk syz-0 --mem=2048 --cpus=2
> --kernel /arch/x86/boot/bzImage --network mode=user --sandbox
> /workdir/kvm/syz-0.sh
It's possible that something in the virtio-9p layer is broken. I'll give
it a look in the evening.
Thanks,
Sasha
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Network hangs when communicating with host
2015-10-20 13:58 ` Sasha Levin
@ 2015-10-27 9:31 ` Will Deacon
0 siblings, 0 replies; 8+ messages in thread
From: Will Deacon @ 2015-10-27 9:31 UTC (permalink / raw)
To: Sasha Levin
Cc: Dmitry Vyukov, syzkaller, Sasha Levin, Pekka Enberg, Asias He,
penberg, Cyrill Gorcunov, matt, Michael Ellerman, Prasad Joshi,
marc.zyngier, Aneesh Kumar K.V, mingo, gorcunov, kvm,
Kostya Serebryany, Evgenii Stepanov, Alexey Samsonov,
Alexander Potapenko
[apologies for the delay -- I've been off for a week and am catching up
on email]
On Tue, Oct 20, 2015 at 09:58:51AM -0400, Sasha Levin wrote:
> On 10/20/2015 09:42 AM, Dmitry Vyukov wrote:
> > I now have another issue. My binary fails to mmap a file within lkvm
> > sandbox. The same binary works fine on host and in qemu. I've added
> > strace into sandbox script, and here is the output:
> >
> > [pid 837] openat(AT_FDCWD, "syzkaller-shm048878722", O_RDWR|O_CLOEXEC) = 5
> > [pid 837] mmap(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_SHARED, 5,
> > 0) = -1 EINVAL (Invalid argument)
> >
> > I don't see anything that can potentially cause EINVAL here. Is it
> > possible that lkvm somehow affects kernel behavior here?
> >
> > I run lkvm as:
> >
> > $ taskset 1 /kvmtool/lkvm sandbox --disk syz-0 --mem=2048 --cpus=2
> > --kernel /arch/x86/boot/bzImage --network mode=user --sandbox
> > /workdir/kvm/syz-0.sh
>
> It's possible that something in the virtio-9p layer is broken. I'll give
> it a look in the evening.
I ended up with the patch below, but it's really ugly and I didn't get
round to posting it.
Will
--->8
>From 7cbcdfef1b9f094db4bf75676f22339f3164e103 Mon Sep 17 00:00:00 2001
From: Will Deacon <will.deacon@arm.com>
Date: Fri, 17 Apr 2015 17:31:36 +0100
Subject: [PATCH] kvmtool: virtio-net: fix VIRTIO_NET_F_MRG_RXBUF usage in rx
thread
When merging virtio-net buffers using the VIRTIO_NET_F_MRG_RXBUF feature,
the first buffer added to the used ring should indicate the total number
of buffers used to hold the packet. Unfortunately, kvmtool has a number
of issues when constructing these merged buffers:
- Commit 5131332e3f1a ("kvmtool: convert net backend to support
bi-endianness") introduced a strange loop counter, which resulted in
hdr->num_buffers being set redundantly the first time round
- When adding the buffers to the ring, we actually add them one-by-one,
allowing the guest to see the header before we've inserted the rest
of the data buffers...
- ... which is made worse because we non-atomically increment the
num_buffers count in the header each time we insert a new data buffer
Consequently, the guest quickly becomes confused in its net rx code and
the whole thing grinds to a halt. This is easily exemplified by trying
to boot a root filesystem over NFS, which seldom succeeds.
This patch resolves the issues by allowing us to insert items into the
used ring without updating the index. Once the full payload has been
added and num_buffers corresponds to the total size, we *then* publish
the buffers to the guest.
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Sasha Levin <sasha.levin@oracle.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
include/kvm/virtio.h | 2 ++
virtio/core.c | 32 +++++++++++++++++++++++++-------
virtio/net.c | 31 +++++++++++++++----------------
3 files changed, 42 insertions(+), 23 deletions(-)
diff --git a/include/kvm/virtio.h b/include/kvm/virtio.h
index 768ee9668d44..8324ba7d38be 100644
--- a/include/kvm/virtio.h
+++ b/include/kvm/virtio.h
@@ -112,6 +112,8 @@ static inline bool virt_queue__available(struct virt_queue *vq)
return virtio_guest_to_host_u16(vq, vq->vring.avail->idx) != vq->last_avail_idx;
}
+void virt_queue__used_idx_advance(struct virt_queue *queue, u16 jump);
+struct vring_used_elem * virt_queue__set_used_elem_no_update(struct virt_queue *queue, u32 head, u32 len, u16 offset);
struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, u32 head, u32 len);
bool virtio_queue__should_signal(struct virt_queue *vq);
diff --git a/virtio/core.c b/virtio/core.c
index 3b6e4d7cd045..d6ac289d450e 100644
--- a/virtio/core.c
+++ b/virtio/core.c
@@ -21,22 +21,17 @@ const char* virtio_trans_name(enum virtio_trans trans)
return "unknown";
}
-struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, u32 head, u32 len)
+void virt_queue__used_idx_advance(struct virt_queue *queue, u16 jump)
{
- struct vring_used_elem *used_elem;
u16 idx = virtio_guest_to_host_u16(queue, queue->vring.used->idx);
- used_elem = &queue->vring.used->ring[idx % queue->vring.num];
- used_elem->id = virtio_host_to_guest_u32(queue, head);
- used_elem->len = virtio_host_to_guest_u32(queue, len);
-
/*
* Use wmb to assure that used elem was updated with head and len.
* We need a wmb here since we can't advance idx unless we're ready
* to pass the used element to the guest.
*/
wmb();
- idx++;
+ idx += jump;
queue->vring.used->idx = virtio_host_to_guest_u16(queue, idx);
/*
@@ -45,6 +40,29 @@ struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, u32
* an updated idx.
*/
wmb();
+}
+
+struct vring_used_elem *
+virt_queue__set_used_elem_no_update(struct virt_queue *queue, u32 head,
+ u32 len, u16 offset)
+{
+ struct vring_used_elem *used_elem;
+ u16 idx = virtio_guest_to_host_u16(queue, queue->vring.used->idx);
+
+ idx += offset;
+ used_elem = &queue->vring.used->ring[idx % queue->vring.num];
+ used_elem->id = virtio_host_to_guest_u32(queue, head);
+ used_elem->len = virtio_host_to_guest_u32(queue, len);
+
+ return used_elem;
+}
+
+struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, u32 head, u32 len)
+{
+ struct vring_used_elem *used_elem;
+
+ used_elem = virt_queue__set_used_elem_no_update(queue, head, len, 0);
+ virt_queue__used_idx_advance(queue, 1);
return used_elem;
}
diff --git a/virtio/net.c b/virtio/net.c
index 9784520336b1..afee75333edb 100644
--- a/virtio/net.c
+++ b/virtio/net.c
@@ -80,14 +80,12 @@ static void virtio_net_fix_tx_hdr(struct virtio_net_hdr *hdr, struct net_dev *nd
hdr->csum_offset = virtio_guest_to_host_u16(&ndev->vdev, hdr->csum_offset);
}
-static void virtio_net_fix_rx_hdr(struct virtio_net_hdr_mrg_rxbuf *hdr, struct net_dev *ndev)
+static void virtio_net_fix_rx_hdr(struct virtio_net_hdr *hdr, struct net_dev *ndev)
{
- hdr->hdr.hdr_len = virtio_host_to_guest_u16(&ndev->vdev, hdr->hdr.hdr_len);
- hdr->hdr.gso_size = virtio_host_to_guest_u16(&ndev->vdev, hdr->hdr.gso_size);
- hdr->hdr.csum_start = virtio_host_to_guest_u16(&ndev->vdev, hdr->hdr.csum_start);
- hdr->hdr.csum_offset = virtio_host_to_guest_u16(&ndev->vdev, hdr->hdr.csum_offset);
- if (has_virtio_feature(ndev, VIRTIO_NET_F_MRG_RXBUF))
- hdr->num_buffers = virtio_host_to_guest_u16(&ndev->vdev, hdr->num_buffers);
+ hdr->hdr_len = virtio_host_to_guest_u16(&ndev->vdev, hdr->hdr_len);
+ hdr->gso_size = virtio_host_to_guest_u16(&ndev->vdev, hdr->gso_size);
+ hdr->csum_start = virtio_host_to_guest_u16(&ndev->vdev, hdr->csum_start);
+ hdr->csum_offset = virtio_host_to_guest_u16(&ndev->vdev, hdr->csum_offset);
}
static void *virtio_net_rx_thread(void *p)
@@ -123,7 +121,7 @@ static void *virtio_net_rx_thread(void *p)
.iov_len = sizeof(buffer),
};
struct virtio_net_hdr_mrg_rxbuf *hdr;
- int i;
+ u16 num_buffers;
len = ndev->ops->rx(&dummy_iov, 1, ndev);
if (len < 0) {
@@ -132,7 +130,7 @@ static void *virtio_net_rx_thread(void *p)
goto out_err;
}
- copied = i = 0;
+ copied = num_buffers = 0;
head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
hdr = iov[0].iov_base;
while (copied < len) {
@@ -140,19 +138,20 @@ static void *virtio_net_rx_thread(void *p)
memcpy_toiovec(iov, buffer + copied, iovsize);
copied += iovsize;
- if (i++ == 0)
- virtio_net_fix_rx_hdr(hdr, ndev);
- if (has_virtio_feature(ndev, VIRTIO_NET_F_MRG_RXBUF)) {
- u16 num_buffers = virtio_guest_to_host_u16(vq, hdr->num_buffers);
- hdr->num_buffers = virtio_host_to_guest_u16(vq, num_buffers + 1);
- }
- virt_queue__set_used_elem(vq, head, iovsize);
+ virt_queue__set_used_elem_no_update(vq, head, iovsize, num_buffers++);
if (copied == len)
break;
while (!virt_queue__available(vq))
sleep(0);
head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
}
+
+ virtio_net_fix_rx_hdr(&hdr->hdr, ndev);
+ if (has_virtio_feature(ndev, VIRTIO_NET_F_MRG_RXBUF))
+ hdr->num_buffers = virtio_host_to_guest_u16(vq, num_buffers);
+
+ virt_queue__used_idx_advance(vq, num_buffers);
+
/* We should interrupt guest right now, otherwise latency is huge. */
if (virtio_queue__should_signal(vq))
ndev->vdev.ops->signal_vq(kvm, &ndev->vdev, id);
--
2.1.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-10-27 9:31 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-15 20:20 Network hangs when communicating with host Dmitry Vyukov
2015-10-16 17:25 ` Sasha Levin
[not found] ` <CACT4Y+bG3gZv7eBUg5hv=5CEasdGUHwYEe6Bae6OVMK3bZe1Rw@mail.gmail.com>
2015-10-19 9:22 ` Andre Przywara
2015-10-19 9:28 ` Dmitry Vyukov
2015-10-19 14:20 ` Sasha Levin
2015-10-20 13:42 ` Dmitry Vyukov
2015-10-20 13:58 ` Sasha Levin
2015-10-27 9:31 ` Will Deacon
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).