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:
Cristian Dumitrescu 2021-03-16 11:40:39 +00:00 committed by Thomas Monjalon
parent 64cfcebd68
commit f38913b7fb
8 changed files with 2132 additions and 0 deletions

View File

@ -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(&params.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(&params.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(&params.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(&params.pbs, tokens[13])) {
snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
return;
}
status = rte_swx_ctl_meter_profile_add(p->p, profile_name, &params);
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[] = static const char cmd_pipeline_stats_help[] =
"pipeline <pipeline_name> stats\n"; "pipeline <pipeline_name> stats\n";
@ -1551,6 +1943,11 @@ cmd_help(char **tokens,
"\tpipeline table update\n" "\tpipeline table update\n"
"\tpipeline regrd\n" "\tpipeline regrd\n"
"\tpipeline regwr\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" "\tpipeline stats\n"
"\tthread pipeline enable\n" "\tthread pipeline enable\n"
"\tthread pipeline disable\n\n"); "\tthread pipeline disable\n\n");
@ -1625,6 +2022,43 @@ cmd_help(char **tokens,
return; 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) && if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "stats") == 0)) { (n_tokens == 2) && (strcmp(tokens[1], "stats") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_stats_help); 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; 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) && if ((n_tokens >= 3) &&
(strcmp(tokens[2], "stats") == 0)) { (strcmp(tokens[2], "stats") == 0)) {
cmd_pipeline_stats(tokens, n_tokens, out, out_size, cmd_pipeline_stats(tokens, n_tokens, out, out_size,

View 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

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

View File

@ -18,6 +18,7 @@ extern "C" {
#include <stdio.h> #include <stdio.h>
#include <rte_compat.h> #include <rte_compat.h>
#include <rte_meter.h>
#include "rte_swx_port.h" #include "rte_swx_port.h"
#include "rte_swx_table.h" #include "rte_swx_table.h"
@ -49,6 +50,9 @@ struct rte_swx_ctl_pipeline_info {
/** Number of register arrays. */ /** Number of register arrays. */
uint32_t n_regarrays; 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, uint32_t regarray_index,
uint64_t value); 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 * Pipeline control free
* *

File diff suppressed because it is too large Load Diff

View File

@ -640,6 +640,28 @@ rte_swx_pipeline_regarray_config(struct rte_swx_pipeline *p,
uint32_t size, uint32_t size,
uint64_t init_val); 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 * Pipeline instructions configure
* *

View File

@ -1015,6 +1015,68 @@ regarray_statement_parse(struct regarray_spec *s,
return 0; 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. * apply.
* *
@ -1142,6 +1204,7 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
struct action_spec action_spec = {0}; struct action_spec action_spec = {0};
struct table_spec table_spec = {0}; struct table_spec table_spec = {0};
struct regarray_spec regarray_spec = {0}; struct regarray_spec regarray_spec = {0};
struct metarray_spec metarray_spec = {0};
struct apply_spec apply_spec = {0}; struct apply_spec apply_spec = {0};
uint32_t n_lines; uint32_t n_lines;
uint32_t block_mask = 0; uint32_t block_mask = 0;
@ -1509,6 +1572,33 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue; 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. */ /* apply. */
if (!strcmp(tokens[0], "apply")) { if (!strcmp(tokens[0], "apply")) {
status = apply_statement_parse(&block_mask, 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); action_spec_free(&action_spec);
table_spec_free(&table_spec); table_spec_free(&table_spec);
regarray_spec_free(&regarray_spec); regarray_spec_free(&regarray_spec);
metarray_spec_free(&metarray_spec);
apply_spec_free(&apply_spec); apply_spec_free(&apply_spec);
return status; return status;
} }

View File

@ -104,8 +104,15 @@ EXPERIMENTAL {
rte_swx_pipeline_table_type_register; rte_swx_pipeline_table_type_register;
#added in 21.05 #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_read;
rte_swx_ctl_pipeline_regarray_write; rte_swx_ctl_pipeline_regarray_write;
rte_swx_ctl_regarray_info_get; rte_swx_ctl_regarray_info_get;
rte_swx_pipeline_metarray_config;
rte_swx_pipeline_regarray_config; rte_swx_pipeline_regarray_config;
}; };