From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from imap.gmail.com [173.194.76.109] by localhost with POP3 (fetchmail-6.3.26) for (single-drop); Tue, 21 May 2024 07:57:39 +0200 (CEST) Received: by 2002:a05:6a10:9148:b0:55f:c3c0:ed08 with SMTP id n8csp851875pxb; Mon, 20 May 2024 22:57:19 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCVZUefE8gW++ubWarKANI9FA+zvMa06Yurz8LxQRD37Wm3Uqw3aMq6/zXnTJufS4Pco+mm1DU1pupSD4QAb+2lXNnqg9qakGNc= X-Google-Smtp-Source: AGHT+IGTPST4TAsVaKVwoPH4qtxsmqlkxWBP2FB22qjIrlwXRXkwzovhOHMxVDTWDZGUe1wTVxx+ X-Received: by 2002:a05:620a:414a:b0:792:dc65:bd80 with SMTP id af79cd13be357-792dc65bf40mr3389789485a.1.1716271039435; Mon, 20 May 2024 22:57:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1716271039; cv=none; d=google.com; s=arc-20160816; b=SX+0jXHZwXoR95vRucp+ae6+jjAjp7QFbM28FW1pnlPa7dxAdGFFeIM7/kyuopCeI5 wukPZsf2MZNYyVE77IM+uU0887HwIUkKKUjP0sHic3R1HadCBpZfhnY5KOz26t1zf5Ov 3LOVVLpC3LTBfiZADPEdSbSM3SuGmJNE8tvh0JIymUl606rfaLJ1rUqeZUrqP+2/MXKO ZQZJ6hA24QU9Re1VXnwIa+x/nU04wzujRt6YdOXmvqlSY+O6dVFBdcwC8TCoqzDqp+8I QDtY3WlUfI4rAbNnzJthPNukWN7RKh59dEWhjo9MY9UPwUWQwo20COGuIHnwYPfC9Vxf JMOQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:delivered-to; bh=jKWul/IJ11vNpAcYsFSJzefqqles4tCIGabXI7WNjJQ=; fh=OvZxoe0l5OQEr5hiks2YsWDyoZfSCuw/Wl/AnSjLRjU=; b=buGtra/4eJk5bHgWXwUYFrXmx2bbA7dmpAaLkYll10qTTnoiq81r8fC85Z+2HVRmtN hhGGrno1grWCRXPBR2UwXCnnR+MsNb7VSGvNF+3iDrovIO4B7wZ3JS0+oN/eMsJN7sW5 tqy8ZI5z6x/JWQ5Wz9VM+YaWIuBkTaAfh323b2XYbgD8A5Xle/AIqvf74nzjNgCwdHow p4j+bgvlhjAioTHNPR5Y/UWw0eAXKZMiWreMRnUgtBeqPUqecxNcXQ+B/Deqi9vVmW8F M27Q6zdgzd1sQh4lb/OiO75GWQADqKdTiyaTl0s+4/Jw4vrBFwl+zEjXM2nSnga8DQyd g1fQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of dgibson@gandalf.ozlabs.org designates 150.107.74.76 as permitted sender) smtp.mailfrom=dgibson@gandalf.ozlabs.org Return-Path: Received: from us-smtp-inbound-delivery-1.mimecast.com (us-smtp-delivery-1.mimecast.com. [170.10.128.131]) by mx.google.com with ESMTPS id af79cd13be357-792bf29a84fsi612585a.209.2024.05.20.22.57.19 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 20 May 2024 22:57:19 -0700 (PDT) Received-SPF: pass (google.com: domain of dgibson@gandalf.ozlabs.org designates 150.107.74.76 as permitted sender) client-ip=150.107.74.76; Authentication-Results: mx.google.com; spf=pass (google.com: domain of dgibson@gandalf.ozlabs.org designates 150.107.74.76 as permitted sender) smtp.mailfrom=dgibson@gandalf.ozlabs.org Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-445-XhuZLcuPOVq_dvwmH2VH0Q-1; Tue, 21 May 2024 01:57:17 -0400 X-MC-Unique: XhuZLcuPOVq_dvwmH2VH0Q-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C8C691955E70 for ; Tue, 21 May 2024 05:57:16 +0000 (UTC) Received: by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) id B61063001D24; Tue, 21 May 2024 05:57:16 +0000 (UTC) Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.33]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A980A3001D1F for ; Tue, 21 May 2024 05:57:16 +0000 (UTC) Received: from us-smtp-inbound-delivery-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5184E1936188 for ; Tue, 21 May 2024 05:57:16 +0000 (UTC) Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-258-TfgnIGfnN_mG48GqxAJ0-Q-1; Tue, 21 May 2024 01:57:13 -0400 X-MC-Unique: TfgnIGfnN_mG48GqxAJ0-Q-1 Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4Vk3c56MWCz4x1C; Tue, 21 May 2024 15:57:09 +1000 (AEST) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Cc: David Gibson Subject: [PATCH 3/6] flow: Clarify and enforce flow state transitions Date: Tue, 21 May 2024 15:57:05 +1000 Message-ID: <20240521055708.1150050-4-david@gibson.dropbear.id.au> In-Reply-To: <20240521055708.1150050-1-david@gibson.dropbear.id.au> References: <20240521055708.1150050-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition;Similar Internal Domain=false;Similar Monitored External Domain=false;Custom External Domain=false;Mimecast External Domain=false;Newly Observed Domain=false;Internal User Name=false;Custom Display Name List=false;Reply-to Address Mismatch=false;Targeted Threat Dictionary=false;Mimecast Threat Dictionary=false;Custom Threat Dictionary=false X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: gibson.dropbear.id.au Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="US-ASCII"; x-default=true List-Id: Flows move over several different states in their lifetime. The rules for these are documented in comments, but they're pretty complex and a number of the transitions are implicit, which makes this pretty fragile and error prone. Change the code to explicitly track the states in a field. Make all transitions explicit and logged. To the extent that it's practical in C, enforce what can and can't be done in various states with ASSERT()s. While we're at it, tweak the docs to clarify the restrictions on each state a bit. Signed-off-by: David Gibson --- flow.c | 146 ++++++++++++++++++++++++++++++--------------------- flow.h | 81 ++++++++++++++++++++++++++-- flow_table.h | 9 ++++ icmp.c | 4 +- tcp.c | 8 ++- tcp_splice.c | 4 +- 6 files changed, 183 insertions(+), 69 deletions(-) diff --git a/flow.c b/flow.c index e257f890..da71fe10 100644 --- a/flow.c +++ b/flow.c @@ -18,6 +18,15 @@ #include "flow.h" #include "flow_table.h" =20 +const char *flow_state_str[] =3D { +=09[FLOW_STATE_FREE]=09=3D "FREE", +=09[FLOW_STATE_NEW]=09=3D "NEW", +=09[FLOW_STATE_TYPED]=09=3D "TYPED", +=09[FLOW_STATE_ACTIVE]=09=3D "ACTIVE", +}; +static_assert(ARRAY_SIZE(flow_state_str) =3D=3D FLOW_NUM_STATES, +=09 "flow_state_str[] doesn't match enum flow_state"); + const char *flow_type_str[] =3D { =09[FLOW_TYPE_NONE]=09=3D "", =09[FLOW_TCP]=09=09=3D "TCP connection", @@ -39,46 +48,6 @@ static_assert(ARRAY_SIZE(flow_proto) =3D=3D FLOW_NUM_TYP= ES, =20 /* Global Flow Table */ =20 -/** - * DOC: Theory of Operation - flow entry life cycle - * - * An individual flow table entry moves through these logical states, usua= lly in - * this order. - * - * FREE - Part of the general pool of free flow table entries - * Operations: - * - flow_alloc() finds an entry and moves it to ALLOC state - * - * ALLOC - A tentatively allocated entry - * Operations: - * - flow_alloc_cancel() returns the entry to FREE state - * - FLOW_START() set the entry's type and moves to START state - * Caveats: - * - It's not safe to write fields in the flow entry - * - It's not safe to allocate further entries with flow_alloc(= ) - * - It's not safe to return to the main epoll loop (use FLOW_S= TART() - * to move to START state before doing so) - * - It's not safe to use flow_*() logging functions - * - * START - An entry being prepared by flow type specific code - * Operations: - * - Flow type specific fields may be accessed - * - flow_*() logging functions - * - flow_alloc_cancel() returns the entry to FREE state - * Caveats: - * - Returning to the main epoll loop or allocating another ent= ry - * with flow_alloc() implicitly moves the entry to ACTIVE sta= te. - * - * ACTIVE - An active flow entry managed by flow type specific code - * Operations: - * - Flow type specific fields may be accessed - * - flow_*() logging functions - * - Flow may be expired by returning 'true' from flow type spe= cific - * deferred or timer handler. This will return it to FREE st= ate. - * Caveats: - * - It's not safe to call flow_alloc_cancel() - */ - /** * DOC: Theory of Operation - allocating and freeing flow entries * @@ -132,6 +101,7 @@ static_assert(ARRAY_SIZE(flow_proto) =3D=3D FLOW_NUM_TY= PES, =20 unsigned flow_first_free; union flow flowtab[FLOW_MAX]; +static const union flow *flow_new_entry; /* =3D NULL */ =20 /* Last time the flow timers ran */ static struct timespec flow_timer_run; @@ -144,6 +114,7 @@ static struct timespec flow_timer_run; */ void flow_log_(const struct flow_common *f, int pri, const char *fmt, ...) { +=09const char *type_or_state; =09char msg[BUFSIZ]; =09va_list args; =20 @@ -151,40 +122,65 @@ void flow_log_(const struct flow_common *f, int pri, = const char *fmt, ...) =09(void)vsnprintf(msg, sizeof(msg), fmt, args); =09va_end(args); =20 -=09logmsg(pri, "Flow %u (%s): %s", flow_idx(f), FLOW_TYPE(f), msg); +=09/* Show type if it's set, otherwise the state */ +=09if (f->state < FLOW_STATE_TYPED) +=09=09type_or_state =3D FLOW_STATE(f); +=09else +=09=09type_or_state =3D FLOW_TYPE(f); + +=09logmsg(pri, "Flow %u (%s): %s", flow_idx(f), type_or_state, msg); +} + +/** + * flow_set_state() - Change flow's state + * @f:=09=09Flow changing state + * @state:=09New state + */ +static void flow_set_state(struct flow_common *f, enum flow_state state) +{ +=09uint8_t oldstate =3D f->state; + +=09ASSERT(state < FLOW_NUM_STATES); +=09ASSERT(oldstate < FLOW_NUM_STATES); + +=09f->state =3D state; +=09flow_log_(f, LOG_DEBUG, "%s -> %s", flow_state_str[oldstate], +=09=09 FLOW_STATE(f)); } =20 /** - * flow_start() - Set flow type for new flow and log - * @flow:=09Flow to set type for + * flow_set_type() - Set type and move to TYPED + * @flow:=09Flow to change state * @type:=09Type for new flow * @iniside:=09Which side initiated the new flow * * Return: @flow - * - * Should be called before setting any flow type specific fields in the fl= ow - * table entry. */ -union flow *flow_start(union flow *flow, enum flow_type type, -=09=09 unsigned iniside) +union flow *flow_set_type(union flow *flow, enum flow_type type, +=09=09=09 unsigned iniside) { +=09struct flow_common *f =3D &flow->f; + +=09ASSERT(type !=3D FLOW_TYPE_NONE); +=09ASSERT(flow_new_entry =3D=3D flow && f->state =3D=3D FLOW_STATE_NEW); +=09ASSERT(f->type =3D=3D FLOW_TYPE_NONE); + =09(void)iniside; -=09flow->f.type =3D type; -=09flow_dbg(flow, "START %s", flow_type_str[flow->f.type]); +=09f->type =3D type; +=09flow_set_state(f, FLOW_STATE_TYPED); =09return flow; } =20 /** - * flow_end() - Clear flow type for finished flow and log - * @flow:=09Flow to clear + * flow_activate() - Move flow to ACTIVE + * @f:=09=09Flow to change state */ -static void flow_end(union flow *flow) +void flow_activate(struct flow_common *f) { -=09if (flow->f.type =3D=3D FLOW_TYPE_NONE) -=09=09return; /* Nothing to do */ +=09ASSERT(&flow_new_entry->f =3D=3D f && f->state =3D=3D FLOW_STATE_TYPED)= ; =20 -=09flow_dbg(flow, "END %s", flow_type_str[flow->f.type]); -=09flow->f.type =3D FLOW_TYPE_NONE; +=09flow_set_state(f, FLOW_STATE_ACTIVE); +=09flow_new_entry =3D NULL; } =20 /** @@ -196,9 +192,12 @@ union flow *flow_alloc(void) { =09union flow *flow =3D &flowtab[flow_first_free]; =20 +=09ASSERT(!flow_new_entry); + =09if (flow_first_free >=3D FLOW_MAX) =09=09return NULL; =20 +=09ASSERT(flow->f.state =3D=3D FLOW_STATE_FREE); =09ASSERT(flow->f.type =3D=3D FLOW_TYPE_NONE); =09ASSERT(flow->free.n >=3D 1); =09ASSERT(flow_first_free + flow->free.n <=3D FLOW_MAX); @@ -221,7 +220,10 @@ union flow *flow_alloc(void) =09=09flow_first_free =3D flow->free.next; =09} =20 +=09flow_new_entry =3D flow; =09memset(flow, 0, sizeof(*flow)); +=09flow_set_state(&flow->f, FLOW_STATE_NEW); + =09return flow; } =20 @@ -233,15 +235,21 @@ union flow *flow_alloc(void) */ void flow_alloc_cancel(union flow *flow) { +=09ASSERT(flow_new_entry =3D=3D flow); +=09ASSERT(flow->f.state =3D=3D FLOW_STATE_NEW || +=09 flow->f.state =3D=3D FLOW_STATE_TYPED); =09ASSERT(flow_first_free > FLOW_IDX(flow)); =20 -=09flow_end(flow); +=09flow_set_state(&flow->f, FLOW_STATE_FREE); +=09memset(flow, 0, sizeof(*flow)); + =09/* Put it back in a length 1 free cluster, don't attempt to fully =09 * reverse flow_alloc()s steps. This will get folded together the next =09 * time flow_defer_handler runs anyway() */ =09flow->free.n =3D 1; =09flow->free.next =3D flow_first_free; =09flow_first_free =3D FLOW_IDX(flow); +=09flow_new_entry =3D NULL; } =20 /** @@ -261,11 +269,14 @@ void flow_defer_handler(const struct ctx *c, const st= ruct timespec *now) =09=09flow_timer_run =3D *now; =09} =20 +=09ASSERT(!flow_new_entry); /* Incomplete flow at end of cycle */ + =09for (idx =3D 0; idx < FLOW_MAX; idx++) { =09=09union flow *flow =3D &flowtab[idx]; =09=09bool closed =3D false; =20 -=09=09if (flow->f.type =3D=3D FLOW_TYPE_NONE) { +=09=09switch (flow->f.state) { +=09=09case FLOW_STATE_FREE: { =09=09=09unsigned skip =3D flow->free.n; =20 =09=09=09/* First entry of a free cluster must have n >=3D 1 */ @@ -287,6 +298,20 @@ void flow_defer_handler(const struct ctx *c, const str= uct timespec *now) =09=09=09continue; =09=09} =20 +=09=09case FLOW_STATE_NEW: +=09=09case FLOW_STATE_TYPED: +=09=09=09/* Incomplete flow at end of cycle */ +=09=09=09ASSERT(false); +=09=09=09break; + +=09=09case FLOW_STATE_ACTIVE: +=09=09=09/* Nothing to do */ +=09=09=09break; + +=09=09default: +=09=09=09ASSERT(false); +=09=09} + =09=09switch (flow->f.type) { =09=09case FLOW_TYPE_NONE: =09=09=09ASSERT(false); @@ -310,7 +335,8 @@ void flow_defer_handler(const struct ctx *c, const stru= ct timespec *now) =09=09} =20 =09=09if (closed) { -=09=09=09flow_end(flow); +=09=09=09flow_set_state(&flow->f, FLOW_STATE_FREE); +=09=09=09memset(flow, 0, sizeof(*flow)); =20 =09=09=09if (free_head) { =09=09=09=09/* Add slot to current free cluster */ diff --git a/flow.h b/flow.h index c943c441..e61d35e8 100644 --- a/flow.h +++ b/flow.h @@ -9,6 +9,68 @@ =20 #define FLOW_TIMER_INTERVAL=09=091000=09/* ms */ =20 +/** + * enum flow_state - States of a flow table entry + * + * An individual flow table entry moves through these states, usually in t= his + * order. + * General rules: + * - Code outside flow.c should never write common fields of union flow= . + * - The state field may always be read. + * + * FREE - Part of the general pool of free flow table entries + * Operations: + * - flow_alloc() finds an entry and moves it to NEW + * + * NEW - Freshly allocated, uninitialised entry + * Operations: + * - flow_alloc_cancel() returns the entry to FREE + * - FLOW_SET_TYPE() sets the entry's type and moves to TYPED + * Caveats: + * - No fields other than state may be accessed + * - At most one entry may be NEW or TYPED at a time, so it's u= nsafe + * to use flow_alloc() again until this entry moves to ACTIVE= or + * FREE + * - You may not return to the main epoll loop while any flow i= s NEW + * + * TYPED - Generic info initialised, type specific initialisation under= way + * Operations: + * - All common fields may be read + * - Type specific fields may be read and written + * - flow_alloc_cancel() returns the entry to FREE + * - FLOW_ACTIVATE() moves the entry to ACTIVE + * Caveats: + * - At most one entry may be NEW or TYPED at a time, so it's u= nsafe + * to use flow_alloc() again until this entry moves to ACTIVE= or + * FREE + * - You may not return to the main epoll loop while any flow i= s + * TYPED + * + * ACTIVE - An active, fully-initialised flow entry + * Operations: + * - All common fields may be read + * - Type specific fields may be read and written + * - Flow returns to FREE when it expires, signalled by returni= ng + * 'true' from flow type specific deferred or timer handler + * Caveats: + * - flow_alloc_cancel() may not be called on it + */ +enum flow_state { +=09FLOW_STATE_FREE, +=09FLOW_STATE_NEW, +=09FLOW_STATE_TYPED, +=09FLOW_STATE_ACTIVE, + +=09FLOW_NUM_STATES, +}; +#define FLOW_STATE_BITS=09=098 +static_assert(FLOW_NUM_STATES <=3D (1 << FLOW_STATE_BITS), +=09 "Too many flow states for FLOW_STATE_BITS"); + +extern const char *flow_state_str[]; +#define FLOW_STATE(f)=09=09=09=09=09=09=09\ + ((f)->state < FLOW_NUM_STATES ? flow_state_str[(f)->state] : "?") + /** * enum flow_type - Different types of packet flows we track */ @@ -26,6 +88,9 @@ enum flow_type { =20 =09FLOW_NUM_TYPES, }; +#define FLOW_TYPE_BITS=09=098 +static_assert(FLOW_NUM_TYPES <=3D (1 << FLOW_TYPE_BITS), +=09 "Too many flow types for FLOW_TYPE_BITS"); =20 extern const char *flow_type_str[]; #define FLOW_TYPE(f)=09=09=09=09=09=09=09\ @@ -37,10 +102,21 @@ extern const uint8_t flow_proto[]; =20 /** * struct flow_common - Common fields for packet flows + * @state:=09State of the flow table entry * @type:=09Type of packet flow */ struct flow_common { +#ifdef __GNUC__ +=09enum flow_state=09state:FLOW_STATE_BITS; +=09enum flow_type=09type:FLOW_TYPE_BITS; +#else +=09uint8_t=09=09state; +=09static_assert(sizeof(uint8_t) * 8 >=3D FLOW_STATE_BITS, +=09=09 "Not enough bits for state field"); =09uint8_t=09=09type; +=09static_assert(sizeof(uint8_t) * 8 >=3D FLOW_TYPE_BITS, +=09=09 "Not enough bits for type field"); +#endif }; =20 #define FLOW_INDEX_BITS=09=0917=09/* 128k - 1 */ @@ -49,11 +125,6 @@ struct flow_common { #define FLOW_TABLE_PRESSURE=09=0930=09/* % of FLOW_MAX */ #define FLOW_FILE_PRESSURE=09=0930=09/* % of c->nofile */ =20 -union flow *flow_start(union flow *flow, enum flow_type type, -=09=09 unsigned iniside); -#define FLOW_START(flow_, t_, var_, i_)=09=09\ -=09(&flow_start((flow_), (t_), (i_))->var_) - /** * struct flow_sidx - ID for one side of a specific flow * @side:=09Side referenced (0 or 1) diff --git a/flow_table.h b/flow_table.h index b7e5529a..17b9ea70 100644 --- a/flow_table.h +++ b/flow_table.h @@ -107,4 +107,13 @@ static inline flow_sidx_t flow_sidx(const struct flow_= common *f, union flow *flow_alloc(void); void flow_alloc_cancel(union flow *flow); =20 +union flow *flow_set_type(union flow *flow, enum flow_type type, +=09=09=09 unsigned iniside); +#define FLOW_SET_TYPE(flow_, t_, var_, i_)=09\ +=09(&flow_set_type((flow_), (t_), (i_))->var_) + +void flow_activate(struct flow_common *f); +#define FLOW_ACTIVATE(flow_)=09=09=09\ +=09(flow_activate(&(flow_)->f)) + #endif /* FLOW_TABLE_H */ diff --git a/icmp.c b/icmp.c index eb559c18..fc729557 100644 --- a/icmp.c +++ b/icmp.c @@ -167,7 +167,7 @@ static struct icmp_ping_flow *icmp_ping_new(const struc= t ctx *c, =09if (!flow) =09=09return NULL; =20 -=09pingf =3D FLOW_START(flow, flowtype, ping, TAPSIDE); +=09pingf =3D FLOW_SET_TYPE(flow, flowtype, ping, TAPSIDE); =20 =09pingf->seq =3D -1; =09pingf->id =3D id; @@ -198,6 +198,8 @@ static struct icmp_ping_flow *icmp_ping_new(const struc= t ctx *c, =20 =09*id_sock =3D pingf; =20 +=09FLOW_ACTIVATE(pingf); + =09return pingf; =20 cancel: diff --git a/tcp.c b/tcp.c index 4512af0b..64fe46e0 100644 --- a/tcp.c +++ b/tcp.c @@ -2004,7 +2004,7 @@ static void tcp_conn_from_tap(struct ctx *c, sa_famil= y_t af, =09=09=09goto cancel; =09} =20 -=09conn =3D FLOW_START(flow, FLOW_TCP, tcp, TAPSIDE); +=09conn =3D FLOW_SET_TYPE(flow, FLOW_TCP, tcp, TAPSIDE); =09conn->sock =3D s; =09conn->timer =3D -1; =09conn_event(c, conn, TAP_SYN_RCVD); @@ -2075,6 +2075,7 @@ static void tcp_conn_from_tap(struct ctx *c, sa_famil= y_t af, =09} =20 =09tcp_epoll_ctl(c, conn); +=09FLOW_ACTIVATE(conn); =09return; =20 cancel: @@ -2715,7 +2716,8 @@ static void tcp_tap_conn_from_sock(struct ctx *c, in_= port_t dstport, =09=09=09=09 const union sockaddr_inany *sa, =09=09=09=09 const struct timespec *now) { -=09struct tcp_tap_conn *conn =3D FLOW_START(flow, FLOW_TCP, tcp, SOCKSIDE)= ; +=09struct tcp_tap_conn *conn =3D FLOW_SET_TYPE(flow, FLOW_TCP, tcp, +=09=09=09=09=09=09 SOCKSIDE); =20 =09conn->sock =3D s; =09conn->timer =3D -1; @@ -2738,6 +2740,8 @@ static void tcp_tap_conn_from_sock(struct ctx *c, in_= port_t dstport, =09conn_flag(c, conn, ACK_FROM_TAP_DUE); =20 =09tcp_get_sndbuf(conn); + +=09FLOW_ACTIVATE(conn); } =20 /** diff --git a/tcp_splice.c b/tcp_splice.c index fb00bc22..852a93b4 100644 --- a/tcp_splice.c +++ b/tcp_splice.c @@ -471,7 +471,7 @@ bool tcp_splice_conn_from_sock(const struct ctx *c, =09=09return false; =09} =20 -=09conn =3D FLOW_START(flow, FLOW_TCP_SPLICE, tcp_splice, 0); +=09conn =3D FLOW_SET_TYPE(flow, FLOW_TCP_SPLICE, tcp_splice, 0); =20 =09conn->flags =3D af =3D=3D AF_INET ? 0 : SPLICE_V6; =09conn->s[0] =3D s0; @@ -485,6 +485,8 @@ bool tcp_splice_conn_from_sock(const struct ctx *c, =09if (tcp_splice_connect(c, conn, af, pif1, dstport)) =09=09conn_flag(c, conn, CLOSING); =20 +=09FLOW_ACTIVATE(conn); + =09return true; } =20 --=20 2.45.1