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:40 +0200 (CEST) Received: by 2002:a05:6a10:9148:b0:55f:c3c0:ed08 with SMTP id n8csp851894pxb; Mon, 20 May 2024 22:57:23 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCXzRO1ccpRjOPonVnxAtZZyz0HV7+CsMwze09NccNv4T3djICeQCsByNJWJ40iBLxezxU/1AFt7EU6Es0JN2kC6ySEOgWiVyxw= X-Google-Smtp-Source: AGHT+IFXb2nU4SGNxpwYdX0EwKoz0Ed3UQq9fRH/hCl2s9632uWjaTo86Gk9/x7R6dTzbOMrJV7x X-Received: by 2002:a25:97c2:0:b0:df4:b627:1ba5 with SMTP id 3f1490d57ef6-df4b6271eecmr3174186276.12.1716271043387; Mon, 20 May 2024 22:57:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1716271043; cv=none; d=google.com; s=arc-20160816; b=pcGk/3uACPTZ2hul77blqz56qeUAJ+nF+8SU/HGd1Lgpdu07XoU6FfhsG+0Cep0+cC oBVTApfUpxPm4qS31zjN/RVNiyunc8kdatmxvc5sTJ/+a3UPRed5kdU1V8UIjV2md1vS yRWhWB2BKzwJ7zqcwsnDpozWFR8oikbeW6fjkN4l8UVgfXZjOACsutKhejOM/8TZLN3b P4lVQiwAFWoZdGju0HbV6ewHB31psuJJAlGXDjnxcq4OXwaeIt9EMpRlmbpVUMtEowCX bpSsmw0/51i4Rj0+OtCx6oBtLNeMlJGIntB6G9kPoku/u/Bm0Alcs/b3+Dx93r866o7u u2Qg== 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=pZQby1hpsr9phvB96NpsBSzQrPuMEpNLnKALa4pZcgM=; fh=OvZxoe0l5OQEr5hiks2YsWDyoZfSCuw/Wl/AnSjLRjU=; b=TEMLnIU4zUWnNV/x8gjxK/3pWKLqx/t9L+BAOvk75Bet63ucVgljIvJVCbWbdgku2f vtPO/+yrJwmSAhGmSxaTNPzqHwkkQ2WJTDpib0LnYq8fF/F0uBpqq0bC/p/x/3O6+T3T gqMIvjBIzCBsL2dV0DGJ/He4T6TS9fFj8fbf9Fo++T/rpgq0OKweq2PctOwR/5TVegy4 L6LeoxNr7MfvgN1e7LtepqfLgVpBYk2edENI7EbDRjk0G6OvJ/8HYHURKdTttNMK5By1 cyEB+5cjWCRa8OlMKq6JeUqheZjdtBFTzlEDB1zLpPz6auFBS4ptzREZlQC8Qo++SqT/ 15gg==; 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. [205.139.110.120]) by mx.google.com with ESMTPS id d75a77b69052e-43df56b2bbesi3460211cf.593.2024.05.20.22.57.23 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 20 May 2024 22:57:23 -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-02.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-130-6q068zWCOay9G-PiVb80kA-1; Tue, 21 May 2024 01:57:21 -0400 X-MC-Unique: 6q068zWCOay9G-PiVb80kA-1 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (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-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6A94D19560A1 for ; Tue, 21 May 2024 05:57:20 +0000 (UTC) Received: by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) id 57A1E1955D7D; Tue, 21 May 2024 05:57:20 +0000 (UTC) Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.46]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 552231955D7C for ; Tue, 21 May 2024 05:57:20 +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-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id EE7F719560A2 for ; Tue, 21 May 2024 05:57:19 +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-642-bf7bQ4zeMVG5yaRTlxzqkg-1; Tue, 21 May 2024 01:57:17 -0400 X-MC-Unique: bf7bQ4zeMVG5yaRTlxzqkg-1 Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4Vk3c56fwWz4x1d; Tue, 21 May 2024 15:57:09 +1000 (AEST) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Cc: David Gibson Subject: [PATCH 5/6] flow: Record the pifs for each side of each flow Date: Tue, 21 May 2024 15:57:07 +1000 Message-ID: <20240521055708.1150050-6-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.0 on 10.30.177.40 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: Currently we have no generic information flows apart from the type and state, everything else is specific to the flow type. Start introducing generic flow information by recording the pifs which the flow connects. To keep track of what information is valid, introduce new flow states: INI for when the initiating side information is complete, and TGT for when both sides information is complete, but we haven't chosen the flow type yet. For now, these states don't do an awful lot, but they'll become more important as we add more generic information. Signed-off-by: David Gibson --- flow.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++---- flow.h | 44 +++++++++++++++++++++++++++++++++++------ flow_table.h | 3 +++ icmp.c | 2 ++ pif.h | 1 - tcp.c | 10 +++++++++- tcp_splice.c | 9 +++++---- 7 files changed, 109 insertions(+), 16 deletions(-) diff --git a/flow.c b/flow.c index 91c00465..d05aa495 100644 --- a/flow.c +++ b/flow.c @@ -21,6 +21,8 @@ const char *flow_state_str[] =3D { =09[FLOW_STATE_FREE]=09=3D "FREE", =09[FLOW_STATE_NEW]=09=3D "NEW", +=09[FLOW_STATE_INI]=09=3D "INI", +=09[FLOW_STATE_TGT]=09=3D "TGT", =09[FLOW_STATE_TYPED]=09=3D "TYPED", =09[FLOW_STATE_ACTIVE]=09=3D "ACTIVE", }; @@ -146,22 +148,63 @@ static void flow_set_state(struct flow_common *f, enu= m flow_state state) =09f->state =3D state; =09flow_log_(f, LOG_DEBUG, "%s -> %s", flow_state_str[oldstate], =09=09 FLOW_STATE(f)); + +=09if (MAX(state, oldstate) >=3D FLOW_STATE_TGT) +=09=09flow_log_(f, LOG_DEBUG, "%s =3D> %s", pif_name(f->pif[INISIDE]), +=09=09=09 pif_name(f->pif[TGTSIDE])); +=09else if (MAX(state, oldstate) >=3D FLOW_STATE_INI) +=09=09flow_log_(f, LOG_DEBUG, "%s =3D> ?", pif_name(f->pif[INISIDE])); +} + +/** + * flow_initiate() - Move flow to INI, setting INISIDE details + * @flow:=09Flow to change state + * @pif:=09pif of the initiating side + */ +void flow_initiate(union flow *flow, uint8_t pif) +{ +=09struct flow_common *f =3D &flow->f; + +=09ASSERT(pif !=3D PIF_NONE); +=09ASSERT(flow_new_entry =3D=3D flow && f->state =3D=3D FLOW_STATE_NEW); +=09ASSERT(f->type =3D=3D FLOW_TYPE_NONE); +=09ASSERT(f->pif[INISIDE] =3D=3D PIF_NONE && f->pif[TGTSIDE] =3D=3D PIF_NO= NE); + +=09f->pif[INISIDE] =3D pif; +=09flow_set_state(f, FLOW_STATE_INI); +} + +/** + * flow_target() - Move flow to TGT, setting TGTSIDE details + * @flow:=09Flow to change state + * @pif:=09pif of the target side + */ +void flow_target(union flow *flow, uint8_t pif) +{ +=09struct flow_common *f =3D &flow->f; + +=09ASSERT(pif !=3D PIF_NONE); +=09ASSERT(flow_new_entry =3D=3D flow && f->state =3D=3D FLOW_STATE_INI); +=09ASSERT(f->type =3D=3D FLOW_TYPE_NONE); +=09ASSERT(f->pif[INISIDE] !=3D PIF_NONE && f->pif[TGTSIDE] =3D=3D PIF_NONE= ); + +=09f->pif[TGTSIDE] =3D pif; +=09flow_set_state(f, FLOW_STATE_TGT); } =20 /** * flow_set_type() - Set type and move to TYPED * @flow:=09Flow to change state - * @type:=09Type for new flow - * - * Return: @flow + * @pif:=09pif of the initiating side */ union flow *flow_set_type(union flow *flow, enum flow_type type) { =09struct flow_common *f =3D &flow->f; =20 =09ASSERT(type !=3D FLOW_TYPE_NONE); -=09ASSERT(flow_new_entry =3D=3D flow && f->state =3D=3D FLOW_STATE_NEW); +=09ASSERT(flow_new_entry =3D=3D flow && f->state =3D=3D FLOW_STATE_TGT); =09ASSERT(f->type =3D=3D FLOW_TYPE_NONE); +=09ASSERT(f->pif[INISIDE] !=3D PIF_NONE && f->pif[TGTSIDE] !=3D PIF_NONE); =20 =09f->type =3D type; =09flow_set_state(f, FLOW_STATE_TYPED); @@ -175,6 +218,7 @@ union flow *flow_set_type(union flow *flow, enum flow_t= ype type) void flow_activate(struct flow_common *f) { =09ASSERT(&flow_new_entry->f =3D=3D f && f->state =3D=3D FLOW_STATE_TYPED)= ; +=09ASSERT(f->pif[INISIDE] !=3D PIF_NONE && f->pif[TGTSIDE] !=3D PIF_NONE); =20 =09flow_set_state(f, FLOW_STATE_ACTIVE); =09flow_new_entry =3D NULL; @@ -234,6 +278,8 @@ 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_INI || +=09 flow->f.state =3D=3D FLOW_STATE_TGT || =09 flow->f.state =3D=3D FLOW_STATE_TYPED); =09ASSERT(flow_first_free > FLOW_IDX(flow)); =20 @@ -296,6 +342,8 @@ void flow_defer_handler(const struct ctx *c, const stru= ct timespec *now) =09=09} =20 =09=09case FLOW_STATE_NEW: +=09=09case FLOW_STATE_INI: +=09=09case FLOW_STATE_TGT: =09=09case FLOW_STATE_TYPED: =09=09=09/* Incomplete flow at end of cycle */ =09=09=09ASSERT(false); diff --git a/flow.h b/flow.h index 95309389..29ef9f12 100644 --- a/flow.h +++ b/flow.h @@ -25,14 +25,42 @@ * NEW - Freshly allocated, uninitialised entry * Operations: * - flow_alloc_cancel() returns the entry to FREE + * - flow_initiate() sets the entry's INISIDE details and moves= to + * INI * - 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 + * - At most one entry may be NEW, INI, TGT or TYPED at a time,= so + * it's unsafe to use flow_alloc() again until this entry mov= es to + * ACTIVE or FREE * - You may not return to the main epoll loop while any flow i= s NEW * + * INI - An entry with INISIDE common information completed + * Operations: + * - Common fields related to INISIDE may be read + * - flow_alloc_cancel() returns the entry to FREE + * - flow_target() sets the entry's TGTSIDE details and moves t= o TGT + * Caveats: + * - Other common fields may not be read + * - Type specific fields may not be read or written + * - At most one entry may be NEW, INI, TGT or TYPED at a time,= so + * it's unsafe to use flow_alloc() again until this entry mov= es to + * ACTIVE or FREE + * - You may not return to the main epoll loop while any flow i= s INI + * + * TGT - An entry with only INISIDE and TGTSIDE common information comp= leted + * Operations: + * - Common fields related to INISIDE & TGTSIDE may be read + * - flow_alloc_cancel() returns the entry to FREE + * - FLOW_SET_TYPE() sets the entry's type and moves to TYPED + * Caveats: + * - Other common fields may not be read + * - Type specific fields may not be read or written + * - At most one entry may be NEW, INI, TGT or TYPED at a time,= so + * it's unsafe to use flow_alloc() again until this entry mov= es to + * ACTIVE or FREE + * - You may not return to the main epoll loop while any flow i= s TGT + * * TYPED - Generic info initialised, type specific initialisation under= way * Operations: * - All common fields may be read @@ -40,9 +68,9 @@ * - 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 + * - At most one entry may be NEW, INI, TGT or TYPED at a time,= so + * it's unsafe to use flow_alloc() again until this entry mov= es to + * ACTIVE or FREE * - You may not return to the main epoll loop while any flow i= s * TYPED * @@ -58,6 +86,8 @@ enum flow_state { =09FLOW_STATE_FREE, =09FLOW_STATE_NEW, +=09FLOW_STATE_INI, +=09FLOW_STATE_TGT, =09FLOW_STATE_TYPED, =09FLOW_STATE_ACTIVE, =20 @@ -109,6 +139,7 @@ extern const uint8_t flow_proto[]; * struct flow_common - Common fields for packet flows * @state:=09State of the flow table entry * @type:=09Type of packet flow + * @pif[]:=09Interface for each side of the flow */ struct flow_common { #ifdef __GNUC__ @@ -122,6 +153,7 @@ struct flow_common { =09static_assert(sizeof(uint8_t) * 8 >=3D FLOW_TYPE_BITS, =09=09 "Not enough bits for type field"); #endif +=09uint8_t=09=09pif[SIDES]; }; =20 #define FLOW_INDEX_BITS=09=0917=09/* 128k - 1 */ diff --git a/flow_table.h b/flow_table.h index 28e36b9a..1b163491 100644 --- a/flow_table.h +++ b/flow_table.h @@ -107,6 +107,9 @@ static inline flow_sidx_t flow_sidx(const struct flow_c= ommon *f, union flow *flow_alloc(void); void flow_alloc_cancel(union flow *flow); =20 +void flow_initiate(union flow *flow, uint8_t pif); +void flow_target(union flow *flow, uint8_t pif); + union flow *flow_set_type(union flow *flow, enum flow_type type); #define FLOW_SET_TYPE(flow_, t_, var_)=09(&flow_set_type((flow_), (t_))->v= ar_) =20 diff --git a/icmp.c b/icmp.c index 3567ad7e..80330f6f 100644 --- a/icmp.c +++ b/icmp.c @@ -163,6 +163,8 @@ static struct icmp_ping_flow *icmp_ping_new(const struc= t ctx *c, =09if (!flow) =09=09return NULL; =20 +=09flow_initiate(flow, PIF_TAP); +=09flow_target(flow, PIF_HOST); =09pingf =3D FLOW_SET_TYPE(flow, flowtype, ping); =20 =09pingf->seq =3D -1; diff --git a/pif.h b/pif.h index bd529364..ca85b349 100644 --- a/pif.h +++ b/pif.h @@ -38,7 +38,6 @@ static inline const char *pif_type(enum pif_type pt) =09=09return "?"; } =20 -/* cppcheck-suppress unusedFunction */ static inline const char *pif_name(uint8_t pif) { =09return pif_type(pif); diff --git a/tcp.c b/tcp.c index 0313dcb9..dad425cb 100644 --- a/tcp.c +++ b/tcp.c @@ -1948,6 +1948,8 @@ static void tcp_conn_from_tap(struct ctx *c, sa_famil= y_t af, =09if (!(flow =3D flow_alloc())) =09=09return; =20 +=09flow_initiate(flow, PIF_TAP); + =09if (af =3D=3D AF_INET) { =09=09if (IN4_IS_ADDR_UNSPECIFIED(saddr) || =09=09 IN4_IS_ADDR_BROADCAST(saddr) || @@ -2000,6 +2002,7 @@ static void tcp_conn_from_tap(struct ctx *c, sa_famil= y_t af, =09=09=09goto cancel; =09} =20 +=09flow_target(flow, PIF_HOST); =09conn =3D FLOW_SET_TYPE(flow, FLOW_TCP, tcp); =09conn->tapside =3D INISIDE; =09conn->sock =3D s; @@ -2713,7 +2716,10 @@ 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_SET_TYPE(flow, FLOW_TCP, tcp); +=09struct tcp_tap_conn *conn; + +=09flow_target(flow, PIF_TAP); +=09conn =3D FLOW_SET_TYPE(flow, FLOW_TCP, tcp); =20 =09conn->tapside =3D TGTSIDE; =09conn->sock =3D s; @@ -2762,6 +2768,8 @@ void tcp_listen_handler(struct ctx *c, union epoll_re= f ref, =09if (s < 0) =09=09goto cancel; =20 +=09flow_initiate(flow, ref.tcp_listen.pif); + =09if (sa.sa_family =3D=3D AF_INET) { =09=09const struct in_addr *addr =3D &sa.sa4.sin_addr; =09=09in_port_t port =3D sa.sa4.sin_port; diff --git a/tcp_splice.c b/tcp_splice.c index 31e21732..b8f64a95 100644 --- a/tcp_splice.c +++ b/tcp_splice.c @@ -431,7 +431,7 @@ bool tcp_splice_conn_from_sock(const struct ctx *c, =09union inany_addr src; =09in_port_t srcport; =09sa_family_t af; -=09uint8_t pif1; +=09uint8_t tgtpif; =20 =09if (c->mode !=3D MODE_PASTA) =09=09return false; @@ -455,7 +455,7 @@ bool tcp_splice_conn_from_sock(const struct ctx *c, =09=09=09return true; =09=09} =20 -=09=09pif1 =3D PIF_HOST; +=09=09tgtpif =3D PIF_HOST; =09=09dstport +=3D c->tcp.fwd_out.delta[dstport]; =09=09break; =20 @@ -463,7 +463,7 @@ bool tcp_splice_conn_from_sock(const struct ctx *c, =09=09if (!inany_is_loopback(&src)) =09=09=09return false; =20 -=09=09pif1 =3D PIF_SPLICE; +=09=09tgtpif =3D PIF_SPLICE; =09=09dstport +=3D c->tcp.fwd_in.delta[dstport]; =09=09break; =20 @@ -471,6 +471,7 @@ bool tcp_splice_conn_from_sock(const struct ctx *c, =09=09return false; =09} =20 +=09flow_target(flow, tgtpif); =09conn =3D FLOW_SET_TYPE(flow, FLOW_TCP_SPLICE, tcp_splice); =20 =09conn->flags =3D af =3D=3D AF_INET ? 0 : SPLICE_V6; @@ -482,7 +483,7 @@ bool tcp_splice_conn_from_sock(const struct ctx *c, =09if (setsockopt(s0, SOL_TCP, TCP_QUICKACK, &((int){ 1 }), sizeof(int))) =09=09flow_trace(conn, "failed to set TCP_QUICKACK on %i", s0); =20 -=09if (tcp_splice_connect(c, conn, af, pif1, dstport)) +=09if (tcp_splice_connect(c, conn, af, tgtpif, dstport)) =09=09conn_flag(c, conn, CLOSING); =20 =09FLOW_ACTIVATE(conn); --=20 2.45.1