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 ECDF15A026D for ; Thu, 21 Dec 2023 07:16:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202312; t=1703139352; bh=kWI94+T1VF5JNtNQGdNOneQ/NZAuwnNmyAGmNSPqjv0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y88lDkbIhKyhy8GtjdYZDy0FxOzC+6RkG7c3ZPhj/R0vr2Ikwp9qGrN28SHF+0GsE MBCnFYflNxyuTUHsX7V3p+8/w3Zy3SThZnniQSdToDdM6WggQPwZMGsRdnScWcO5rt 0oAotG0FmFJ4uVeMP3N8c5d4UdPIXL4hVcuuwSQZMPvw7Sen4ezz6qEljjBcrkulck vWBdoKP1REZaq98l/DBImlcPp/dr82vsyCPH7R3rHHbnsfzWU2pbCfuTGFVqJYMz5z HlhXsg1BcpY86X5sQ5YoF6k4GcedcNm6cCh54N49BLkc9gq9t2Oa3g01tRx8CnmDUg QkbepcMRaWzNA== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4SwgCr4fTmz4xS0; Thu, 21 Dec 2023 17:15:52 +1100 (AEDT) From: David Gibson To: passt-dev@passt.top, Stefano Brivio Subject: [PATCH v3 11/13] flow: Abstract allocation of new flows with helper function Date: Thu, 21 Dec 2023 17:15:47 +1100 Message-ID: <20231221061549.976358-12-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231221061549.976358-1-david@gibson.dropbear.id.au> References: <20231221061549.976358-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: 7Y57EJHV363LF7G64RLG53FKW3HSYZQE X-Message-ID-Hash: 7Y57EJHV363LF7G64RLG53FKW3HSYZQE 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.8 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: Currently tcp.c open codes the process of allocating a new flow from the flow table: twice, in fact, once for guest to host and once for host to guest connections. This duplication isn't ideal and will get worse as we add more protocols to the flow table. It also makes it harder to experiment with different ways of handling flow table allocation. Instead, introduce a function to allocate a new flow: flow_alloc(). In some cases we currently check if we're able to allocate, but delay the actual allocation. We now handle that slightly differently with a flow_alloc_cancel() function to back out a recent allocation. We have that separate from a flow_free() function, because future changes we have in mind will need to handle this case a little differently. Signed-off-by: David Gibson --- flow.c | 26 ++++++++++++++++++++++++++ flow_table.h | 3 +++ tcp.c | 29 ++++++++++++++++++----------- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/flow.c b/flow.c index 294412a..8fbe512 100644 --- a/flow.c +++ b/flow.c @@ -49,6 +49,32 @@ void flow_log_(const struct flow_common *f, int pri, const char *fmt, ...) logmsg(pri, "Flow %u (%s): %s", flow_idx(f), FLOW_TYPE(f), msg); } +/** + * flow_alloc() - Allocate a new flow + * + * Return: pointer to an unused flow entry, or NULL if the table is full + */ +union flow *flow_alloc(void) +{ + if (flow_count >= FLOW_MAX) + return NULL; + + return &flowtab[flow_count++]; +} + +/** + * flow_alloc_cancel() - Free a newly allocated flow + * @flow: Flow to deallocate + * + * @flow must be the last flow allocated by flow_alloc() + */ +void flow_alloc_cancel(union flow *flow) +{ + ASSERT(FLOW_IDX(flow) == flow_count - 1); + memset(flow, 0, sizeof(*flow)); + flow_count--; +} + /** * flow_table_compact() - Perform compaction on flow table * @c: Execution context diff --git a/flow_table.h b/flow_table.h index 4aa2398..2773a2b 100644 --- a/flow_table.h +++ b/flow_table.h @@ -88,4 +88,7 @@ static inline flow_sidx_t flow_sidx(const struct flow_common *f, */ #define FLOW_SIDX(f_, side) (flow_sidx(&(f_)->f, (side))) +union flow *flow_alloc(void); +void flow_alloc_cancel(union flow *flow); + #endif /* FLOW_TABLE_H */ diff --git a/tcp.c b/tcp.c index 6aefd0b..6477203 100644 --- a/tcp.c +++ b/tcp.c @@ -1943,17 +1943,18 @@ static void tcp_conn_from_tap(struct ctx *c, }; const struct sockaddr *sa; struct tcp_tap_conn *conn; + union flow *flow; socklen_t sl; int s, mss; (void)saddr; - if (flow_count >= FLOW_MAX) + if (!(flow = flow_alloc())) return; if ((s = tcp_conn_pool_sock(pool)) < 0) if ((s = tcp_conn_new_sock(c, af)) < 0) - return; + goto cancel; if (!c->no_map_gw) { if (af == AF_INET && IN4_ARE_ADDR_EQUAL(daddr, &c->ip4.gw)) @@ -1968,13 +1969,11 @@ static void tcp_conn_from_tap(struct ctx *c, .sin6_addr = c->ip6.addr_ll, .sin6_scope_id = c->ifi6, }; - if (bind(s, (struct sockaddr *)&addr6_ll, sizeof(addr6_ll))) { - close(s); - return; - } + if (bind(s, (struct sockaddr *)&addr6_ll, sizeof(addr6_ll))) + goto cancel; } - conn = CONN(flow_count++); + conn = &flow->tcp; conn->f.type = FLOW_TCP; conn->sock = s; conn->timer = -1; @@ -2046,6 +2045,12 @@ static void tcp_conn_from_tap(struct ctx *c, } tcp_epoll_ctl(c, conn); + return; + +cancel: + if (s >= 0) + close(s); + flow_alloc_cancel(flow); } /** @@ -2723,14 +2728,12 @@ void tcp_listen_handler(struct ctx *c, union epoll_ref ref, union flow *flow; int s; - if (c->no_tcp || flow_count >= FLOW_MAX) + if (c->no_tcp || !(flow = flow_alloc())) return; s = accept4(ref.fd, (struct sockaddr *)&sa, &sl, SOCK_NONBLOCK); if (s < 0) - return; - - flow = flowtab + flow_count++; + goto cancel; if (c->mode == MODE_PASTA && tcp_splice_conn_from_sock(c, ref.tcp_listen, &flow->tcp_splice, @@ -2739,6 +2742,10 @@ void tcp_listen_handler(struct ctx *c, union epoll_ref ref, tcp_tap_conn_from_sock(c, ref.tcp_listen, &flow->tcp, s, (struct sockaddr *)&sa, now); + return; + +cancel: + flow_alloc_cancel(flow); } /** -- 2.43.0