From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from gandalf.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 43C355A005E for ; Tue, 22 Nov 2022 04:44:07 +0100 (CET) Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4NGVVX0PPyz4xN5; Tue, 22 Nov 2022 14:44:04 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=201602; t=1669088644; bh=d6cjsPki2DXL0CXxVFmbIlvpKM+2L6DOX3H9xAgIrvk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RGxVOA/GCmMYV0G2nq6vJHWQdmG1baJJlllqCYgvdV64o+SmpHwPkspHDSe0NQ6H3 1+9bdGIL6ufNVwUENOz7SSmRbdch6H4UW/0Q6yeupNXjSzexUkAZigXgFygMsGn/nF imJHiyGNRWIci8GF/6AobM7QsTKEYBy5GqT12It0= From: David Gibson To: Stefano Brivio , passt-dev@passt.top Subject: [PATCH 02/11] udp: Separate tracking of inbound and outbound packet flows Date: Tue, 22 Nov 2022 14:43:53 +1100 Message-Id: <20221122034402.1517544-3-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221122034402.1517544-1-david@gibson.dropbear.id.au> References: <20221122034402.1517544-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: MR5VEZWBM4BJ4WXYQRN2LXJI34SRAGBK X-Message-ID-Hash: MR5VEZWBM4BJ4WXYQRN2LXJI34SRAGBK X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: David Gibson X-Mailman-Version: 3.3.3 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Each entry udp_splice_map[v6][N] keeps information about two essentially unrelated packet flows. @ns_conn_sock, @ns_conn_ts and @init_bound_sock track a packet flow from port N in the host init namespace to some other port in the pasta namespace (the one @ns_conn_sock is connected to). @init_conn_sock, @init_conn_ts and @ns_bound_sock track packet flow from port N in the pasta namespace to some other port in the host init namespace (the one @init_conn_sock is connected to). Split udp_splice_map[][] into two separate tables for the two directions. Each entry in each table is a 'struct udp_splice_flow' with @orig_sock (previously the bound socket), @target_sock (previously the connected socket) and @ts (the timeout for the target socket). Signed-off-by: David Gibson --- udp.c | 111 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 56 insertions(+), 55 deletions(-) diff --git a/udp.c b/udp.c index a025a48..4caf73e 100644 --- a/udp.c +++ b/udp.c @@ -47,44 +47,44 @@ * * - forward direction: 127.0.0.1:5000 -> 127.0.0.1:80 in init from bound * socket s, with epoll reference: index = 80, splice = UDP_TO_NS - * - if udp_splice_map[V4][5000].ns_conn_sock: - * - send packet to udp4_splice_map[5000].ns_conn_sock + * - if udp_splice_to_ns[V4][5000].target_sock: + * - send packet to udp_splice_to_ns[V4][5000].target_sock * - otherwise: - * - create new socket udp_splice_map[V4][5000].ns_conn_sock + * - create new socket udp_splice_to_ns[V4][5000].target_sock * - bind in namespace to 127.0.0.1:5000 * - connect in namespace to 127.0.0.1:80 (note: this destination port * might be remapped to another port instead) * - add to epoll with reference: index = 5000, splice: UDP_BACK_TO_INIT - * - set udp_splice_map[V4][5000].init_bound_sock to s - * - update udp_splice_map[V4][5000].ns_conn_ts with current time + * - set udp_splice_to_ns[V4][5000].orig_sock to s + * - update udp_splice_to_ns[V4][5000].ts with current time * * - reverse direction: 127.0.0.1:80 -> 127.0.0.1:5000 in namespace from * connected socket s, having epoll reference: index = 5000, * splice = UDP_BACK_TO_INIT - * - if udp_splice_map[V4][5000].init_bound_sock: - * - send to udp_splice_map[V4][5000].init_bound_sock, with destination - * port 5000 + * - if udp_splice_to_ns[V4][5000].orig_sock: + * - send to udp_splice_to_ns[V4][5000].orig_sock, with destination port + * 5000 * - otherwise, discard * * - from namespace to init: * * - forward direction: 127.0.0.1:2000 -> 127.0.0.1:22 in namespace from bound * socket s, with epoll reference: index = 22, splice = UDP_TO_INIT - * - if udp4_splice_map[V4][2000].init_conn_sock: - * - send packet to udp4_splice_map[2000].init_conn_sock + * - if udp4_splice_to_init[V4][2000].target_sock: + * - send packet to udp_splice_to_init[V4][2000].target_sock * - otherwise: - * - create new socket udp_splice_map[V4][2000].init_conn_sock + * - create new socket udp_splice_to_init[V4][2000].target_sock * - bind in init to 127.0.0.1:2000 * - connect in init to 127.0.0.1:22 (note: this destination port * might be remapped to another port instead) * - add to epoll with reference: index = 2000, splice = UDP_BACK_TO_NS - * - set udp_splice_map[V4][2000].ns_bound_sock to s - * - update udp_splice_map[V4][2000].init_conn_ts with current time + * - set udp_splice_to_init[V4][2000].orig_sock to s + * - update udp_splice_to_init[V4][2000].ts with current time * * - reverse direction: 127.0.0.1:22 -> 127.0.0.1:2000 in init from connected * socket s, having epoll reference: index = 2000, splice = UDP_BACK_TO_NS - * - if udp_splice_map[V4][2000].ns_bound_sock: - * - send to udp_splice_map[V4][2000].ns_bound_sock, with destination port + * - if udp_splice_to_init[V4][2000].orig_sock: + * - send to udp_splice_to_init[V4][2000].orig_sock, with destination port * 2000 * - otherwise, discard */ @@ -138,28 +138,26 @@ struct udp_tap_port { }; /** - * struct udp_splice_port - Source port tracking for traffic between namespaces - * @ns_conn_sock: Socket connected in namespace for init source port - * @init_conn_sock: Socket connected in init for namespace source port - * @ns_conn_ts: Timestamp of activity for socket connected in namespace - * @init_conn_ts: Timestamp of activity for socket connceted in init - * @ns_bound_sock: Bound socket in namespace for this source port in init - * @init_bound_sock: Bound socket in init for this source port in namespace + * struct udp_splice_flow - Spliced "connection" + * @orig_sock: Originating socket, bound to dest port in source ns of + * originating datagram + * @target_sock: Target socket, bound to source port of originating + * datagram in dest ns, connected to dest port of + * originating datagram in dest ns + * @ts: Activity timestamp */ -struct udp_splice_port { - int ns_conn_sock; - int init_conn_sock; - - time_t ns_conn_ts; - time_t init_conn_ts; - - int ns_bound_sock; - int init_bound_sock; +struct udp_splice_flow { + int orig_sock; + int target_sock; + time_t ts; }; /* Port tracking, arrays indexed by packet source port (host order) */ static struct udp_tap_port udp_tap_map [IP_VERSIONS][NUM_PORTS]; -static struct udp_splice_port udp_splice_map [IP_VERSIONS][NUM_PORTS]; + +/* Spliced "connections" indexed by originating source port (host order) */ +static struct udp_splice_flow udp_splice_to_ns [IP_VERSIONS][NUM_PORTS]; +static struct udp_splice_flow udp_splice_to_init[IP_VERSIONS][NUM_PORTS]; enum udp_act_type { UDP_ACT_TAP, @@ -421,8 +419,17 @@ int udp_splice_connect(const struct ctx *c, int v6, int bound_sock, .r.p.udp.udp = { .splice = splice, .v6 = v6, .port = src } }; - struct udp_splice_port *sp = &udp_splice_map[v6 ? V6 : V4][src]; + struct udp_splice_flow *flow; int s; + int act; + + if (splice == UDP_BACK_TO_INIT) { + flow = &udp_splice_to_ns[v6 ? V6 : V4][src]; + act = UDP_ACT_NS_CONN; + } else { + flow = &udp_splice_to_init[v6 ? V6 : V4][src]; + act = UDP_ACT_INIT_CONN; + } s = socket(v6 ? AF_INET6 : AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); @@ -461,15 +468,9 @@ int udp_splice_connect(const struct ctx *c, int v6, int bound_sock, goto fail; } - if (splice == UDP_BACK_TO_INIT) { - sp->init_bound_sock = bound_sock; - sp->ns_conn_sock = s; - bitmap_set(udp_act[v6 ? V6 : V4][UDP_ACT_NS_CONN], src); - } else if (splice == UDP_BACK_TO_NS) { - sp->ns_bound_sock = bound_sock; - sp->init_conn_sock = s; - bitmap_set(udp_act[v6 ? V6 : V4][UDP_ACT_INIT_CONN], src); - } + flow->orig_sock = bound_sock; + flow->target_sock = s; + bitmap_set(udp_act[v6 ? V6 : V4][act], src); ev.data.u64 = ref.u64; epoll_ctl(c->epollfd, EPOLL_CTL_ADD, s, &ev); @@ -556,7 +557,7 @@ static void udp_sock_handler_splice(const struct ctx *c, union epoll_ref ref, case UDP_TO_NS: src += c->udp.fwd_out.rdelta[src]; - if (!(s = udp_splice_map[v6][src].ns_conn_sock)) { + if (!(s = udp_splice_to_ns[v6][src].target_sock)) { struct udp_splice_connect_ns_arg arg = { c, v6, ref.r.s, src, dst, -1, }; @@ -565,10 +566,10 @@ static void udp_sock_handler_splice(const struct ctx *c, union epoll_ref ref, if ((s = arg.s) < 0) return; } - udp_splice_map[v6][src].ns_conn_ts = now->tv_sec; + udp_splice_to_ns[v6][src].ts = now->tv_sec; break; case UDP_BACK_TO_INIT: - if (!(s = udp_splice_map[v6][dst].init_bound_sock)) + if (!(s = udp_splice_to_ns[v6][dst].orig_sock)) return; send_dst = dst; @@ -576,16 +577,16 @@ static void udp_sock_handler_splice(const struct ctx *c, union epoll_ref ref, case UDP_TO_INIT: src += c->udp.fwd_in.rdelta[src]; - if (!(s = udp_splice_map[v6][src].init_conn_sock)) { + if (!(s = udp_splice_to_init[v6][src].target_sock)) { s = udp_splice_connect(c, v6, ref.r.s, src, dst, UDP_BACK_TO_NS); if (s < 0) return; } - udp_splice_map[v6][src].init_conn_ts = now->tv_sec; + udp_splice_to_init[v6][src].ts = now->tv_sec; break; case UDP_BACK_TO_NS: - if (!(s = udp_splice_map[v6][dst].ns_bound_sock)) + if (!(s = udp_splice_to_init[v6][dst].orig_sock)) return; send_dst = dst; @@ -1286,7 +1287,7 @@ int udp_init(struct ctx *c) static void udp_timer_one(struct ctx *c, int v6, enum udp_act_type type, in_port_t port, const struct timespec *ts) { - struct udp_splice_port *sp; + struct udp_splice_flow *flow; struct udp_tap_port *tp; int s = -1; @@ -1301,17 +1302,17 @@ static void udp_timer_one(struct ctx *c, int v6, enum udp_act_type type, break; case UDP_ACT_INIT_CONN: - sp = &udp_splice_map[v6 ? V6 : V4][port]; + flow = &udp_splice_to_init[v6 ? V6 : V4][port]; - if (ts->tv_sec - sp->init_conn_ts > UDP_CONN_TIMEOUT) - s = sp->init_conn_sock; + if (ts->tv_sec - flow->ts > UDP_CONN_TIMEOUT) + s = flow->target_sock; break; case UDP_ACT_NS_CONN: - sp = &udp_splice_map[v6 ? V6 : V4][port]; + flow = &udp_splice_to_ns[v6 ? V6 : V4][port]; - if (ts->tv_sec - sp->ns_conn_ts > UDP_CONN_TIMEOUT) - s = sp->ns_conn_sock; + if (ts->tv_sec - flow->ts > UDP_CONN_TIMEOUT) + s = flow->target_sock; break; default: -- 2.38.1