pipeline: fix emit instruction for invalid headers
[dpdk.git] / lib / pipeline / rte_swx_pipeline_internal.h
index 3baae55..8d93299 100644 (file)
@@ -225,6 +225,7 @@ enum instruction_type {
         */
        INSTR_TX,   /* port_out = M */
        INSTR_TX_I, /* port_out = I */
+       INSTR_DROP,
 
        /* extract h.header */
        INSTR_HDR_EXTRACT,
@@ -304,16 +305,16 @@ enum instruction_type {
        INSTR_ALU_SUB_HI, /* dst = H, src = I */
 
        /* ckadd dst src
-        * dst = dst '+ src[0:1] '+ src[2:3] + ...
-        * dst = H, src = {H, h.header}
+        * dst = dst '+ src[0:1] '+ src[2:3] '+ ...
+        * dst = H, src = {H, h.header}, '+ = 1's complement addition operator
         */
        INSTR_ALU_CKADD_FIELD,    /* src = H */
-       INSTR_ALU_CKADD_STRUCT20, /* src = h.header, with sizeof(header) = 20 */
-       INSTR_ALU_CKADD_STRUCT,   /* src = h.hdeader, with any sizeof(header) */
+       INSTR_ALU_CKADD_STRUCT20, /* src = h.header, with sizeof(header) = 20 bytes. */
+       INSTR_ALU_CKADD_STRUCT,   /* src = h.header, with sizeof(header) any 4-byte multiple. */
 
        /* cksub dst src
         * dst = dst '- src
-        * dst = H, src = H
+        * dst = H, src = H, '- = 1's complement subtraction operator
         */
        INSTR_ALU_CKSUB_FIELD,
 
@@ -448,7 +449,7 @@ enum instruction_type {
        INSTR_LEARNER,
        INSTR_LEARNER_AF,
 
-       /* learn LEARNER ACTION_NAME */
+       /* learn LEARNER ACTION_NAME [ m.action_first_arg ] */
        INSTR_LEARNER_LEARN,
 
        /* forget */
@@ -583,6 +584,7 @@ struct instr_table {
 
 struct instr_learn {
        uint8_t action_id;
+       uint8_t mf_offset;
 };
 
 struct instr_extern_obj {
@@ -745,6 +747,8 @@ struct table {
        uint32_t n_actions;
        int default_action_is_const;
        uint32_t action_data_size_max;
+       int *action_is_for_table_entries;
+       int *action_is_for_default_entry;
 
        uint32_t size;
        uint32_t id;
@@ -809,12 +813,13 @@ struct learner {
 
        /* Action. */
        struct action **actions;
-       struct field **action_arg;
        struct action *default_action;
        uint8_t *default_action_data;
        uint32_t n_actions;
        int default_action_is_const;
        uint32_t action_data_size_max;
+       int *action_is_for_table_entries;
+       int *action_is_for_default_entry;
 
        uint32_t size;
        uint32_t timeout;
@@ -826,7 +831,6 @@ TAILQ_HEAD(learner_tailq, learner);
 struct learner_runtime {
        void *mailbox;
        uint8_t **key;
-       uint8_t **action_data;
 };
 
 struct learner_statistics {
@@ -1559,7 +1563,7 @@ emit_handler(struct thread *t)
                return;
        }
 
-       /* Header encapsulation (optionally, with prior header decasulation). */
+       /* Header encapsulation (optionally, with prior header decapsulation). */
        if ((t->n_headers_out == 2) &&
            (h1->ptr + h1->n_bytes == t->ptr) &&
            (h0->ptr == h0->ptr0)) {
@@ -1628,6 +1632,25 @@ __instr_tx_i_exec(struct rte_swx_pipeline *p, struct thread *t, const struct ins
        port->pkt_tx(port->obj, pkt);
 }
 
+static inline void
+__instr_drop_exec(struct rte_swx_pipeline *p,
+                 struct thread *t,
+                 const struct instruction *ip __rte_unused)
+{
+       uint64_t port_id = p->n_ports_out - 1;
+       struct port_out_runtime *port = &p->out[port_id];
+       struct rte_swx_pkt *pkt = &t->pkt;
+
+       TRACE("[Thread %2u]: drop 1 pkt\n",
+             p->thread_id);
+
+       /* Headers. */
+       emit_handler(t);
+
+       /* Packet. */
+       port->pkt_tx(port->obj, pkt);
+}
+
 /*
  * extract.
  */
@@ -1817,9 +1840,9 @@ __instr_hdr_emit_many_exec(struct rte_swx_pipeline *p __rte_unused,
 {
        uint64_t valid_headers = t->valid_headers;
        uint32_t n_headers_out = t->n_headers_out;
-       struct header_out_runtime *ho = &t->headers_out[n_headers_out - 1];
+       struct header_out_runtime *ho = NULL;
        uint8_t *ho_ptr = NULL;
-       uint32_t ho_nbytes = 0, first = 1, i;
+       uint32_t ho_nbytes = 0, i;
 
        for (i = 0; i < n_emit; i++) {
                uint32_t header_id = ip->io.hdr.header_id[i];
@@ -1831,18 +1854,21 @@ __instr_hdr_emit_many_exec(struct rte_swx_pipeline *p __rte_unused,
 
                uint8_t *hi_ptr = t->structs[struct_id];
 
-               if (!MASK64_BIT_GET(valid_headers, header_id))
+               if (!MASK64_BIT_GET(valid_headers, header_id)) {
+                       TRACE("[Thread %2u]: emit header %u (invalid)\n",
+                             p->thread_id,
+                             header_id);
+
                        continue;
+               }
 
-               TRACE("[Thread %2u]: emit header %u\n",
+               TRACE("[Thread %2u]: emit header %u (valid)\n",
                      p->thread_id,
                      header_id);
 
                /* Headers. */
-               if (first) {
-                       first = 0;
-
-                       if (!t->n_headers_out) {
+               if (!ho) {
+                       if (!n_headers_out) {
                                ho = &t->headers_out[0];
 
                                ho->ptr0 = hi_ptr0;
@@ -1855,6 +1881,8 @@ __instr_hdr_emit_many_exec(struct rte_swx_pipeline *p __rte_unused,
 
                                continue;
                        } else {
+                               ho = &t->headers_out[n_headers_out - 1];
+
                                ho_ptr = ho->ptr;
                                ho_nbytes = ho->n_bytes;
                        }
@@ -1876,7 +1904,8 @@ __instr_hdr_emit_many_exec(struct rte_swx_pipeline *p __rte_unused,
                }
        }
 
-       ho->n_bytes = ho_nbytes;
+       if (ho)
+               ho->n_bytes = ho_nbytes;
        t->n_headers_out = n_headers_out;
 }
 
@@ -2017,6 +2046,7 @@ __instr_learn_exec(struct rte_swx_pipeline *p,
                   const struct instruction *ip)
 {
        uint64_t action_id = ip->learn.action_id;
+       uint32_t mf_offset = ip->learn.mf_offset;
        uint32_t learner_id = t->learner_id;
        struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
                p->n_selectors + learner_id];
@@ -2029,7 +2059,7 @@ __instr_learn_exec(struct rte_swx_pipeline *p,
                                           l->mailbox,
                                           t->time,
                                           action_id,
-                                          l->action_data[action_id]);
+                                          &t->metadata[mf_offset]);
 
        TRACE("[Thread %2u] learner %u learn %s\n",
              p->thread_id,
@@ -2676,6 +2706,7 @@ __instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p __rte_unused,
        src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
        src = src64 & src64_mask;
 
+       /* Initialize the result with destination 1's complement. */
        r = dst;
        r = ~r & 0xFFFF;
 
@@ -2703,6 +2734,7 @@ __instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p __rte_unused,
         */
        r = (r & 0xFFFF) + (r >> 16);
 
+       /* Apply 1's complement to the result. */
        r = ~r & 0xFFFF;
        r = r ? r : 0xFFFF;
 
@@ -2732,6 +2764,7 @@ __instr_alu_cksub_field_exec(struct rte_swx_pipeline *p __rte_unused,
        src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
        src = src64 & src64_mask;
 
+       /* Initialize the result with destination 1's complement. */
        r = dst;
        r = ~r & 0xFFFF;
 
@@ -2771,6 +2804,7 @@ __instr_alu_cksub_field_exec(struct rte_swx_pipeline *p __rte_unused,
         */
        r = (r & 0xFFFF) + (r >> 16);
 
+       /* Apply 1's complement to the result. */
        r = ~r & 0xFFFF;
        r = r ? r : 0xFFFF;
 
@@ -2783,7 +2817,7 @@ __instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p __rte_unused,
                                const struct instruction *ip)
 {
        uint8_t *dst_struct, *src_struct;
-       uint16_t *dst16_ptr;
+       uint16_t *dst16_ptr, dst;
        uint32_t *src32_ptr;
        uint64_t r0, r1;
 
@@ -2792,13 +2826,18 @@ __instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p __rte_unused,
        /* Structs. */
        dst_struct = t->structs[ip->alu.dst.struct_id];
        dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
+       dst = *dst16_ptr;
 
        src_struct = t->structs[ip->alu.src.struct_id];
        src32_ptr = (uint32_t *)&src_struct[0];
 
-       r0 = src32_ptr[0]; /* r0 is a 32-bit number. */
+       /* Initialize the result with destination 1's complement. */
+       r0 = dst;
+       r0 = ~r0 & 0xFFFF;
+
+       r0 += src32_ptr[0]; /* The output r0 is a 33-bit number. */
        r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
-       r0 += src32_ptr[2]; /* The output r0 is a 33-bit number. */
+       r0 += src32_ptr[2]; /* The output r0 is a 34-bit number. */
        r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
        r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
 
@@ -2819,6 +2858,7 @@ __instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p __rte_unused,
         */
        r0 = (r0 & 0xFFFF) + (r0 >> 16);
 
+       /* Apply 1's complement to the result. */
        r0 = ~r0 & 0xFFFF;
        r0 = r0 ? r0 : 0xFFFF;
 
@@ -2830,45 +2870,58 @@ __instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p __rte_unused,
                              struct thread *t,
                              const struct instruction *ip)
 {
+       uint32_t src_header_id = ip->alu.src.n_bits; /* The src header ID is stored here. */
+       uint32_t n_src_header_bytes = t->headers[src_header_id].n_bytes;
        uint8_t *dst_struct, *src_struct;
-       uint16_t *dst16_ptr;
+       uint16_t *dst16_ptr, dst;
        uint32_t *src32_ptr;
-       uint64_t r = 0;
+       uint64_t r;
        uint32_t i;
 
+       if (n_src_header_bytes == 20) {
+               __instr_alu_ckadd_struct20_exec(p, t, ip);
+               return;
+       }
+
        TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
 
        /* Structs. */
        dst_struct = t->structs[ip->alu.dst.struct_id];
        dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
+       dst = *dst16_ptr;
 
        src_struct = t->structs[ip->alu.src.struct_id];
        src32_ptr = (uint32_t *)&src_struct[0];
 
-       /* The max number of 32-bit words in a 256-byte header is 8 = 2^3.
-        * Therefore, in the worst case scenario, a 35-bit number is added to a
-        * 16-bit number (the input r), so the output r is 36-bit number.
+       /* Initialize the result with destination 1's complement. */
+       r = dst;
+       r = ~r & 0xFFFF;
+
+       /* The max number of 32-bit words in a 32K-byte header is 2^13.
+        * Therefore, in the worst case scenario, a 45-bit number is added to a
+        * 16-bit number (the input r), so the output r is 46-bit number.
         */
-       for (i = 0; i < ip->alu.src.n_bits / 32; i++, src32_ptr++)
+       for (i = 0; i < n_src_header_bytes / 4; i++, src32_ptr++)
                r += *src32_ptr;
 
-       /* The first input is a 16-bit number. The second input is a 20-bit
-        * number. Their sum is a 21-bit number.
+       /* The first input is a 16-bit number. The second input is a 30-bit
+        * number. Their sum is a 31-bit number.
         */
        r = (r & 0xFFFF) + (r >> 16);
 
        /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
-        * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1000E).
+        * a 15-bit number (0 .. 0x7FFF). The sum is a 17-bit number (0 .. 0x17FFE).
         */
        r = (r & 0xFFFF) + (r >> 16);
 
        /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
         * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
-        * 0x1001E), the output r is (0 .. 31). So no carry bit can be
+        * 0x17FFE), the output r is (0 .. 0x7FFF). So no carry bit can be
         * generated, therefore the output r is always a 16-bit number.
         */
        r = (r & 0xFFFF) + (r >> 16);
 
+       /* Apply 1's complement to the result. */
        r = ~r & 0xFFFF;
        r = r ? r : 0xFFFF;