Skip to content
  • Stefan Hajnoczi's avatar
    68e5ec64
    tap: avoid deadlocking rx · 68e5ec64
    Stefan Hajnoczi authored
    
    
    The net subsystem has a control flow mechanism so peer NetClientStates
    can tell each other to stop sending packets.  This is used to stop
    monitoring the tap file descriptor for incoming packets if the guest rx
    ring has no spare buffers.
    
    There is a corner case when tap_can_send() is true at the beginning of
    an event loop iteration but becomes false before the tap_send() fd
    handler is invoked.
    
    tap_send() will read the packet from the tap file descriptor and attempt
    to send it.  The net queue will hold on to the packet and return 0,
    indicating that further I/O is not possible.  tap then stops monitoring
    the file descriptor for reads.
    
    This is unlike the normal case where tap_can_send() is the same before
    and during the event loop iteration.  The event loop would simply not
    monitor the file descriptor if tap_can_send() returns true.  Upon next
    iteration it would check tap_can_send() again and begin monitoring if we
    can send.
    
    The deadlock happens because tap_send() explicitly disabled read_poll.
    This is done with the expectation that the peer will call
    qemu_net_queue_flush().  But hw/net/virtio-net.c does not monitor
    vm_running transitions and issue the flush.  Hence we're left with a
    broken tap device.
    
    Cc: qemu-stable@nongnu.org
    Reported-by: default avatarNeil Skrypuch <neil@tembosocial.com>
    Tested-by: default avatarNeil Skrypuch <neil@tembosocial.com>
    Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
    68e5ec64
    tap: avoid deadlocking rx
    Stefan Hajnoczi authored
    
    
    The net subsystem has a control flow mechanism so peer NetClientStates
    can tell each other to stop sending packets.  This is used to stop
    monitoring the tap file descriptor for incoming packets if the guest rx
    ring has no spare buffers.
    
    There is a corner case when tap_can_send() is true at the beginning of
    an event loop iteration but becomes false before the tap_send() fd
    handler is invoked.
    
    tap_send() will read the packet from the tap file descriptor and attempt
    to send it.  The net queue will hold on to the packet and return 0,
    indicating that further I/O is not possible.  tap then stops monitoring
    the file descriptor for reads.
    
    This is unlike the normal case where tap_can_send() is the same before
    and during the event loop iteration.  The event loop would simply not
    monitor the file descriptor if tap_can_send() returns true.  Upon next
    iteration it would check tap_can_send() again and begin monitoring if we
    can send.
    
    The deadlock happens because tap_send() explicitly disabled read_poll.
    This is done with the expectation that the peer will call
    qemu_net_queue_flush().  But hw/net/virtio-net.c does not monitor
    vm_running transitions and issue the flush.  Hence we're left with a
    broken tap device.
    
    Cc: qemu-stable@nongnu.org
    Reported-by: default avatarNeil Skrypuch <neil@tembosocial.com>
    Tested-by: default avatarNeil Skrypuch <neil@tembosocial.com>
    Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Loading