passt: Relicense to GPL 2.0, or any later version
In practical terms, passt doesn't benefit from the additional
protection offered by the AGPL over the GPL, because it's not
suitable to be executed over a computer network.
Further, restricting the distribution under the version 3 of the GPL
wouldn't provide any practical advantage either, as long as the passt
codebase is concerned, and might cause unnecessary compatibility
dilemmas.
Change licensing terms to the GNU General Public License Version 2,
or any later version, with written permission from all current and
past contributors, namely: myself, David Gibson, Laine Stump, Andrea
Bolognani, Paul Holzinger, Richard W.M. Jones, Chris Kuhn, Florian
Weimer, Giuseppe Scrivano, Stefan Hajnoczi, and Vasiliy Ulyanov.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
2023-04-05 18:11:44 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
2021-10-19 10:43:28 +00:00
|
|
|
* Copyright (c) 2021 Red Hat GmbH
|
|
|
|
* Author: Stefano Brivio <sbrivio@redhat.com>
|
|
|
|
*/
|
|
|
|
|
2022-03-25 23:05:31 +00:00
|
|
|
#ifndef TAP_H
|
|
|
|
#define TAP_H
|
|
|
|
|
2023-01-06 00:43:17 +00:00
|
|
|
/**
|
|
|
|
* struct tap_hdr - L2 and tap specific headers
|
|
|
|
* @vnet_len: Frame length (for qemu socket transport)
|
|
|
|
* @eh: Ethernet header
|
|
|
|
*/
|
|
|
|
struct tap_hdr {
|
|
|
|
uint32_t vnet_len;
|
|
|
|
struct ethhdr eh;
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
#define TAP_HDR_INIT(proto) { .eh.h_proto = htons_constant(proto) }
|
|
|
|
|
|
|
|
static inline size_t tap_hdr_len_(const struct ctx *c)
|
|
|
|
{
|
2023-01-06 00:43:19 +00:00
|
|
|
if (c->mode == MODE_PASST)
|
|
|
|
return sizeof(struct tap_hdr);
|
|
|
|
else
|
|
|
|
return sizeof(struct ethhdr);
|
2023-01-06 00:43:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-03-08 06:53:25 +00:00
|
|
|
* tap_frame_base() - Find start of tap frame
|
2023-01-06 00:43:17 +00:00
|
|
|
* @c: Execution context
|
2024-03-08 06:53:25 +00:00
|
|
|
* @taph: Pointer to L2 and tap specific header buffer
|
2023-01-06 00:43:17 +00:00
|
|
|
*
|
|
|
|
* Returns: pointer to the start of tap frame - suitable for an
|
|
|
|
* iov_base to be passed to tap_send_frames())
|
|
|
|
*/
|
2024-03-08 06:53:25 +00:00
|
|
|
static inline void *tap_frame_base(const struct ctx *c, struct tap_hdr *taph)
|
2023-01-06 00:43:17 +00:00
|
|
|
{
|
|
|
|
return (char *)(taph + 1) - tap_hdr_len_(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-03-08 06:53:25 +00:00
|
|
|
* tap_frame_len() - Finalize tap frame and return total length
|
2023-01-06 00:43:17 +00:00
|
|
|
* @c: Execution context
|
|
|
|
* @taph: Tap header to finalize
|
2024-03-08 06:53:25 +00:00
|
|
|
* @plen: L3 packet length (excludes L2 and tap specific headers)
|
2023-01-06 00:43:17 +00:00
|
|
|
*
|
|
|
|
* Returns: length of the tap frame including L2 and tap specific
|
|
|
|
* headers - suitable for an iov_len to be passed to
|
|
|
|
* tap_send_frames()
|
|
|
|
*/
|
2024-03-08 06:53:25 +00:00
|
|
|
static inline size_t tap_frame_len(const struct ctx *c, struct tap_hdr *taph,
|
|
|
|
size_t plen)
|
2023-01-06 00:43:17 +00:00
|
|
|
{
|
|
|
|
if (c->mode == MODE_PASST)
|
|
|
|
taph->vnet_len = htonl(plen + sizeof(taph->eh));
|
|
|
|
return plen + tap_hdr_len_(c);
|
|
|
|
}
|
|
|
|
|
2022-11-04 03:10:35 +00:00
|
|
|
struct in_addr tap_ip4_daddr(const struct ctx *c);
|
|
|
|
void tap_udp4_send(const struct ctx *c, struct in_addr src, in_port_t sport,
|
|
|
|
struct in_addr dst, in_port_t dport,
|
2022-10-19 00:43:56 +00:00
|
|
|
const void *in, size_t len);
|
2022-11-04 03:10:35 +00:00
|
|
|
void tap_icmp4_send(const struct ctx *c, struct in_addr src, struct in_addr dst,
|
2023-09-29 05:50:19 +00:00
|
|
|
const void *in, size_t len);
|
2022-10-19 00:43:49 +00:00
|
|
|
const struct in6_addr *tap_ip6_daddr(const struct ctx *c,
|
|
|
|
const struct in6_addr *src);
|
2022-10-19 00:43:53 +00:00
|
|
|
void tap_udp6_send(const struct ctx *c,
|
|
|
|
const struct in6_addr *src, in_port_t sport,
|
|
|
|
const struct in6_addr *dst, in_port_t dport,
|
|
|
|
uint32_t flow, const void *in, size_t len);
|
|
|
|
void tap_icmp6_send(const struct ctx *c,
|
|
|
|
const struct in6_addr *src, const struct in6_addr *dst,
|
2023-09-29 05:50:19 +00:00
|
|
|
const void *in, size_t len);
|
2024-03-08 06:53:24 +00:00
|
|
|
void tap_send_single(const struct ctx *c, const void *data, size_t len);
|
2024-03-08 06:53:22 +00:00
|
|
|
size_t tap_send_frames(const struct ctx *c, const struct iovec *iov,
|
|
|
|
size_t bufs_per_frame, size_t nframes);
|
2024-03-06 05:58:37 +00:00
|
|
|
void eth_update_mac(struct ethhdr *eh,
|
2023-01-06 00:43:17 +00:00
|
|
|
const unsigned char *eth_d, const unsigned char *eth_s);
|
2023-08-11 05:12:28 +00:00
|
|
|
void tap_listen_handler(struct ctx *c, uint32_t events);
|
2023-08-11 05:12:29 +00:00
|
|
|
void tap_handler_pasta(struct ctx *c, uint32_t events,
|
|
|
|
const struct timespec *now);
|
|
|
|
void tap_handler_passt(struct ctx *c, uint32_t events,
|
|
|
|
const struct timespec *now);
|
passt: Add PASTA mode, major rework
PASTA (Pack A Subtle Tap Abstraction) provides quasi-native host
connectivity to an otherwise disconnected, unprivileged network
and user namespace, similarly to slirp4netns. Given that the
implementation is largely overlapping with PASST, no separate binary
is built: 'pasta' (and 'passt4netns' for clarity) both link to
'passt', and the mode of operation is selected depending on how the
binary is invoked. Usage example:
$ unshare -rUn
# echo $$
1871759
$ ./pasta 1871759 # From another terminal
# udhcpc -i pasta0 2>/dev/null
# ping -c1 pasta.pizza
PING pasta.pizza (64.190.62.111) 56(84) bytes of data.
64 bytes from 64.190.62.111 (64.190.62.111): icmp_seq=1 ttl=255 time=34.6 ms
--- pasta.pizza ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 34.575/34.575/34.575/0.000 ms
# ping -c1 spaghetti.pizza
PING spaghetti.pizza(2606:4700:3034::6815:147a (2606:4700:3034::6815:147a)) 56 data bytes
64 bytes from 2606:4700:3034::6815:147a (2606:4700:3034::6815:147a): icmp_seq=1 ttl=255 time=29.0 ms
--- spaghetti.pizza ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 28.967/28.967/28.967/0.000 ms
This entails a major rework, especially with regard to the storage of
tracked connections and to the semantics of epoll(7) references.
Indexing TCP and UDP bindings merely by socket proved to be
inflexible and unsuitable to handle different connection flows: pasta
also provides Layer-2 to Layer-2 socket mapping between init and a
separate namespace for local connections, using a pair of splice()
system calls for TCP, and a recvmmsg()/sendmmsg() pair for UDP local
bindings. For instance, building on the previous example:
# ip link set dev lo up
# iperf3 -s
$ iperf3 -c ::1 -Z -w 32M -l 1024k -P2 | tail -n4
[SUM] 0.00-10.00 sec 52.3 GBytes 44.9 Gbits/sec 283 sender
[SUM] 0.00-10.43 sec 52.3 GBytes 43.1 Gbits/sec receiver
iperf Done.
epoll(7) references now include a generic part in order to
demultiplex data to the relevant protocol handler, using 24
bits for the socket number, and an opaque portion reserved for
usage by the single protocol handlers, in order to track sockets
back to corresponding connections and bindings.
A number of fixes pertaining to TCP state machine and congestion
window handling are also included here.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
2021-07-17 06:34:53 +00:00
|
|
|
void tap_sock_init(struct ctx *c);
|
2022-03-25 23:05:31 +00:00
|
|
|
|
|
|
|
#endif /* TAP_H */
|