aboutgitcodebugslistschat
Commit message (Collapse)AuthorAgeFilesLines
...
* conf: Introduce PASST_LEGACY_NO_OPTIONS ifdef for legacyStefano Brivio2021-09-091-0/+12
| | | | | | | | 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>
* tcp, udp: Restore usage of gateway for guest to connect to local hostStefano Brivio2021-09-012-6/+11
| | | | | | | 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>
* Makefile: Make sure destination directories exist on installStefano Brivio2021-09-011-0/+1
| | | | | | Mostly theoretical, but convenient for testing. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* udp: Handle partial failure in sendmmsg() to UNIX domain socketStefano Brivio2021-09-011-20/+60
| | | | | | | | | | | | | | | 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>
* doc/demo: Also forward all UDP ports from namespaceStefano Brivio2021-09-011-1/+1
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* doc/demo: Explicitly run in foreground, drop pipe to catStefano Brivio2021-09-011-1/+1
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* dhcp: Send option 121 if the default gateway is not on the assigned subnetStefano Brivio2021-09-011-0/+11
| | | | | | | | 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>
* conf: Fix check for IPv6 DNS address being already setStefano Brivio2021-09-011-1/+1
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* arp: Don't resolve own, configured IPv4 addressStefano Brivio2021-09-011-0/+4
| | | | | | | 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>
* Makefile: Quick hack to build convenience Debian and RPM packagesStefano Brivio2021-09-011-1/+15
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* Makefile: Add install, uninstall targetsStefano Brivio2021-09-011-1/+16
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt, qrap: Add man pagesStefano Brivio2021-09-012-0/+784
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* qrap: Minor fixes in comments and usage messageStefano Brivio2021-09-011-2/+2
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta: If a new namespace is created, wait for it to be ready before proceedingStefano Brivio2021-09-011-1/+15
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* conf: Minor fixes for usage messageStefano Brivio2021-09-011-4/+4
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* arp: Don't answer announcements from guest or namespaceStefano Brivio2021-09-011-0/+6
| | | | | | | 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>
* passt, pasta: Introduce command-line options and port re-mappingStefano Brivio2021-09-0117-691/+1644
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Fixes for early data in SOCK_SYN_SENT, closing states, clamping windowStefano Brivio2021-09-011-23/+30
| | | | | | More details here after rebase. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tap: Make sure we don't receive frames bigger than ETH_MAX_MTU from qemuStefano Brivio2021-09-011-5/+4
| | | | | | | 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>
* dhcpv6: Fix parsing for IA_ADDR suboptions of IA_NA/IA_TAStefano Brivio2021-09-011-7/+11
| | | | | | | | | | | 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>
* tcp: Proper error handling for sendmmsg() to UNIX domain socketStefano Brivio2021-08-261-37/+64
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* tcp: Never send ACK because of pending unacknowleged data when sending SYNStefano Brivio2021-08-241-1/+3
| | | | | | | | | | | | | | 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>
* tcp: Drop EPOLLET for non-spliced connectionsStefano Brivio2021-08-241-4/+4
| | | | | | | 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>
* util: Don't close ping sockets if bind() failsStefano Brivio2021-08-041-3/+6
| | | | | | | ...they're still usable, thanks to the workaround implemented in icmp_tap_handler(). Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* util: Fix millisecond logging timestamp calculationStefano Brivio2021-08-041-1/+1
| | | | | | | Four sub-second digits means 0.1ms units: divide nanoseconds by 10^5, not 10^6. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Fast re-transmit, more fixes for closing states and no_snd_wndStefano Brivio2021-08-041-45/+73
| | | | | | | | | | | ...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>
* tcp: Always allow ACKs when pending, fixes for no_snd_wnd and closing statesStefano Brivio2021-08-041-10/+23
| | | | | | | | | | | | | | | | 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>
* tcp: Lower TCP_TAP_FRAMES to 32Stefano Brivio2021-08-041-1/+1
| | | | | | | | 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>
* doc/demo.sh: Pick IPv6 interface only if it has a nexthop routeStefano Brivio2021-08-041-1/+1
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Full batched processing for tap messagesStefano Brivio2021-07-271-121/+156
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* tcp: Limit TCP_INFO getsockopt() syscallsStefano Brivio2021-07-271-1/+2
| | | | | | | | 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>
* tap: Increase amount of tap receive buffers to 128Stefano Brivio2021-07-272-12/+13
| | | | | | | | ...boom. To make it slightly more reasonable, shrink struct tap_msg down a bit, and move the main message array away from the stack of tap_handler_passt(). Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp, udp: Map source address to gateway for any traffic from 127.0.0.0/8Stefano Brivio2021-07-262-6/+7
| | | | | | ...instead of just 127.0.0.1. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* icmp: Work around possible failure on bind() due to e.g. broken SELinux policyStefano Brivio2021-07-263-5/+22
| | | | | | | | | | | | | | | If we can't bind() ping sockets, the echo identifier sent out from the socket won't be the original one seen from the tap. Binding a ping socket doesn't require any security capability, but it might still fail due to a broken SELinux policy, see for example: https://bugzilla.redhat.com/show_bug.cgi?id=1848929 Track the ICMP echo identifier as part of the epoll reference for the socket and replace it in the reply on mismatch. We won't send out the original identifier as sent from the guest, but still better than missing replies. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Fix re-send mechanism to tap on ACK timeoutStefano Brivio2021-07-261-2/+3
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Simplify ACK accounting, skip some useless operations on tap handlingStefano Brivio2021-07-261-19/+10
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Introduce scatter-gather IO path from socket to tapStefano Brivio2021-07-264-45/+514
| | | | | | | | | | | | | | | | | ...similarly to what was done for UDP. Quick performance test with 32KiB buffers, host to VM: $ iperf3 -c 192.0.2.2 -N [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 8.47 GBytes 7.27 Gbits/sec 0 sender [ 5] 0.00-10.00 sec 8.45 GBytes 7.26 Gbits/sec receiver $ iperf3 -c 2a01:598:88ba:a056:271f:473a:c0d9:abc1 [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 8.43 GBytes 7.24 Gbits/sec 0 sender [ 5] 0.00-10.00 sec 8.41 GBytes 7.22 Gbits/sec receiver Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tap: Don't override address observed from guest with our own notion of itStefano Brivio2021-07-261-15/+22
| | | | | | | | | | | If a tap protocol handler doesn't consume the full batch of packets in one go, we already overrode the destination address in the packet buffer with the address which is configured at start. If we re-enter the tap handler, we shouldn't use the address from the packet buffers anymore to set the observed address of the guest: that's not the address observed from the guest, it's the configured one now. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp, udp: Allow binding ports in init namespace to both tap and loopbackStefano Brivio2021-07-266-60/+140
| | | | | | | | Traffic with loopback source address will be forwarded to the direct loopback connection in the namespace, and the tap interface is used for the rest. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* doc/demo.sh: Increase tcp_rmem and tcp_wmem before running passtStefano Brivio2021-07-261-0/+2
| | | | | | ...this is convenient for performance testing. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tap: Fill the IPv6 flow label field to represent flow associationStefano Brivio2021-07-265-10/+25
| | | | | | | | | This isn't optional: TCP streams must carry a unique, hard-to-guess, non-zero label for each direction. Linux, probably among others, will otherwise refuse to associate packets in a given stream to the same connection. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* checksum: Introduce AVX2 implementation, unify helpersStefano Brivio2021-07-268-92/+332
| | | | | | | | | | | | | | | | | | | Provide an AVX2-based function using compiler intrinsics for TCP/IP-style checksums. The load/unpack/add idea and implementation is largely based on code from BESS (the Berkeley Extensible Software Switch) licensed as 3-Clause BSD, with a number of modifications to further decrease pipeline stalls and to minimise cache pollution. This speeds up considerably data paths from sockets to tap interfaces, decreasing overhead for checksum computation, with 16-64KiB packet buffers, from approximately 11% to 7%. The rest is just syscalls at this point. While at it, provide convenience targets in the Makefile for avx2, avx2_debug, and debug targets -- these simply add target-specific CFLAGS to the build. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* dhcpv6: Drop bogus option length test while checking for not-on-link IA_NAStefano Brivio2021-07-261-4/+1
| | | | | | | | | | | dhcpv6_opt() already reflects consumed bytes on the remaining length, and that we're not exceeding the message length. At this point, the remaining length is usually zero. While at it, drop a useless __packed__ attribute that triggers a gcc warning. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Don't open a new connection from tap if both SYN and ACK are setStefano Brivio2021-07-211-1/+1
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tap: Fix comment for tap_handler_pasta()Stefano Brivio2021-07-211-1/+1
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp, udp: Split IPv4 and IPv6 bound port setsStefano Brivio2021-07-215-79/+131
| | | | | | | | | | | Allow to bind IPv4 and IPv6 ports to tap, namespace or init separately. Port numbers of TCP ports that are bound in a namespace are also bound for UDP for convenience (e.g. iperf3), and IPv4 ports are always bound if the corresponding IPv6 port is bound (socket might not have the IPV6_V6ONLY option set). This will also be configurable later. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Replace source address also if it's the same as the guest addressStefano Brivio2021-07-211-2/+4
| | | | | | | | ...not just for loopback addresses, with the address of the default gateway. Otherwise, the guest might receive packets with source and destination set to the same address. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Increase maximum window scaling factor from 8 to 9Stefano Brivio2021-07-211-1/+1
| | | | | | | This is actually reasonable in terms of memory consumption and allows for better performance with local services. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* udp: Introduce recvmmsg()/sendmmsg(), zero-copy path from socketStefano Brivio2021-07-219-61/+537
| | | | | | | | | | Packets are received directly onto pre-cooked, static buffers for IPv4 (with partial checksum pre-calculation) and IPv6 frames, with pre-filled Ethernet addresses and, partially, IP headers, and sent out from the same buffers with sendmmsg(), for both passt and pasta (non-local traffic only) modes. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* ndp: Store link-local or global address on any NDP message receivedStefano Brivio2021-07-211-0/+5
| | | | | | | | The guest might not send other types of traffic before we try to communicate to it, so take also this chance to store its configured addresses. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>