DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH 0/4] pipeline: support large structure fields
@ 2022-08-12  9:54 Cristian Dumitrescu
  2022-08-12  9:54 ` [PATCH 1/4] pipeline: remove the 64-bit limit for " Cristian Dumitrescu
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Cristian Dumitrescu @ 2022-08-12  9:54 UTC (permalink / raw)
  To: dev

This patch set adds support for structure fields bigger than 64 bits.
These fields can be packet header or meta-data fields. They can be
used as part of the table lookup key or as action arguments. They are
now valid operands for the move instruction.

This is required for supporting the 128-bit IPv6 addresses, which up
to now had to be split into two 64-bit fields.

Cristian Dumitrescu (4):
  pipeline: remove the 64-bit limit for structure fields
  pipeline: read large structure fields on the control path
  pipeline: support large default action arguments
  pipeline: add instruction support for moving large structure fields

 lib/pipeline/rte_swx_ctl.c               | 357 +++++++++++++++++++----
 lib/pipeline/rte_swx_pipeline.c          | 256 +++++++++++-----
 lib/pipeline/rte_swx_pipeline_internal.h |  78 ++++-
 lib/pipeline/rte_swx_pipeline_spec.c     |   3 +-
 4 files changed, 559 insertions(+), 135 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/4] pipeline: remove the 64-bit limit for structure fields
  2022-08-12  9:54 [PATCH 0/4] pipeline: support large structure fields Cristian Dumitrescu
@ 2022-08-12  9:54 ` Cristian Dumitrescu
  2022-08-12  9:54 ` [PATCH 2/4] pipeline: read large structure fields on the control path Cristian Dumitrescu
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Cristian Dumitrescu @ 2022-08-12  9:54 UTC (permalink / raw)
  To: dev; +Cc: Harshad Suresh Narayane

Remove the generic limitation of structure fields to 64 bits or less
and push this restriction to the instructions that require it.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Harshad Suresh Narayane <harshad.suresh.narayane@intel.com>
---
 lib/pipeline/rte_swx_pipeline.c      | 104 ++++++++++++++-------------
 lib/pipeline/rte_swx_pipeline_spec.c |   3 +-
 2 files changed, 56 insertions(+), 51 deletions(-)

diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 12e156b00b..15c840b352 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -138,12 +138,10 @@ rte_swx_pipeline_struct_type_register(struct rte_swx_pipeline *p,
 
 	for (i = 0; i < n_fields; i++) {
 		struct rte_swx_field_params *f = &fields[i];
-		int var_size = ((i == n_fields - 1) && last_field_has_variable_size) ? 1 : 0;
 		uint32_t j;
 
 		CHECK_NAME(f->name, EINVAL);
 		CHECK(f->n_bits, EINVAL);
-		CHECK((f->n_bits <= 64) || var_size, EINVAL);
 		CHECK((f->n_bits & 7) == 0, EINVAL);
 
 		for (j = 0; j < i; j++) {
@@ -1728,6 +1726,7 @@ instr_rx_translate(struct rte_swx_pipeline *p,
 
 	f = metadata_field_parse(p, tokens[1]);
 	CHECK(f, EINVAL);
+	CHECK(f->n_bits <= 64, EINVAL);
 
 	instr->type = INSTR_RX;
 	instr->io.io.offset = f->offset / 8;
@@ -1754,6 +1753,7 @@ instr_tx_translate(struct rte_swx_pipeline *p,
 
 	f = metadata_field_parse(p, port);
 	if (f) {
+		CHECK(f->n_bits <= 64, EINVAL);
 		instr->type = INSTR_TX;
 		instr->io.io.offset = f->offset / 8;
 		instr->io.io.n_bits = f->n_bits;
@@ -1843,12 +1843,12 @@ instr_mirror_translate(struct rte_swx_pipeline *p,
 	fdst = struct_field_parse(p, action, dst, &dst_struct_id);
 	CHECK(fdst, EINVAL);
 	CHECK(dst[0] != 'h', EINVAL);
-	CHECK(!fdst->var_size, EINVAL);
+	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
 
 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
 	CHECK(fsrc, EINVAL);
 	CHECK(src[0] != 'h', EINVAL);
-	CHECK(!fsrc->var_size, EINVAL);
+	CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 	instr->type = INSTR_MIRROR;
 	instr->mirror.dst.struct_id = (uint8_t)dst_struct_id;
@@ -1904,6 +1904,7 @@ instr_recircid_translate(struct rte_swx_pipeline *p,
 
 	f = metadata_field_parse(p, tokens[1]);
 	CHECK(f, EINVAL);
+	CHECK(f->n_bits <= 64, EINVAL);
 
 	instr->type = INSTR_RECIRCID;
 	instr->io.io.offset = f->offset / 8;
@@ -1968,7 +1969,7 @@ instr_hdr_extract_translate(struct rte_swx_pipeline *p,
 
 		mf = metadata_field_parse(p, tokens[2]);
 		CHECK(mf, EINVAL);
-		CHECK(!mf->var_size, EINVAL);
+		CHECK(mf->n_bits <= 64, EINVAL);
 
 		instr->type = INSTR_HDR_EXTRACT_M;
 		instr->io.io.offset = mf->offset / 8;
@@ -2693,6 +2694,7 @@ instr_learn_translate(struct rte_swx_pipeline *p,
 	if (mf_first_arg_name) {
 		mf_first_arg = metadata_field_parse(p, mf_first_arg_name);
 		CHECK(mf_first_arg, EINVAL);
+		CHECK(mf_first_arg->n_bits <= 64, EINVAL);
 	}
 
 	/* Timeout ID. */
@@ -2700,6 +2702,7 @@ instr_learn_translate(struct rte_swx_pipeline *p,
 	CHECK_NAME(mf_timeout_id_name, EINVAL);
 	mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
 	CHECK(mf_timeout_id, EINVAL);
+	CHECK(mf_timeout_id->n_bits <= 64, EINVAL);
 
 	/* Instruction. */
 	instr->type = INSTR_LEARNER_LEARN;
@@ -2751,6 +2754,7 @@ instr_rearm_translate(struct rte_swx_pipeline *p,
 	CHECK_NAME(mf_timeout_id_name, EINVAL);
 	mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
 	CHECK(mf_timeout_id, EINVAL);
+	CHECK(mf_timeout_id->n_bits <= 64, EINVAL);
 
 	instr->type = INSTR_LEARNER_REARM_NEW;
 	instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
@@ -2910,12 +2914,14 @@ instr_hash_translate(struct rte_swx_pipeline *p,
 
 	dst = metadata_field_parse(p, tokens[2]);
 	CHECK(dst, EINVAL);
+	CHECK(dst->n_bits <= 64, EINVAL);
 
 	src_first = struct_field_parse(p, action, tokens[3], &src_struct_id_first);
 	CHECK(src_first, EINVAL);
 
 	src_last = struct_field_parse(p, action, tokens[4], &src_struct_id_last);
 	CHECK(src_last, EINVAL);
+	CHECK(!src_last->var_size, EINVAL);
 	CHECK(src_struct_id_first == src_struct_id_last, EINVAL);
 
 	instr->type = INSTR_HASH_FUNC;
@@ -2963,12 +2969,12 @@ instr_mov_translate(struct rte_swx_pipeline *p,
 
 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
 	CHECK(fdst, EINVAL);
-	CHECK(!fdst->var_size, EINVAL);
+	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
 
 	/* MOV, MOV_MH, MOV_HM or MOV_HH. */
 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
 	if (fsrc) {
-		CHECK(!fsrc->var_size, EINVAL);
+		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_MOV;
 		if (dst[0] != 'h' && src[0] == 'h')
@@ -3181,12 +3187,12 @@ instr_alu_add_translate(struct rte_swx_pipeline *p,
 
 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
 	CHECK(fdst, EINVAL);
-	CHECK(!fdst->var_size, EINVAL);
+	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
 
 	/* ADD, ADD_HM, ADD_MH, ADD_HH. */
 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
 	if (fsrc) {
-		CHECK(!fsrc->var_size, EINVAL);
+		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_ALU_ADD;
 		if (dst[0] == 'h' && src[0] != 'h')
@@ -3237,12 +3243,12 @@ instr_alu_sub_translate(struct rte_swx_pipeline *p,
 
 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
 	CHECK(fdst, EINVAL);
-	CHECK(!fdst->var_size, EINVAL);
+	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
 
 	/* SUB, SUB_HM, SUB_MH, SUB_HH. */
 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
 	if (fsrc) {
-		CHECK(!fsrc->var_size, EINVAL);
+		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_ALU_SUB;
 		if (dst[0] == 'h' && src[0] != 'h')
@@ -3297,7 +3303,7 @@ instr_alu_ckadd_translate(struct rte_swx_pipeline *p,
 	/* CKADD_FIELD. */
 	fsrc = header_field_parse(p, src, &hsrc);
 	if (fsrc) {
-		CHECK(!fsrc->var_size, EINVAL);
+		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_ALU_CKADD_FIELD;
 		instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
@@ -3346,7 +3352,7 @@ instr_alu_cksub_translate(struct rte_swx_pipeline *p,
 
 	fsrc = header_field_parse(p, src, &hsrc);
 	CHECK(fsrc, EINVAL);
-	CHECK(!fsrc->var_size, EINVAL);
+	CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 	instr->type = INSTR_ALU_CKSUB_FIELD;
 	instr->alu.dst.struct_id = (uint8_t)hdst->struct_id;
@@ -3375,12 +3381,12 @@ instr_alu_shl_translate(struct rte_swx_pipeline *p,
 
 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
 	CHECK(fdst, EINVAL);
-	CHECK(!fdst->var_size, EINVAL);
+	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
 
 	/* SHL, SHL_HM, SHL_MH, SHL_HH. */
 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
 	if (fsrc) {
-		CHECK(!fsrc->var_size, EINVAL);
+		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_ALU_SHL;
 		if (dst[0] == 'h' && src[0] != 'h')
@@ -3431,12 +3437,12 @@ instr_alu_shr_translate(struct rte_swx_pipeline *p,
 
 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
 	CHECK(fdst, EINVAL);
-	CHECK(!fdst->var_size, EINVAL);
+	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
 
 	/* SHR, SHR_HM, SHR_MH, SHR_HH. */
 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
 	if (fsrc) {
-		CHECK(!fsrc->var_size, EINVAL);
+		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_ALU_SHR;
 		if (dst[0] == 'h' && src[0] != 'h')
@@ -3487,12 +3493,12 @@ instr_alu_and_translate(struct rte_swx_pipeline *p,
 
 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
 	CHECK(fdst, EINVAL);
-	CHECK(!fdst->var_size, EINVAL);
+	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
 
 	/* AND, AND_MH, AND_HM, AND_HH. */
 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
 	if (fsrc) {
-		CHECK(!fsrc->var_size, EINVAL);
+		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_ALU_AND;
 		if (dst[0] != 'h' && src[0] == 'h')
@@ -3543,12 +3549,12 @@ instr_alu_or_translate(struct rte_swx_pipeline *p,
 
 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
 	CHECK(fdst, EINVAL);
-	CHECK(!fdst->var_size, EINVAL);
+	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
 
 	/* OR, OR_MH, OR_HM, OR_HH. */
 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
 	if (fsrc) {
-		CHECK(!fsrc->var_size, EINVAL);
+		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_ALU_OR;
 		if (dst[0] != 'h' && src[0] == 'h')
@@ -3599,12 +3605,12 @@ instr_alu_xor_translate(struct rte_swx_pipeline *p,
 
 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
 	CHECK(fdst, EINVAL);
-	CHECK(!fdst->var_size, EINVAL);
+	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
 
 	/* XOR, XOR_MH, XOR_HM, XOR_HH. */
 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
 	if (fsrc) {
-		CHECK(!fsrc->var_size, EINVAL);
+		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_ALU_XOR;
 		if (dst[0] != 'h' && src[0] == 'h')
@@ -4224,7 +4230,7 @@ instr_regprefetch_translate(struct rte_swx_pipeline *p,
 	/* REGPREFETCH_RH, REGPREFETCH_RM. */
 	fidx = struct_field_parse(p, action, idx, &idx_struct_id);
 	if (fidx) {
-		CHECK(!fidx->var_size, EINVAL);
+		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_REGPREFETCH_RM;
 		if (idx[0] == 'h')
@@ -4269,12 +4275,12 @@ instr_regrd_translate(struct rte_swx_pipeline *p,
 
 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
 	CHECK(fdst, EINVAL);
-	CHECK(!fdst->var_size, EINVAL);
+	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
 
 	/* REGRD_HRH, REGRD_HRM, REGRD_MRH, REGRD_MRM. */
 	fidx = struct_field_parse(p, action, idx, &idx_struct_id);
 	if (fidx) {
-		CHECK(!fidx->var_size, EINVAL);
+		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_REGRD_MRM;
 		if (dst[0] == 'h' && idx[0] != 'h')
@@ -4333,8 +4339,8 @@ instr_regwr_translate(struct rte_swx_pipeline *p,
 	fidx = struct_field_parse(p, action, idx, &idx_struct_id);
 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
 	if (fidx && fsrc) {
-		CHECK(!fidx->var_size, EINVAL);
-		CHECK(!fsrc->var_size, EINVAL);
+		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
+		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_REGWR_RMM;
 		if (idx[0] == 'h' && src[0] != 'h')
@@ -4356,7 +4362,7 @@ instr_regwr_translate(struct rte_swx_pipeline *p,
 
 	/* REGWR_RHI, REGWR_RMI. */
 	if (fidx && !fsrc) {
-		CHECK(!fidx->var_size, EINVAL);
+		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
 
 		src_val = strtoull(src, &src, 0);
 		CHECK(!src[0], EINVAL);
@@ -4378,7 +4384,7 @@ instr_regwr_translate(struct rte_swx_pipeline *p,
 		idx_val = strtoul(idx, &idx, 0);
 		CHECK(!idx[0], EINVAL);
 
-		CHECK(!fsrc->var_size, EINVAL);
+		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_REGWR_RIM;
 		if (src[0] == 'h')
@@ -4429,8 +4435,8 @@ instr_regadd_translate(struct rte_swx_pipeline *p,
 	fidx = struct_field_parse(p, action, idx, &idx_struct_id);
 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
 	if (fidx && fsrc) {
-		CHECK(!fidx->var_size, EINVAL);
-		CHECK(!fsrc->var_size, EINVAL);
+		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
+		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_REGADD_RMM;
 		if (idx[0] == 'h' && src[0] != 'h')
@@ -4452,7 +4458,7 @@ instr_regadd_translate(struct rte_swx_pipeline *p,
 
 	/* REGADD_RHI, REGADD_RMI. */
 	if (fidx && !fsrc) {
-		CHECK(!fidx->var_size, EINVAL);
+		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
 
 		src_val = strtoull(src, &src, 0);
 		CHECK(!src[0], EINVAL);
@@ -4474,7 +4480,7 @@ instr_regadd_translate(struct rte_swx_pipeline *p,
 		idx_val = strtoul(idx, &idx, 0);
 		CHECK(!idx[0], EINVAL);
 
-		CHECK(!fsrc->var_size, EINVAL);
+		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_REGADD_RIM;
 		if (src[0] == 'h')
@@ -4879,7 +4885,7 @@ instr_metprefetch_translate(struct rte_swx_pipeline *p,
 	/* METPREFETCH_H, METPREFETCH_M. */
 	fidx = struct_field_parse(p, action, idx, &idx_struct_id);
 	if (fidx) {
-		CHECK(!fidx->var_size, EINVAL);
+		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_METPREFETCH_M;
 		if (idx[0] == 'h')
@@ -4926,18 +4932,18 @@ instr_meter_translate(struct rte_swx_pipeline *p,
 
 	flength = struct_field_parse(p, action, length, &length_struct_id);
 	CHECK(flength, EINVAL);
-	CHECK(!flength->var_size, EINVAL);
+	CHECK(!flength->var_size && (flength->n_bits <= 64), EINVAL);
 
 	fcin = struct_field_parse(p, action, color_in, &color_in_struct_id);
 
 	fcout = struct_field_parse(p, NULL, color_out, &color_out_struct_id);
 	CHECK(fcout, EINVAL);
-	CHECK(!fcout->var_size, EINVAL);
+	CHECK(!fcout->var_size  && (fcout->n_bits <= 64), EINVAL);
 
 	/* index = HMEFT, length = HMEFT, color_in = MEFT, color_out = MEF. */
 	if (fidx && fcin) {
-		CHECK(!fidx->var_size, EINVAL);
-		CHECK(!fcin->var_size, EINVAL);
+		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
+		CHECK(!fcin->var_size && (fcin->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_METER_MMM;
 		if (idx[0] == 'h' && length[0] == 'h')
@@ -4970,7 +4976,7 @@ instr_meter_translate(struct rte_swx_pipeline *p,
 	if (fidx && !fcin) {
 		uint32_t color_in_val;
 
-		CHECK(!fidx->var_size, EINVAL);
+		CHECK(!fidx->var_size && (fidx->n_bits <= 64), EINVAL);
 
 		color_in_val = strtoul(color_in, &color_in, 0);
 		CHECK(!color_in[0], EINVAL);
@@ -5007,7 +5013,7 @@ instr_meter_translate(struct rte_swx_pipeline *p,
 		idx_val = strtoul(idx, &idx, 0);
 		CHECK(!idx[0], EINVAL);
 
-		CHECK(!fcin->var_size, EINVAL);
+		CHECK(!fcin->var_size && (fcin->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_METER_IMM;
 		if (length[0] == 'h')
@@ -5426,12 +5432,12 @@ instr_jmp_eq_translate(struct rte_swx_pipeline *p,
 
 	fa = struct_field_parse(p, action, a, &a_struct_id);
 	CHECK(fa, EINVAL);
-	CHECK(!fa->var_size, EINVAL);
+	CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
 
 	/* JMP_EQ, JMP_EQ_MH, JMP_EQ_HM, JMP_EQ_HH. */
 	fb = struct_field_parse(p, action, b, &b_struct_id);
 	if (fb) {
-		CHECK(!fb->var_size, EINVAL);
+		CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_JMP_EQ;
 		if (a[0] != 'h' && b[0] == 'h')
@@ -5486,12 +5492,12 @@ instr_jmp_neq_translate(struct rte_swx_pipeline *p,
 
 	fa = struct_field_parse(p, action, a, &a_struct_id);
 	CHECK(fa, EINVAL);
-	CHECK(!fa->var_size, EINVAL);
+	CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
 
 	/* JMP_NEQ, JMP_NEQ_MH, JMP_NEQ_HM, JMP_NEQ_HH. */
 	fb = struct_field_parse(p, action, b, &b_struct_id);
 	if (fb) {
-		CHECK(!fb->var_size, EINVAL);
+		CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_JMP_NEQ;
 		if (a[0] != 'h' && b[0] == 'h')
@@ -5546,12 +5552,12 @@ instr_jmp_lt_translate(struct rte_swx_pipeline *p,
 
 	fa = struct_field_parse(p, action, a, &a_struct_id);
 	CHECK(fa, EINVAL);
-	CHECK(!fa->var_size, EINVAL);
+	CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
 
 	/* JMP_LT, JMP_LT_MH, JMP_LT_HM, JMP_LT_HH. */
 	fb = struct_field_parse(p, action, b, &b_struct_id);
 	if (fb) {
-		CHECK(!fb->var_size, EINVAL);
+		CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_JMP_LT;
 		if (a[0] == 'h' && b[0] != 'h')
@@ -5606,12 +5612,12 @@ instr_jmp_gt_translate(struct rte_swx_pipeline *p,
 
 	fa = struct_field_parse(p, action, a, &a_struct_id);
 	CHECK(fa, EINVAL);
-	CHECK(!fa->var_size, EINVAL);
+	CHECK(!fa->var_size && (fa->n_bits <= 64), EINVAL);
 
 	/* JMP_GT, JMP_GT_MH, JMP_GT_HM, JMP_GT_HH. */
 	fb = struct_field_parse(p, action, b, &b_struct_id);
 	if (fb) {
-		CHECK(!fb->var_size, EINVAL);
+		CHECK(!fb->var_size && (fb->n_bits <= 64), EINVAL);
 
 		instr->type = INSTR_JMP_GT;
 		if (a[0] == 'h' && b[0] != 'h')
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 3c16daf7de..1b4183ef55 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -228,8 +228,7 @@ struct_block_parse(struct struct_spec *s,
 	n_bits = strtoul(p, &p, 0);
 	if ((p[0]) ||
 	    !n_bits ||
-	    (n_bits % 8) ||
-	    ((n_bits > 64) && !varbit)) {
+	    (n_bits % 8)) {
 		error = -EINVAL;
 		error_size_invalid = 1;
 		goto error;
-- 
2.34.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 2/4] pipeline: read large structure fields on the control path
  2022-08-12  9:54 [PATCH 0/4] pipeline: support large structure fields Cristian Dumitrescu
  2022-08-12  9:54 ` [PATCH 1/4] pipeline: remove the 64-bit limit for " Cristian Dumitrescu
