If pasta created the namespace, it's probably expected that processes
started in the same namespace are terminated once pasta exits. Scan
procfs namespace links for corresponding processes, send SIGQUIT and
SIGKILL (after one second) if found.
While at it, make the signal handler reap otherwise-zombies resulting
from clone().
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
If we couldn't write the whole batch of received packets to the socket,
and we have missing segments, we still need to request their
retransmission right away, otherwise it will take ages for the guest to
figure out we're missing them.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
...instead of waiting for the remote peer to do that -- it's
especially important in case we request retransmissions from the
guest, but it also helps speeding up slow start. This should
probably be a configurable behaviour in the future.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Seen with iperf3: a control connection is established, no data flows
for a while, all segments are acknowledged. The socket starts closing
it, and we immediately time out because the last ACK from tap was one
minute before that.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Seen with iperf3: the first packet from socket (data connection) is
65520 bytes and doesn't fit in the window.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Flooding a virtio-net interface connected to a socket back-end results
in a TX stall I'm still debugging. The stall goes away by setting a
higher value for x-txburst (256 by default).
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This fixes a number of issues found with some heavier testing with
uperf and neper:
- in most closing states, we can still accept data, check for EPOLLIN
when appropriate
- introduce a new state, ESTABLISHED_SOCK_FIN_SENT, to track the fact
we already sent a FIN segment to the tap device, for proper sequence
number bookkeeping
- for pasta mode only: spliced connections also need tracking of
(inferred) FIN segments and clean half-pipe shutdowns
- streamline resetting epoll_wait bitmaps with a new function,
tcp_tap_epoll_mask(), instead of repeating the logic all over the
place
- set EPOLLET for tap connections too, whenever we are waiting for
EPOLLRDHUP or an event from the tap to proceed with data transfer,
to avoid useless loops with EPOLLIN set
- impose an additional limit on the sending window advertised to the
guest, given by SO_SNDBUF: it makes no sense to completely fill
the sending buffer and send a zero window: stop a bit before we
hit that
- handle *all* interrupted system calls as needed
- simplify the logic for reordering of out-of-order segments received
from tap: it's not a corner case, and the previous logic allowed
for deadloops
- fix comparison of seen IPv4 address when we get a new connection
from a socket directed to the configured guest address
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
...this allows processes running as the only group available in the
namespace to create ICMP Echo sockets.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Before introducing options, the default behaviour in passt mode was
to forward all ports, to run in foreground and to log to stderr.
Make it a bit more convenient to restore that at build time.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This went lost in a recent rework: if the guest wants to connect
directly to the host, it can use the address of the default gateway.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Similarly to the handling introduced by commit "tcp: Proper error
handling for sendmmsg() to UNIX domain socket" for TCP, we need to
deal with partial sendmmsg() failures for UDP as well.
Here, we can lose messages, but we need to make sure that the last
message is delivered completely, otherwise qemu will fail to
reassemble further packets. For UDP, this is somewhat complicated
by the fact that one message might include multiple datagrams, and
we need to respect message boundaries: go through headers, and
calculate what we need to re-send, if anything.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This enables CirrOS with udhcpc to set up a route to a gateway
that's not on the assigned subnet, together with:
https://bugs.launchpad.net/cirros/+bug/1190372
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
DHCP clients might try to resolve the assigned address to check if it's
already in use: don't resolve the configured IPv4 address.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Depending on the configuration, the host might have the same address.
Don't answer them to avoid a duplicate IP address detection.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
And while at it, remove some attributes that are not needed anymore
after introducing command line options.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Once we're past the IA_NA or IA_TA option itself, before we start
looking for IA_ADDR suboptions, we need to subtract the length
of the option we parsed so far, otherwise we might end up reading
past the end of the message, or miss some parts.
While at it, streamline calculations in dhcpv6_opt().
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
As data from socket is forwarded to the guest, sendmmsg() might send
fewer bytes than requested in three different ways:
- failing altogether with a negative error code -- ignore that,
we'll get an error on the UNIX domain socket later if there's
really an issue with it and reset the connection to the guest
- sending less than 'vlen' messages -- instead of assuming success
in that case and waiting for the guest to send a duplicate ACK
indicating missing data, update the sequence number according to
what was actually sent and spare some retransmissions
- somewhat unexpectedly to me, sending 'vlen' or less than 'vlen'
messages, returning up to 'vlen', with the last message being
partially sent, and no further indication of errors other than
the returned msg_len for the last partially sent message being
less than iov_len.
In this case, we would assume success and proceed as nothing
happened. However, qemu would fail to parse any further message,
having received a partial descriptor, and eventually close the
connection, logging:
serious error: oversized packet received,connection terminated.
as the length descriptor for the next message would be sourced
from the middle of the next successfully sent message, not from
its header.
Handle this by checking the msg_len returned for the last (even
partially) sent message, and force re-sending the missing bytes,
if any, with a blocking sendmsg() -- qemu must not receive
anything else than that anyway.
While at it, allow to send up to 64KiB for each message, the
previous 32KiB limit isn't actually required, and just switch to a
new message at each iteration on sending buffers, they are already
MSS-sized anyway, so the check in the loop isn't really needed.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
With a kernel older than 5.3 (no_snd_wnd set), ack_pending in
tcp_send_to_tap() might be true at the beginning of a new connection
initiated by a socket. This means we send the first SYN segment to the
tap together with ACK set, which is clearly invalid and triggers the
receiver to reply with an RST segment right away.
Set ack_pending to 0 whenever we're sending a SYN segment. In case of a
SYN, ACK segment sent by the caller, the caller passes the ACK flag
explicitly.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Socket-facing functions don't guarantee that all data is handled before
they return: stick to level-triggered mode for TCP sockets.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
...and while at it, fix an issue in the calculation of the last IOV
buffer size: if we can't receive enough data to fill up the window,
the last buffer can be filled completely.
Also streamline the code setting iovec lengths if cached values are
not matching.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
We won't necessarily have another choice to ACK in a timely fashion
if we skip ACKs from a number of states (including ESTABLISHED) when
there's enough window left. Check for ACKed bytes as soon as it makes
sense.
If the sending window is not reported by the kernel, ACK as soon as
we queue onto the socket, given that we're forced to use a rather
small window.
In FIN_WAIT_1_SOCK_FIN, we also have to account for the FIN flag sent
by the peer in the sequence.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Sending 64 frames in a batch looks quite bad when a duplicate ACK
comes right at the beginning of it. Lowering this to 32 doesn't
affect performance noticeably, with 16 the impact is more apparent.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Similar to UDP, but using a simple sendmsg() on iovec-style buffers
from tap instead, as we don't need to preserve message boundaries.
A quick test in PASTA mode, from namespace to init via tap:
# ip link set dev pasta0 mtu 16384
# iperf3 -c 192.168.1.222 -t 60
[...]
[ ID] Interval Transfer Bitrate
[ 5] 0.00-60.00 sec 80.4 GBytes 11.5 Gbits/sec receiver
# iperf3 -c 2a02:6d40:3cfc:3a01:2b20:4a6a:c25a:3056 -t 60
[...]
[ ID] Interval Transfer Bitrate
[ 5] 0.00-60.01 sec 39.9 GBytes 5.71 Gbits/sec receiver
# ip link set dev pasta0 mtu 65520
# iperf3 -c 192.168.1.222 -t 60
[...]
[ ID] Interval Transfer Bitrate
[ 5] 0.00-60.01 sec 88.7 GBytes 12.7 Gbits/sec receiver
# iperf3 -c 2a02:6d40:3cfc:3a01:2b20:4a6a:c25a:3056 -t 60
[...]
[ ID] Interval Transfer Bitrate
[ 5] 0.00-60.00 sec 79.5 GBytes 11.4 Gbits/sec receiver
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
There's no need to constantly query the socket for number of
acknowledged bytes if we're far from exhausting the sending window,
just do it if we're at least down to 90% of it.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>