aboutgitcodebugslistschat
path: root/tcp.c
Commit message (Collapse)AuthorAgeFilesLines
* ndp, dhcpv6, tcp, udp: Always use link-local as source if gateway isn'tStefano Brivio2021-10-201-2/+10
| | | | | | | | | | | | This shouldn't happen on any sane configuration, but I just met an example of that: the default IPv6 gateway on the host is configured with a global unicast address, we use that as source for RA, DHCPv6 replies, and the guest ignores it. Same later on if we talk TCP or UDP and the guest has no idea where that address comes from. Use our link-local address in case the gateway address is global. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Add clang-tidy Makefile target and test, take care of warningsStefano Brivio2021-10-201-30/+32
| | | | | | | Most are just about style and form, but a few were actually serious mistakes (NDP-related). Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Address warnings from Clang's scan-buildStefano Brivio2021-10-201-16/+21
| | | | | | All false positives so far. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Address gcc 11 warningsStefano Brivio2021-10-201-11/+25
| | | | | | | | | A mix of unchecked return values, a missing permission mask for open(2) with O_CREAT, and some false positives from -Wstringop-overflow and -Wmaybe-uninitialized. Reported-by: Martin Hauke <mardnh@gmx.de> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Fix for non-blocking splice() on older kernelsStefano Brivio2021-10-191-2/+2
| | | | | | | | For some reason, on 4.19, splice() doesn't honour SOCK_NONBLOCK from accept4() while reading from a TCP socket. Pass SPLICE_F_NONBLOCK explicitly in all cases. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Fix ACK reporting on older kernels (no tcp.kernel_snd_wnd case)Stefano Brivio2021-10-191-3/+4
| | | | | | | | If the window isn't updated on !c->tcp.kernel_snd_wnd, we still have to send ACKs if the ACK sequence was updated, or if an error occurred while querying TCP_INFO. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Arm tcp_data_noack on insufficient window too, don't reset if ACK ↵Stefano Brivio2021-10-161-2/+4
| | | | | | | | | | doesn't match ...and while at it, reverse the operands in the window equality comparison to detect the need for fast re-transmit: it's easier to read this way. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: ...and so I got a socket called zeroStefano Brivio2021-10-151-35/+44
| | | | | | | | I thought I'd get away with it, but no, after some clean-ups, I finally got a socket with number 0. Fix up all the convenient, yet botched assumptions. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Bump TCP_TAP_FRAMES back to 256Stefano Brivio2021-10-151-1/+1
| | | | | | With a batched sendmsg(), this is now beneficial. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Get rid of iov with cached MSS, drop sendmmsg(), add deferred flushStefano Brivio2021-10-151-139/+130
| | | | | | | | | | | | | | | Caching iov_len for messages from socket doesn't actually decrease overhead by the tiniest bit, and added a lot of complexity. Drop that. Also drop the sendmmsg(), we don't need to send multiple messages with TCP, as long as we make sure no messages with a length descriptor are sent partially, qemu is fine with it. Just like it's done for segments without data (flags), also defer the sendmsg() for sending data segments, to improve batching. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Clamp MSS depending on IP version, properly derive buffer sizesStefano Brivio2021-10-151-17/+19
| | | | | | | It makes no sense to include an IPv6 header in the calculation for clamping MSS on IPv4. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Explicitly align IP headers in tcp4_l2_{,flags}buf_t also in non-AVX2 buildStefano Brivio2021-10-141-14/+12
| | | | | | | Otherwise, tcp4_l2_flags_buf_t is not consistent with tcp4_l2_buf_t and header fields get all mixed up in tcp_l2_buf_fill_headers(). Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* conf, tcp, udp: Add --no-map-gw to disable mapping gateway address to hostStefano Brivio2021-10-141-2/+3
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt, pasta: Add seccomp supportStefano Brivio2021-10-141-0/+11
| | | | | | | | | | | | | | | | | | List of allowed syscalls comes from comments in the form: #syscalls <list> for syscalls needed both in passt and pasta mode, and: #syscalls:pasta <list> #syscalls:passt <list> for syscalls specifically needed in pasta or passt mode only. seccomp.sh builds a list of BPF statements from those comments, prefixed by a binary search tree to keep lookup fast. While at it, clean up a bit the Makefile using wildcards. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Decrease pool size for pipes to 16Stefano Brivio2021-10-141-1/+1
| | | | | | | This should be a reasonable balance between quick connection establishment and a fast start-up. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* conf, tap: Split netlink and pasta functions, allow interface configurationStefano Brivio2021-10-141-1/+1
| | | | | | | | | | Move netlink routines to their own file, and use netlink to configure or fetch all the information we need, except for the TUNSETIFF ioctl. Move pasta-specific functions to their own file as well, add parameters and calls to configure the tap interface in the namespace. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta: Allow specifying paths and names of namespacesGiuseppe Scrivano2021-10-071-5/+5
| | | | | | | | | | | | | | | | | | Based on a patch from Giuseppe Scrivano, this adds the ability to: - specify paths and names of target namespaces to join, instead of a PID, also for user namespaces, with --userns - request to join or create a network namespace only, without entering or creating a user namespace, with --netns-only - specify the base directory for netns mountpoints, with --nsrun-dir Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com> [sbrivio: reworked logic to actually join the given namespaces when they're not created, implemented --netns-only and --nsrun-dir, updated pasta demo script and man page] Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Check if timestamp is passed also while sending FIN to tap/guestStefano Brivio2021-10-051-1/+1
| | | | | | | ...it's probably possible that we might need to reset a connection together with a FIN segment. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Drop EPOLLOUT for connections being established earlierStefano Brivio2021-10-051-3/+3
| | | | | | | | That's the first thing we have to do, before sending SYN, ACK: if tcp_send_to_tap() fails, we'll get a lot of useless events otherwise. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Shrink binary size by dropping static initialisersStefano Brivio2021-10-051-44/+49
| | | | | | ...from 11MiB to 155KiB for 'make avx2', 95KiB with -Os and stripped. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Simplify ACK-sending conditions in tcp_data_from_tap()Stefano Brivio2021-10-051-20/+9
| | | | | | | | Now that we have a proper function checking when and how to send ACKs and window updates, we don't need to duplicate this logic in tcp_data_from_tap(). Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Always probe SO_SNDBUF, second attemptStefano Brivio2021-10-051-3/+0
| | | | | | I fell for this already: the sending buffer might shrink later! Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Defer and coalesce all segments with no data (flags) to handlerStefano Brivio2021-10-051-142/+376
| | | | | | | | | | ...using pre-cooked buffers, just like we do with other segments. While at it, remove some code duplication by having separate functions for updating ACK sequence and window, and for filling in buffer headers. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Increase LOW_RTT_THRESHOLD to 10usStefano Brivio2021-10-051-1/+1
| | | | | | Sometimes we can get up to 6-7us minimum RTT for local connections too. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Reduce size of socket poolsStefano Brivio2021-10-051-2/+2
| | | | | | | A large pool helps marginally with CRR latency, but has detrimental effects on TCP memory pressure. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Increase TCP_TAP_FRAMES once moreStefano Brivio2021-10-051-1/+1
| | | | | | | With an increased sending buffer size for the AF_UNIX socket, we can get slightly lower overhead. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp, tap: Turn tcp_probe_mem() into sock_probe_mem(), use for AF_UNIX socket tooStefano Brivio2021-10-051-35/+3
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Fix botched timeout comparisonStefano Brivio2021-10-041-2/+2
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Check pending ACK every two thirds of window, not every halfStefano Brivio2021-10-041-1/+1
| | | | | | | ...to spare some syscalls. If it's not enough, the timer will take care of it. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Don't set ACK flag while merely updating window valueStefano Brivio2021-10-041-15/+19
| | | | | | The receiver might take this as a duplicate ACK othewise. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Set TCP_TAP_FRAMES back to 32Stefano Brivio2021-10-041-1/+1
| | | | | | | Now that we fixed the issue with small receiving buffers, we can safely increase this back and get slightly lower syscall overhead. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Probe net.core.{r,w}mem_max, don't set SO_{RCV,SND}BUF if lowStefano Brivio2021-10-041-16/+22
| | | | | | | | | | | | | | | If net.core.rmem_max and net.core.wmem_max sysctls have low values, we can get bigger buffers by not trying to set them high -- the kernel would lock their values to what we get. Try, instead, to get bigger buffers by queueing as much as possible, and if maximum values in tcp_wmem and tcp_rmem are bigger than this, that will work. While at it, drop QUICKACK option for non-spliced sockets, I set that earlier by mistake. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Check if connection is local or low RTT was seen before using large MSSStefano Brivio2021-10-041-0/+59
| | | | | | | | If the connection is local or the RTT was comparable to the time it takes to queue a batch of messages, we can safely use a large MSS regardless of the sending buffer, but otherwise not. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Adjust usage of sending buffer depending on its sizeStefano Brivio2021-10-041-12/+63
| | | | | | | | | | | | | If we start with a very small sending buffer, we can make the kernel expand it if we cause the congestion window to get bigger, but this won't reliably happen if we use just half (other half is accounted as overhead). Scale usage depending on its own size, we might eventually get some retransmissions because we can't queue messages the sender sends us in-window, but it's better than keeping that small buffer forever. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Derive MSS announced to guest/namespace from configured MTU if presentStefano Brivio2021-09-291-1/+14
| | | | | | | | | | | ...and from the sending socket only if the MTU is not configured. Otherwise, a connection to a host from a local guest, with a non-loopback destination address, will get its MSS from the MTU of the outbound interface with that address, which is unnecessary as we know the guest can send us larger segments. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* conf, tcp: Periodic detection of bound ports for pasta port forwardingStefano Brivio2021-09-271-53/+239
| | | | | | | | | | Detecting bound ports at start-up time isn't terribly useful: do this periodically instead, if configured. This is only implemented for TCP at the moment, UDP is somewhat more complicated: leave a TODO there. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Rework window handling, timers, add SO_RCVLOWAT and pools for sockets/pipesStefano Brivio2021-09-271-456/+719
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This introduces a number of fundamental changes that would be quite messy to split. Summary: - advertised window scaling can be as big as we want, we just need to clamp window sizes to avoid exceeding the size of our "discard" buffer for unacknowledged data from socket - add macros to compare sequence numbers - force sending ACK to guest/tap on PSH segments, always in pasta mode, whenever we see an overlapping segment, or when we reach a given threshold compared to our window - we don't actually use recvmmsg() here, fix comments and label - introduce pools for pre-opened sockets and pipes, to decrease latency on new connections - set receiving and sending buffer sizes to the maximum allowed, kernel will clamp and round appropriately - defer clean-up of spliced and non-spliced connection to timer - in tcp_send_to_tap(), there's no need anymore to keep a large buffer, shrink it down to what we actually need - introduce SO_RCVLOWAT setting and activity tracking for spliced connections, to coalesce data moved by splice() calls as much as possible - as we now have a compacted connection table, there's no need to keep sparse bitmaps tracking connection activity -- simply go through active connections with a loop in the timer handler - always clamp the advertised window to half our sending buffer, too, to minimise retransmissions from the guest/tap - set TCP_QUICKACK for originating socket in spliced connections, there's no need to delay them - fix up timeout for unacknowledged data from socket Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Drop TODO about sequence collision attacksStefano Brivio2021-09-271-1/+0
| | | | | | | A random initial sequence number based on a secret has already been there for a while. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tap: Completely de-serialise input message batchesStefano Brivio2021-09-271-15/+11
| | | | | | | | | | | | | Until now, messages would be passed to protocol handlers in a single batch only if they happened to be dequeued in a row. Packets interleaved between different connections would result in multiple calls to the same protocol handler for a single connection. Instead, keep track of incoming packet descriptors, arrange them in sequences, and call protocol handlers only as we completely sorted input messages in batches. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Decrease TCP_TAP_FRAMES to 8Stefano Brivio2021-09-271-1/+1
| | | | | | This significantly improves fairness in serving concurrent connections. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta, tcp: Update comment about spliced connection statesStefano Brivio2021-09-271-1/+4
| | | | | | ...we now have SPLICE_FIN_{FROM,TO,BOTH} too. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Don't reset connection from ESTABLISHED state on EPOLLHUPStefano Brivio2021-09-161-6/+1
| | | | | | | | | | | That might just mean we shut down the socket -- but we still have to go through the other states to ensure a orderly shutdown guest-side. While at it, drop the EPOLLHUP check for unhandled states: we should never hit that, but if we do, resetting the connection at that point is probably the wrong thing to do. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta, tcp: Mask EPOLLIN and EPOLLRDHUP after sending FINStefano Brivio2021-09-161-2/+14
| | | | | | | Now that we dropped EPOLLET, we'll keep getting EPOLLRDHUP, and possibly EPOLLIN, even if there's nothing to read anymore. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta, tcp: Break splice() loop once we've written everything that was readStefano Brivio2021-09-161-2/+7
| | | | | | That's a guarantee that we don't need to retry writing. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta, tcp: Don't set SPLICE_FIN_BOTH state on EPOLLHUPStefano Brivio2021-09-161-3/+1
| | | | | | | EPOLLHUP just means we shut down one side of the connection on *one* socket: remember, we have two sockets here. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta, tcp: Don't reset 'never_read' flag on write retriesStefano Brivio2021-09-161-2/+3
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta, tcp: Don't set TCP_CORK on spliced socketsStefano Brivio2021-09-161-6/+1
| | | | | | | | ...throughput isn't everything: this leads (of course) to horrible latency with small, sparse messages. As a consequence, there's no need to set TCP_NODELAY either. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Fix setting window from maximum ACK sequence in batchStefano Brivio2021-09-161-6/+2
| | | | | | | | | If we're at the first message in a batch, it's safe to get the window value from it, and there's no need to subtract anything for a comparison on that's not even done -- we'll override it later in any case if we find messages with a higher ACK sequence number. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta, tcp: Set pipe descriptor numbers to -1 after closingStefano Brivio2021-09-161-0/+4
| | | | | | ...so that we don't try to close them again, even if harmless. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta, tcp: Drop EPOLLET for spliced, established connectionsStefano Brivio2021-09-161-5/+5
| | | | | | | ...tcp_handler_splice() doesn't guarantee we read all the available data, the sending buffer might be full. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>