@ 2022-08-12  9:54 ` Cristian Dumitrescu
  2022-08-12  9:54 ` [PATCH 3/4] pipeline: support large default action arguments Cristian Dumitrescu
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Cristian Dumitrescu @ 2022-08-12  9:54 UTC (permalink / raw)
  To: dev; +Cc: Harshad Suresh Narayane

Support reading structure fields that are bigger than 64 bits on the
control path for the table update operations.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Harshad Suresh Narayane <harshad.suresh.narayane@intel.com>
---
 lib/pipeline/rte_swx_ctl.c | 357 +++++++++++++++++++++++++++++++------
 1 file changed, 298 insertions(+), 59 deletions(-)

diff --git a/lib/pipeline/rte_swx_ctl.c b/lib/pipeline/rte_swx_ctl.c
index 1b776fc543..bdbcd8f50a 100644
--- a/lib/pipeline/rte_swx_ctl.c
+++ b/lib/pipeline/rte_swx_ctl.c
@@ -2694,6 +2694,270 @@ mask_to_prefix(uint64_t mask, uint32_t mask_length, uint32_t *prefix_length)
 	return 0;
 }
 
+static int
+large_mask_to_prefix(uint8_t *mask, uint32_t n_mask_bytes, uint32_t *prefix_length)
+{
+	uint32_t pl, i;
+
+	/* Check input arguments. */
+	if (!mask || !n_mask_bytes || !prefix_length)
+		return -EINVAL;
+
+	/* Count leading bits of one. */
+	for (i = 0; i < n_mask_bytes * 8; i++) {
+		uint32_t byte_id = i / 8;
+		uint32_t bit_id = i & 7;
+
+		uint32_t byte = mask[byte_id];
+		uint32_t bit = byte & (1 << (7 - bit_id));
+
+		if (!bit)
+			break;
+	}
+
+	/* Save the potential prefix length. */
+	pl = i;
+
+	/* Check that all remaining bits are zeros. */
+	for ( ; i < n_mask_bytes * 8; i++) {
+		uint32_t byte_id = i / 8;
+		uint32_t bit_id = i & 7;
+
+		uint32_t byte = mask[byte_id];
+		uint32_t bit = byte & (1 << (7 - bit_id));
+
+		if (bit)
+			break;
+	}
+
+	if (i < n_mask_bytes * 8)
+		return -EINVAL;
+
+	*prefix_length = pl;
+	return 0;
+}
+
+static int
+char_to_hex(char c, uint8_t *val)
+{
+	if (c >= '0' && c <= '9') {
+		*val = c - '0';
+		return 0;
+	}
+
+	if (c >= 'A' && c <= 'F') {
+		*val = c - 'A' + 10;
+		return 0;
+	}
+
+	if (c >= 'a' && c <= 'f') {
+		*val = c - 'a' + 10;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int
+hex_string_parse(char *src, uint8_t *dst, uint32_t n_dst_bytes)
+{
+	uint32_t i;
+
+	/* Check input arguments. */
+	if (!src || !src[0] || !dst || !n_dst_bytes)
+		return -EINVAL;
+
+	/* Skip any leading "0x" or "0X" in the src string. */
+	if ((src[0] == '0') && (src[1] == 'x' || src[1] == 'X'))
+		src += 2;
+
+	/* Convert each group of two hex characters in the src string to one byte in dst array. */
+	for (i = 0; i < n_dst_bytes; i++) {
+		uint8_t a, b;
+		int status;
+
+		status = char_to_hex(*src, &a);
+		if (status)
+			return status;
+		src++;
+
+		status = char_to_hex(*src, &b);
+		if (status)
+			return status;
+		src++;
+
+		dst[i] = a * 16 + b;
+	}
+
+	/* Check for the end of the src string. */
+	if (*src)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int
+table_entry_match_field_read(struct table *table,
+			     struct rte_swx_table_entry *entry,
+			     uint32_t mf_id,
+			     char *mf_val,
+			     char *mf_mask,
+			     int *lpm,
+			     uint32_t *lpm_prefix_length_max,
+			     uint32_t *lpm_prefix_length)
+{
+	struct rte_swx_ctl_table_match_field_info *mf = &table->mf[mf_id];
+	uint64_t val, mask = UINT64_MAX;
+	uint32_t offset = (mf->offset - table->mf_first->offset) / 8;
+
+	/*
+	 * Mask.
+	 */
+	if (mf_mask) {
+		/* Parse. */
+		mask = strtoull(mf_mask, &mf_mask, 0);
+		if (mf_mask[0])
+			return -EINVAL;
+
+		/* LPM. */
+		if (mf->match_type == RTE_SWX_TABLE_MATCH_LPM) {
+			int status;
+
+			*lpm = 1;
+
+			*lpm_prefix_length_max = mf->n_bits;
+
+			status = mask_to_prefix(mask, mf->n_bits, lpm_prefix_length);
+			if (status)
+				return status;
+		}
+
+		/* Endianness conversion. */
+		if (mf->is_header)
+			mask = field_hton(mask, mf->n_bits);
+	}
+
+	/* Copy to entry. */
+	if (entry->key_mask)
+		memcpy(&entry->key_mask[offset], (uint8_t *)&mask, mf->n_bits / 8);
+
+	/*
+	 * Value.
+	 */
+	/* Parse. */
+	val = strtoull(mf_val, &mf_val, 0);
+	if (mf_val[0])
+		return -EINVAL;
+
+	/* Endianness conversion. */
+	if (mf->is_header)
+		val = field_hton(val, mf->n_bits);
+
+	/* Copy to entry. */
+	memcpy(&entry->key[offset], (uint8_t *)&val, mf->n_bits / 8);
+
+	return 0;
+}
+
+static int
+table_entry_action_argument_read(struct action *action,
+				 struct rte_swx_table_entry *entry,
+				 uint32_t arg_id,
+				 uint32_t arg_offset,
+				 char *arg_val)
+{
+	struct rte_swx_ctl_action_arg_info *arg = &action->args[arg_id];
+	uint64_t val;
+
+	val = strtoull(arg_val, &arg_val, 0);
+	if (arg_val[0])
+		return -EINVAL;
+
+	/* Endianness conversion. */
+	if (arg->is_network_byte_order)
+		val = field_hton(val, arg->n_bits);
+
+	/* Copy to entry. */
+	memcpy(&entry->action_data[arg_offset],
+	       (uint8_t *)&val,
+	       arg->n_bits / 8);
+
+	return 0;
+}
+
+static int
+table_entry_large_match_field_read(struct table *table,
+				   struct rte_swx_table_entry *entry,
+				   uint32_t mf_id,
+				   char *mf_val,
+				   char *mf_mask,
+				   int *lpm,
+				   uint32_t *lpm_prefix_length_max,
+				   uint32_t *lpm_prefix_length)
+{
+	struct rte_swx_ctl_table_match_field_info *mf = &table->mf[mf_id];
+	uint32_t offset = (mf->offset - table->mf_first->offset) / 8;
+	int status;
+
+	/*
+	 * Mask.
+	 */
+	if (!entry->key_mask)
+		goto value;
+
+	if (!mf_mask) {
+		/* Set mask to all-ones. */
+		memset(&entry->key_mask[offset], 0xFF, mf->n_bits / 8);
+		goto value;
+	}
+
+	/* Parse. */
+	status = hex_string_parse(mf_mask, &entry->key_mask[offset], mf->n_bits / 8);
+	if (status)
+		return -EINVAL;
+
+	/* LPM. */
+	if (mf->match_type == RTE_SWX_TABLE_MATCH_LPM) {
+		*lpm = 1;
+
+		*lpm_prefix_length_max = mf->n_bits;
+
+		status = large_mask_to_prefix(&entry->key_mask[offset],
+					      mf->n_bits / 8,
+					      lpm_prefix_length);
+		if (status)
+			return status;
+	}
+
+	/*
+	 * Value.
+	 */
+value:
+	/* Parse. */
+	status = hex_string_parse(mf_val, &entry->key[offset], mf->n_bits / 8);
+	if (status)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int
+table_entry_large_action_argument_read(struct action *action,
+				       struct rte_swx_table_entry *entry,
+				       uint32_t arg_id,
+				       uint32_t arg_offset,
+				       char *arg_val)
+{
+	struct rte_swx_ctl_action_arg_info *arg = &action->args[arg_id];
+	int status;
+
+	status = hex_string_parse(arg_val, &entry->action_data[arg_offset], arg->n_bits / 8);
+	if (status)
+		return -EINVAL;
+
+	return 0;
+}
+
 static int
 token_is_comment(const char *token)
 {
@@ -2778,62 +3042,35 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
 	for (i = 0; i < table->info.n_match_fields; i++) {
 		struct rte_swx_ctl_table_match_field_info *mf = &table->mf[i];
 		char *mf_val = tokens[1 + i], *mf_mask = NULL;
-		uint64_t val, mask = UINT64_MAX;
-		uint32_t offset = (mf->offset - table->mf_first->offset) / 8;
+		int status;
 
-		/*
-		 * Mask.
-		 */
 		mf_mask = strchr(mf_val, '/');
 		if (mf_mask) {
 			*mf_mask = 0;
 			mf_mask++;
-
-			/* Parse. */
-			mask = strtoull(mf_mask, &mf_mask, 0);
-			if (mf_mask[0])
-				goto error;
-
-			/* LPM. */
-			if (mf->match_type == RTE_SWX_TABLE_MATCH_LPM) {
-				int status;
-
-				lpm = 1;
-
-				lpm_prefix_length_max = mf->n_bits;
-
-				status = mask_to_prefix(mask, mf->n_bits, &lpm_prefix_length);
-				if (status)
-					goto error;
-			}
-
-			/* Endianness conversion. */
-			if (mf->is_header)
-				mask = field_hton(mask, mf->n_bits);
 		}
 
-		/* Copy to entry. */
-		if (entry->key_mask)
-			memcpy(&entry->key_mask[offset],
-			       (uint8_t *)&mask,
-			       mf->n_bits / 8);
-
-		/*
-		 * Value.
-		 */
-		/* Parse. */
-		val = strtoull(mf_val, &mf_val, 0);
-		if (mf_val[0])
+		if (mf->n_bits <= 64)
+			status = table_entry_match_field_read(table,
+							      entry,
+							      i,
+							      mf_val,
+							      mf_mask,
+							      &lpm,
+							      &lpm_prefix_length_max,
+							      &lpm_prefix_length);
+		else
+			status = table_entry_large_match_field_read(table,
+								    entry,
+								    i,
+								    mf_val,
+								    mf_mask,
+								    &lpm,
+								    &lpm_prefix_length_max,
+								    &lpm_prefix_length);
+		if (status)
 			goto error;
 
-		/* Endianness conversion. */
-		if (mf->is_header)
-			val = field_hton(val, mf->n_bits);
-
-		/* Copy to entry. */
-		memcpy(&entry->key[offset],
-		       (uint8_t *)&val,
-		       mf->n_bits / 8);
 	}
 
 	tokens += 1 + table->info.n_match_fields;
@@ -2889,7 +3126,7 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
 	for (i = 0; i < action->info.n_args; i++) {
 		struct rte_swx_ctl_action_arg_info *arg = &action->args[i];
 		char *arg_name, *arg_val;
-		uint64_t val;
+		int status;
 
 		arg_name = tokens[2 + i * 2];
 		arg_val = tokens[2 + i * 2 + 1];
@@ -2897,19 +3134,21 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
 		if (strcmp(arg_name, arg->name))
 			goto error;
 
-		val = strtoull(arg_val, &arg_val, 0);
-		if (arg_val[0])
+		if (arg->n_bits <= 64)
+			status = table_entry_action_argument_read(action,
+								  entry,
+								  i,
+								  arg_offset,
+								  arg_val);
+		else
+			status = table_entry_large_action_argument_read(action,
+									entry,
+									i,
+									arg_offset,
+									arg_val);
+		if (status)
 			goto error;
 
-		/* Endianness conversion. */
-		if (arg->is_network_byte_order)
-			val = field_hton(val, arg->n_bits);
-
-		/* Copy to entry. */
-		memcpy(&entry->action_data[arg_offset],
-		       (uint8_t *)&val,
-		       arg->n_bits / 8);
-
 		arg_offset += arg->n_bits / 8;
 	}
 
-- 
2.34.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 3/4] pipeline: support large default action arguments
  2022-08-12  9:54 [PATCH 0/4] pipeline: support large structure fields Cristian Dumitrescu
  2022-08-12  9:54 ` [PATCH 1/4] pipeline: remove the 64-bit limit for " Cristian Dumitrescu
  2022-08-12  9:54 ` [PATCH 2/4] pipeline: read large structure fields on the control path Cristian Dumitrescu
@ 2022-08-12  9:54 ` Cristian Dumitrescu
  2022-08-12  9:54 ` [PATCH 4/4] pipeline: add instruction support for moving large structure fields Cristian Dumitrescu
  2022-09-23 11:56 ` [PATCH 0/4] pipeline: support " Thomas Monjalon
  4 siblings, 0 replies; 6+ messages in thread
From: Cristian Dumitrescu @ 2022-08-12  9:54 UTC (permalink / raw)
  To: dev; +Cc: Harshad Suresh Narayane

Support structure fields bigger than 64 bits as default action
arguments.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Harshad Suresh Narayane <harshad.suresh.narayane@intel.com>
---
 lib/pipeline/rte_swx_pipeline.c | 89 +++++++++++++++++++++++++++++----
 1 file changed, 78 insertions(+), 11 deletions(-)

diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 15c840b352..48b9df0fef 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -7576,6 +7576,65 @@ action_arg_src_mov_count(struct action *a,
 	return n_users;
 }
 
+static int
+char_to_hex(char c, uint8_t *val)
+{
+	if (c >= '0' && c <= '9') {
+		*val = c - '0';
+		return 0;
+	}
+
+	if (c >= 'A' && c <= 'F') {
+		*val = c - 'A' + 10;
+		return 0;
+	}
+
+	if (c >= 'a' && c <= 'f') {
+		*val = c - 'a' + 10;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int
+hex_string_parse(char *src, uint8_t *dst, uint32_t n_dst_bytes)
+{
+	uint32_t i;
+
+	/* Check input arguments. */
+	if (!src || !src[0] || !dst || !n_dst_bytes)
+		return -EINVAL;
+
+	/* Skip any leading "0x" or "0X" in the src string. */
+	if ((src[0] == '0') && (src[1] == 'x' || src[1] == 'X'))
+		src += 2;
+
+	/* Convert each group of two hex characters in the src string to one byte in dst array. */
+	for (i = 0; i < n_dst_bytes; i++) {
+		uint8_t a, b;
+		int status;
+
+		status = char_to_hex(*src, &a);
+		if (status)
+			return status;
+		src++;
+
+		status = char_to_hex(*src, &b);
+		if (status)
+			return status;
+		src++;
+
+		dst[i] = a * 16 + b;
+	}
+
+	/* Check for the end of the src string. */
+	if (*src)
+		return -EINVAL;
+
+	return 0;
+}
+
 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
 #define field_ntoh(val, n_bits) (ntoh64((val) << (64 - n_bits)))
 #define field_hton(val, n_bits) (hton64((val) << (64 - n_bits)))
@@ -7634,25 +7693,33 @@ action_args_parse(struct action *a, const char *args, uint8_t *data)
 		struct field *f = &a->st->fields[i];
 		char *arg_name = tokens[i * 2];
 		char *arg_val = tokens[i * 2 + 1];
-		uint64_t val;
 
 		if (strcmp(arg_name, f->name)) {
 			status = -EINVAL;
 			goto error;
 		}
 
-		val = strtoull(arg_val, &arg_val, 0);
-		if (arg_val[0]) {
-			status = -EINVAL;
-			goto error;
-		}
+		if (f->n_bits <= 64) {
+			uint64_t val;
 
-		/* Endianness conversion. */
-		if (a->args_endianness[i])
-			val = field_hton(val, f->n_bits);
+			val = strtoull(arg_val, &arg_val, 0);
+			if (arg_val[0]) {
+				status = -EINVAL;
+				goto error;
+			}
+
+			/* Endianness conversion. */
+			if (a->args_endianness[i])
+				val = field_hton(val, f->n_bits);
+
+			/* Copy to entry. */
+			memcpy(&data[offset], (uint8_t *)&val, f->n_bits / 8);
+		} else {
+			status = hex_string_parse(arg_val, &data[offset], f->n_bits / 8);
+			if (status)
+				goto error;
+		}
 
-		/* Copy to entry. */
-		memcpy(&data[offset], (uint8_t *)&val, f->n_bits / 8);
 		offset += f->n_bits / 8;
 	}
 
-- 
2.34.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 4/4] pipeline: add instruction support for moving large structure fields
  2022-08-12  9:54 [PATCH 0/4] pipeline: support large structure fields Cristian Dumitrescu
                   ` (2 preceding siblings ...)
  2022-08-12  9:54 ` [PATCH 3/4] pipeline: support large default action arguments Cristian Dumitrescu
@ 2022-08-12  9:54 ` Cristian Dumitrescu
  2022-09-23 11:56 ` [PATCH 0/4] pipeline: support " Thomas Monjalon
  4 siblings, 0 replies; 6+ messages in thread
From: Cristian Dumitrescu @ 2022-08-12  9:54 UTC (permalink / raw)
  To: dev; +Cc: Harshad Suresh Narayane

Add support to the move instruction for operands bigger than 64 bits.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Harshad Suresh Narayane <harshad.suresh.narayane@intel.com>
---
 lib/pipeline/rte_swx_pipeline.c          | 71 +++++++++++++++++----
 lib/pipeline/rte_swx_pipeline_internal.h | 78 ++++++++++++++++++++++--
 2 files changed, 131 insertions(+), 18 deletions(-)

diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 48b9df0fef..2cac4caa95 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -2969,20 +2969,28 @@ instr_mov_translate(struct rte_swx_pipeline *p,
 
 	fdst = struct_field_parse(p, NULL, dst, &dst_struct_id);
 	CHECK(fdst, EINVAL);
-	CHECK(!fdst->var_size && (fdst->n_bits <= 64), EINVAL);
+	CHECK(!fdst->var_size, EINVAL);
 
-	/* MOV, MOV_MH, MOV_HM or MOV_HH. */
+	/* MOV, MOV_MH, MOV_HM, MOV_HH, MOV16, MOVDMA. */
 	fsrc = struct_field_parse(p, action, src, &src_struct_id);
 	if (fsrc) {
-		CHECK(!fsrc->var_size && (fsrc->n_bits <= 64), EINVAL);
+		CHECK(!fsrc->var_size, EINVAL);
+
+		if (fdst->n_bits <= 64 && fsrc->n_bits <= 64) {
+			instr->type = INSTR_MOV;
+			if (dst[0] != 'h' && src[0] == 'h')
+				instr->type = INSTR_MOV_MH;
+			if (dst[0] == 'h' && src[0] != 'h')
+				instr->type = INSTR_MOV_HM;
+			if (dst[0] == 'h' && src[0] == 'h')
+				instr->type = INSTR_MOV_HH;
+		} else {
+			CHECK(fdst->n_bits == fsrc->n_bits, EINVAL);
 
-		instr->type = INSTR_MOV;
-		if (dst[0] != 'h' && src[0] == 'h')
-			instr->type = INSTR_MOV_MH;
-		if (dst[0] == 'h' && src[0] != 'h')
-			instr->type = INSTR_MOV_HM;
-		if (dst[0] == 'h' && src[0] == 'h')
-			instr->type = INSTR_MOV_HH;
+			instr->type = INSTR_MOV_DMA;
+			if (fdst->n_bits == 128)
+				instr->type = INSTR_MOV_128;
+		}
 
 		instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
 		instr->mov.dst.n_bits = fdst->n_bits;
@@ -2994,6 +3002,7 @@ instr_mov_translate(struct rte_swx_pipeline *p,
 	}
 
 	/* MOV_I. */
+	CHECK(fdst->n_bits <= 64, EINVAL);
 	src_val = strtoull(src, &src, 0);
 	CHECK(!src[0], EINVAL);
 
@@ -3056,6 +3065,30 @@ instr_mov_hh_exec(struct rte_swx_pipeline *p)
 	thread_ip_inc(p);
 }
 
+static inline void
+instr_mov_dma_exec(struct rte_swx_pipeline *p)
+{
+	struct thread *t = &p->threads[p->thread_id];
+	struct instruction *ip = t->ip;
+
+	__instr_mov_dma_exec(p, t, ip);
+
+	/* Thread. */
+	thread_ip_inc(p);
+}
+
+static inline void
+instr_mov_128_exec(struct rte_swx_pipeline *p)
+{
+	struct thread *t = &p->threads[p->thread_id];
+	struct instruction *ip = t->ip;
+
+	__instr_mov_128_exec(p, t, ip);
+
+	/* Thread. */
+	thread_ip_inc(p);
+}
+
 static inline void
 instr_mov_i_exec(struct rte_swx_pipeline *p)
 {
@@ -6781,12 +6814,14 @@ instr_pattern_validate_mov_all_search(struct rte_swx_pipeline *p,
 	if (!a || !a->st)
 		return 0;
 
-	/* First instruction: HDR_VALIDATE. Second instruction: MOV_HM. */
+	/* First instruction: HDR_VALIDATE. Second instruction: MOV_HM, MOV_DMA or MOV_128. */
 	if (data[0].invalid ||
 	    (instr[0].type != INSTR_HDR_VALIDATE) ||
 	    (n_instr < 2) ||
 	    data[1].invalid ||
-	    (instr[1].type != INSTR_MOV_HM) ||
+	    (instr[1].type != INSTR_MOV_HM &&
+	     instr[1].type != INSTR_MOV_DMA &&
+	     instr[1].type != INSTR_MOV_128) ||
 	    instr[1].mov.src.struct_id)
 		return 0;
 
@@ -6807,7 +6842,9 @@ instr_pattern_validate_mov_all_search(struct rte_swx_pipeline *p,
 	for (i = 0; i < h->st->n_fields; i++)
 		if (data[1 + i].invalid ||
 		    data[1 + i].n_users ||
-		    (instr[1 + i].type != INSTR_MOV_HM) ||
+		    (instr[1 + i].type != INSTR_MOV_HM &&
+		     instr[1 + i].type != INSTR_MOV_DMA &&
+		     instr[1 + i].type != INSTR_MOV_128) ||
 		    (instr[1 + i].mov.dst.struct_id != h->struct_id) ||
 		    (instr[1 + i].mov.dst.offset != h->st->fields[i].offset / 8) ||
 		    (instr[1 + i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
@@ -7147,6 +7184,8 @@ static instr_exec_t instruction_table[] = {
 	[INSTR_MOV_MH] = instr_mov_mh_exec,
 	[INSTR_MOV_HM] = instr_mov_hm_exec,
 	[INSTR_MOV_HH] = instr_mov_hh_exec,
+	[INSTR_MOV_DMA] = instr_mov_dma_exec,
+	[INSTR_MOV_128] = instr_mov_128_exec,
 	[INSTR_MOV_I] = instr_mov_i_exec,
 
 	[INSTR_DMA_HT] = instr_dma_ht_exec,
@@ -10950,6 +10989,8 @@ instr_type_to_name(struct instruction *instr)
 	case INSTR_MOV_MH: return "INSTR_MOV_MH";
 	case INSTR_MOV_HM: return "INSTR_MOV_HM";
 	case INSTR_MOV_HH: return "INSTR_MOV_HH";
+	case INSTR_MOV_DMA: return "INSTR_MOV_DMA";
+	case INSTR_MOV_128: return "INSTR_MOV_128";
 	case INSTR_MOV_I: return "INSTR_MOV_I";
 
 	case INSTR_DMA_HT: return "INSTR_DMA_HT";
@@ -11938,6 +11979,8 @@ static instruction_export_t export_table[] = {
 	[INSTR_MOV_MH] = instr_mov_export,
 	[INSTR_MOV_HM] = instr_mov_export,
 	[INSTR_MOV_HH] = instr_mov_export,
+	[INSTR_MOV_DMA] = instr_mov_export,
+	[INSTR_MOV_128] = instr_mov_export,
 	[INSTR_MOV_I] = instr_mov_export,
 
 	[INSTR_DMA_HT]  = instr_dma_ht_export,
@@ -12162,6 +12205,8 @@ instr_type_to_func(struct instruction *instr)
 	case INSTR_MOV_MH: return "__instr_mov_mh_exec";
 	case INSTR_MOV_HM: return "__instr_mov_hm_exec";
 	case INSTR_MOV_HH: return "__instr_mov_hh_exec";
+	case INSTR_MOV_DMA: return "__instr_mov_dma_exec";
+	case INSTR_MOV_128: return "__instr_mov_128_exec";
 	case INSTR_MOV_I: return "__instr_mov_i_exec";
 
 	case INSTR_DMA_HT: return "__instr_dma_ht_exec";
diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h
index 588cad62b5..6d65b635c6 100644
--- a/lib/pipeline/rte_swx_pipeline_internal.h
+++ b/lib/pipeline/rte_swx_pipeline_internal.h
@@ -307,11 +307,13 @@ enum instruction_type {
 	 * dst = src
 	 * dst = HMEF, src = HMEFTI
 	 */
-	INSTR_MOV,    /* dst = MEF, src = MEFT */
-	INSTR_MOV_MH, /* dst = MEF, src = H */
-	INSTR_MOV_HM, /* dst = H, src = MEFT */
-	INSTR_MOV_HH, /* dst = H, src = H */
-	INSTR_MOV_I,  /* dst = HMEF, src = I */
+	INSTR_MOV,     /* dst = MEF, src = MEFT; size(dst) <= 64 bits, size(src) <= 64 bits. */
+	INSTR_MOV_MH,  /* dst = MEF, src = H; size(dst) <= 64 bits, size(src) <= 64 bits. */
+	INSTR_MOV_HM,  /* dst = H, src = MEFT; size(dst) <= 64 bits, size(src) <= 64 bits. */
+	INSTR_MOV_HH,  /* dst = H, src = H; size(dst) <= 64 bits, size(src) <= 64 bits. */
+	INSTR_MOV_DMA, /* dst = HMEF, src = HMEF; size(dst) = size(src) > 64 bits, NBO format. */
+	INSTR_MOV_128, /* dst = HMEF, src = HMEF; size(dst) = size(src) = 128 bits, NBO format. */
+	INSTR_MOV_I,   /* dst = HMEF, src = I; size(dst) <= 64 bits. */
 
 	/* dma h.header t.field
 	 * memcpy(h.header, t.field, sizeof(h.header))
@@ -2485,6 +2487,72 @@ __instr_mov_hh_exec(struct rte_swx_pipeline *p __rte_unused,
 	MOV_HH(t, ip);
 }
 
+static inline void
+__instr_mov_dma_exec(struct rte_swx_pipeline *p __rte_unused,
+		     struct thread *t,
+		     const struct instruction *ip)
+{
+	uint8_t *dst_struct = t->structs[ip->mov.dst.struct_id];
+	uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->mov.dst.offset];
+	uint32_t *dst32_ptr;
+	uint16_t *dst16_ptr;
+	uint8_t *dst8_ptr;
+
+	uint8_t *src_struct = t->structs[ip->mov.src.struct_id];
+	uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->mov.src.offset];
+	uint32_t *src32_ptr;
+	uint16_t *src16_ptr;
+	uint8_t *src8_ptr;
+
+	uint32_t n = ip->mov.dst.n_bits >> 3, i;
+
+	TRACE("[Thread %2u] mov (dma) %u bytes\n", p->thread_id, n);
+
+	/* 8-byte transfers. */
+	for (i = 0; i < n >> 3; i++)
+		*dst64_ptr++ = *src64_ptr++;
+
+	/* 4-byte transfers. */
+	n &= 7;
+	dst32_ptr = (uint32_t *)dst64_ptr;
+	src32_ptr = (uint32_t *)src64_ptr;
+
+	for (i = 0; i < n >> 2; i++)
+		*dst32_ptr++ = *src32_ptr++;
+
+	/* 2-byte transfers. */
+	n &= 3;
+	dst16_ptr = (uint16_t *)dst32_ptr;
+	src16_ptr = (uint16_t *)src32_ptr;
+
+	for (i = 0; i < n >> 1; i++)
+		*dst16_ptr++ = *src16_ptr++;
+
+	/* 1-byte transfer. */
+	n &= 1;
+	dst8_ptr = (uint8_t *)dst16_ptr;
+	src8_ptr = (uint8_t *)src16_ptr;
+	if (n)
+		*dst8_ptr = *src8_ptr;
+}
+
+static inline void
+__instr_mov_128_exec(struct rte_swx_pipeline *p __rte_unused,
+		     struct thread *t,
+		     const struct instruction *ip)
+{
+	uint8_t *dst_struct = t->structs[ip->mov.dst.struct_id];
+	uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->mov.dst.offset];
+
+	uint8_t *src_struct = t->structs[ip->mov.src.struct_id];
+	uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->mov.src.offset];
+
+	TRACE("[Thread %2u] mov (128)\n", p->thread_id);
+
+	dst64_ptr[0] = src64_ptr[0];
+	dst64_ptr[1] = src64_ptr[1];
+}
+
 static inline void
 __instr_mov_i_exec(struct rte_swx_pipeline *p __rte_unused,
 		   struct thread *t,
-- 
2.34.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/4] pipeline: support large structure fields
  2022-08-12  9:54 [PATCH 0/4] pipeline: support large structure fields Cristian Dumitrescu
                   ` (3 preceding siblings ...)
  2022-08-12  9:54 ` [PATCH 4/4] pipeline: add instruction support for moving large structure fields Cristian Dumitrescu
@ 2022-09-23 11:56 ` Thomas Monjalon
  4 siblings, 0 replies; 6+ messages in thread
From: Thomas Monjalon @ 2022-09-23 11:56 UTC (permalink / raw)
  To: Cristian Dumitrescu; +Cc: dev

12/08/2022 11:54, Cristian Dumitrescu:
> This patch set adds support for structure fields bigger than 64 bits.
> These fields can be packet header or meta-data fields. They can be
> used as part of the table lookup key or as action arguments. They are
> now valid operands for the move instruction.
> 
> This is required for supporting the 128-bit IPv6 addresses, which up
> to now had to be split into two 64-bit fields.
> 
> Cristian Dumitrescu (4):
>   pipeline: remove the 64-bit limit for structure fields
>   pipeline: read large structure fields on the control path
>   pipeline: support large default action arguments
>   pipeline: add instruction support for moving large structure fields

Applied, thanks.




^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-09-23 11:56 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-12  9:54 [PATCH 0/4] pipeline: support large structure fields Cristian Dumitrescu
2022-08-12  9:54 ` [PATCH 1/4] pipeline: remove the 64-bit limit for " Cristian Dumitrescu
2022-08-12  9:54 ` [PATCH 2/4] pipeline: read large structure fields on the control path Cristian Dumitrescu
2022-08-12  9:54 ` [PATCH 3/4] pipeline: support large default action arguments Cristian Dumitrescu
2022-08-12  9:54 ` [PATCH 4/4] pipeline: add instruction support for moving large structure fields Cristian Dumitrescu
2022-09-23 11:56 ` [PATCH 0/4] pipeline: support " Thomas Monjalon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).