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:
Jasvinder Singh 2018-03-29 19:31:48 +01:00 committed by Cristian Dumitrescu
parent 719374345c
commit d75c371e9b
7 changed files with 2088 additions and 2 deletions

View File

@ -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

View File

@ -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]);
}

View File

@ -7,8 +7,6 @@
#include <stddef.h>
#include "action.h"
void
cli_process(char *in, char *out, size_t out_size);

View File

@ -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,

View File

@ -17,6 +17,7 @@ sources = files(
'main.c',
'mempool.c',
'parser.c',
'pipeline.c',
'swq.c',
'tap.c',
'tmgr.c'

View 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;
}

View 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_ */