pipeline: add meter array to SWX
Meter arrays are stateful objects that are updated by the data plane and configured & monitored by the control plane. The meters implement the RFC 2698 Two Rate Three Color Marker (trTCM) algorithm. Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
This commit is contained in:
parent
64cfcebd68
commit
f38913b7fb
@ -1355,6 +1355,398 @@ cmd_pipeline_regwr(char **tokens,
|
||||
}
|
||||
}
|
||||
|
||||
static const char cmd_pipeline_meter_profile_add_help[] =
|
||||
"pipeline <pipeline_name> meter profile <profile_name> add "
|
||||
"cir <cir> pir <pir> cbs <cbs> pbs <pbs>\n";
|
||||
|
||||
static void
|
||||
cmd_pipeline_meter_profile_add(char **tokens,
|
||||
uint32_t n_tokens,
|
||||
char *out,
|
||||
size_t out_size,
|
||||
void *obj)
|
||||
{
|
||||
struct rte_meter_trtcm_params params;
|
||||
struct pipeline *p;
|
||||
const char *profile_name;
|
||||
int status;
|
||||
|
||||
if (n_tokens != 14) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
p = pipeline_find(obj, tokens[1]);
|
||||
if (!p || !p->ctl) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[2], "meter")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[3], "profile")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
|
||||
return;
|
||||
}
|
||||
|
||||
profile_name = tokens[4];
|
||||
|
||||
if (strcmp(tokens[5], "add")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[6], "cir")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint64(¶ms.cir, tokens[7])) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "cir");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[8], "pir")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint64(¶ms.pir, tokens[9])) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "pir");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[10], "cbs")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint64(¶ms.cbs, tokens[11])) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[12], "pbs")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint64(¶ms.pbs, tokens[13])) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
|
||||
return;
|
||||
}
|
||||
|
||||
status = rte_swx_ctl_meter_profile_add(p->p, profile_name, ¶ms);
|
||||
if (status) {
|
||||
snprintf(out, out_size, "Command failed.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static const char cmd_pipeline_meter_profile_delete_help[] =
|
||||
"pipeline <pipeline_name> meter profile <profile_name> delete\n";
|
||||
|
||||
static void
|
||||
cmd_pipeline_meter_profile_delete(char **tokens,
|
||||
uint32_t n_tokens,
|
||||
char *out,
|
||||
size_t out_size,
|
||||
void *obj)
|
||||
{
|
||||
struct pipeline *p;
|
||||
const char *profile_name;
|
||||
int status;
|
||||
|
||||
if (n_tokens != 6) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
p = pipeline_find(obj, tokens[1]);
|
||||
if (!p || !p->ctl) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[2], "meter")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[3], "profile")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
|
||||
return;
|
||||
}
|
||||
|
||||
profile_name = tokens[4];
|
||||
|
||||
if (strcmp(tokens[5], "delete")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
|
||||
return;
|
||||
}
|
||||
|
||||
status = rte_swx_ctl_meter_profile_delete(p->p, profile_name);
|
||||
if (status) {
|
||||
snprintf(out, out_size, "Command failed.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static const char cmd_pipeline_meter_reset_help[] =
|
||||
"pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> "
|
||||
"reset\n";
|
||||
|
||||
static void
|
||||
cmd_pipeline_meter_reset(char **tokens,
|
||||
uint32_t n_tokens,
|
||||
char *out,
|
||||
size_t out_size,
|
||||
void *obj)
|
||||
{
|
||||
struct pipeline *p;
|
||||
const char *name;
|
||||
uint32_t idx0, idx1;
|
||||
|
||||
if (n_tokens != 9) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
p = pipeline_find(obj, tokens[1]);
|
||||
if (!p || !p->ctl) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[2], "meter")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
|
||||
return;
|
||||
}
|
||||
|
||||
name = tokens[3];
|
||||
|
||||
if (strcmp(tokens[4], "from")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&idx0, tokens[5])) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "index0");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[6], "to")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&idx1, tokens[7]) || (idx1 < idx0)) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "index1");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[8], "reset")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "reset");
|
||||
return;
|
||||
}
|
||||
|
||||
for ( ; idx0 <= idx1; idx0++) {
|
||||
int status;
|
||||
|
||||
status = rte_swx_ctl_meter_reset(p->p, name, idx0);
|
||||
if (status) {
|
||||
snprintf(out, out_size, "Command failed for index %u.\n", idx0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char cmd_pipeline_meter_set_help[] =
|
||||
"pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> "
|
||||
"set profile <profile_name>\n";
|
||||
|
||||
static void
|
||||
cmd_pipeline_meter_set(char **tokens,
|
||||
uint32_t n_tokens,
|
||||
char *out,
|
||||
size_t out_size,
|
||||
void *obj)
|
||||
{
|
||||
struct pipeline *p;
|
||||
const char *name, *profile_name;
|
||||
uint32_t idx0, idx1;
|
||||
|
||||
if (n_tokens != 11) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
p = pipeline_find(obj, tokens[1]);
|
||||
if (!p || !p->ctl) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[2], "meter")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
|
||||
return;
|
||||
}
|
||||
|
||||
name = tokens[3];
|
||||
|
||||
if (strcmp(tokens[4], "from")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&idx0, tokens[5])) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "index0");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[6], "to")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&idx1, tokens[7]) || (idx1 < idx0)) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "index1");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[8], "set")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "set");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[9], "profile")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
|
||||
return;
|
||||
}
|
||||
|
||||
profile_name = tokens[10];
|
||||
|
||||
for ( ; idx0 <= idx1; idx0++) {
|
||||
int status;
|
||||
|
||||
status = rte_swx_ctl_meter_set(p->p, name, idx0, profile_name);
|
||||
if (status) {
|
||||
snprintf(out, out_size, "Command failed for index %u.\n", idx0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char cmd_pipeline_meter_stats_help[] =
|
||||
"pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> "
|
||||
"stats\n";
|
||||
|
||||
static void
|
||||
cmd_pipeline_meter_stats(char **tokens,
|
||||
uint32_t n_tokens,
|
||||
char *out,
|
||||
size_t out_size,
|
||||
void *obj)
|
||||
{
|
||||
struct rte_swx_ctl_meter_stats stats;
|
||||
struct pipeline *p;
|
||||
const char *name;
|
||||
uint32_t idx0, idx1;
|
||||
|
||||
if (n_tokens != 9) {
|
||||
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
p = pipeline_find(obj, tokens[1]);
|
||||
if (!p || !p->ctl) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[2], "meter")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
|
||||
return;
|
||||
}
|
||||
|
||||
name = tokens[3];
|
||||
|
||||
if (strcmp(tokens[4], "from")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&idx0, tokens[5])) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "index0");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[6], "to")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser_read_uint32(&idx1, tokens[7]) || (idx1 < idx0)) {
|
||||
snprintf(out, out_size, MSG_ARG_INVALID, "index1");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[8], "stats")) {
|
||||
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Table header. */
|
||||
snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
|
||||
"-------",
|
||||
"----------------", "----------------", "----------------",
|
||||
"----------------", "----------------", "----------------");
|
||||
out_size -= strlen(out);
|
||||
out += strlen(out);
|
||||
|
||||
snprintf(out, out_size, "| %4s | %16s | %16s | %16s | %16s | %16s | %16s |\n",
|
||||
"METER #",
|
||||
"GREEN (packets)", "YELLOW (packets)", "RED (packets)",
|
||||
"GREEN (bytes)", "YELLOW (bytes)", "RED (bytes)");
|
||||
out_size -= strlen(out);
|
||||
out += strlen(out);
|
||||
|
||||
snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
|
||||
"-------",
|
||||
"----------------", "----------------", "----------------",
|
||||
"----------------", "----------------", "----------------");
|
||||
out_size -= strlen(out);
|
||||
out += strlen(out);
|
||||
|
||||
/* Table rows. */
|
||||
for ( ; idx0 <= idx1; idx0++) {
|
||||
int status;
|
||||
|
||||
status = rte_swx_ctl_meter_stats_read(p->p, name, idx0, &stats);
|
||||
if (status) {
|
||||
snprintf(out, out_size, "Pipeline meter stats error at index %u.\n", idx0);
|
||||
out_size -= strlen(out);
|
||||
out += strlen(out);
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(out, out_size, "| %7d | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64
|
||||
" | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 " |\n",
|
||||
idx0,
|
||||
stats.n_pkts[RTE_COLOR_GREEN],
|
||||
stats.n_pkts[RTE_COLOR_YELLOW],
|
||||
stats.n_pkts[RTE_COLOR_RED],
|
||||
stats.n_bytes[RTE_COLOR_GREEN],
|
||||
stats.n_bytes[RTE_COLOR_YELLOW],
|
||||
stats.n_bytes[RTE_COLOR_RED]);
|
||||
out_size -= strlen(out);
|
||||
out += strlen(out);
|
||||
}
|
||||
}
|
||||
|
||||
static const char cmd_pipeline_stats_help[] =
|
||||
"pipeline <pipeline_name> stats\n";
|
||||
|
||||
@ -1551,6 +1943,11 @@ cmd_help(char **tokens,
|
||||
"\tpipeline table update\n"
|
||||
"\tpipeline regrd\n"
|
||||
"\tpipeline regwr\n"
|
||||
"\tpipeline meter profile add\n"
|
||||
"\tpipeline meter profile delete\n"
|
||||
"\tpipeline meter reset\n"
|
||||
"\tpipeline meter set\n"
|
||||
"\tpipeline meter stats\n"
|
||||
"\tpipeline stats\n"
|
||||
"\tthread pipeline enable\n"
|
||||
"\tthread pipeline disable\n\n");
|
||||
@ -1625,6 +2022,43 @@ cmd_help(char **tokens,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(tokens[0], "pipeline") &&
|
||||
(n_tokens == 4) && !strcmp(tokens[1], "meter")
|
||||
&& !strcmp(tokens[2], "profile")
|
||||
&& !strcmp(tokens[3], "add")) {
|
||||
snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_profile_add_help);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(tokens[0], "pipeline") &&
|
||||
(n_tokens == 4) && !strcmp(tokens[1], "meter")
|
||||
&& !strcmp(tokens[2], "profile")
|
||||
&& !strcmp(tokens[3], "delete")) {
|
||||
snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_profile_delete_help);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(tokens[0], "pipeline") &&
|
||||
(n_tokens == 3) && !strcmp(tokens[1], "meter")
|
||||
&& !strcmp(tokens[2], "reset")) {
|
||||
snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_reset_help);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(tokens[0], "pipeline") &&
|
||||
(n_tokens == 3) && !strcmp(tokens[1], "meter")
|
||||
&& !strcmp(tokens[2], "set")) {
|
||||
snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_set_help);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(tokens[0], "pipeline") &&
|
||||
(n_tokens == 3) && !strcmp(tokens[1], "meter")
|
||||
&& !strcmp(tokens[2], "stats")) {
|
||||
snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_stats_help);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((strcmp(tokens[0], "pipeline") == 0) &&
|
||||
(n_tokens == 2) && (strcmp(tokens[1], "stats") == 0)) {
|
||||
snprintf(out, out_size, "\n%s\n", cmd_pipeline_stats_help);
|
||||
@ -1749,6 +2183,43 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n_tokens >= 6) &&
|
||||
(strcmp(tokens[2], "meter") == 0) &&
|
||||
(strcmp(tokens[3], "profile") == 0) &&
|
||||
(strcmp(tokens[5], "add") == 0)) {
|
||||
cmd_pipeline_meter_profile_add(tokens, n_tokens, out, out_size, obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n_tokens >= 6) &&
|
||||
(strcmp(tokens[2], "meter") == 0) &&
|
||||
(strcmp(tokens[3], "profile") == 0) &&
|
||||
(strcmp(tokens[5], "delete") == 0)) {
|
||||
cmd_pipeline_meter_profile_delete(tokens, n_tokens, out, out_size, obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n_tokens >= 9) &&
|
||||
(strcmp(tokens[2], "meter") == 0) &&
|
||||
(strcmp(tokens[8], "reset") == 0)) {
|
||||
cmd_pipeline_meter_reset(tokens, n_tokens, out, out_size, obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n_tokens >= 9) &&
|
||||
(strcmp(tokens[2], "meter") == 0) &&
|
||||
(strcmp(tokens[8], "set") == 0)) {
|
||||
cmd_pipeline_meter_set(tokens, n_tokens, out, out_size, obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n_tokens >= 9) &&
|
||||
(strcmp(tokens[2], "meter") == 0) &&
|
||||
(strcmp(tokens[8], "stats") == 0)) {
|
||||
cmd_pipeline_meter_stats(tokens, n_tokens, out, out_size, obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n_tokens >= 3) &&
|
||||
(strcmp(tokens[2], "stats") == 0)) {
|
||||
cmd_pipeline_stats(tokens, n_tokens, out, out_size,
|
||||
|
31
examples/pipeline/examples/meter.cli
Normal file
31
examples/pipeline/examples/meter.cli
Normal file
@ -0,0 +1,31 @@
|
||||
; SPDX-License-Identifier: BSD-3-Clause
|
||||
; Copyright(c) 2020 Intel Corporation
|
||||
|
||||
; Example command line:
|
||||
; ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/meter.cli
|
||||
|
||||
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
|
||||
|
||||
link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
|
||||
link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
|
||||
link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
|
||||
link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
|
||||
|
||||
pipeline PIPELINE0 create 0
|
||||
|
||||
pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
|
||||
pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
|
||||
pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
|
||||
pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
|
||||
|
||||
pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
|
||||
pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
|
||||
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
|
||||
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
|
||||
|
||||
pipeline PIPELINE0 build ./examples/pipeline/examples/meter.spec
|
||||
|
||||
pipeline PIPELINE0 meter profile platinum add cir 46000000 pir 138000000 cbs 1000000 pbs 1000000
|
||||
pipeline PIPELINE0 meter meters from 0 to 15 set profile platinum
|
||||
|
||||
thread 1 pipeline PIPELINE0 enable
|
63
examples/pipeline/examples/meter.spec
Normal file
63
examples/pipeline/examples/meter.spec
Normal file
@ -0,0 +1,63 @@
|
||||
; SPDX-License-Identifier: BSD-3-Clause
|
||||
; Copyright(c) 2021 Intel Corporation
|
||||
|
||||
; This program is setting up an array of Two Rate Three Color Marker (trTCM) meters called "meters".
|
||||
; Every input packet (Ethernet/IPv4) is metered by the meter at the location indexed by the IPv4
|
||||
; header "Source Address" field. All green packets are sent out on port 0, the yellow ones on port 1
|
||||
; and the red ones on port 2.
|
||||
;
|
||||
; The "meter stats" CLI command can be used to read the packet and byte statistics counters of any
|
||||
; meter in the array.
|
||||
|
||||
//
|
||||
// Headers.
|
||||
//
|
||||
struct ethernet_h {
|
||||
bit<48> dst_addr
|
||||
bit<48> src_addr
|
||||
bit<16> ethertype
|
||||
}
|
||||
|
||||
struct ipv4_h {
|
||||
bit<8> ver_ihl
|
||||
bit<8> diffserv
|
||||
bit<16> total_len
|
||||
bit<16> identification
|
||||
bit<16> flags_offset
|
||||
bit<8> ttl
|
||||
bit<8> protocol
|
||||
bit<16> hdr_checksum
|
||||
bit<32> src_addr
|
||||
bit<32> dst_addr
|
||||
}
|
||||
|
||||
header ethernet instanceof ethernet_h
|
||||
header ipv4 instanceof ipv4_h
|
||||
|
||||
//
|
||||
// Meta-data.
|
||||
//
|
||||
struct metadata_t {
|
||||
bit<32> port_in
|
||||
bit<32> port_out
|
||||
}
|
||||
|
||||
metadata instanceof metadata_t
|
||||
|
||||
//
|
||||
// Registers.
|
||||
//
|
||||
metarray meters size 65536
|
||||
|
||||
//
|
||||
// Pipeline.
|
||||
//
|
||||
apply {
|
||||
rx m.port_in
|
||||
extract h.ethernet
|
||||
extract h.ipv4
|
||||
meter meters h.ipv4.src_addr h.ipv4.total_len 0 m.port_out
|
||||
emit h.ethernet
|
||||
emit h.ipv4
|
||||
tx m.port_out
|
||||
}
|
@ -18,6 +18,7 @@ extern "C" {
|
||||
#include <stdio.h>
|
||||
|
||||
#include <rte_compat.h>
|
||||
#include <rte_meter.h>
|
||||
|
||||
#include "rte_swx_port.h"
|
||||
#include "rte_swx_table.h"
|
||||
@ -49,6 +50,9 @@ struct rte_swx_ctl_pipeline_info {
|
||||
|
||||
/** Number of register arrays. */
|
||||
uint32_t n_regarrays;
|
||||
|
||||
/** Number of meter arrays. */
|
||||
uint32_t n_metarrays;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -636,6 +640,157 @@ rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
|
||||
uint32_t regarray_index,
|
||||
uint64_t value);
|
||||
|
||||
/*
|
||||
* Meter Array Query and Configuration API.
|
||||
*/
|
||||
|
||||
/** Meter array info. */
|
||||
struct rte_swx_ctl_metarray_info {
|
||||
/** Meter array name. */
|
||||
char name[RTE_SWX_CTL_NAME_SIZE];
|
||||
|
||||
/** Meter array size. */
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Meter array info get
|
||||
*
|
||||
* @param[in] p
|
||||
* Pipeline handle.
|
||||
* @param[in] metarray_id
|
||||
* Meter array ID (0 .. *n_metarrays* - 1).
|
||||
* @param[out] metarray
|
||||
* Meter array info.
|
||||
* @return
|
||||
* 0 on success or the following error codes otherwise:
|
||||
* -EINVAL: Invalid argument.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_swx_ctl_metarray_info_get(struct rte_swx_pipeline *p,
|
||||
uint32_t metarray_id,
|
||||
struct rte_swx_ctl_metarray_info *metarray);
|
||||
|
||||
/**
|
||||
* Meter profile add
|
||||
*
|
||||
* @param[in] p
|
||||
* Pipeline handle.
|
||||
* @param[in] name
|
||||
* Meter profile name.
|
||||
* @param[in] params
|
||||
* Meter profile parameters.
|
||||
* @return
|
||||
* 0 on success or the following error codes otherwise:
|
||||
* -EINVAL: Invalid argument;
|
||||
* -ENOMEM: Not enough space/cannot allocate memory;
|
||||
* -EEXIST: Meter profile with this name already exists.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_swx_ctl_meter_profile_add(struct rte_swx_pipeline *p,
|
||||
const char *name,
|
||||
struct rte_meter_trtcm_params *params);
|
||||
|
||||
/**
|
||||
* Meter profile delete
|
||||
*
|
||||
* @param[in] p
|
||||
* Pipeline handle.
|
||||
* @param[in] name
|
||||
* Meter profile name.
|
||||
* @return
|
||||
* 0 on success or the following error codes otherwise:
|
||||
* -EINVAL: Invalid argument;
|
||||
* -EBUSY: Meter profile is currently in use.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_swx_ctl_meter_profile_delete(struct rte_swx_pipeline *p,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* Meter reset
|
||||
*
|
||||
* Reset a meter within a given meter array to use the default profile that
|
||||
* causes all the input packets to be colored as green. It is the responsibility
|
||||
* of the control plane to make sure this meter is not used by the data plane
|
||||
* pipeline before calling this function.
|
||||
*
|
||||
* @param[in] p
|
||||
* Pipeline handle.
|
||||
* @param[in] metarray_name
|
||||
* Meter array name.
|
||||
* @param[in] metarray_index
|
||||
* Meter index within the meter array.
|
||||
* @return
|
||||
* 0 on success or the following error codes otherwise:
|
||||
* -EINVAL: Invalid argument.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_swx_ctl_meter_reset(struct rte_swx_pipeline *p,
|
||||
const char *metarray_name,
|
||||
uint32_t metarray_index);
|
||||
|
||||
/**
|
||||
* Meter set
|
||||
*
|
||||
* Set a meter within a given meter array to use a specific profile. It is the
|
||||
* responsibility of the control plane to make sure this meter is not used by
|
||||
* the data plane pipeline before calling this function.
|
||||
*
|
||||
* @param[in] p
|
||||
* Pipeline handle.
|
||||
* @param[in] metarray_name
|
||||
* Meter array name.
|
||||
* @param[in] metarray_index
|
||||
* Meter index within the meter array.
|
||||
* @param[in] profile_name
|
||||
* Existing meter profile name.
|
||||
* @return
|
||||
* 0 on success or the following error codes otherwise:
|
||||
* -EINVAL: Invalid argument.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_swx_ctl_meter_set(struct rte_swx_pipeline *p,
|
||||
const char *metarray_name,
|
||||
uint32_t metarray_index,
|
||||
const char *profile_name);
|
||||
|
||||
/** Meter statistics counters. */
|
||||
struct rte_swx_ctl_meter_stats {
|
||||
/** Number of packets tagged by the meter for each color. */
|
||||
uint64_t n_pkts[RTE_COLORS];
|
||||
|
||||
/** Number of bytes tagged by the meter for each color. */
|
||||
uint64_t n_bytes[RTE_COLORS];
|
||||
};
|
||||
|
||||
/**
|
||||
* Meter statistics counters read
|
||||
*
|
||||
* @param[in] p
|
||||
* Pipeline handle.
|
||||
* @param[in] metarray_name
|
||||
* Meter array name.
|
||||
* @param[in] metarray_index
|
||||
* Meter index within the meter array.
|
||||
* @param[out] stats
|
||||
* Meter statistics counters.
|
||||
* @return
|
||||
* 0 on success or the following error codes otherwise:
|
||||
* -EINVAL: Invalid argument.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_swx_ctl_meter_stats_read(struct rte_swx_pipeline *p,
|
||||
const char *metarray_name,
|
||||
uint32_t metarray_index,
|
||||
struct rte_swx_ctl_meter_stats *stats);
|
||||
|
||||
/**
|
||||
* Pipeline control free
|
||||
*
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -640,6 +640,28 @@ rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
|
||||
uint32_t size,
|
||||
uint64_t init_val);
|
||||
|
||||
/**
|
||||
* Pipeline meter array configure
|
||||
*
|
||||
* @param[in] p
|
||||
* Pipeline handle.
|
||||
* @param[in] name
|
||||
* Meter array name.
|
||||
* @param[in] size
|
||||
* Number of meters in the array. Each meter in the array implements the Two
|
||||
* Rate Three Color Marker (trTCM) algorithm, as specified by RFC 2698.
|
||||
* @return
|
||||
* 0 on success or the following error codes otherwise:
|
||||
* -EINVAL: Invalid argument;
|
||||
* -ENOMEM: Not enough space/cannot allocate memory;
|
||||
* -EEXIST: Meter array with this name already exists.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_swx_pipeline_metarray_config(struct rte_swx_pipeline *p,
|
||||
const char *name,
|
||||
uint32_t size);
|
||||
|
||||
/**
|
||||
* Pipeline instructions configure
|
||||
*
|
||||
|
@ -1015,6 +1015,68 @@ regarray_statement_parse(struct regarray_spec *s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* metarray.
|
||||
*
|
||||
* metarray NAME size SIZE
|
||||
*/
|
||||
struct metarray_spec {
|
||||
char *name;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
static void
|
||||
metarray_spec_free(struct metarray_spec *s)
|
||||
{
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
free(s->name);
|
||||
s->name = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
metarray_statement_parse(struct metarray_spec *s,
|
||||
char **tokens,
|
||||
uint32_t n_tokens,
|
||||
uint32_t n_lines,
|
||||
uint32_t *err_line,
|
||||
const char **err_msg)
|
||||
{
|
||||
char *p;
|
||||
|
||||
/* Check format. */
|
||||
if ((n_tokens != 4) || strcmp(tokens[2], "size")) {
|
||||
if (err_line)
|
||||
*err_line = n_lines;
|
||||
if (err_msg)
|
||||
*err_msg = "Invalid metarray statement.";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* spec. */
|
||||
s->name = strdup(tokens[1]);
|
||||
if (!s->name) {
|
||||
if (err_line)
|
||||
*err_line = n_lines;
|
||||
if (err_msg)
|
||||
*err_msg = "Memory allocation failed.";
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
p = tokens[3];
|
||||
s->size = strtoul(p, &p, 0);
|
||||
if (p[0] || !s->size) {
|
||||
if (err_line)
|
||||
*err_line = n_lines;
|
||||
if (err_msg)
|
||||
*err_msg = "Invalid size argument.";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* apply.
|
||||
*
|
||||
@ -1142,6 +1204,7 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
|
||||
struct action_spec action_spec = {0};
|
||||
struct table_spec table_spec = {0};
|
||||
struct regarray_spec regarray_spec = {0};
|
||||
struct metarray_spec metarray_spec = {0};
|
||||
struct apply_spec apply_spec = {0};
|
||||
uint32_t n_lines;
|
||||
uint32_t block_mask = 0;
|
||||
@ -1509,6 +1572,33 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* metarray. */
|
||||
if (!strcmp(tokens[0], "metarray")) {
|
||||
status = metarray_statement_parse(&metarray_spec,
|
||||
tokens,
|
||||
n_tokens,
|
||||
n_lines,
|
||||
err_line,
|
||||
err_msg);
|
||||
if (status)
|
||||
goto error;
|
||||
|
||||
status = rte_swx_pipeline_metarray_config(p,
|
||||
metarray_spec.name,
|
||||
metarray_spec.size);
|
||||
if (status) {
|
||||
if (err_line)
|
||||
*err_line = n_lines;
|
||||
if (err_msg)
|
||||
*err_msg = "Meter array configuration error.";
|
||||
goto error;
|
||||
}
|
||||
|
||||
metarray_spec_free(&metarray_spec);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* apply. */
|
||||
if (!strcmp(tokens[0], "apply")) {
|
||||
status = apply_statement_parse(&block_mask,
|
||||
@ -1562,6 +1652,7 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
|
||||
action_spec_free(&action_spec);
|
||||
table_spec_free(&table_spec);
|
||||
regarray_spec_free(®array_spec);
|
||||
metarray_spec_free(&metarray_spec);
|
||||
apply_spec_free(&apply_spec);
|
||||
return status;
|
||||
}
|
||||
|
@ -104,8 +104,15 @@ EXPERIMENTAL {
|
||||
rte_swx_pipeline_table_type_register;
|
||||
|
||||
#added in 21.05
|
||||
rte_swx_ctl_metarray_info_get;
|
||||
rte_swx_ctl_meter_profile_add;
|
||||
rte_swx_ctl_meter_profile_delete;
|
||||
rte_swx_ctl_meter_reset;
|
||||
rte_swx_ctl_meter_set;
|
||||
rte_swx_ctl_meter_stats_read;
|
||||
rte_swx_ctl_pipeline_regarray_read;
|
||||
rte_swx_ctl_pipeline_regarray_write;
|
||||
rte_swx_ctl_regarray_info_get;
|
||||
rte_swx_pipeline_metarray_config;
|
||||
rte_swx_pipeline_regarray_config;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user