pipeline: support hash functions
Add support for hash functions that compute a signature for an array of bytes read from a packet header or meta-data. Useful for flow affinity-based load balancing. Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
This commit is contained in:
parent
80dd28aff8
commit
92f2944daf
@ -6,6 +6,9 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#include <rte_jhash.h>
|
||||||
|
#include <rte_hash_crc.h>
|
||||||
|
|
||||||
#include <rte_swx_port_ethdev.h>
|
#include <rte_swx_port_ethdev.h>
|
||||||
#include <rte_swx_port_fd.h>
|
#include <rte_swx_port_fd.h>
|
||||||
#include <rte_swx_port_ring.h>
|
#include <rte_swx_port_ring.h>
|
||||||
@ -1166,6 +1169,94 @@ extern_func_free(struct rte_swx_pipeline *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hash function.
|
||||||
|
*/
|
||||||
|
static struct hash_func *
|
||||||
|
hash_func_find(struct rte_swx_pipeline *p, const char *name)
|
||||||
|
{
|
||||||
|
struct hash_func *elem;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(elem, &p->hash_funcs, node)
|
||||||
|
if (strcmp(elem->name, name) == 0)
|
||||||
|
return elem;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rte_swx_pipeline_hash_func_register(struct rte_swx_pipeline *p,
|
||||||
|
const char *name,
|
||||||
|
rte_swx_hash_func_t func)
|
||||||
|
{
|
||||||
|
struct hash_func *f;
|
||||||
|
|
||||||
|
CHECK(p, EINVAL);
|
||||||
|
|
||||||
|
CHECK_NAME(name, EINVAL);
|
||||||
|
CHECK(!hash_func_find(p, name), EEXIST);
|
||||||
|
|
||||||
|
CHECK(func, EINVAL);
|
||||||
|
|
||||||
|
/* Node allocation. */
|
||||||
|
f = calloc(1, sizeof(struct hash_func));
|
||||||
|
CHECK(func, ENOMEM);
|
||||||
|
|
||||||
|
/* Node initialization. */
|
||||||
|
strcpy(f->name, name);
|
||||||
|
f->func = func;
|
||||||
|
f->id = p->n_hash_funcs;
|
||||||
|
|
||||||
|
/* Node add to tailq. */
|
||||||
|
TAILQ_INSERT_TAIL(&p->hash_funcs, f, node);
|
||||||
|
p->n_hash_funcs++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hash_func_build(struct rte_swx_pipeline *p)
|
||||||
|
{
|
||||||
|
struct hash_func *func;
|
||||||
|
|
||||||
|
/* Memory allocation. */
|
||||||
|
p->hash_func_runtime = calloc(p->n_hash_funcs, sizeof(struct hash_func_runtime));
|
||||||
|
CHECK(p->hash_func_runtime, ENOMEM);
|
||||||
|
|
||||||
|
/* Hash function. */
|
||||||
|
TAILQ_FOREACH(func, &p->hash_funcs, node) {
|
||||||
|
struct hash_func_runtime *r = &p->hash_func_runtime[func->id];
|
||||||
|
|
||||||
|
r->func = func->func;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hash_func_build_free(struct rte_swx_pipeline *p)
|
||||||
|
{
|
||||||
|
free(p->hash_func_runtime);
|
||||||
|
p->hash_func_runtime = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hash_func_free(struct rte_swx_pipeline *p)
|
||||||
|
{
|
||||||
|
hash_func_build_free(p);
|
||||||
|
|
||||||
|
for ( ; ; ) {
|
||||||
|
struct hash_func *elem;
|
||||||
|
|
||||||
|
elem = TAILQ_FIRST(&p->hash_funcs);
|
||||||
|
if (!elem)
|
||||||
|
break;
|
||||||
|
|
||||||
|
TAILQ_REMOVE(&p->hash_funcs, elem, node);
|
||||||
|
free(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Header.
|
* Header.
|
||||||
*/
|
*/
|
||||||
@ -2796,6 +2887,61 @@ instr_extern_func_exec(struct rte_swx_pipeline *p)
|
|||||||
thread_yield_cond(p, done ^ 1);
|
thread_yield_cond(p, done ^ 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hash.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
instr_hash_translate(struct rte_swx_pipeline *p,
|
||||||
|
struct action *action,
|
||||||
|
char **tokens,
|
||||||
|
int n_tokens,
|
||||||
|
struct instruction *instr,
|
||||||
|
struct instruction_data *data __rte_unused)
|
||||||
|
{
|
||||||
|
struct hash_func *func;
|
||||||
|
struct field *dst, *src_first, *src_last;
|
||||||
|
uint32_t src_struct_id_first = 0, src_struct_id_last = 0;
|
||||||
|
|
||||||
|
CHECK(n_tokens == 5, EINVAL);
|
||||||
|
|
||||||
|
func = hash_func_find(p, tokens[1]);
|
||||||
|
CHECK(func, EINVAL);
|
||||||
|
|
||||||
|
dst = metadata_field_parse(p, tokens[2]);
|
||||||
|
CHECK(dst, 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_struct_id_first == src_struct_id_last, EINVAL);
|
||||||
|
|
||||||
|
instr->type = INSTR_HASH_FUNC;
|
||||||
|
instr->hash_func.hash_func_id = (uint8_t)func->id;
|
||||||
|
instr->hash_func.dst.offset = (uint8_t)dst->offset / 8;
|
||||||
|
instr->hash_func.dst.n_bits = (uint8_t)dst->n_bits;
|
||||||
|
instr->hash_func.src.struct_id = (uint8_t)src_struct_id_first;
|
||||||
|
instr->hash_func.src.offset = (uint16_t)src_first->offset / 8;
|
||||||
|
instr->hash_func.src.n_bytes = (uint16_t)((src_last->offset + src_last->n_bits -
|
||||||
|
src_first->offset) / 8);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
instr_hash_func_exec(struct rte_swx_pipeline *p)
|
||||||
|
{
|
||||||
|
struct thread *t = &p->threads[p->thread_id];
|
||||||
|
struct instruction *ip = t->ip;
|
||||||
|
|
||||||
|
/* Extern function execute. */
|
||||||
|
__instr_hash_func_exec(p, t, ip);
|
||||||
|
|
||||||
|
/* Thread. */
|
||||||
|
thread_ip_inc(p);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mov.
|
* mov.
|
||||||
*/
|
*/
|
||||||
@ -6142,6 +6288,14 @@ instr_translate(struct rte_swx_pipeline *p,
|
|||||||
instr,
|
instr,
|
||||||
data);
|
data);
|
||||||
|
|
||||||
|
if (!strcmp(tokens[tpos], "hash"))
|
||||||
|
return instr_hash_translate(p,
|
||||||
|
action,
|
||||||
|
&tokens[tpos],
|
||||||
|
n_tokens - tpos,
|
||||||
|
instr,
|
||||||
|
data);
|
||||||
|
|
||||||
if (!strcmp(tokens[tpos], "jmp"))
|
if (!strcmp(tokens[tpos], "jmp"))
|
||||||
return instr_jmp_translate(p,
|
return instr_jmp_translate(p,
|
||||||
action,
|
action,
|
||||||
@ -7119,6 +7273,7 @@ static instr_exec_t instruction_table[] = {
|
|||||||
[INSTR_LEARNER_FORGET] = instr_forget_exec,
|
[INSTR_LEARNER_FORGET] = instr_forget_exec,
|
||||||
[INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
|
[INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
|
||||||
[INSTR_EXTERN_FUNC] = instr_extern_func_exec,
|
[INSTR_EXTERN_FUNC] = instr_extern_func_exec,
|
||||||
|
[INSTR_HASH_FUNC] = instr_hash_func_exec,
|
||||||
|
|
||||||
[INSTR_JMP] = instr_jmp_exec,
|
[INSTR_JMP] = instr_jmp_exec,
|
||||||
[INSTR_JMP_VALID] = instr_jmp_valid_exec,
|
[INSTR_JMP_VALID] = instr_jmp_valid_exec,
|
||||||
@ -9462,6 +9617,7 @@ rte_swx_pipeline_free(struct rte_swx_pipeline *p)
|
|||||||
instruction_table_free(p);
|
instruction_table_free(p);
|
||||||
metadata_free(p);
|
metadata_free(p);
|
||||||
header_free(p);
|
header_free(p);
|
||||||
|
hash_func_free(p);
|
||||||
extern_func_free(p);
|
extern_func_free(p);
|
||||||
extern_obj_free(p);
|
extern_obj_free(p);
|
||||||
mirroring_free(p);
|
mirroring_free(p);
|
||||||
@ -9563,6 +9719,22 @@ table_types_register(struct rte_swx_pipeline *p)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hash_funcs_register(struct rte_swx_pipeline *p)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = rte_swx_pipeline_hash_func_register(p, "jhash", rte_jhash);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = rte_swx_pipeline_hash_func_register(p, "crc32", rte_hash_crc);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
|
rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
|
||||||
{
|
{
|
||||||
@ -9588,6 +9760,7 @@ rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
|
|||||||
TAILQ_INIT(&pipeline->extern_types);
|
TAILQ_INIT(&pipeline->extern_types);
|
||||||
TAILQ_INIT(&pipeline->extern_objs);
|
TAILQ_INIT(&pipeline->extern_objs);
|
||||||
TAILQ_INIT(&pipeline->extern_funcs);
|
TAILQ_INIT(&pipeline->extern_funcs);
|
||||||
|
TAILQ_INIT(&pipeline->hash_funcs);
|
||||||
TAILQ_INIT(&pipeline->headers);
|
TAILQ_INIT(&pipeline->headers);
|
||||||
TAILQ_INIT(&pipeline->actions);
|
TAILQ_INIT(&pipeline->actions);
|
||||||
TAILQ_INIT(&pipeline->table_types);
|
TAILQ_INIT(&pipeline->table_types);
|
||||||
@ -9613,6 +9786,10 @@ rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
|
|||||||
if (status)
|
if (status)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
status = hash_funcs_register(pipeline);
|
||||||
|
if (status)
|
||||||
|
goto error;
|
||||||
|
|
||||||
*p = pipeline;
|
*p = pipeline;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -9689,6 +9866,10 @@ rte_swx_pipeline_build(struct rte_swx_pipeline *p)
|
|||||||
if (status)
|
if (status)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
status = hash_func_build(p);
|
||||||
|
if (status)
|
||||||
|
goto error;
|
||||||
|
|
||||||
status = header_build(p);
|
status = header_build(p);
|
||||||
if (status)
|
if (status)
|
||||||
goto error;
|
goto error;
|
||||||
@ -9746,6 +9927,7 @@ error:
|
|||||||
instruction_table_build_free(p);
|
instruction_table_build_free(p);
|
||||||
metadata_build_free(p);
|
metadata_build_free(p);
|
||||||
header_build_free(p);
|
header_build_free(p);
|
||||||
|
hash_func_build_free(p);
|
||||||
extern_func_build_free(p);
|
extern_func_build_free(p);
|
||||||
extern_obj_build_free(p);
|
extern_obj_build_free(p);
|
||||||
mirroring_build_free(p);
|
mirroring_build_free(p);
|
||||||
@ -10731,6 +10913,7 @@ instr_type_to_name(struct instruction *instr)
|
|||||||
|
|
||||||
case INSTR_EXTERN_OBJ: return "INSTR_EXTERN_OBJ";
|
case INSTR_EXTERN_OBJ: return "INSTR_EXTERN_OBJ";
|
||||||
case INSTR_EXTERN_FUNC: return "INSTR_EXTERN_FUNC";
|
case INSTR_EXTERN_FUNC: return "INSTR_EXTERN_FUNC";
|
||||||
|
case INSTR_HASH_FUNC: return "INSTR_HASH_FUNC";
|
||||||
|
|
||||||
case INSTR_JMP: return "INSTR_JMP";
|
case INSTR_JMP: return "INSTR_JMP";
|
||||||
case INSTR_JMP_VALID: return "INSTR_JMP_VALID";
|
case INSTR_JMP_VALID: return "INSTR_JMP_VALID";
|
||||||
@ -11149,6 +11332,34 @@ instr_alu_export(struct instruction *instr, FILE *f)
|
|||||||
instr->alu.src_val);
|
instr->alu.src_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
instr_hash_export(struct instruction *instr, FILE *f)
|
||||||
|
{
|
||||||
|
fprintf(f,
|
||||||
|
"\t{\n"
|
||||||
|
"\t\t.type = %s,\n"
|
||||||
|
"\t\t.hash_func = {\n"
|
||||||
|
"\t\t\t.hash_func_id = %u,\n"
|
||||||
|
"\t\t\t.dst = {\n"
|
||||||
|
"\t\t\t\t.offset = %u,\n"
|
||||||
|
"\t\t\t\t.n_bits = %u,\n"
|
||||||
|
"\t\t\t},\n"
|
||||||
|
"\t\t\t.src = {\n"
|
||||||
|
"\t\t\t\t.struct_id = %u,\n"
|
||||||
|
"\t\t\t\t.offset = %u,\n"
|
||||||
|
"\t\t\t\t.n_bytes = %u,\n"
|
||||||
|
"\t\t\t},\n"
|
||||||
|
"\t\t},\n"
|
||||||
|
"\t},\n",
|
||||||
|
instr_type_to_name(instr),
|
||||||
|
instr->hash_func.hash_func_id,
|
||||||
|
instr->hash_func.dst.offset,
|
||||||
|
instr->hash_func.dst.n_bits,
|
||||||
|
instr->hash_func.src.struct_id,
|
||||||
|
instr->hash_func.src.offset,
|
||||||
|
instr->hash_func.src.n_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
instr_reg_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
|
instr_reg_export(struct instruction *instr __rte_unused, FILE *f __rte_unused)
|
||||||
{
|
{
|
||||||
@ -11688,6 +11899,7 @@ static instruction_export_t export_table[] = {
|
|||||||
|
|
||||||
[INSTR_EXTERN_OBJ] = instr_extern_export,
|
[INSTR_EXTERN_OBJ] = instr_extern_export,
|
||||||
[INSTR_EXTERN_FUNC] = instr_extern_export,
|
[INSTR_EXTERN_FUNC] = instr_extern_export,
|
||||||
|
[INSTR_HASH_FUNC] = instr_hash_export,
|
||||||
|
|
||||||
[INSTR_JMP] = instr_jmp_export,
|
[INSTR_JMP] = instr_jmp_export,
|
||||||
[INSTR_JMP_VALID] = instr_jmp_export,
|
[INSTR_JMP_VALID] = instr_jmp_export,
|
||||||
@ -11911,6 +12123,7 @@ instr_type_to_func(struct instruction *instr)
|
|||||||
|
|
||||||
case INSTR_EXTERN_OBJ: return NULL;
|
case INSTR_EXTERN_OBJ: return NULL;
|
||||||
case INSTR_EXTERN_FUNC: return NULL;
|
case INSTR_EXTERN_FUNC: return NULL;
|
||||||
|
case INSTR_HASH_FUNC: return "__instr_hash_func_exec";
|
||||||
|
|
||||||
case INSTR_JMP: return NULL;
|
case INSTR_JMP: return NULL;
|
||||||
case INSTR_JMP_VALID: return NULL;
|
case INSTR_JMP_VALID: return NULL;
|
||||||
|
@ -301,6 +301,47 @@ rte_swx_pipeline_extern_func_register(struct rte_swx_pipeline *p,
|
|||||||
const char *name,
|
const char *name,
|
||||||
const char *mailbox_struct_type_name,
|
const char *mailbox_struct_type_name,
|
||||||
rte_swx_extern_func_t func);
|
rte_swx_extern_func_t func);
|
||||||
|
/*
|
||||||
|
* Hash function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash function prototype
|
||||||
|
*
|
||||||
|
* @param[in] key
|
||||||
|
* Key to hash. Must be non-NULL.
|
||||||
|
* @param[in] length
|
||||||
|
* Key length in bytes.
|
||||||
|
* @param[in] seed
|
||||||
|
* Hash seed.
|
||||||
|
* @return
|
||||||
|
* Hash value.
|
||||||
|
*/
|
||||||
|
typedef uint32_t
|
||||||
|
(*rte_swx_hash_func_t)(const void *key,
|
||||||
|
uint32_t length,
|
||||||
|
uint32_t seed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pipeline hash function register
|
||||||
|
*
|
||||||
|
* @param[in] p
|
||||||
|
* Pipeline handle.
|
||||||
|
* @param[in] name
|
||||||
|
* Hash function name.
|
||||||
|
* @param[in] func
|
||||||
|
* Hash function.
|
||||||
|
* @return
|
||||||
|
* 0 on success or the following error codes otherwise:
|
||||||
|
* -EINVAL: Invalid argument;
|
||||||
|
* -ENOMEM: Not enough space/cannot allocate memory;
|
||||||
|
* -EEXIST: Hash function with this name already exists.
|
||||||
|
*/
|
||||||
|
__rte_experimental
|
||||||
|
int
|
||||||
|
rte_swx_pipeline_hash_func_register(struct rte_swx_pipeline *p,
|
||||||
|
const char *name,
|
||||||
|
rte_swx_hash_func_t func);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Packet headers and meta-data
|
* Packet headers and meta-data
|
||||||
|
@ -183,6 +183,22 @@ struct extern_func_runtime {
|
|||||||
rte_swx_extern_func_t func;
|
rte_swx_extern_func_t func;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hash function.
|
||||||
|
*/
|
||||||
|
struct hash_func {
|
||||||
|
TAILQ_ENTRY(hash_func) node;
|
||||||
|
char name[RTE_SWX_NAME_SIZE];
|
||||||
|
rte_swx_hash_func_t func;
|
||||||
|
uint32_t id;
|
||||||
|
};
|
||||||
|
|
||||||
|
TAILQ_HEAD(hash_func_tailq, hash_func);
|
||||||
|
|
||||||
|
struct hash_func_runtime {
|
||||||
|
rte_swx_hash_func_t func;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Header.
|
* Header.
|
||||||
*/
|
*/
|
||||||
@ -492,6 +508,15 @@ enum instruction_type {
|
|||||||
/* extern f.func */
|
/* extern f.func */
|
||||||
INSTR_EXTERN_FUNC,
|
INSTR_EXTERN_FUNC,
|
||||||
|
|
||||||
|
/* hash HASH_FUNC_NAME dst src_first src_last
|
||||||
|
* Compute hash value over range of struct fields.
|
||||||
|
* dst = M
|
||||||
|
* src_first = HMEFT
|
||||||
|
* src_last = HMEFT
|
||||||
|
* src_first and src_last must be fields within the same struct
|
||||||
|
*/
|
||||||
|
INSTR_HASH_FUNC,
|
||||||
|
|
||||||
/* jmp LABEL
|
/* jmp LABEL
|
||||||
* Unconditional jump
|
* Unconditional jump
|
||||||
*/
|
*/
|
||||||
@ -629,6 +654,21 @@ struct instr_extern_func {
|
|||||||
uint8_t ext_func_id;
|
uint8_t ext_func_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct instr_hash_func {
|
||||||
|
uint8_t hash_func_id;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint8_t offset;
|
||||||
|
uint8_t n_bits;
|
||||||
|
} dst;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint8_t struct_id;
|
||||||
|
uint16_t offset;
|
||||||
|
uint16_t n_bytes;
|
||||||
|
} src;
|
||||||
|
};
|
||||||
|
|
||||||
struct instr_dst_src {
|
struct instr_dst_src {
|
||||||
struct instr_operand dst;
|
struct instr_operand dst;
|
||||||
union {
|
union {
|
||||||
@ -714,6 +754,7 @@ struct instruction {
|
|||||||
struct instr_learn learn;
|
struct instr_learn learn;
|
||||||
struct instr_extern_obj ext_obj;
|
struct instr_extern_obj ext_obj;
|
||||||
struct instr_extern_func ext_func;
|
struct instr_extern_func ext_func;
|
||||||
|
struct instr_hash_func hash_func;
|
||||||
struct instr_jmp jmp;
|
struct instr_jmp jmp;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -1425,6 +1466,7 @@ struct rte_swx_pipeline {
|
|||||||
struct extern_type_tailq extern_types;
|
struct extern_type_tailq extern_types;
|
||||||
struct extern_obj_tailq extern_objs;
|
struct extern_obj_tailq extern_objs;
|
||||||
struct extern_func_tailq extern_funcs;
|
struct extern_func_tailq extern_funcs;
|
||||||
|
struct hash_func_tailq hash_funcs;
|
||||||
struct header_tailq headers;
|
struct header_tailq headers;
|
||||||
struct struct_type *metadata_st;
|
struct struct_type *metadata_st;
|
||||||
uint32_t metadata_struct_id;
|
uint32_t metadata_struct_id;
|
||||||
@ -1446,6 +1488,7 @@ struct rte_swx_pipeline {
|
|||||||
struct table_statistics *table_stats;
|
struct table_statistics *table_stats;
|
||||||
struct selector_statistics *selector_stats;
|
struct selector_statistics *selector_stats;
|
||||||
struct learner_statistics *learner_stats;
|
struct learner_statistics *learner_stats;
|
||||||
|
struct hash_func_runtime *hash_func_runtime;
|
||||||
struct regarray_runtime *regarray_runtime;
|
struct regarray_runtime *regarray_runtime;
|
||||||
struct metarray_runtime *metarray_runtime;
|
struct metarray_runtime *metarray_runtime;
|
||||||
struct instruction *instructions;
|
struct instruction *instructions;
|
||||||
@ -1461,6 +1504,7 @@ struct rte_swx_pipeline {
|
|||||||
uint32_t n_mirroring_sessions;
|
uint32_t n_mirroring_sessions;
|
||||||
uint32_t n_extern_objs;
|
uint32_t n_extern_objs;
|
||||||
uint32_t n_extern_funcs;
|
uint32_t n_extern_funcs;
|
||||||
|
uint32_t n_hash_funcs;
|
||||||
uint32_t n_actions;
|
uint32_t n_actions;
|
||||||
uint32_t n_tables;
|
uint32_t n_tables;
|
||||||
uint32_t n_selectors;
|
uint32_t n_selectors;
|
||||||
@ -2357,6 +2401,33 @@ __instr_extern_func_exec(struct rte_swx_pipeline *p __rte_unused,
|
|||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hash.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
__instr_hash_func_exec(struct rte_swx_pipeline *p,
|
||||||
|
struct thread *t,
|
||||||
|
const struct instruction *ip)
|
||||||
|
{
|
||||||
|
uint32_t hash_func_id = ip->hash_func.hash_func_id;
|
||||||
|
uint32_t dst_offset = ip->hash_func.dst.offset;
|
||||||
|
uint32_t n_dst_bits = ip->hash_func.dst.n_bits;
|
||||||
|
uint32_t src_struct_id = ip->hash_func.src.struct_id;
|
||||||
|
uint32_t src_offset = ip->hash_func.src.offset;
|
||||||
|
uint32_t n_src_bytes = ip->hash_func.src.n_bytes;
|
||||||
|
|
||||||
|
struct hash_func_runtime *func = &p->hash_func_runtime[hash_func_id];
|
||||||
|
uint8_t *src_ptr = t->structs[src_struct_id];
|
||||||
|
uint32_t result;
|
||||||
|
|
||||||
|
TRACE("[Thread %2u] hash %u\n",
|
||||||
|
p->thread_id,
|
||||||
|
hash_func_id);
|
||||||
|
|
||||||
|
result = func->func(&src_ptr[src_offset], n_src_bytes, 0);
|
||||||
|
METADATA_WRITE(t, dst_offset, n_dst_bits, result);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mov.
|
* mov.
|
||||||
*/
|
*/
|
||||||
|
@ -144,4 +144,5 @@ EXPERIMENTAL {
|
|||||||
#added in 22.07
|
#added in 22.07
|
||||||
rte_swx_ctl_pipeline_learner_timeout_get;
|
rte_swx_ctl_pipeline_learner_timeout_get;
|
||||||
rte_swx_ctl_pipeline_learner_timeout_set;
|
rte_swx_ctl_pipeline_learner_timeout_set;
|
||||||
|
rte_swx_pipeline_hash_func_register;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user