*/
INSTR_TX, /* port_out = M */
INSTR_TX_I, /* port_out = I */
+ INSTR_DROP,
/* extract h.header */
INSTR_HDR_EXTRACT,
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,
INSTR_LEARNER,
INSTR_LEARNER_AF,
- /* learn LEARNER ACTION_NAME */
+ /* learn LEARNER ACTION_NAME [ m.action_first_arg ] */
INSTR_LEARNER_LEARN,
/* forget */
struct instr_learn {
uint8_t action_id;
+ uint8_t mf_offset;
};
struct instr_extern_obj {
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;
/* 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;
struct learner_runtime {
void *mailbox;
uint8_t **key;
- uint8_t **action_data;
};
struct learner_statistics {
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)) {
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.
*/
{
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];
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;
continue;
} else {
+ ho = &t->headers_out[n_headers_out - 1];
+
ho_ptr = ho->ptr;
ho_nbytes = ho->n_bytes;
}
}
}
- ho->n_bytes = ho_nbytes;
+ if (ho)
+ ho->n_bytes = ho_nbytes;
t->n_headers_out = n_headers_out;
}
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];
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,
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;
*/
r = (r & 0xFFFF) + (r >> 16);
+ /* Apply 1's complement to the result. */
r = ~r & 0xFFFF;
r = r ? r : 0xFFFF;
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;
*/
r = (r & 0xFFFF) + (r >> 16);
+ /* Apply 1's complement to the result. */
r = ~r & 0xFFFF;
r = r ? r : 0xFFFF;
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;
/* 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. */
*/
r0 = (r0 & 0xFFFF) + (r0 >> 16);
+ /* Apply 1's complement to the result. */
r0 = ~r0 & 0xFFFF;
r0 = r0 ? r0 : 0xFFFF;
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;