From patchwork Wed Apr 6 18:55:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 109349 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 58F32A0509; Wed, 6 Apr 2022 20:56:04 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E727D42879; Wed, 6 Apr 2022 20:55:44 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mails.dpdk.org (Postfix) with ESMTP id AFD2F4014F for ; Wed, 6 Apr 2022 20:55:42 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649271342; x=1680807342; h=from:to:subject:date:message-id:in-reply-to:references; bh=f+BY1vLKNoKQI+/O2dhJ4mc+NwAlKUVdrbmA1OAjHfM=; b=JKb+8gPr8iZelsXYa4y4MIoYaJVjY4S+fg8c8XY+kllG9frqtDV99/pX 53818j/sIdmU9lTIXHH1B9sPt5ckeBjvnnd08SGYVUFqomiIxII6G6BRz kU7g7mXT0kcCYcy2fKGfCTvB2NbjN7ih7oxSv6jM3Y/vPWXgJhizM8cxu 0LZWgV9nlSeqZdZvf5fXGl23fyQDd8lXjqAhjnO+ZK/0rmqfguU4Epmle i54Jmnc0vODPT95EqH2bDeKh7JmTro/E/oe/rijBvSXz9cs+SWDjhtDsD VvBGMNtyIaUU/0V0p56+r1+0S7fNoqG4kILHgEgW0J99/oZL3A5UpKHW7 Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10309"; a="243266969" X-IronPort-AV: E=Sophos;i="5.90,240,1643702400"; d="scan'208";a="243266969" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Apr 2022 11:55:42 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,240,1643702400"; d="scan'208";a="524055148" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.223.107]) by orsmga002.jf.intel.com with ESMTP; 06 Apr 2022 11:55:41 -0700 From: Cristian Dumitrescu To: dev@dpdk.org Subject: [PATCH V5 5/6] pipeline: support packet recirculation Date: Wed, 6 Apr 2022 19:55:34 +0100 Message-Id: <20220406185535.73084-5-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220406185535.73084-1-cristian.dumitrescu@intel.com> References: <20220406184836.72784-1-cristian.dumitrescu@intel.com> <20220406185535.73084-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 | 86 +++++++++++++++++ 2 files changed, 198 insertions(+) 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..381a35c6e0 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,28 @@ __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 + 1); + + /* Packet. */ + t->ptr = &pkt->pkt[pkt->offset]; + 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 +1569,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; @@ -1656,6 +1690,20 @@ __instr_tx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instr struct port_out_runtime *port = &p->out[port_id]; struct rte_swx_pkt *pkt = &t->pkt; + /* Recirculation: keep the current packet. */ + if (t->recirculate) { + TRACE("[Thread %2u]: tx 1 pkt - recirculate\n", + p->thread_id); + + /* Headers. */ + emit_handler(t); + + /* Packet. */ + mirroring_handler(p, t, pkt); + + return; + } + TRACE("[Thread %2u]: tx 1 pkt to port %u\n", p->thread_id, (uint32_t)port_id); @@ -1675,6 +1723,20 @@ __instr_tx_i_exec(struct rte_swx_pipeline *p, struct thread *t, const struct ins struct port_out_runtime *port = &p->out[port_id]; struct rte_swx_pkt *pkt = &t->pkt; + /* Recirculation: keep the current packet. */ + if (t->recirculate) { + TRACE("[Thread %2u]: tx (i) 1 pkt - recirculate\n", + p->thread_id); + + /* Headers. */ + emit_handler(t); + + /* Packet. */ + mirroring_handler(p, t, pkt); + + return; + } + TRACE("[Thread %2u]: tx (i) 1 pkt to port %u\n", p->thread_id, (uint32_t)port_id); @@ -1727,6 +1789,30 @@ __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 (pass %u)\n", + p->thread_id, + t->recirc_pass_id); + + /* Meta-data. */ + METADATA_WRITE(t, ip->io.io.offset, ip->io.io.n_bits, t->recirc_pass_id); +} + /* * extract. */