examples/ip_pipeline: add pipeline object
Add pipeline object implementation to the application. Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com> Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
This commit is contained in:
parent
719374345c
commit
d75c371e9b
@ -13,6 +13,7 @@ SRCS-y += link.c
|
||||
SRCS-y += main.c
|
||||
SRCS-y += mempool.c
|
||||
SRCS-y += parser.c
|
||||
SRCS-y += pipeline.c
|
||||
SRCS-y += swq.c
|
||||
SRCS-y += tap.c
|
||||
SRCS-y += tmgr.c
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "link.h"
|
||||
#include "mempool.h"
|
||||
#include "parser.h"
|
||||
#include "pipeline.h"
|
||||
#include "swq.h"
|
||||
#include "tap.h"
|
||||
#include "tmgr.h"
|
||||
@ -1157,6 +1158,784 @@ cmd_table_action_profile(char **tokens,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pipeline <pipeline_name>
|
||||
* period <timer_period_ms>
|
||||
* offset_port_id <offset_port_id>
|
||||
* cpu <cpu_id>
|
||||
*/
|
||||
static void
|
||||
cmd_pipeline(char **tokens,
|
||||
uint32_t n_tokens,
|
||||
char *out,
|
||||
size_t out_size)
|
||||
{
|
||||
struct pipeline_params p;
|
||||
char *name;
|
||||
struct pipeline *pipeline;
|
||||
|
||||
if (n_tokens != 8) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
name = tokens[1];
|
||||
|
||||
if (strcmp(tokens[2], "period") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.timer_period_ms, tokens[3]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[4], "offset_port_id") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.offset_port_id, tokens[5]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[6], "cpu") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.cpu_id, tokens[7]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
|
||||
return;
|
||||
}
|
||||
|
||||
pipeline = pipeline_create(name, &p);
|
||||
if (pipeline == NULL) {
|
||||
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pipeline <pipeline_name> port in
|
||||
* bsz <burst_size>
|
||||
* link <link_name> rxq <queue_id>
|
||||
* | swq <swq_name>
|
||||
* | tmgr <tmgr_name>
|
||||
* | tap <tap_name> mempool <mempool_name> mtu <mtu>
|
||||
* | kni <kni_name>
|
||||
* | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
|
||||
* [action <port_in_action_profile_name>]
|
||||
* [disabled]
|
||||
*/
|
||||
static void
|
||||
cmd_pipeline_port_in(char **tokens,
|
||||
uint32_t n_tokens,
|
||||
char *out,
|
||||
size_t out_size)
|
||||
{
|
||||
struct port_in_params p;
|
||||
char *pipeline_name;
|
||||
uint32_t t0;
|
||||
int enabled, status;
|
||||
|
||||
if (n_tokens < 7) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
pipeline_name = tokens[1];
|
||||
|
||||
if (strcmp(tokens[2], "port") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[3], "in") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[4], "bsz") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
|
||||
return;
|
||||
}
|
||||
|
||||
t0 = 6;
|
||||
|
||||
if (strcmp(tokens[t0], "link") == 0) {
|
||||
if (n_tokens < t0 + 4) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline port in link");
|
||||
return;
|
||||
}
|
||||
|
||||
p.type = PORT_IN_RXQ;
|
||||
|
||||
p.dev_name = tokens[t0 + 1];
|
||||
|
||||
if (strcmp(tokens[t0 + 2], "rxq") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint16(&p.rxq.queue_id, tokens[t0 + 3]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID,
|
||||
"queue_id");
|
||||
return;
|
||||
}
|
||||
t0 += 4;
|
||||
} else if (strcmp(tokens[t0], "swq") == 0) {
|
||||
if (n_tokens < t0 + 2) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline port in swq");
|
||||
return;
|
||||
}
|
||||
|
||||
p.type = PORT_IN_SWQ;
|
||||
|
||||
p.dev_name = tokens[t0 + 1];
|
||||
|
||||
t0 += 2;
|
||||
} else if (strcmp(tokens[t0], "tmgr") == 0) {
|
||||
if (n_tokens < t0 + 2) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline port in tmgr");
|
||||
return;
|
||||
}
|
||||
|
||||
p.type = PORT_IN_TMGR;
|
||||
|
||||
p.dev_name = tokens[t0 + 1];
|
||||
|
||||
t0 += 2;
|
||||
} else if (strcmp(tokens[t0], "tap") == 0) {
|
||||
if (n_tokens < t0 + 6) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline port in tap");
|
||||
return;
|
||||
}
|
||||
|
||||
p.type = PORT_IN_TAP;
|
||||
|
||||
p.dev_name = tokens[t0 + 1];
|
||||
|
||||
if (strcmp(tokens[t0 + 2], "mempool") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
|
||||
"mempool");
|
||||
return;
|
||||
}
|
||||
|
||||
p.tap.mempool_name = tokens[t0 + 3];
|
||||
|
||||
if (strcmp(tokens[t0 + 4], "mtu") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
|
||||
"mtu");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.tap.mtu, tokens[t0 + 5]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
|
||||
return;
|
||||
}
|
||||
|
||||
t0 += 6;
|
||||
} else if (strcmp(tokens[t0], "kni") == 0) {
|
||||
if (n_tokens < t0 + 2) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline port in kni");
|
||||
return;
|
||||
}
|
||||
|
||||
p.type = PORT_IN_KNI;
|
||||
|
||||
p.dev_name = tokens[t0 + 1];
|
||||
|
||||
t0 += 2;
|
||||
} else if (strcmp(tokens[t0], "source") == 0) {
|
||||
if (n_tokens < t0 + 6) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline port in source");
|
||||
return;
|
||||
}
|
||||
|
||||
p.type = PORT_IN_SOURCE;
|
||||
|
||||
p.dev_name = NULL;
|
||||
|
||||
if (strcmp(tokens[t0 + 1], "mempool") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
|
||||
"mempool");
|
||||
return;
|
||||
}
|
||||
|
||||
p.source.mempool_name = tokens[t0 + 2];
|
||||
|
||||
if (strcmp(tokens[t0 + 3], "file") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
|
||||
"file");
|
||||
return;
|
||||
}
|
||||
|
||||
p.source.file_name = tokens[t0 + 4];
|
||||
|
||||
if (strcmp(tokens[t0 + 5], "bpp") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
|
||||
"bpp");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.source.n_bytes_per_pkt, tokens[t0 + 6]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID,
|
||||
"n_bytes_per_pkt");
|
||||
return;
|
||||
}
|
||||
|
||||
t0 += 7;
|
||||
} else {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
p.action_profile_name = NULL;
|
||||
if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) {
|
||||
if (n_tokens < t0 + 2) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
|
||||
return;
|
||||
}
|
||||
|
||||
p.action_profile_name = tokens[t0 + 1];
|
||||
|
||||
t0 += 2;
|
||||
}
|
||||
|
||||
enabled = 1;
|
||||
if ((n_tokens > t0) &&
|
||||
(strcmp(tokens[t0], "disabled") == 0)) {
|
||||
enabled = 0;
|
||||
|
||||
t0 += 1;
|
||||
}
|
||||
|
||||
if (n_tokens != t0) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
status = pipeline_port_in_create(pipeline_name,
|
||||
&p, enabled);
|
||||
if (status) {
|
||||
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pipeline <pipeline_name> port out
|
||||
* bsz <burst_size>
|
||||
* link <link_name> txq <txq_id>
|
||||
* | swq <swq_name>
|
||||
* | tmgr <tmgr_name>
|
||||
* | tap <tap_name>
|
||||
* | kni <kni_name>
|
||||
* | sink [file <file_name> pkts <max_n_pkts>]
|
||||
*/
|
||||
static void
|
||||
cmd_pipeline_port_out(char **tokens,
|
||||
uint32_t n_tokens,
|
||||
char *out,
|
||||
size_t out_size)
|
||||
{
|
||||
struct port_out_params p;
|
||||
char *pipeline_name;
|
||||
int status;
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
|
||||
if (n_tokens < 7) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
pipeline_name = tokens[1];
|
||||
|
||||
if (strcmp(tokens[2], "port") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[3], "out") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[4], "bsz") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[6], "link") == 0) {
|
||||
if (n_tokens != 10) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline port out link");
|
||||
return;
|
||||
}
|
||||
|
||||
p.type = PORT_OUT_TXQ;
|
||||
|
||||
p.dev_name = tokens[7];
|
||||
|
||||
if (strcmp(tokens[8], "txq") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint16(&p.txq.queue_id, tokens[9]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
|
||||
return;
|
||||
}
|
||||
} else if (strcmp(tokens[6], "swq") == 0) {
|
||||
if (n_tokens != 8) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline port out swq");
|
||||
return;
|
||||
}
|
||||
|
||||
p.type = PORT_OUT_SWQ;
|
||||
|
||||
p.dev_name = tokens[7];
|
||||
} else if (strcmp(tokens[6], "tmgr") == 0) {
|
||||
if (n_tokens != 8) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline port out tmgr");
|
||||
return;
|
||||
}
|
||||
|
||||
p.type = PORT_OUT_TMGR;
|
||||
|
||||
p.dev_name = tokens[7];
|
||||
} else if (strcmp(tokens[6], "tap") == 0) {
|
||||
if (n_tokens != 8) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline port out tap");
|
||||
return;
|
||||
}
|
||||
|
||||
p.type = PORT_OUT_TAP;
|
||||
|
||||
p.dev_name = tokens[7];
|
||||
} else if (strcmp(tokens[6], "kni") == 0) {
|
||||
if (n_tokens != 8) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline port out kni");
|
||||
return;
|
||||
}
|
||||
|
||||
p.type = PORT_OUT_KNI;
|
||||
|
||||
p.dev_name = tokens[7];
|
||||
} else if (strcmp(tokens[6], "sink") == 0) {
|
||||
if ((n_tokens != 7) && (n_tokens != 11)) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline port out sink");
|
||||
return;
|
||||
}
|
||||
|
||||
p.type = PORT_OUT_SINK;
|
||||
|
||||
p.dev_name = NULL;
|
||||
|
||||
if (n_tokens == 7) {
|
||||
p.sink.file_name = NULL;
|
||||
p.sink.max_n_pkts = 0;
|
||||
} else {
|
||||
if (strcmp(tokens[7], "file") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
|
||||
"file");
|
||||
return;
|
||||
}
|
||||
|
||||
p.sink.file_name = tokens[8];
|
||||
|
||||
if (strcmp(tokens[9], "pkts") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.sink.max_n_pkts, tokens[10]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
status = pipeline_port_out_create(pipeline_name, &p);
|
||||
if (status) {
|
||||
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pipeline <pipeline_name> table
|
||||
* match
|
||||
* acl
|
||||
* ipv4 | ipv6
|
||||
* offset <ip_header_offset>
|
||||
* size <n_rules>
|
||||
* | array
|
||||
* offset <key_offset>
|
||||
* size <n_keys>
|
||||
* | hash
|
||||
* ext | lru
|
||||
* key <key_size>
|
||||
* mask <key_mask>
|
||||
* offset <key_offset>
|
||||
* buckets <n_buckets>
|
||||
* size <n_keys>
|
||||
* | lpm
|
||||
* ipv4 | ipv6
|
||||
* offset <ip_header_offset>
|
||||
* size <n_rules>
|
||||
* | stub
|
||||
* [action <table_action_profile_name>]
|
||||
*/
|
||||
static void
|
||||
cmd_pipeline_table(char **tokens,
|
||||
uint32_t n_tokens,
|
||||
char *out,
|
||||
size_t out_size)
|
||||
{
|
||||
uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX];
|
||||
struct table_params p;
|
||||
char *pipeline_name;
|
||||
uint32_t t0;
|
||||
int status;
|
||||
|
||||
if (n_tokens < 5) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
pipeline_name = tokens[1];
|
||||
|
||||
if (strcmp(tokens[2], "table") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[3], "match") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
|
||||
return;
|
||||
}
|
||||
|
||||
t0 = 4;
|
||||
if (strcmp(tokens[t0], "acl") == 0) {
|
||||
if (n_tokens < t0 + 6) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline table acl");
|
||||
return;
|
||||
}
|
||||
|
||||
p.match_type = TABLE_ACL;
|
||||
|
||||
if (strcmp(tokens[t0 + 1], "ipv4") == 0)
|
||||
p.match.acl.ip_version = 1;
|
||||
else if (strcmp(tokens[t0 + 1], "ipv6") == 0)
|
||||
p.match.acl.ip_version = 0;
|
||||
else {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
|
||||
"ipv4 or ipv6");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[t0 + 2], "offset") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.match.acl.ip_header_offset,
|
||||
tokens[t0 + 3]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID,
|
||||
"ip_header_offset");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[t0 + 4], "size") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.match.acl.n_rules,
|
||||
tokens[t0 + 5]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
|
||||
return;
|
||||
}
|
||||
|
||||
t0 += 6;
|
||||
} else if (strcmp(tokens[t0], "array") == 0) {
|
||||
if (n_tokens < t0 + 5) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline table array");
|
||||
return;
|
||||
}
|
||||
|
||||
p.match_type = TABLE_ARRAY;
|
||||
|
||||
if (strcmp(tokens[t0 + 1], "offset") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.match.array.key_offset,
|
||||
tokens[t0 + 2]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[t0 + 3], "size") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.match.array.n_keys,
|
||||
tokens[t0 + 4]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
|
||||
return;
|
||||
}
|
||||
|
||||
t0 += 5;
|
||||
} else if (strcmp(tokens[t0], "hash") == 0) {
|
||||
uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX;
|
||||
|
||||
if (n_tokens < t0 + 12) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline table hash");
|
||||
return;
|
||||
}
|
||||
|
||||
p.match_type = TABLE_HASH;
|
||||
|
||||
if (strcmp(tokens[t0 + 1], "ext") == 0)
|
||||
p.match.hash.extendable_bucket = 1;
|
||||
else if (strcmp(tokens[t0 + 1], "lru") == 0)
|
||||
p.match.hash.extendable_bucket = 0;
|
||||
else {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
|
||||
"ext or lru");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[t0 + 2], "key") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((parser_read_uint32(&p.match.hash.key_size,
|
||||
tokens[t0 + 3]) != 0) ||
|
||||
(p.match.hash.key_size == 0) ||
|
||||
(p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX)) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "key_size");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[t0 + 4], "mask") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((parse_hex_string(tokens[t0 + 5],
|
||||
key_mask, &key_mask_size) != 0) ||
|
||||
(key_mask_size != p.match.hash.key_size)) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
|
||||
return;
|
||||
}
|
||||
p.match.hash.key_mask = key_mask;
|
||||
|
||||
if (strcmp(tokens[t0 + 6], "offset") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.match.hash.key_offset,
|
||||
tokens[t0 + 7]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[t0 + 8], "buckets") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.match.hash.n_buckets,
|
||||
tokens[t0 + 9]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[t0 + 10], "size") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.match.hash.n_keys,
|
||||
tokens[t0 + 11]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
|
||||
return;
|
||||
}
|
||||
|
||||
t0 += 12;
|
||||
} else if (strcmp(tokens[t0], "lpm") == 0) {
|
||||
if (n_tokens < t0 + 6) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline table lpm");
|
||||
return;
|
||||
}
|
||||
|
||||
p.match_type = TABLE_LPM;
|
||||
|
||||
if (strcmp(tokens[t0 + 1], "ipv4") == 0)
|
||||
p.match.lpm.key_size = 4;
|
||||
else if (strcmp(tokens[t0 + 1], "ipv6") == 0)
|
||||
p.match.lpm.key_size = 16;
|
||||
else {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
|
||||
"ipv4 or ipv6");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[t0 + 2], "offset") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.match.lpm.key_offset,
|
||||
tokens[t0 + 3]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[t0 + 4], "size") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&p.match.lpm.n_rules,
|
||||
tokens[t0 + 5]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
|
||||
return;
|
||||
}
|
||||
|
||||
t0 += 6;
|
||||
} else if (strcmp(tokens[t0], "stub") == 0) {
|
||||
if (n_tokens < t0 + 1) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH,
|
||||
"pipeline table stub");
|
||||
return;
|
||||
}
|
||||
|
||||
p.match_type = TABLE_STUB;
|
||||
|
||||
t0 += 1;
|
||||
} else {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
p.action_profile_name = NULL;
|
||||
if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) {
|
||||
if (n_tokens < t0 + 2) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
|
||||
return;
|
||||
}
|
||||
|
||||
p.action_profile_name = tokens[t0 + 1];
|
||||
|
||||
t0 += 2;
|
||||
}
|
||||
|
||||
if (n_tokens > t0) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
status = pipeline_table_create(pipeline_name, &p);
|
||||
if (status) {
|
||||
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pipeline <pipeline_name> port in <port_id> table <table_id>
|
||||
*/
|
||||
static void
|
||||
cmd_pipeline_port_in_table(char **tokens,
|
||||
uint32_t n_tokens,
|
||||
char *out,
|
||||
size_t out_size)
|
||||
{
|
||||
char *pipeline_name;
|
||||
uint32_t port_id, table_id;
|
||||
int status;
|
||||
|
||||
if (n_tokens != 7) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
pipeline_name = tokens[1];
|
||||
|
||||
if (strcmp(tokens[2], "port") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[3], "in") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&port_id, tokens[4]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[5], "table") != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&table_id, tokens[6]) != 0) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
|
||||
return;
|
||||
}
|
||||
|
||||
status = pipeline_port_in_connect_to_table(pipeline_name,
|
||||
port_id,
|
||||
table_id);
|
||||
if (status) {
|
||||
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cli_process(char *in, char *out, size_t out_size)
|
||||
{
|
||||
@ -1245,6 +2024,46 @@ cli_process(char *in, char *out, size_t out_size)
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[0], "pipeline") == 0) {
|
||||
if ((n_tokens >= 3) &&
|
||||
(strcmp(tokens[2], "period") == 0)) {
|
||||
cmd_pipeline(tokens, n_tokens, out, out_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n_tokens >= 5) &&
|
||||
(strcmp(tokens[2], "port") == 0) &&
|
||||
(strcmp(tokens[3], "in") == 0) &&
|
||||
(strcmp(tokens[4], "bsz") == 0)) {
|
||||
cmd_pipeline_port_in(tokens, n_tokens, out, out_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n_tokens >= 5) &&
|
||||
(strcmp(tokens[2], "port") == 0) &&
|
||||
(strcmp(tokens[3], "out") == 0) &&
|
||||
(strcmp(tokens[4], "bsz") == 0)) {
|
||||
cmd_pipeline_port_out(tokens, n_tokens, out, out_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n_tokens >= 4) &&
|
||||
(strcmp(tokens[2], "table") == 0) &&
|
||||
(strcmp(tokens[3], "match") == 0)) {
|
||||
cmd_pipeline_table(tokens, n_tokens, out, out_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n_tokens >= 6) &&
|
||||
(strcmp(tokens[2], "port") == 0) &&
|
||||
(strcmp(tokens[3], "in") == 0) &&
|
||||
(strcmp(tokens[5], "table") == 0)) {
|
||||
cmd_pipeline_port_in_table(tokens, n_tokens,
|
||||
out, out_size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,6 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "action.h"
|
||||
|
||||
void
|
||||
cli_process(char *in, char *out, size_t out_size);
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "kni.h"
|
||||
#include "link.h"
|
||||
#include "mempool.h"
|
||||
#include "pipeline.h"
|
||||
#include "swq.h"
|
||||
#include "tap.h"
|
||||
#include "tmgr.h"
|
||||
@ -221,6 +222,13 @@ main(int argc, char **argv)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Pipeline */
|
||||
status = pipeline_init();
|
||||
if (status) {
|
||||
printf("Error: Pipeline initialization failed (%d)\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Script */
|
||||
if (app.script_name)
|
||||
cli_script_process(app.script_name,
|
||||
|
@ -17,6 +17,7 @@ sources = files(
|
||||
'main.c',
|
||||
'mempool.c',
|
||||
'parser.c',
|
||||
'pipeline.c',
|
||||
'swq.c',
|
||||
'tap.c',
|
||||
'tmgr.c'
|
||||
|
987
examples/ip_pipeline/pipeline.c
Normal file
987
examples/ip_pipeline/pipeline.c
Normal file
@ -0,0 +1,987 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright(c) 2010-2018 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rte_common.h>
|
||||
#include <rte_ip.h>
|
||||
#include <rte_tcp.h>
|
||||
|
||||
#include <rte_port_ethdev.h>
|
||||
#ifdef RTE_LIBRTE_KNI
|
||||
#include <rte_port_kni.h>
|
||||
#endif
|
||||
#include <rte_port_ring.h>
|
||||
#include <rte_port_source_sink.h>
|
||||
#include <rte_port_fd.h>
|
||||
#include <rte_port_sched.h>
|
||||
|
||||
#include <rte_table_acl.h>
|
||||
#include <rte_table_array.h>
|
||||
#include <rte_table_hash.h>
|
||||
#include <rte_table_lpm.h>
|
||||
#include <rte_table_lpm_ipv6.h>
|
||||
#include <rte_table_stub.h>
|
||||
|
||||
#ifdef RTE_LIBRTE_KNI
|
||||
#include "kni.h"
|
||||
#endif
|
||||
#include "link.h"
|
||||
#include "mempool.h"
|
||||
#include "pipeline.h"
|
||||
#include "tap.h"
|
||||
#include "tmgr.h"
|
||||
#include "swq.h"
|
||||
|
||||
#include "hash_func.h"
|
||||
|
||||
#ifndef PIPELINE_MSGQ_SIZE
|
||||
#define PIPELINE_MSGQ_SIZE 64
|
||||
#endif
|
||||
|
||||
#ifndef TABLE_LPM_NUMBER_TBL8
|
||||
#define TABLE_LPM_NUMBER_TBL8 256
|
||||
#endif
|
||||
|
||||
static struct pipeline_list pipeline_list;
|
||||
|
||||
int
|
||||
pipeline_init(void)
|
||||
{
|
||||
TAILQ_INIT(&pipeline_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pipeline *
|
||||
pipeline_find(const char *name)
|
||||
{
|
||||
struct pipeline *pipeline;
|
||||
|
||||
if (name == NULL)
|
||||
return NULL;
|
||||
|
||||
TAILQ_FOREACH(pipeline, &pipeline_list, node)
|
||||
if (strcmp(name, pipeline->name) == 0)
|
||||
return pipeline;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pipeline *
|
||||
pipeline_create(const char *name, struct pipeline_params *params)
|
||||
{
|
||||
char msgq_name[NAME_MAX];
|
||||
struct rte_pipeline_params pp;
|
||||
struct pipeline *pipeline;
|
||||
struct rte_pipeline *p;
|
||||
struct rte_ring *msgq_req;
|
||||
struct rte_ring *msgq_rsp;
|
||||
|
||||
/* Check input params */
|
||||
if ((name == NULL) ||
|
||||
pipeline_find(name) ||
|
||||
(params == NULL) ||
|
||||
(params->timer_period_ms == 0))
|
||||
return NULL;
|
||||
|
||||
/* Resource create */
|
||||
snprintf(msgq_name, sizeof(msgq_name), "%s-MSGQ-REQ", name);
|
||||
|
||||
msgq_req = rte_ring_create(msgq_name,
|
||||
PIPELINE_MSGQ_SIZE,
|
||||
params->cpu_id,
|
||||
RING_F_SP_ENQ | RING_F_SC_DEQ);
|
||||
if (msgq_req == NULL)
|
||||
return NULL;
|
||||
|
||||
snprintf(msgq_name, sizeof(msgq_name), "%s-MSGQ-RSP", name);
|
||||
|
||||
msgq_rsp = rte_ring_create(msgq_name,
|
||||
PIPELINE_MSGQ_SIZE,
|
||||
params->cpu_id,
|
||||
RING_F_SP_ENQ | RING_F_SC_DEQ);
|
||||
if (msgq_rsp == NULL) {
|
||||
rte_ring_free(msgq_req);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pp.name = name;
|
||||
pp.socket_id = (int) params->cpu_id;
|
||||
pp.offset_port_id = params->offset_port_id;
|
||||
|
||||
p = rte_pipeline_create(&pp);
|
||||
if (p == NULL) {
|
||||
rte_ring_free(msgq_rsp);
|
||||
rte_ring_free(msgq_req);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Node allocation */
|
||||
pipeline = calloc(1, sizeof(struct pipeline));
|
||||
if (pipeline == NULL) {
|
||||
rte_pipeline_free(p);
|
||||
rte_ring_free(msgq_rsp);
|
||||
rte_ring_free(msgq_req);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Node fill in */
|
||||
strncpy(pipeline->name, name, sizeof(pipeline->name));
|
||||
pipeline->p = p;
|
||||
pipeline->n_ports_in = 0;
|
||||
pipeline->n_ports_out = 0;
|
||||
pipeline->n_tables = 0;
|
||||
pipeline->msgq_req = msgq_req;
|
||||
pipeline->msgq_rsp = msgq_rsp;
|
||||
pipeline->timer_period_ms = params->timer_period_ms;
|
||||
pipeline->enabled = 0;
|
||||
pipeline->cpu_id = params->cpu_id;
|
||||
|
||||
/* Node add to list */
|
||||
TAILQ_INSERT_TAIL(&pipeline_list, pipeline, node);
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
int
|
||||
pipeline_port_in_create(const char *pipeline_name,
|
||||
struct port_in_params *params,
|
||||
int enabled)
|
||||
{
|
||||
struct rte_pipeline_port_in_params p;
|
||||
|
||||
union {
|
||||
struct rte_port_ethdev_reader_params ethdev;
|
||||
struct rte_port_ring_reader_params ring;
|
||||
struct rte_port_sched_reader_params sched;
|
||||
struct rte_port_fd_reader_params fd;
|
||||
#ifdef RTE_LIBRTE_KNI
|
||||
struct rte_port_kni_reader_params kni;
|
||||
#endif
|
||||
struct rte_port_source_params source;
|
||||
} pp;
|
||||
|
||||
struct pipeline *pipeline;
|
||||
struct port_in *port_in;
|
||||
struct port_in_action_profile *ap;
|
||||
struct rte_port_in_action *action;
|
||||
uint32_t port_id;
|
||||
int status;
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
memset(&pp, 0, sizeof(pp));
|
||||
|
||||
/* Check input params */
|
||||
if ((pipeline_name == NULL) ||
|
||||
(params == NULL) ||
|
||||
(params->burst_size == 0) ||
|
||||
(params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX))
|
||||
return -1;
|
||||
|
||||
pipeline = pipeline_find(pipeline_name);
|
||||
if (pipeline == NULL)
|
||||
return -1;
|
||||
|
||||
ap = NULL;
|
||||
if (params->action_profile_name) {
|
||||
ap = port_in_action_profile_find(params->action_profile_name);
|
||||
if (ap == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (params->type) {
|
||||
case PORT_IN_RXQ:
|
||||
{
|
||||
struct link *link;
|
||||
|
||||
link = link_find(params->dev_name);
|
||||
if (link == NULL)
|
||||
return -1;
|
||||
|
||||
if (params->rxq.queue_id >= link->n_rxq)
|
||||
return -1;
|
||||
|
||||
pp.ethdev.port_id = link->port_id;
|
||||
pp.ethdev.queue_id = params->rxq.queue_id;
|
||||
|
||||
p.ops = &rte_port_ethdev_reader_ops;
|
||||
p.arg_create = &pp.ethdev;
|
||||
break;
|
||||
}
|
||||
|
||||
case PORT_IN_SWQ:
|
||||
{
|
||||
struct swq *swq;
|
||||
|
||||
swq = swq_find(params->dev_name);
|
||||
if (swq == NULL)
|
||||
return -1;
|
||||
|
||||
pp.ring.ring = swq->r;
|
||||
|
||||
p.ops = &rte_port_ring_reader_ops;
|
||||
p.arg_create = &pp.ring;
|
||||
break;
|
||||
}
|
||||
|
||||
case PORT_IN_TMGR:
|
||||
{
|
||||
struct tmgr_port *tmgr_port;
|
||||
|
||||
tmgr_port = tmgr_port_find(params->dev_name);
|
||||
if (tmgr_port == NULL)
|
||||
return -1;
|
||||
|
||||
pp.sched.sched = tmgr_port->s;
|
||||
|
||||
p.ops = &rte_port_sched_reader_ops;
|
||||
p.arg_create = &pp.sched;
|
||||
break;
|
||||
}
|
||||
|
||||
case PORT_IN_TAP:
|
||||
{
|
||||
struct tap *tap;
|
||||
struct mempool *mempool;
|
||||
|
||||
tap = tap_find(params->dev_name);
|
||||
mempool = mempool_find(params->tap.mempool_name);
|
||||
if ((tap == NULL) || (mempool == NULL))
|
||||
return -1;
|
||||
|
||||
pp.fd.fd = tap->fd;
|
||||
pp.fd.mempool = mempool->m;
|
||||
pp.fd.mtu = params->tap.mtu;
|
||||
|
||||
p.ops = &rte_port_fd_reader_ops;
|
||||
p.arg_create = &pp.fd;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef RTE_LIBRTE_KNI
|
||||
case PORT_IN_KNI:
|
||||
{
|
||||
struct kni *kni;
|
||||
|
||||
kni = kni_find(params->dev_name);
|
||||
if (kni == NULL)
|
||||
return -1;
|
||||
|
||||
pp.kni.kni = kni->k;
|
||||
|
||||
p.ops = &rte_port_kni_reader_ops;
|
||||
p.arg_create = &pp.kni;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case PORT_IN_SOURCE:
|
||||
{
|
||||
struct mempool *mempool;
|
||||
|
||||
mempool = mempool_find(params->source.mempool_name);
|
||||
if (mempool == NULL)
|
||||
return -1;
|
||||
|
||||
pp.source.mempool = mempool->m;
|
||||
pp.source.file_name = params->source.file_name;
|
||||
pp.source.n_bytes_per_pkt = params->source.n_bytes_per_pkt;
|
||||
|
||||
p.ops = &rte_port_source_ops;
|
||||
p.arg_create = &pp.source;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
p.burst_size = params->burst_size;
|
||||
|
||||
/* Resource create */
|
||||
action = NULL;
|
||||
p.f_action = NULL;
|
||||
p.arg_ah = NULL;
|
||||
|
||||
if (ap) {
|
||||
action = rte_port_in_action_create(ap->ap,
|
||||
pipeline->cpu_id);
|
||||
if (action == NULL)
|
||||
return -1;
|
||||
|
||||
status = rte_port_in_action_params_get(
|
||||
action,
|
||||
&p);
|
||||
if (status) {
|
||||
rte_port_in_action_free(action);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
status = rte_pipeline_port_in_create(pipeline->p,
|
||||
&p,
|
||||
&port_id);
|
||||
if (status) {
|
||||
rte_port_in_action_free(action);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (enabled)
|
||||
rte_pipeline_port_in_enable(pipeline->p, port_id);
|
||||
|
||||
/* Pipeline */
|
||||
port_in = &pipeline->port_in[pipeline->n_ports_in];
|
||||
memcpy(&port_in->params, params, sizeof(*params));
|
||||
port_in->ap = ap;
|
||||
port_in->a = action;
|
||||
pipeline->n_ports_in++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
pipeline_port_in_connect_to_table(const char *pipeline_name,
|
||||
uint32_t port_id,
|
||||
uint32_t table_id)
|
||||
{
|
||||
struct pipeline *pipeline;
|
||||
int status;
|
||||
|
||||
/* Check input params */
|
||||
if (pipeline_name == NULL)
|
||||
return -1;
|
||||
|
||||
pipeline = pipeline_find(pipeline_name);
|
||||
if ((pipeline == NULL) ||
|
||||
(port_id >= pipeline->n_ports_in) ||
|
||||
(table_id >= pipeline->n_tables))
|
||||
return -1;
|
||||
|
||||
/* Resource */
|
||||
status = rte_pipeline_port_in_connect_to_table(pipeline->p,
|
||||
port_id,
|
||||
table_id);
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
pipeline_port_out_create(const char *pipeline_name,
|
||||
struct port_out_params *params)
|
||||
{
|
||||
struct rte_pipeline_port_out_params p;
|
||||
|
||||
union {
|
||||
struct rte_port_ethdev_writer_params ethdev;
|
||||
struct rte_port_ring_writer_params ring;
|
||||
struct rte_port_sched_writer_params sched;
|
||||
struct rte_port_fd_writer_params fd;
|
||||
#ifdef RTE_LIBRTE_KNI
|
||||
struct rte_port_kni_writer_params kni;
|
||||
#endif
|
||||
struct rte_port_sink_params sink;
|
||||
} pp;
|
||||
|
||||
union {
|
||||
struct rte_port_ethdev_writer_nodrop_params ethdev;
|
||||
struct rte_port_ring_writer_nodrop_params ring;
|
||||
struct rte_port_fd_writer_nodrop_params fd;
|
||||
#ifdef RTE_LIBRTE_KNI
|
||||
struct rte_port_kni_writer_nodrop_params kni;
|
||||
#endif
|
||||
} pp_nodrop;
|
||||
|
||||
struct pipeline *pipeline;
|
||||
uint32_t port_id;
|
||||
int status;
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
memset(&pp, 0, sizeof(pp));
|
||||
memset(&pp_nodrop, 0, sizeof(pp_nodrop));
|
||||
|
||||
/* Check input params */
|
||||
if ((pipeline_name == NULL) ||
|
||||
(params == NULL) ||
|
||||
(params->burst_size == 0) ||
|
||||
(params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX))
|
||||
return -1;
|
||||
|
||||
pipeline = pipeline_find(pipeline_name);
|
||||
if (pipeline == NULL)
|
||||
return -1;
|
||||
|
||||
switch (params->type) {
|
||||
case PORT_OUT_TXQ:
|
||||
{
|
||||
struct link *link;
|
||||
|
||||
link = link_find(params->dev_name);
|
||||
if (link == NULL)
|
||||
return -1;
|
||||
|
||||
if (params->txq.queue_id >= link->n_txq)
|
||||
return -1;
|
||||
|
||||
pp.ethdev.port_id = link->port_id;
|
||||
pp.ethdev.queue_id = params->txq.queue_id;
|
||||
pp.ethdev.tx_burst_sz = params->burst_size;
|
||||
|
||||
pp_nodrop.ethdev.port_id = link->port_id;
|
||||
pp_nodrop.ethdev.queue_id = params->txq.queue_id;
|
||||
pp_nodrop.ethdev.tx_burst_sz = params->burst_size;
|
||||
pp_nodrop.ethdev.n_retries = params->n_retries;
|
||||
|
||||
if (params->retry == 0) {
|
||||
p.ops = &rte_port_ethdev_writer_ops;
|
||||
p.arg_create = &pp.ethdev;
|
||||
} else {
|
||||
p.ops = &rte_port_ethdev_writer_nodrop_ops;
|
||||
p.arg_create = &pp_nodrop.ethdev;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PORT_OUT_SWQ:
|
||||
{
|
||||
struct swq *swq;
|
||||
|
||||
swq = swq_find(params->dev_name);
|
||||
if (swq == NULL)
|
||||
return -1;
|
||||
|
||||
pp.ring.ring = swq->r;
|
||||
pp.ring.tx_burst_sz = params->burst_size;
|
||||
|
||||
pp_nodrop.ring.ring = swq->r;
|
||||
pp_nodrop.ring.tx_burst_sz = params->burst_size;
|
||||
pp_nodrop.ring.n_retries = params->n_retries;
|
||||
|
||||
if (params->retry == 0) {
|
||||
p.ops = &rte_port_ring_writer_ops;
|
||||
p.arg_create = &pp.ring;
|
||||
} else {
|
||||
p.ops = &rte_port_ring_writer_nodrop_ops;
|
||||
p.arg_create = &pp_nodrop.ring;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PORT_OUT_TMGR:
|
||||
{
|
||||
struct tmgr_port *tmgr_port;
|
||||
|
||||
tmgr_port = tmgr_port_find(params->dev_name);
|
||||
if (tmgr_port == NULL)
|
||||
return -1;
|
||||
|
||||
pp.sched.sched = tmgr_port->s;
|
||||
pp.sched.tx_burst_sz = params->burst_size;
|
||||
|
||||
p.ops = &rte_port_sched_writer_ops;
|
||||
p.arg_create = &pp.sched;
|
||||
break;
|
||||
}
|
||||
|
||||
case PORT_OUT_TAP:
|
||||
{
|
||||
struct tap *tap;
|
||||
|
||||
tap = tap_find(params->dev_name);
|
||||
if (tap == NULL)
|
||||
return -1;
|
||||
|
||||
pp.fd.fd = tap->fd;
|
||||
pp.fd.tx_burst_sz = params->burst_size;
|
||||
|
||||
pp_nodrop.fd.fd = tap->fd;
|
||||
pp_nodrop.fd.tx_burst_sz = params->burst_size;
|
||||
pp_nodrop.fd.n_retries = params->n_retries;
|
||||
|
||||
if (params->retry == 0) {
|
||||
p.ops = &rte_port_fd_writer_ops;
|
||||
p.arg_create = &pp.fd;
|
||||
} else {
|
||||
p.ops = &rte_port_fd_writer_nodrop_ops;
|
||||
p.arg_create = &pp_nodrop.fd;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef RTE_LIBRTE_KNI
|
||||
case PORT_OUT_KNI:
|
||||
{
|
||||
struct kni *kni;
|
||||
|
||||
kni = kni_find(params->dev_name);
|
||||
if (kni == NULL)
|
||||
return -1;
|
||||
|
||||
pp.kni.kni = kni->k;
|
||||
pp.kni.tx_burst_sz = params->burst_size;
|
||||
|
||||
pp_nodrop.kni.kni = kni->k;
|
||||
pp_nodrop.kni.tx_burst_sz = params->burst_size;
|
||||
pp_nodrop.kni.n_retries = params->n_retries;
|
||||
|
||||
if (params->retry == 0) {
|
||||
p.ops = &rte_port_kni_writer_ops;
|
||||
p.arg_create = &pp.kni;
|
||||
} else {
|
||||
p.ops = &rte_port_kni_writer_nodrop_ops;
|
||||
p.arg_create = &pp_nodrop.kni;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case PORT_OUT_SINK:
|
||||
{
|
||||
pp.sink.file_name = params->sink.file_name;
|
||||
pp.sink.max_n_pkts = params->sink.max_n_pkts;
|
||||
|
||||
p.ops = &rte_port_sink_ops;
|
||||
p.arg_create = &pp.sink;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
p.f_action = NULL;
|
||||
p.arg_ah = NULL;
|
||||
|
||||
/* Resource create */
|
||||
status = rte_pipeline_port_out_create(pipeline->p,
|
||||
&p,
|
||||
&port_id);
|
||||
|
||||
if (status)
|
||||
return -1;
|
||||
|
||||
/* Pipeline */
|
||||
pipeline->n_ports_out++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rte_acl_field_def table_acl_field_format_ipv4[] = {
|
||||
/* Protocol */
|
||||
[0] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_BITMASK,
|
||||
.size = sizeof(uint8_t),
|
||||
.field_index = 0,
|
||||
.input_index = 0,
|
||||
.offset = offsetof(struct ipv4_hdr, next_proto_id),
|
||||
},
|
||||
|
||||
/* Source IP address (IPv4) */
|
||||
[1] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_MASK,
|
||||
.size = sizeof(uint32_t),
|
||||
.field_index = 1,
|
||||
.input_index = 1,
|
||||
.offset = offsetof(struct ipv4_hdr, src_addr),
|
||||
},
|
||||
|
||||
/* Destination IP address (IPv4) */
|
||||
[2] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_MASK,
|
||||
.size = sizeof(uint32_t),
|
||||
.field_index = 2,
|
||||
.input_index = 2,
|
||||
.offset = offsetof(struct ipv4_hdr, dst_addr),
|
||||
},
|
||||
|
||||
/* Source Port */
|
||||
[3] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_RANGE,
|
||||
.size = sizeof(uint16_t),
|
||||
.field_index = 3,
|
||||
.input_index = 3,
|
||||
.offset = sizeof(struct ipv4_hdr) +
|
||||
offsetof(struct tcp_hdr, src_port),
|
||||
},
|
||||
|
||||
/* Destination Port */
|
||||
[4] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_RANGE,
|
||||
.size = sizeof(uint16_t),
|
||||
.field_index = 4,
|
||||
.input_index = 3,
|
||||
.offset = sizeof(struct ipv4_hdr) +
|
||||
offsetof(struct tcp_hdr, dst_port),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
|
||||
/* Protocol */
|
||||
[0] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_BITMASK,
|
||||
.size = sizeof(uint8_t),
|
||||
.field_index = 0,
|
||||
.input_index = 0,
|
||||
.offset = offsetof(struct ipv6_hdr, proto),
|
||||
},
|
||||
|
||||
/* Source IP address (IPv6) */
|
||||
[1] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_MASK,
|
||||
.size = sizeof(uint32_t),
|
||||
.field_index = 1,
|
||||
.input_index = 1,
|
||||
.offset = offsetof(struct ipv6_hdr, src_addr[0]),
|
||||
},
|
||||
|
||||
[2] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_MASK,
|
||||
.size = sizeof(uint32_t),
|
||||
.field_index = 2,
|
||||
.input_index = 2,
|
||||
.offset = offsetof(struct ipv6_hdr, src_addr[4]),
|
||||
},
|
||||
|
||||
[3] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_MASK,
|
||||
.size = sizeof(uint32_t),
|
||||
.field_index = 3,
|
||||
.input_index = 3,
|
||||
.offset = offsetof(struct ipv6_hdr, src_addr[8]),
|
||||
},
|
||||
|
||||
[4] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_MASK,
|
||||
.size = sizeof(uint32_t),
|
||||
.field_index = 4,
|
||||
.input_index = 4,
|
||||
.offset = offsetof(struct ipv6_hdr, src_addr[12]),
|
||||
},
|
||||
|
||||
/* Destination IP address (IPv6) */
|
||||
[5] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_MASK,
|
||||
.size = sizeof(uint32_t),
|
||||
.field_index = 5,
|
||||
.input_index = 5,
|
||||
.offset = offsetof(struct ipv6_hdr, dst_addr[0]),
|
||||
},
|
||||
|
||||
[6] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_MASK,
|
||||
.size = sizeof(uint32_t),
|
||||
.field_index = 6,
|
||||
.input_index = 6,
|
||||
.offset = offsetof(struct ipv6_hdr, dst_addr[4]),
|
||||
},
|
||||
|
||||
[7] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_MASK,
|
||||
.size = sizeof(uint32_t),
|
||||
.field_index = 7,
|
||||
.input_index = 7,
|
||||
.offset = offsetof(struct ipv6_hdr, dst_addr[8]),
|
||||
},
|
||||
|
||||
[8] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_MASK,
|
||||
.size = sizeof(uint32_t),
|
||||
.field_index = 8,
|
||||
.input_index = 8,
|
||||
.offset = offsetof(struct ipv6_hdr, dst_addr[12]),
|
||||
},
|
||||
|
||||
/* Source Port */
|
||||
[9] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_RANGE,
|
||||
.size = sizeof(uint16_t),
|
||||
.field_index = 9,
|
||||
.input_index = 9,
|
||||
.offset = sizeof(struct ipv6_hdr) +
|
||||
offsetof(struct tcp_hdr, src_port),
|
||||
},
|
||||
|
||||
/* Destination Port */
|
||||
[10] = {
|
||||
.type = RTE_ACL_FIELD_TYPE_RANGE,
|
||||
.size = sizeof(uint16_t),
|
||||
.field_index = 10,
|
||||
.input_index = 9,
|
||||
.offset = sizeof(struct ipv6_hdr) +
|
||||
offsetof(struct tcp_hdr, dst_port),
|
||||
},
|
||||
};
|
||||
|
||||
int
|
||||
pipeline_table_create(const char *pipeline_name,
|
||||
struct table_params *params)
|
||||
{
|
||||
char name[NAME_MAX];
|
||||
struct rte_pipeline_table_params p;
|
||||
|
||||
union {
|
||||
struct rte_table_acl_params acl;
|
||||
struct rte_table_array_params array;
|
||||
struct rte_table_hash_params hash;
|
||||
struct rte_table_lpm_params lpm;
|
||||
struct rte_table_lpm_ipv6_params lpm_ipv6;
|
||||
} pp;
|
||||
|
||||
struct pipeline *pipeline;
|
||||
struct table *table;
|
||||
struct table_action_profile *ap;
|
||||
struct rte_table_action *action;
|
||||
uint32_t table_id;
|
||||
int status;
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
memset(&pp, 0, sizeof(pp));
|
||||
|
||||
/* Check input params */
|
||||
if ((pipeline_name == NULL) ||
|
||||
(params == NULL))
|
||||
return -1;
|
||||
|
||||
pipeline = pipeline_find(pipeline_name);
|
||||
if ((pipeline == NULL) ||
|
||||
(pipeline->n_tables >= RTE_PIPELINE_TABLE_MAX))
|
||||
return -1;
|
||||
|
||||
ap = NULL;
|
||||
if (params->action_profile_name) {
|
||||
ap = table_action_profile_find(params->action_profile_name);
|
||||
if (ap == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(name, NAME_MAX, "%s_table%u",
|
||||
pipeline_name, pipeline->n_tables);
|
||||
|
||||
switch (params->match_type) {
|
||||
case TABLE_ACL:
|
||||
{
|
||||
uint32_t ip_header_offset = params->match.acl.ip_header_offset -
|
||||
(sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM);
|
||||
uint32_t i;
|
||||
|
||||
if (params->match.acl.n_rules == 0)
|
||||
return -1;
|
||||
|
||||
pp.acl.name = name;
|
||||
pp.acl.n_rules = params->match.acl.n_rules;
|
||||
if (params->match.acl.ip_version) {
|
||||
memcpy(&pp.acl.field_format,
|
||||
&table_acl_field_format_ipv4,
|
||||
sizeof(table_acl_field_format_ipv4));
|
||||
pp.acl.n_rule_fields =
|
||||
RTE_DIM(table_acl_field_format_ipv4);
|
||||
} else {
|
||||
memcpy(&pp.acl.field_format,
|
||||
&table_acl_field_format_ipv6,
|
||||
sizeof(table_acl_field_format_ipv6));
|
||||
pp.acl.n_rule_fields =
|
||||
RTE_DIM(table_acl_field_format_ipv6);
|
||||
}
|
||||
|
||||
for (i = 0; i < pp.acl.n_rule_fields; i++)
|
||||
pp.acl.field_format[i].offset += ip_header_offset;
|
||||
|
||||
p.ops = &rte_table_acl_ops;
|
||||
p.arg_create = &pp.acl;
|
||||
break;
|
||||
}
|
||||
|
||||
case TABLE_ARRAY:
|
||||
{
|
||||
if (params->match.array.n_keys == 0)
|
||||
return -1;
|
||||
|
||||
pp.array.n_entries = params->match.array.n_keys;
|
||||
pp.array.offset = params->match.array.key_offset;
|
||||
|
||||
p.ops = &rte_table_array_ops;
|
||||
p.arg_create = &pp.array;
|
||||
break;
|
||||
}
|
||||
|
||||
case TABLE_HASH:
|
||||
{
|
||||
struct rte_table_ops *ops;
|
||||
rte_table_hash_op_hash f_hash;
|
||||
|
||||
if (params->match.hash.n_keys == 0)
|
||||
return -1;
|
||||
|
||||
switch (params->match.hash.key_size) {
|
||||
case 8:
|
||||
f_hash = hash_default_key8;
|
||||
break;
|
||||
case 16:
|
||||
f_hash = hash_default_key16;
|
||||
break;
|
||||
case 24:
|
||||
f_hash = hash_default_key24;
|
||||
break;
|
||||
case 32:
|
||||
f_hash = hash_default_key32;
|
||||
break;
|
||||
case 40:
|
||||
f_hash = hash_default_key40;
|
||||
break;
|
||||
case 48:
|
||||
f_hash = hash_default_key48;
|
||||
break;
|
||||
case 56:
|
||||
f_hash = hash_default_key56;
|
||||
break;
|
||||
case 64:
|
||||
f_hash = hash_default_key64;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
pp.hash.name = name;
|
||||
pp.hash.key_size = params->match.hash.key_size;
|
||||
pp.hash.key_offset = params->match.hash.key_offset;
|
||||
pp.hash.key_mask = params->match.hash.key_mask;
|
||||
pp.hash.n_keys = params->match.hash.n_keys;
|
||||
pp.hash.n_buckets = params->match.hash.n_buckets;
|
||||
pp.hash.f_hash = f_hash;
|
||||
pp.hash.seed = 0;
|
||||
|
||||
if (params->match.hash.extendable_bucket)
|
||||
switch (params->match.hash.key_size) {
|
||||
case 8:
|
||||
ops = &rte_table_hash_key8_ext_ops;
|
||||
break;
|
||||
case 16:
|
||||
ops = &rte_table_hash_key16_ext_ops;
|
||||
break;
|
||||
default:
|
||||
ops = &rte_table_hash_ext_ops;
|
||||
}
|
||||
else
|
||||
switch (params->match.hash.key_size) {
|
||||
case 8:
|
||||
ops = &rte_table_hash_key8_lru_ops;
|
||||
break;
|
||||
case 16:
|
||||
ops = &rte_table_hash_key16_lru_ops;
|
||||
break;
|
||||
default:
|
||||
ops = &rte_table_hash_lru_ops;
|
||||
}
|
||||
|
||||
p.ops = ops;
|
||||
p.arg_create = &pp.hash;
|
||||
break;
|
||||
}
|
||||
|
||||
case TABLE_LPM:
|
||||
{
|
||||
if (params->match.lpm.n_rules == 0)
|
||||
return -1;
|
||||
|
||||
switch (params->match.lpm.key_size) {
|
||||
case 4:
|
||||
{
|
||||
pp.lpm.name = name;
|
||||
pp.lpm.n_rules = params->match.lpm.n_rules;
|
||||
pp.lpm.number_tbl8s = TABLE_LPM_NUMBER_TBL8;
|
||||
pp.lpm.flags = 0;
|
||||
pp.lpm.entry_unique_size = p.action_data_size +
|
||||
sizeof(struct rte_pipeline_table_entry);
|
||||
pp.lpm.offset = params->match.lpm.key_offset;
|
||||
|
||||
p.ops = &rte_table_lpm_ops;
|
||||
p.arg_create = &pp.lpm;
|
||||
break;
|
||||
}
|
||||
|
||||
case 16:
|
||||
{
|
||||
pp.lpm_ipv6.name = name;
|
||||
pp.lpm_ipv6.n_rules = params->match.lpm.n_rules;
|
||||
pp.lpm_ipv6.number_tbl8s = TABLE_LPM_NUMBER_TBL8;
|
||||
pp.lpm_ipv6.entry_unique_size = p.action_data_size +
|
||||
sizeof(struct rte_pipeline_table_entry);
|
||||
pp.lpm_ipv6.offset = params->match.lpm.key_offset;
|
||||
|
||||
p.ops = &rte_table_lpm_ipv6_ops;
|
||||
p.arg_create = &pp.lpm_ipv6;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TABLE_STUB:
|
||||
{
|
||||
p.ops = &rte_table_stub_ops;
|
||||
p.arg_create = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Resource create */
|
||||
action = NULL;
|
||||
p.f_action_hit = NULL;
|
||||
p.f_action_miss = NULL;
|
||||
p.arg_ah = NULL;
|
||||
|
||||
if (ap) {
|
||||
action = rte_table_action_create(ap->ap,
|
||||
pipeline->cpu_id);
|
||||
if (action == NULL)
|
||||
return -1;
|
||||
|
||||
status = rte_table_action_table_params_get(
|
||||
action,
|
||||
&p);
|
||||
if (status ||
|
||||
((p.action_data_size +
|
||||
sizeof(struct rte_pipeline_table_entry)) >
|
||||
TABLE_RULE_ACTION_SIZE_MAX)) {
|
||||
rte_table_action_free(action);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (params->match_type == TABLE_LPM) {
|
||||
if (params->match.lpm.key_size == 4)
|
||||
pp.lpm.entry_unique_size = p.action_data_size +
|
||||
sizeof(struct rte_pipeline_table_entry);
|
||||
|
||||
if (params->match.lpm.key_size == 16)
|
||||
pp.lpm_ipv6.entry_unique_size = p.action_data_size +
|
||||
sizeof(struct rte_pipeline_table_entry);
|
||||
}
|
||||
|
||||
status = rte_pipeline_table_create(pipeline->p,
|
||||
&p,
|
||||
&table_id);
|
||||
if (status) {
|
||||
rte_table_action_free(action);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Pipeline */
|
||||
table = &pipeline->table[pipeline->n_tables];
|
||||
memcpy(&table->params, params, sizeof(*params));
|
||||
table->ap = ap;
|
||||
table->a = action;
|
||||
pipeline->n_tables++;
|
||||
|
||||
return 0;
|
||||
}
|
272
examples/ip_pipeline/pipeline.h
Normal file
272
examples/ip_pipeline/pipeline.h
Normal file
@ -0,0 +1,272 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright(c) 2010-2018 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_PIPELINE_H_
|
||||
#define _INCLUDE_PIPELINE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <rte_pipeline.h>
|
||||
#include <rte_table_action.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "action.h"
|
||||
|
||||
struct pipeline_params {
|
||||
uint32_t timer_period_ms;
|
||||
uint32_t offset_port_id;
|
||||
uint32_t cpu_id;
|
||||
};
|
||||
|
||||
enum port_in_type {
|
||||
PORT_IN_RXQ,
|
||||
PORT_IN_SWQ,
|
||||
PORT_IN_TMGR,
|
||||
PORT_IN_TAP,
|
||||
PORT_IN_KNI,
|
||||
PORT_IN_SOURCE,
|
||||
};
|
||||
|
||||
struct port_in_params {
|
||||
/* Read */
|
||||
enum port_in_type type;
|
||||
const char *dev_name;
|
||||
union {
|
||||
struct {
|
||||
uint16_t queue_id;
|
||||
} rxq;
|
||||
|
||||
struct {
|
||||
const char *mempool_name;
|
||||
uint32_t mtu;
|
||||
} tap;
|
||||
|
||||
struct {
|
||||
const char *mempool_name;
|
||||
const char *file_name;
|
||||
uint32_t n_bytes_per_pkt;
|
||||
} source;
|
||||
};
|
||||
uint32_t burst_size;
|
||||
|
||||
/* Action */
|
||||
const char *action_profile_name;
|
||||
};
|
||||
|
||||
enum port_out_type {
|
||||
PORT_OUT_TXQ,
|
||||
PORT_OUT_SWQ,
|
||||
PORT_OUT_TMGR,
|
||||
PORT_OUT_TAP,
|
||||
PORT_OUT_KNI,
|
||||
PORT_OUT_SINK,
|
||||
};
|
||||
|
||||
struct port_out_params {
|
||||
enum port_out_type type;
|
||||
const char *dev_name;
|
||||
union {
|
||||
struct {
|
||||
uint16_t queue_id;
|
||||
} txq;
|
||||
|
||||
struct {
|
||||
const char *file_name;
|
||||
uint32_t max_n_pkts;
|
||||
} sink;
|
||||
};
|
||||
uint32_t burst_size;
|
||||
int retry;
|
||||
uint32_t n_retries;
|
||||
};
|
||||
|
||||
enum table_type {
|
||||
TABLE_ACL,
|
||||
TABLE_ARRAY,
|
||||
TABLE_HASH,
|
||||
TABLE_LPM,
|
||||
TABLE_STUB,
|
||||
};
|
||||
|
||||
struct table_acl_params {
|
||||
uint32_t n_rules;
|
||||
uint32_t ip_header_offset;
|
||||
int ip_version;
|
||||
};
|
||||
|
||||
struct table_array_params {
|
||||
uint32_t n_keys;
|
||||
uint32_t key_offset;
|
||||
};
|
||||
|
||||
struct table_hash_params {
|
||||
uint32_t n_keys;
|
||||
uint32_t key_offset;
|
||||
uint32_t key_size;
|
||||
uint8_t *key_mask;
|
||||
uint32_t n_buckets;
|
||||
int extendable_bucket;
|
||||
};
|
||||
|
||||
struct table_lpm_params {
|
||||
uint32_t n_rules;
|
||||
uint32_t key_offset;
|
||||
uint32_t key_size;
|
||||
};
|
||||
|
||||
struct table_params {
|
||||
/* Match */
|
||||
enum table_type match_type;
|
||||
union {
|
||||
struct table_acl_params acl;
|
||||
struct table_array_params array;
|
||||
struct table_hash_params hash;
|
||||
struct table_lpm_params lpm;
|
||||
} match;
|
||||
|
||||
/* Action */
|
||||
const char *action_profile_name;
|
||||
};
|
||||
|
||||
struct port_in {
|
||||
struct port_in_params params;
|
||||
struct port_in_action_profile *ap;
|
||||
struct rte_port_in_action *a;
|
||||
};
|
||||
|
||||
struct table {
|
||||
struct table_params params;
|
||||
struct table_action_profile *ap;
|
||||
struct rte_table_action *a;
|
||||
};
|
||||
|
||||
struct pipeline {
|
||||
TAILQ_ENTRY(pipeline) node;
|
||||
char name[NAME_SIZE];
|
||||
|
||||
struct rte_pipeline *p;
|
||||
struct port_in port_in[RTE_PIPELINE_PORT_IN_MAX];
|
||||
struct table table[RTE_PIPELINE_TABLE_MAX];
|
||||
uint32_t n_ports_in;
|
||||
uint32_t n_ports_out;
|
||||
uint32_t n_tables;
|
||||
|
||||
struct rte_ring *msgq_req;
|
||||
struct rte_ring *msgq_rsp;
|
||||
uint32_t timer_period_ms;
|
||||
|
||||
int enabled;
|
||||
uint32_t thread_id;
|
||||
uint32_t cpu_id;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(pipeline_list, pipeline);
|
||||
|
||||
int
|
||||
pipeline_init(void);
|
||||
|
||||
struct pipeline *
|
||||
pipeline_find(const char *name);
|
||||
|
||||
struct pipeline *
|
||||
pipeline_create(const char *name, struct pipeline_params *params);
|
||||
|
||||
int
|
||||
pipeline_port_in_create(const char *pipeline_name,
|
||||
struct port_in_params *params,
|
||||
int enabled);
|
||||
|
||||
int
|
||||
pipeline_port_in_connect_to_table(const char *pipeline_name,
|
||||
uint32_t port_id,
|
||||
uint32_t table_id);
|
||||
|
||||
int
|
||||
pipeline_port_out_create(const char *pipeline_name,
|
||||
struct port_out_params *params);
|
||||
|
||||
int
|
||||
pipeline_table_create(const char *pipeline_name,
|
||||
struct table_params *params);
|
||||
|
||||
struct table_rule_match_acl {
|
||||
int ip_version;
|
||||
|
||||
RTE_STD_C11
|
||||
union {
|
||||
struct {
|
||||
uint32_t sa;
|
||||
uint32_t da;
|
||||
} ipv4;
|
||||
|
||||
struct {
|
||||
uint8_t sa[16];
|
||||
uint8_t da[16];
|
||||
} ipv6;
|
||||
};
|
||||
|
||||
uint32_t sa_depth;
|
||||
uint32_t da_depth;
|
||||
uint16_t sp0;
|
||||
uint16_t sp1;
|
||||
uint16_t dp0;
|
||||
uint16_t dp1;
|
||||
uint8_t proto;
|
||||
uint8_t proto_mask;
|
||||
uint32_t priority;
|
||||
};
|
||||
|
||||
struct table_rule_match_array {
|
||||
uint32_t pos;
|
||||
};
|
||||
|
||||
#ifndef TABLE_RULE_MATCH_SIZE_MAX
|
||||
#define TABLE_RULE_MATCH_SIZE_MAX 256
|
||||
#endif
|
||||
|
||||
#ifndef TABLE_RULE_ACTION_SIZE_MAX
|
||||
#define TABLE_RULE_ACTION_SIZE_MAX 2048
|
||||
#endif
|
||||
|
||||
struct table_rule_match_hash {
|
||||
uint8_t key[TABLE_RULE_MATCH_SIZE_MAX];
|
||||
};
|
||||
|
||||
struct table_rule_match_lpm {
|
||||
int ip_version;
|
||||
|
||||
RTE_STD_C11
|
||||
union {
|
||||
uint32_t ipv4;
|
||||
uint8_t ipv6[16];
|
||||
};
|
||||
|
||||
uint8_t depth;
|
||||
};
|
||||
|
||||
struct table_rule_match {
|
||||
enum table_type match_type;
|
||||
|
||||
union {
|
||||
struct table_rule_match_acl acl;
|
||||
struct table_rule_match_array array;
|
||||
struct table_rule_match_hash hash;
|
||||
struct table_rule_match_lpm lpm;
|
||||
} match;
|
||||
};
|
||||
|
||||
struct table_rule_action {
|
||||
uint64_t action_mask;
|
||||
struct rte_table_action_fwd_params fwd;
|
||||
struct rte_table_action_mtr_params mtr;
|
||||
struct rte_table_action_tm_params tm;
|
||||
struct rte_table_action_encap_params encap;
|
||||
struct rte_table_action_nat_params nat;
|
||||
struct rte_table_action_ttl_params ttl;
|
||||
struct rte_table_action_stats_params stats;
|
||||
struct rte_table_action_time_params time;
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE_PIPELINE_H_ */
|
Loading…
Reference in New Issue
Block a user