From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7C2BAC433F5 for ; Tue, 5 Apr 2022 21:36:59 +0000 (UTC) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7834F42854; Tue, 5 Apr 2022 23:36:42 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mails.dpdk.org (Postfix) with ESMTP id AB37642862 for ; Tue, 5 Apr 2022 23:36:40 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649194600; x=1680730600; h=from:to:subject:date:message-id:in-reply-to:references; bh=N0312fmA9HARITIf/AYBxkmZEKlD+tPP9QS0umRghwg=; b=mAzSXFp/Dl1qlbtfgFMjkcXcOxrjdRNadU0KCblbjI4FtJvLh4Fm9OfN lbvurMLKuH81gJVF/UUONyETEqNLVFgAPNTu+T1g6z2zUysKarphkYz8D T7w8ys/zbSGX2P4RWlKWXhsdvZjnAjP2RcMGnXEuYp1L8V/1/7IwNSoEu gIgpxXDIeQVoecO1Og9c97etqmjW/apN0veg0E06DW2Q8ZRXtyVREOpYu hju44enWqUC3pxMaIEBpJvWNwl9+48ulBqaulEG4LrX3X93I2C5eh/1Qw I4rDLTuV4RE0BUqKgu2b/wlRrCaeSpbWIyAygjUW2HsyAkyqPMsZN6SoK g==; X-IronPort-AV: E=McAfee;i="6200,9189,10308"; a="261044269" X-IronPort-AV: E=Sophos;i="5.90,238,1643702400"; d="scan'208";a="261044269" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Apr 2022 14:36:37 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,238,1643702400"; d="scan'208";a="608616235" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.223.107]) by fmsmga008.fm.intel.com with ESMTP; 05 Apr 2022 14:36:36 -0700 From: Cristian Dumitrescu To: dev@dpdk.org Subject: [PATCH V3 4/4] pipeline: support packet recirculation Date: Tue, 5 Apr 2022 22:36:32 +0100 Message-Id: <20220405213632.48028-4-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220405213632.48028-1-cristian.dumitrescu@intel.com> References: <20220405123002.40671-1-cristian.dumitrescu@intel.com> <20220405213632.48028-1-cristian.dumitrescu@intel.com> X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add support for packet recirculation. The current packet is flagged for recirculation using the new "recirculate" instruction; on TX, this flag causes the packet to execute the full pipeline again as if it was a new packet, except the packet meta-data is preserved. The new "recircid" instruction can be used to read the pass number in case the packet goes several times through the pipeline. Signed-off-by: Cristian Dumitrescu --- lib/pipeline/rte_swx_pipeline.c | 112 +++++++++++++++++++++++ lib/pipeline/rte_swx_pipeline_internal.h | 62 ++++++++++++- 2 files changed, 172 insertions(+), 2 deletions(-) diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c index 062fbcfc89..17da11c015 100644 --- a/lib/pipeline/rte_swx_pipeline.c +++ b/lib/pipeline/rte_swx_pipeline.c @@ -1782,6 +1782,68 @@ instr_mirror_exec(struct rte_swx_pipeline *p) thread_ip_inc(p); } +/* + * recirculate. + */ +static int +instr_recirculate_translate(struct rte_swx_pipeline *p __rte_unused, + struct action *action __rte_unused, + char **tokens __rte_unused, + int n_tokens, + struct instruction *instr, + struct instruction_data *data __rte_unused) +{ + CHECK(n_tokens == 1, EINVAL); + + instr->type = INSTR_RECIRCULATE; + return 0; +} + +static int +instr_recircid_translate(struct rte_swx_pipeline *p, + struct action *action __rte_unused, + char **tokens, + int n_tokens, + struct instruction *instr, + struct instruction_data *data __rte_unused) +{ + struct field *f; + + CHECK(n_tokens == 2, EINVAL); + + f = metadata_field_parse(p, tokens[1]); + CHECK(f, EINVAL); + + instr->type = INSTR_RECIRCID; + instr->io.io.offset = f->offset / 8; + instr->io.io.n_bits = f->n_bits; + return 0; +} + +static inline void +instr_recirculate_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + + __instr_recirculate_exec(p, t, ip); + + /* Thread. */ + thread_ip_inc(p); +} + +static inline void +instr_recircid_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + + __instr_recircid_exec(p, t, ip); + + /* Thread. */ + thread_ip_inc(p); +} + /* * extract. */ @@ -5790,6 +5852,22 @@ instr_translate(struct rte_swx_pipeline *p, instr, data); + if (!strcmp(tokens[tpos], "recirculate")) + return instr_recirculate_translate(p, + action, + &tokens[tpos], + n_tokens - tpos, + instr, + data); + + if (!strcmp(tokens[tpos], "recircid")) + return instr_recircid_translate(p, + action, + &tokens[tpos], + n_tokens - tpos, + instr, + data); + if (!strcmp(tokens[tpos], "extract")) return instr_hdr_extract_translate(p, action, @@ -6815,6 +6893,8 @@ static instr_exec_t instruction_table[] = { [INSTR_TX_I] = instr_tx_i_exec, [INSTR_DROP] = instr_drop_exec, [INSTR_MIRROR] = instr_mirror_exec, + [INSTR_RECIRCULATE] = instr_recirculate_exec, + [INSTR_RECIRCID] = instr_recircid_exec, [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec, [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec, @@ -10223,6 +10303,8 @@ instr_type_to_name(struct instruction *instr) case INSTR_TX_I: return "INSTR_TX_I"; case INSTR_DROP: return "INSTR_DROP"; case INSTR_MIRROR: return "INSTR_MIRROR"; + case INSTR_RECIRCULATE: return "INSTR_RECIRCULATE"; + case INSTR_RECIRCID: return "INSTR_RECIRCID"; case INSTR_HDR_EXTRACT: return "INSTR_HDR_EXTRACT"; case INSTR_HDR_EXTRACT2: return "INSTR_HDR_EXTRACT2"; @@ -10553,6 +10635,32 @@ instr_mirror_export(struct instruction *instr, FILE *f) instr->mirror.src.offset); } +static void +instr_recirculate_export(struct instruction *instr, FILE *f) +{ + fprintf(f, + "\t{\n" + "\t\t.type = %s,\n" + "\t},\n", + instr_type_to_name(instr)); +} + +static void +instr_recircid_export(struct instruction *instr, FILE *f) +{ + fprintf(f, + "\t{\n" + "\t\t.type = %s,\n" + "\t\t.io = {\n" + "\t\t\t.offset = %u,\n" + "\t\t\t.n_bits = %u,\n" + "\t\t},\n" + "\t},\n", + instr_type_to_name(instr), + instr->io.io.offset, + instr->io.io.n_bits); +} + static void instr_hdr_validate_export(struct instruction *instr, FILE *f) { @@ -11121,6 +11229,8 @@ static instruction_export_t export_table[] = { [INSTR_TX_I] = instr_io_export, [INSTR_DROP] = instr_io_export, [INSTR_MIRROR] = instr_mirror_export, + [INSTR_RECIRCULATE] = instr_recirculate_export, + [INSTR_RECIRCID] = instr_recircid_export, [INSTR_HDR_EXTRACT] = instr_io_export, [INSTR_HDR_EXTRACT2] = instr_io_export, @@ -11340,6 +11450,8 @@ instr_type_to_func(struct instruction *instr) case INSTR_TX_I: return "__instr_tx_i_exec"; case INSTR_DROP: return "__instr_drop_exec"; case INSTR_MIRROR: return "__instr_mirror_exec"; + case INSTR_RECIRCULATE: return "__instr_recirculate_exec"; + case INSTR_RECIRCID: return "__instr_recircid_exec"; case INSTR_HDR_EXTRACT: return "__instr_hdr_extract_exec"; case INSTR_HDR_EXTRACT2: return "__instr_hdr_extract2_exec"; diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h index 808a0cbdbb..156ac27d6f 100644 --- a/lib/pipeline/rte_swx_pipeline_internal.h +++ b/lib/pipeline/rte_swx_pipeline_internal.h @@ -245,6 +245,15 @@ enum instruction_type { */ INSTR_MIRROR, + /* recirculate + */ + INSTR_RECIRCULATE, + + /* recircid m.recirc_pass_id + * Read the internal recirculation pass ID into the specified meta-data field. + */ + INSTR_RECIRCID, + /* extract h.header */ INSTR_HDR_EXTRACT, INSTR_HDR_EXTRACT2, @@ -923,6 +932,8 @@ struct thread { uint8_t *ptr; uint32_t *mirroring_slots; uint64_t mirroring_slots_mask; + int recirculate; + uint32_t recirc_pass_id; /* Structures. */ uint8_t **structs; @@ -1525,6 +1536,27 @@ __instr_rx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instr struct rte_swx_pkt *pkt = &t->pkt; int pkt_received; + /* Recirculation: keep the current packet. */ + if (t->recirculate) { + TRACE("[Thread %2u] rx (recirculate pass %u)\n", + p->thread_id, + t->recirc_pass_id); + + /* Packet. */ + t->mirroring_slots_mask = 0; + t->recirculate = 0; + t->recirc_pass_id++; + + /* Headers. */ + t->valid_headers = 0; + t->n_headers_out = 0; + + /* Tables. */ + t->table_state = p->table_state; + + return 1; + } + /* Packet. */ pkt_received = port->pkt_rx(port->obj, pkt); t->ptr = &pkt->pkt[pkt->offset]; @@ -1536,6 +1568,7 @@ __instr_rx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instr p->port_id); t->mirroring_slots_mask = 0; + t->recirc_pass_id = 0; /* Headers. */ t->valid_headers = 0; @@ -1665,7 +1698,8 @@ __instr_tx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instr /* Packet. */ mirroring_handler(p, t, pkt); - port->pkt_tx(port->obj, pkt); + if (!t->recirculate) + port->pkt_tx(port->obj, pkt); } static inline void @@ -1684,7 +1718,8 @@ __instr_tx_i_exec(struct rte_swx_pipeline *p, struct thread *t, const struct ins /* Packet. */ mirroring_handler(p, t, pkt); - port->pkt_tx(port->obj, pkt); + if (!t->recirculate) + port->pkt_tx(port->obj, pkt); } static inline void @@ -1727,6 +1762,29 @@ __instr_mirror_exec(struct rte_swx_pipeline *p, t->mirroring_slots_mask |= 1LLU << slot_id; } +static inline void +__instr_recirculate_exec(struct rte_swx_pipeline *p __rte_unused, + struct thread *t, + const struct instruction *ip __rte_unused) +{ + TRACE("[Thread %2u]: recirculate\n", + p->thread_id); + + t->recirculate = 1; +} + +static inline void +__instr_recircid_exec(struct rte_swx_pipeline *p __rte_unused, + struct thread *t, + const struct instruction *ip) +{ + TRACE("[Thread %2u]: recircid\n", + p->thread_id); + + /* Meta-data. */ + METADATA_WRITE(t, ip->io.io.offset, ip->io.io.n_bits, t->recirc_pass_id); +} + /* * extract. */ -- 2.17.1