mirror of
https://passt.top/passt
synced 2025-06-11 01:55:34 +02:00

Currently we have an asymmetry in how we handle UDP sockets. For flows where the target side is a socket, we create a new connect()ed socket - the "reply socket" specifically for that flow used for sending and receiving datagrams on that flow and only that flow. For flows where the initiating side is a socket, we continue to use the "listening" socket (or rather, a dup() of it). This has some disadvantages: * We need a hash lookup for every datagram on the listening socket in order to work out what flow it belongs to * The dup() keeps the socket alive even if automatic forwarding removes the listening socket. However, the epoll data remains the same including containing the now stale original fd. This causes bug 103. * We can't (easily) set flow-specific options on an initiating side socket, because that could affect other flows as well Alter the code to use a connect()ed socket on the initiating side as well as the target side. There's no way to "clone and connect" the listening socket (a loose equivalent of accept() for UDP), so we have to create a new socket. We have to bind() this socket before we connect() it, which is allowed thanks to SO_REUSEADDR, but does leave a small window where it could receive datagrams not intended for this flow. For now we handle this by simply discarding any datagrams received between bind() and connect(), but I intend to improve this in a later patch. Link: https://bugs.passt.top/show_bug.cgi?id=103 Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
53 lines
1.6 KiB
C
53 lines
1.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
* Copyright (c) 2021 Red Hat GmbH
|
|
* Author: Stefano Brivio <sbrivio@redhat.com>
|
|
*/
|
|
|
|
#ifndef UDP_H
|
|
#define UDP_H
|
|
|
|
#define UDP_TIMER_INTERVAL 1000 /* ms */
|
|
|
|
void udp_portmap_clear(void);
|
|
void udp_listen_sock_handler(const struct ctx *c, union epoll_ref ref,
|
|
uint32_t events, const struct timespec *now);
|
|
void udp_sock_handler(const struct ctx *c, union epoll_ref ref,
|
|
uint32_t events, const struct timespec *now);
|
|
int udp_tap_handler(const struct ctx *c, uint8_t pif,
|
|
sa_family_t af, const void *saddr, const void *daddr,
|
|
uint8_t ttl, const struct pool *p, int idx,
|
|
const struct timespec *now);
|
|
int udp_sock_init(const struct ctx *c, int ns, const union inany_addr *addr,
|
|
const char *ifname, in_port_t port);
|
|
int udp_init(struct ctx *c);
|
|
void udp_timer(struct ctx *c, const struct timespec *now);
|
|
void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s);
|
|
|
|
/**
|
|
* union udp_listen_epoll_ref - epoll reference for "listening" UDP sockets
|
|
* @port: Source port for connected sockets, bound port otherwise
|
|
* @pif: pif for this socket
|
|
* @u32: Opaque u32 value of reference
|
|
*/
|
|
union udp_listen_epoll_ref {
|
|
struct {
|
|
in_port_t port;
|
|
uint8_t pif;
|
|
};
|
|
uint32_t u32;
|
|
};
|
|
|
|
|
|
/**
|
|
* struct udp_ctx - Execution context for UDP
|
|
* @fwd_in: Port forwarding configuration for inbound packets
|
|
* @fwd_out: Port forwarding configuration for outbound packets
|
|
* @timer_run: Timestamp of most recent timer run
|
|
*/
|
|
struct udp_ctx {
|
|
struct fwd_ports fwd_in;
|
|
struct fwd_ports fwd_out;
|
|
struct timespec timer_run;
|
|
};
|
|
|
|
#endif /* UDP_H */
|