Closed mwiget closed 8 years ago
I took a closer look at the bogus idx value of 407011329. Its the same every time I ran into the issue.
407011329 = 0x18428001 and usually I saw set_vring_num() being called with idx set to 0 or 1. Could this be an issue where an int16 being passed into an int64? As a quick-and-dirty test, I made the following code change and voila, this actually helped:
diff --git a/src/lib/virtio/net_device.lua b/src/lib/virtio/net_device.lua
index 58b040b..a476c9d 100644
--- a/src/lib/virtio/net_device.lua
+++ b/src/lib/virtio/net_device.lua
@@ -401,6 +401,10 @@ function VirtioNetDevice:set_vring_num(idx, num)
error("vring_num should be power of 2")
end
+ print(string.format("TODO virtq idx=%d n=%d", idx, n))
+ if idx > 256 then
+ idx = idx % 256
+ end
self.virtq[idx].vring_num = n
-- update the curent virtq pairs
self.virtq_pairs = math.max(self.virtq_pairs, math.floor(idx/2)+1)
Snabb doesn't crash anymore, all while passing traffic (though low speed, just ping floods) ...
got a new crash after about an hour or so, this time in a different place.
lib/virtio/net_device.lua:357: mapping to host address failedcdata<void *>: 0xffff8801677f7320
stack traceback:
core/main.lua:118: in function <core/main.lua:116>
[C]: in function 'error'
lib/virtio/net_device.lua:357: in function 'map_from_guest'
lib/virtio/net_device.lua:129: in function 'packet_start'
lib/virtio/virtq.lua:67: in function 'get_buffers'
lib/virtio/net_device.lua:122: in function 'receive_packets_from_vm'
lib/virtio/net_device.lua:108: in function 'poll_vring_receive'
apps/vhost/vhost_user.lua:76: in function 'method'
core/app.lua:76: in function 'with_restart'
core/app.lua:281: in function 'breathe'
core/app.lua:234: in function 'main'
program/snabbnfv/traffic/traffic.lua:85: in function 'traffic'
program/snabbnfv/traffic/traffic.lua:61: in function 'run'
program/snabbnfv/snabbnfv.lua:15: in function 'run'
core/main.lua:56: in function <core/main.lua:32>
[C]: in function 'xpcall'
core/main.lua:125: in main chunk
[C]: at 0x0044d9e0
[C]: in function 'pcall'
core/startup.lua:1: in main chunk
[C]: in function 'require'
[string "require "core.startup""]:1: in main chunk
Howdy! Getting up to speed here... btw, the vhost-user protocol spec could be handy as a reference.
Just responding based on referring to the information in the issue and related specs for now:
It does indeed sound plausible that an integer datatype is being mismatched. I wonder why. The vhost-user protocol says that the argument is expected to be vring_state
i.e. 32-bit ring index and 32-bit number. On the Snabb side I see a couple of mildly suspicious things: our struct vhostu_vring_state
is not declared with __attribute__((packed))
and we are using types like unsigned int
instead of uint32_t
where the vhost-user spec specifically calls for a 32-bit number. I am not sure if this is a problem but it does seem conceivable that the compiler would give us a different memory layout than we expect and so I am testing a small fix to tighten up these types.
(If I recall correctly the Linux kernel vhost
ABI does not nail down the exact memory layout as vhost-user does and rather depends on C compiler behavior for the target platform. It is easy to imagine how issues like this could lead to subtle bugs when some QEMU internal functions are common between vhost and vhost-user.)
It could be interesting to run with strace -e sendmsg,recvmsg
to see the payload of the vhost-user protocol messages i.e. is an invalid value arriving over the wire (bug elsewhere that we need to report and workaround) or is the wire value correct and only our interpretation wrong (bug we need to fix).
This seems to be the Snabb vhost-user app complaining that it received a vhost-user protocol message with id 0. The spec has no message with this id. I think that the same strace
command would let us see what is happening here too.
The error seems to be saying that we failed to translate the address of a packet buffer from guest address space into our own address space. I am not sure why this would happen but here are a few quick ideas:
iperf
to trigger. Snabb Switch could potentially trigger race condition bugs in guest drivers since we are polling their vring at a high frequency instead of waiting for them to signal an interrupt.ff
values, but unless I am mistaken we are expecting a guest physical address here. (I may well be mistaken on that score.)Could be interesting to get an strace
for fixing the first two and then move on to the third?
thanks Luke ! I ran the original code of snabb (without my quick-and-dirty modulo patch) under strace for over 30 minutes, no crash. I run the same snabb binary without strace and get a crash in less than a minute ;-). I'll let it run under strace, hoping to trigger the issue at some point. But strace clearly influences the result somehow...
Well, after an hour or so, I got a traceback, but for "vhost_user: unrecognized request: 0":
recvmsg(8, 0x7ffcd7f26760, MSG_DONTWAIT|MSG_WAITALL) = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(9, 0x7ffcd7f26760, MSG_DONTWAIT|MSG_WAITALL) = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(10, 0x7ffcd7f26760, MSG_DONTWAIT|MSG_WAITALL) = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(11, 0x7ffcd7f26760, MSG_DONTWAIT|MSG_WAITALL) = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(12, 0x7ffcd7f26760, MSG_DONTWAIT|MSG_WAITALL) = -1 EAGAIN (Resource temporarily unavailable)
load: time: 1.00s fps: 3,484 fpGbps: 0.021 fpb: 0 bpp: 749 sleep: 100 us
recvmsg(7, 0x7ffcd7f26850, MSG_DONTWAIT|MSG_WAITALL) = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(8, {msg_name(0)=NULL, msg_iov(1)=[{"\r\0\0\0\1\0\0\0\10\0\0\0", 12}], msg_controllen=24, {cmsg_len=20, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, {1021}}, msg_flags=0}, MSG_DONTWAIT|MSG_WAITALL) = 12
recvmsg(8, {msg_name(0)=NULL, msg_iov(1)=[{"\r\0\0\0\1\0\0\0\10\0\0\0", 12}], msg_controllen=24, {cmsg_len=20, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, {1022}}, msg_flags=0}, MSG_DONTWAIT|MSG_WAITALL) = 12
recvmsg(8, {msg_name(0)=NULL, msg_iov(1)=[{"\r\0\0\0\1\0\0\0\10\0\0\0", 12}], msg_controllen=24, {cmsg_len=20, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, {1023}}, msg_flags=0}, MSG_DONTWAIT|MSG_WAITALL) = 12
recvmsg(8, {msg_name(0)=NULL, msg_iov(1)=[{"\r\0\0\0\1\0\0\0\10\0\0\0", 12}], msg_controllen=0, msg_flags=MSG_CTRUNC}, MSG_DONTWAIT|MSG_WAITALL) = 12
recvmsg(9, 0x7ffcd7f26850, MSG_DONTWAIT|MSG_WAITALL) = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(10, 0x7ffcd7f26850, MSG_DONTWAIT|MSG_WAITALL) = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(11, 0x7ffcd7f26850, MSG_DONTWAIT|MSG_WAITALL) = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(12, 0x7ffcd7f26850, MSG_DONTWAIT|MSG_WAITALL) = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(7, 0x7ffcd7f26760, MSG_DONTWAIT|MSG_WAITALL) = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(8, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0\0\0\0\0", 12}], msg_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_WAITALL) = 8
apps/vhost/vhost_user.lua:161: vhost_user: unrecognized request: 0
stack traceback:
core/main.lua:118: in function <core/main.lua:116>
[C]: in function 'error'
apps/vhost/vhost_user.lua:161: in function 'method'
apps/vhost/vhost_user.lua:142: in function 'process_qemu_requests'
apps/vhost/vhost_user.lua:39: in function 'fn'
core/timer.lua:33: in function 'call_timers'
core/timer.lua:42: in function 'run_to_time'
core/timer.lua:23: in function 'run'
core/app.lua:235: in function 'main'
program/snabbnfv/traffic/traffic.lua:85: in function 'traffic'
program/snabbnfv/traffic/traffic.lua:61: in function 'run'
program/snabbnfv/snabbnfv.lua:15: in function 'run'
core/main.lua:56: in function <core/main.lua:32>
[C]: in function 'xpcall'
core/main.lua:125: in main chunk
[C]: at 0x0044d9e0
[C]: in function 'pcall'
core/startup.lua:1: in main chunk
[C]: in function 'require'
[string "require "core.startup""]:1: in main chunk
Isn't the message passed to snabb too short?
msg_iov(1)=[{"\0\0\0\0\0\0\0\0", 12}]
I only see 8 bytes, whereas in other recvmsg calls i always get 12... Is that an issue within the guest VM?
Interesting. I suspect QEMU is the place to track this down, either reading the source or catching that message send in gdb.
Could also try a newer QEMU and see if it's reproducible.
While trying to run Juniper's virtual router vMX on top of snabb snabbnfv traffic. The lab setup is described in detail in my blog post at https://marcelwiget.wordpress.com/2015/07/12/juniper-networks-vmx-on-snabb-nfv/.
I added a print statement to show the value of idx, and it shows an illegal value 407011329.
So somehow things get corrupt after successfully passing some traffic for a minute or so.
The other error message I get is