#include <string.h>
#include <stdio.h>
#include <errno.h>
+#include <inttypes.h>
#include <sys/queue.h>
#include <arpa/inet.h>
} while (0)
#define CHECK_NAME(name, err_code) \
- CHECK((name) && (name)[0], err_code)
+ CHECK((name) && \
+ (name)[0] && \
+ (strnlen((name), RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), \
+ err_code)
+
+#define CHECK_INSTRUCTION(instr, err_code) \
+ CHECK((instr) && \
+ (instr)[0] && \
+ (strnlen((instr), RTE_SWX_INSTRUCTION_SIZE) < \
+ RTE_SWX_INSTRUCTION_SIZE), \
+ err_code)
#ifndef TRACE_LEVEL
#define TRACE_LEVEL 0
struct instr_operand dst;
union {
struct instr_operand src;
- uint32_t src_val;
+ uint64_t src_val;
};
};
union {
struct instr_operand b;
- uint32_t b_val;
+ uint64_t b_val;
};
};
CHECK(p, EINVAL);
- CHECK(extern_type_name, EINVAL);
+ CHECK_NAME(extern_type_name, EINVAL);
type = extern_type_find(p, extern_type_name);
CHECK(type, EINVAL);
CHECK(type->n_funcs < RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX, ENOSPC);
- CHECK(name, EINVAL);
+ CHECK_NAME(name, EINVAL);
CHECK(!extern_type_member_func_find(type, name), EEXIST);
CHECK(member_func, EINVAL);
{
char *dst = tokens[1], *src = tokens[2];
struct field *fdst, *fsrc;
- uint32_t dst_struct_id, src_struct_id, src_val;
+ uint64_t src_val;
+ uint32_t dst_struct_id, src_struct_id;
CHECK(n_tokens == 3, EINVAL);
}
/* MOV_I. */
- src_val = strtoul(src, &src, 0);
+ src_val = strtoull(src, &src, 0);
CHECK(!src[0], EINVAL);
if (dst[0] == 'h')
- src_val = htonl(src_val);
+ src_val = hton64(src_val) >> (64 - fdst->n_bits);
instr->type = INSTR_MOV_I;
instr->mov.dst.struct_id = (uint8_t)dst_struct_id;
instr->mov.dst.n_bits = fdst->n_bits;
instr->mov.dst.offset = fdst->offset / 8;
- instr->mov.src_val = (uint32_t)src_val;
+ instr->mov.src_val = src_val;
return 0;
}
struct thread *t = &p->threads[p->thread_id];
struct instruction *ip = t->ip;
- TRACE("[Thread %2u] mov m.f %x\n",
+ TRACE("[Thread %2u] mov m.f %" PRIx64 "\n",
p->thread_id,
ip->mov.src_val);
{
char *dst = tokens[1], *src = tokens[2];
struct field *fdst, *fsrc;
- uint32_t dst_struct_id, src_struct_id, src_val;
+ uint64_t src_val;
+ uint32_t dst_struct_id, src_struct_id;
CHECK(n_tokens == 3, EINVAL);
}
/* ADD_MI, ADD_HI. */
- src_val = strtoul(src, &src, 0);
+ src_val = strtoull(src, &src, 0);
CHECK(!src[0], EINVAL);
instr->type = INSTR_ALU_ADD_MI;
instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
instr->alu.dst.n_bits = fdst->n_bits;
instr->alu.dst.offset = fdst->offset / 8;
- instr->alu.src_val = (uint32_t)src_val;
+ instr->alu.src_val = src_val;
return 0;
}
{
char *dst = tokens[1], *src = tokens[2];
struct field *fdst, *fsrc;
- uint32_t dst_struct_id, src_struct_id, src_val;
+ uint64_t src_val;
+ uint32_t dst_struct_id, src_struct_id;
CHECK(n_tokens == 3, EINVAL);
}
/* SUB_MI, SUB_HI. */
- src_val = strtoul(src, &src, 0);
+ src_val = strtoull(src, &src, 0);
CHECK(!src[0], EINVAL);
instr->type = INSTR_ALU_SUB_MI;
instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
instr->alu.dst.n_bits = fdst->n_bits;
instr->alu.dst.offset = fdst->offset / 8;
- instr->alu.src_val = (uint32_t)src_val;
+ instr->alu.src_val = src_val;
return 0;
}
{
char *dst = tokens[1], *src = tokens[2];
struct field *fdst, *fsrc;
- uint32_t dst_struct_id, src_struct_id, src_val;
+ uint64_t src_val;
+ uint32_t dst_struct_id, src_struct_id;
CHECK(n_tokens == 3, EINVAL);
}
/* SHL_MI, SHL_HI. */
- src_val = strtoul(src, &src, 0);
+ src_val = strtoull(src, &src, 0);
CHECK(!src[0], EINVAL);
instr->type = INSTR_ALU_SHL_MI;
instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
instr->alu.dst.n_bits = fdst->n_bits;
instr->alu.dst.offset = fdst->offset / 8;
- instr->alu.src_val = (uint32_t)src_val;
+ instr->alu.src_val = src_val;
return 0;
}
{
char *dst = tokens[1], *src = tokens[2];
struct field *fdst, *fsrc;
- uint32_t dst_struct_id, src_struct_id, src_val;
+ uint64_t src_val;
+ uint32_t dst_struct_id, src_struct_id;
CHECK(n_tokens == 3, EINVAL);
}
/* SHR_MI, SHR_HI. */
- src_val = strtoul(src, &src, 0);
+ src_val = strtoull(src, &src, 0);
CHECK(!src[0], EINVAL);
instr->type = INSTR_ALU_SHR_MI;
instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
instr->alu.dst.n_bits = fdst->n_bits;
instr->alu.dst.offset = fdst->offset / 8;
- instr->alu.src_val = (uint32_t)src_val;
+ instr->alu.src_val = src_val;
return 0;
}
{
char *dst = tokens[1], *src = tokens[2];
struct field *fdst, *fsrc;
- uint32_t dst_struct_id, src_struct_id, src_val;
+ uint64_t src_val;
+ uint32_t dst_struct_id, src_struct_id;
CHECK(n_tokens == 3, EINVAL);
}
/* AND_I. */
- src_val = strtoul(src, &src, 0);
+ src_val = strtoull(src, &src, 0);
CHECK(!src[0], EINVAL);
if (dst[0] == 'h')
- src_val = htonl(src_val);
+ src_val = hton64(src_val) >> (64 - fdst->n_bits);
instr->type = INSTR_ALU_AND_I;
instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
instr->alu.dst.n_bits = fdst->n_bits;
instr->alu.dst.offset = fdst->offset / 8;
- instr->alu.src_val = (uint32_t)src_val;
+ instr->alu.src_val = src_val;
return 0;
}
{
char *dst = tokens[1], *src = tokens[2];
struct field *fdst, *fsrc;
- uint32_t dst_struct_id, src_struct_id, src_val;
+ uint64_t src_val;
+ uint32_t dst_struct_id, src_struct_id;
CHECK(n_tokens == 3, EINVAL);
}
/* OR_I. */
- src_val = strtoul(src, &src, 0);
+ src_val = strtoull(src, &src, 0);
CHECK(!src[0], EINVAL);
if (dst[0] == 'h')
- src_val = htonl(src_val);
+ src_val = hton64(src_val) >> (64 - fdst->n_bits);
instr->type = INSTR_ALU_OR_I;
instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
instr->alu.dst.n_bits = fdst->n_bits;
instr->alu.dst.offset = fdst->offset / 8;
- instr->alu.src_val = (uint32_t)src_val;
+ instr->alu.src_val = src_val;
return 0;
}
{
char *dst = tokens[1], *src = tokens[2];
struct field *fdst, *fsrc;
- uint32_t dst_struct_id, src_struct_id, src_val;
+ uint64_t src_val;
+ uint32_t dst_struct_id, src_struct_id;
CHECK(n_tokens == 3, EINVAL);
}
/* XOR_I. */
- src_val = strtoul(src, &src, 0);
+ src_val = strtoull(src, &src, 0);
CHECK(!src[0], EINVAL);
if (dst[0] == 'h')
- src_val = htonl(src_val);
+ src_val = hton64(src_val) >> (64 - fdst->n_bits);
instr->type = INSTR_ALU_XOR_I;
instr->alu.dst.struct_id = (uint8_t)dst_struct_id;
instr->alu.dst.n_bits = fdst->n_bits;
instr->alu.dst.offset = fdst->offset / 8;
- instr->alu.src_val = (uint32_t)src_val;
+ instr->alu.src_val = src_val;
return 0;
}
{
struct header *h;
- CHECK(n_tokens == 2, EINVAL);
+ CHECK(n_tokens == 3, EINVAL);
strcpy(data->jmp_label, tokens[1]);
{
char *a = tokens[2], *b = tokens[3];
struct field *fa, *fb;
- uint32_t a_struct_id, b_struct_id, b_val;
+ uint64_t b_val;
+ uint32_t a_struct_id, b_struct_id;
CHECK(n_tokens == 4, EINVAL);
}
/* JMP_EQ_I. */
- b_val = strtoul(b, &b, 0);
+ b_val = strtoull(b, &b, 0);
CHECK(!b[0], EINVAL);
if (a[0] == 'h')
- b_val = htonl(b_val);
+ b_val = hton64(b_val) >> (64 - fa->n_bits);
instr->type = INSTR_JMP_EQ_I;
instr->jmp.ip = NULL; /* Resolved later. */
instr->jmp.a.struct_id = (uint8_t)a_struct_id;
instr->jmp.a.n_bits = fa->n_bits;
instr->jmp.a.offset = fa->offset / 8;
- instr->jmp.b_val = (uint32_t)b_val;
+ instr->jmp.b_val = b_val;
return 0;
}
{
char *a = tokens[2], *b = tokens[3];
struct field *fa, *fb;
- uint32_t a_struct_id, b_struct_id, b_val;
+ uint64_t b_val;
+ uint32_t a_struct_id, b_struct_id;
CHECK(n_tokens == 4, EINVAL);
}
/* JMP_NEQ_I. */
- b_val = strtoul(b, &b, 0);
+ b_val = strtoull(b, &b, 0);
CHECK(!b[0], EINVAL);
if (a[0] == 'h')
- b_val = htonl(b_val);
+ b_val = hton64(b_val) >> (64 - fa->n_bits);
instr->type = INSTR_JMP_NEQ_I;
instr->jmp.ip = NULL; /* Resolved later. */
instr->jmp.a.struct_id = (uint8_t)a_struct_id;
instr->jmp.a.n_bits = fa->n_bits;
instr->jmp.a.offset = fa->offset / 8;
- instr->jmp.b_val = (uint32_t)b_val;
+ instr->jmp.b_val = b_val;
return 0;
}
{
char *a = tokens[2], *b = tokens[3];
struct field *fa, *fb;
- uint32_t a_struct_id, b_struct_id, b_val;
+ uint64_t b_val;
+ uint32_t a_struct_id, b_struct_id;
CHECK(n_tokens == 4, EINVAL);
}
/* JMP_LT_MI, JMP_LT_HI. */
- b_val = strtoul(b, &b, 0);
+ b_val = strtoull(b, &b, 0);
CHECK(!b[0], EINVAL);
instr->type = INSTR_JMP_LT_MI;
instr->jmp.a.struct_id = (uint8_t)a_struct_id;
instr->jmp.a.n_bits = fa->n_bits;
instr->jmp.a.offset = fa->offset / 8;
- instr->jmp.b_val = (uint32_t)b_val;
+ instr->jmp.b_val = b_val;
return 0;
}
{
char *a = tokens[2], *b = tokens[3];
struct field *fa, *fb;
- uint32_t a_struct_id, b_struct_id, b_val;
+ uint64_t b_val;
+ uint32_t a_struct_id, b_struct_id;
CHECK(n_tokens == 4, EINVAL);
}
/* JMP_GT_MI, JMP_GT_HI. */
- b_val = strtoul(b, &b, 0);
+ b_val = strtoull(b, &b, 0);
CHECK(!b[0], EINVAL);
instr->type = INSTR_JMP_GT_MI;
instr->jmp.a.struct_id = (uint8_t)a_struct_id;
instr->jmp.a.n_bits = fa->n_bits;
instr->jmp.a.offset = fa->offset / 8;
- instr->jmp.b_val = (uint32_t)b_val;
+ instr->jmp.b_val = b_val;
return 0;
}
t->ip = t->ret;
}
-#define RTE_SWX_INSTRUCTION_TOKENS_MAX 16
-
static int
instr_translate(struct rte_swx_pipeline *p,
struct action *action,
break;
CHECK(n_tokens < RTE_SWX_INSTRUCTION_TOKENS_MAX, EINVAL);
+ CHECK_NAME(token, EINVAL);
tokens[n_tokens] = token;
n_tokens++;
data->jmp_label);
CHECK(found, EINVAL);
- instr->jmp.ip = &instr[found - instruction_data];
+ instr->jmp.ip = &instructions[found - instruction_data];
}
return 0;
for (i = 0; i < n_instructions; i++) {
type = instr[i].type;
- if (instr[i].type == INSTR_TX)
+ if (type == INSTR_TX)
break;
}
CHECK(i < n_instructions, EINVAL);
{
struct instruction *instr = NULL;
struct instruction_data *data = NULL;
- char *string = NULL;
int err = 0;
uint32_t i;
CHECK(n_instructions, EINVAL);
CHECK(instructions, EINVAL);
for (i = 0; i < n_instructions; i++)
- CHECK(instructions[i], EINVAL);
+ CHECK_INSTRUCTION(instructions[i], EINVAL);
/* Memory allocation. */
instr = calloc(n_instructions, sizeof(struct instruction));
}
for (i = 0; i < n_instructions; i++) {
- string = strdup(instructions[i]);
+ char *string = strdup(instructions[i]);
if (!string) {
err = ENOMEM;
goto error;
}
err = instr_translate(p, a, string, &instr[i], &data[i]);
- if (err)
+ if (err) {
+ free(string);
goto error;
+ }
free(string);
}
if (err)
goto error;
- free(data);
-
if (a) {
a->instructions = instr;
a->n_instructions = n_instructions;
p->n_instructions = n_instructions;
}
+ free(data);
return 0;
error:
- free(string);
free(data);
free(instr);
return err;
return NULL;
}
+static struct action *
+action_find_by_id(struct rte_swx_pipeline *p, uint32_t id)
+{
+ struct action *action = NULL;
+
+ TAILQ_FOREACH(action, &p->actions, node)
+ if (action->id == id)
+ return action;
+
+ return NULL;
+}
+
static struct field *
action_field_find(struct action *a, const char *name)
{
struct action *a;
uint32_t action_data_size;
- CHECK(action_name, EINVAL);
+ CHECK_NAME(action_name, EINVAL);
a = action_find(p, action_name);
CHECK(a, EINVAL);
action_data_size_max = action_data_size;
}
- CHECK(params->default_action_name, EINVAL);
+ CHECK_NAME(params->default_action_name, EINVAL);
for (i = 0; i < p->n_actions; i++)
if (!strcmp(params->action_names[i],
params->default_action_name))
!params->default_action_data, EINVAL);
/* Table type checks. */
+ if (recommended_table_type_name)
+ CHECK_NAME(recommended_table_type_name, EINVAL);
+
if (params->n_fields) {
enum rte_swx_table_match_type match_type;
instr_exec(p);
}
+void
+rte_swx_pipeline_flush(struct rte_swx_pipeline *p)
+{
+ uint32_t i;
+
+ for (i = 0; i < p->n_ports_out; i++) {
+ struct port_out_runtime *port = &p->out[i];
+
+ if (port->flush)
+ port->flush(port->obj);
+ }
+}
+
/*
* Control.
*/
+int
+rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
+ struct rte_swx_ctl_pipeline_info *pipeline)
+{
+ struct action *action;
+ struct table *table;
+ uint32_t n_actions = 0, n_tables = 0;
+
+ if (!p || !pipeline)
+ return -EINVAL;
+
+ TAILQ_FOREACH(action, &p->actions, node)
+ n_actions++;
+
+ TAILQ_FOREACH(table, &p->tables, node)
+ n_tables++;
+
+ pipeline->n_ports_in = p->n_ports_in;
+ pipeline->n_ports_out = p->n_ports_out;
+ pipeline->n_actions = n_actions;
+ pipeline->n_tables = n_tables;
+
+ return 0;
+}
+
+int
+rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node)
+{
+ if (!p || !numa_node)
+ return -EINVAL;
+
+ *numa_node = p->numa_node;
+ return 0;
+}
+
+int
+rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p,
+ uint32_t action_id,
+ struct rte_swx_ctl_action_info *action)
+{
+ struct action *a = NULL;
+
+ if (!p || (action_id >= p->n_actions) || !action)
+ return -EINVAL;
+
+ a = action_find_by_id(p, action_id);
+ if (!a)
+ return -EINVAL;
+
+ strcpy(action->name, a->name);
+ action->n_args = a->st ? a->st->n_fields : 0;
+ return 0;
+}
+
+int
+rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
+ uint32_t action_id,
+ uint32_t action_arg_id,
+ struct rte_swx_ctl_action_arg_info *action_arg)
+{
+ struct action *a = NULL;
+ struct field *arg = NULL;
+
+ if (!p || (action_id >= p->n_actions) || !action_arg)
+ return -EINVAL;
+
+ a = action_find_by_id(p, action_id);
+ if (!a || !a->st || (action_arg_id >= a->st->n_fields))
+ return -EINVAL;
+
+ arg = &a->st->fields[action_arg_id];
+ strcpy(action_arg->name, arg->name);
+ action_arg->n_bits = arg->n_bits;
+
+ return 0;
+}
+
+int
+rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p,
+ uint32_t table_id,
+ struct rte_swx_ctl_table_info *table)
+{
+ struct table *t = NULL;
+
+ if (!p || !table)
+ return -EINVAL;
+
+ t = table_find_by_id(p, table_id);
+ if (!t)
+ return -EINVAL;
+
+ strcpy(table->name, t->name);
+ strcpy(table->args, t->args);
+ table->n_match_fields = t->n_fields;
+ table->n_actions = t->n_actions;
+ table->default_action_is_const = t->default_action_is_const;
+ table->size = t->size;
+ return 0;
+}
+
+int
+rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p,
+ uint32_t table_id,
+ uint32_t match_field_id,
+ struct rte_swx_ctl_table_match_field_info *match_field)
+{
+ struct table *t;
+ struct match_field *f;
+
+ if (!p || (table_id >= p->n_tables) || !match_field)
+ return -EINVAL;
+
+ t = table_find_by_id(p, table_id);
+ if (!t || (match_field_id >= t->n_fields))
+ return -EINVAL;
+
+ f = &t->fields[match_field_id];
+ match_field->match_type = f->match_type;
+ match_field->is_header = t->is_header;
+ match_field->n_bits = f->field->n_bits;
+ match_field->offset = f->field->offset;
+
+ return 0;
+}
+
+int
+rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p,
+ uint32_t table_id,
+ uint32_t table_action_id,
+ struct rte_swx_ctl_table_action_info *table_action)
+{
+ struct table *t;
+
+ if (!p || (table_id >= p->n_tables) || !table_action)
+ return -EINVAL;
+
+ t = table_find_by_id(p, table_id);
+ if (!t || (table_action_id >= t->n_actions))
+ return -EINVAL;
+
+ table_action->action_id = t->actions[table_action_id]->id;
+
+ return 0;
+}
+
+int
+rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
+ uint32_t table_id,
+ struct rte_swx_table_ops *table_ops,
+ int *is_stub)
+{
+ struct table *t;
+
+ if (!p || (table_id >= p->n_tables))
+ return -EINVAL;
+
+ t = table_find_by_id(p, table_id);
+ if (!t)
+ return -EINVAL;
+
+ if (t->type) {
+ if (table_ops)
+ memcpy(table_ops, &t->type->ops, sizeof(*table_ops));
+ *is_stub = 0;
+ } else {
+ *is_stub = 1;
+ }
+
+ return 0;
+}
+
int
rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
struct rte_swx_table_state **table_state)
p->table_state = table_state;
return 0;
}
+
+int
+rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p,
+ uint32_t port_id,
+ struct rte_swx_port_in_stats *stats)
+{
+ struct port_in *port;
+
+ if (!p || !stats)
+ return -EINVAL;
+
+ port = port_in_find(p, port_id);
+ if (!port)
+ return -EINVAL;
+
+ port->type->ops.stats_read(port->obj, stats);
+ return 0;
+}
+
+int
+rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
+ uint32_t port_id,
+ struct rte_swx_port_out_stats *stats)
+{
+ struct port_out *port;
+
+ if (!p || !stats)
+ return -EINVAL;
+
+ port = port_out_find(p, port_id);
+ if (!port)
+ return -EINVAL;
+
+ port->type->ops.stats_read(port->obj, stats);
+ return 0;
+}