summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2019-07-23 08:16:19 -0700
committerDamjan Marion <dmarion@me.com>2019-07-24 14:55:59 +0000
commit5281a9029ea56f397a37ea1cf478ac526882770a (patch)
treef0d295cbfdc83c632d57104f3c8c0de3f0f21a02 /src
parentc89c76737dfcf2aea2515f84a6ec5175c9f1e237 (diff)
qos: QoS dump APIs
Type: feature Change-Id: I514b40026986f3828c8727453456b20a0a45f3af Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src')
-rw-r--r--src/vat/api_format.c4
-rw-r--r--src/vnet/qos/qos.api174
-rw-r--r--src/vnet/qos/qos_api.c168
-rw-r--r--src/vnet/qos/qos_egress_map.c150
-rw-r--r--src/vnet/qos/qos_egress_map.h9
-rw-r--r--src/vnet/qos/qos_mark.c102
-rw-r--r--src/vnet/qos/qos_mark.h6
-rw-r--r--src/vnet/qos/qos_record.c102
-rw-r--r--src/vnet/qos/qos_record.h5
-rw-r--r--src/vpp/api/custom_dump.c4
10 files changed, 601 insertions, 123 deletions
diff --git a/src/vat/api_format.c b/src/vat/api_format.c
index d2313106fc6..69a57ab3d33 100644
--- a/src/vat/api_format.c
+++ b/src/vat/api_format.c
@@ -21373,8 +21373,8 @@ api_qos_record_enable_disable (vat_main_t * vam)
M (QOS_RECORD_ENABLE_DISABLE, mp);
- mp->sw_if_index = ntohl (sw_if_index);
- mp->input_source = qs;
+ mp->record.sw_if_index = ntohl (sw_if_index);
+ mp->record.input_source = qs;
mp->enable = enable;
S (mp);
diff --git a/src/vnet/qos/qos.api b/src/vnet/qos/qos.api
index 1960ccb9548..11c91638c5b 100644
--- a/src/vnet/qos/qos.api
+++ b/src/vnet/qos/qos.api
@@ -22,7 +22,7 @@
option version = "1.0.0";
-enum qos_source
+enum qos_source : u8
{
QOS_API_SOURCE_EXT = 0,
QOS_API_SOURCE_VLAN = 1,
@@ -30,76 +30,164 @@ enum qos_source
QOS_API_SOURCE_IP = 3,
};
-/** \brief Enable/Disable QoS recording
- The QoS bits from the packet at the specified input layer are copied
- into the packet. Recording should be used in conjunction with marking
- @param sw_if_index - The interface on which recording is enabled.
- @param enable - enable=1 or disable the feature
- @param input_source - The input source/layer at which the QoS bits
- are copied from the packet. See qos_source_t.
-*/
+/**
+ * QoS recording.
+ * @param sw_if_index - The interface on which recording is enabled.
+ * @param input_source - The input source/layer at which the QoS bits
+ are copied from the packet. See qos_source_t.
+ */
+typedef qos_record
+{
+ u32 sw_if_index;
+ vl_api_qos_source_t input_source;
+};
+
+/**
+ * Enable/Disable QoS recording
+ * The QoS bits from the packet at the specified input layer are copied
+ * into the packet. Recording should be used in conjunction with marking
+ * @param enable - enable=1 or disable the feature
+ * @param record - Recording configuration
+ */
autoreply define qos_record_enable_disable
{
u32 client_index;
u32 context;
- u32 sw_if_index;
- vl_api_qos_source_t input_source;
u8 enable;
+ vl_api_qos_record_t record;
};
-/** \brief A row within a QoS map
- Each value translates from an input value to an output.
-*/
-typeonly define qos_egress_map_row
+/**
+ * Dump the QoS record configs
+ */
+define qos_record_dump
{
- u8 outputs[256];
+ u32 client_index;
+ u32 context;
};
-/** \brief Update a QoS Map
- A QoS map, translates from the QoS value in the packet set by the 'record'
- feature, to the value used for output in the 'mark' feature.
- There is one row in the map for each input/record source.
- The MAP is then applied to the egress interface at for a given output source
- @param map_id - client provided identifier for the map
- @param rows - one row (per-input source) of output values
-*/
+/**
+ * Details of QoS recording configs
+ */
+define qos_record_details
+{
+ u32 context;
+ vl_api_qos_record_t record;
+};
+
+/**
+ * @brief A row within a QoS map
+ * Each value translates from an input value to an output.
+ */
+typedef qos_egress_map_row
+{
+ u8 outputs[256];
+};
+
+/**
+ * QoS Translation Map
+ *
+ * @param id - client provided identifier for the map
+ * @param rows - one row (per-input source) of output values
+ */
+typedef qos_egress_map
+{
+ u32 id;
+ vl_api_qos_egress_map_row_t rows[4];
+};
+
+/**
+ * @brief Update a QoS Map
+ * A QoS map, translates from the QoS value in the packet set by the 'record'
+ * feature, to the value used for output in the 'mark' feature.
+ * There is one row in the map for each input/record source.
+ * The MAP is then applied to the egress interface at for a given output source
+ * @param map - The Map
+ */
autoreply define qos_egress_map_update
{
u32 client_index;
u32 context;
- u32 map_id;
- vl_api_qos_egress_map_row_t rows[4];
+ vl_api_qos_egress_map_t map;
};
-/** \brief Delete a Qos Map
- @param map_id - ID of the map to delete
-*/
+/**
+ * @brief Delete a Qos Map
+ * @param map_id - ID of the map to delete
+ */
autoreply define qos_egress_map_delete
{
u32 client_index;
u32 context;
- u32 map_id;
+ u32 id;
};
-/** \brief Enable/Disable QoS marking
- The QoS bits from the packet are mapped (using the desired egress map)
- into the header of the 'output-source'. Marking should be used in
- conjunction with recording
- @param sw_if_index - The interface on which recording is enabled.
- @param enable - enable=1 or disable the feature
- @param output_source - The output source/layer at which the QoS bits
- are written into the packet. See qos_source_t.
- @param map_id - The ID of the MAP in which the translation from input
- to output is performed.
-*/
-autoreply define qos_mark_enable_disable
+/**
+ * Dump the QoS egress maps
+ */
+define qos_egress_map_dump
{
u32 client_index;
u32 context;
- u32 map_id;
+};
+
+/**
+ * QoS map details
+ */
+define qos_egress_map_details
+{
+ u32 context;
+ vl_api_qos_egress_map_t map;
+};
+
+/**
+ * QoS marking Cponfiguration
+ * The QoS bits from the buffer are mapped (using the desired egress map)
+ * into the header of the 'output-source'. Marking should be used in
+ * conjunction with recording
+ * @param sw_if_index - The interface on which recording is enabled.
+ * @param output_source - The output source/layer at which the QoS bits
+ * are written into the packet. See qos_source_t.
+ * @param map_id - The ID of the MAP in which the translation from input
+ * to output is performed.
+ */
+typedef qos_mark
+{
u32 sw_if_index;
+ u32 map_id;
vl_api_qos_source_t output_source;
+};
+
+/**
+ * @brief Enable/Disable QoS marking
+ * @param enable - enable=1 or disable the feature
+ * @param mark - Marking config
+ */
+autoreply define qos_mark_enable_disable
+{
+ u32 client_index;
+ u32 context;
u8 enable;
+ vl_api_qos_mark_t mark;
+};
+
+/**
+ * Dump QoS marking configs
+ */
+define qos_mark_dump
+{
+ u32 client_index;
+ u32 context;
+ u32 sw_if_index;
+};
+
+/**
+ * QoS marking details
+ */
+autoreply define qos_mark_details
+{
+ u32 context;
+ vl_api_qos_mark_t mark;
};
/*
diff --git a/src/vnet/qos/qos_api.c b/src/vnet/qos/qos_api.c
index 6297c24a843..966ffcce395 100644
--- a/src/vnet/qos/qos_api.c
+++ b/src/vnet/qos/qos_api.c
@@ -44,15 +44,16 @@
#define foreach_qos_api_msg \
_(QOS_RECORD_ENABLE_DISABLE, qos_record_enable_disable) \
+ _(QOS_RECORD_DUMP, qos_record_dump) \
_(QOS_EGRESS_MAP_DELETE, qos_egress_map_delete) \
_(QOS_EGRESS_MAP_UPDATE, qos_egress_map_update) \
- _(QOS_MARK_ENABLE_DISABLE, qos_mark_enable_disable)
+ _(QOS_EGRESS_MAP_DUMP, qos_egress_map_dump) \
+ _(QOS_MARK_ENABLE_DISABLE, qos_mark_enable_disable) \
+ _(QOS_MARK_DUMP, qos_mark_dump)
static int
qos_source_decode (vl_api_qos_source_t v, qos_source_t * q)
{
- v = ntohl (v);
-
switch (v)
{
case QOS_API_SOURCE_EXT:
@@ -72,6 +73,12 @@ qos_source_decode (vl_api_qos_source_t v, qos_source_t * q)
return (VNET_API_ERROR_INVALID_VALUE);
}
+static vl_api_qos_source_t
+qos_source_encode (qos_source_t q)
+{
+ return ((vl_api_qos_source_t) q);
+}
+
void
vl_api_qos_record_enable_disable_t_handler (vl_api_qos_record_enable_disable_t
* mp)
@@ -80,19 +87,63 @@ vl_api_qos_record_enable_disable_t_handler (vl_api_qos_record_enable_disable_t
qos_source_t qs;
int rv = 0;
- rv = qos_source_decode (mp->input_source, &qs);
+ VALIDATE_SW_IF_INDEX (&(mp->record));
+
+ rv = qos_source_decode (mp->record.input_source, &qs);
if (0 == rv)
{
if (mp->enable)
- rv = qos_record_enable (ntohl (mp->sw_if_index), qs);
+ rv = qos_record_enable (ntohl (mp->record.sw_if_index), qs);
else
- rv = qos_record_disable (ntohl (mp->sw_if_index), qs);
+ rv = qos_record_disable (ntohl (mp->record.sw_if_index), qs);
}
+ BAD_SW_IF_INDEX_LABEL;
REPLY_MACRO (VL_API_QOS_RECORD_ENABLE_DISABLE_REPLY);
}
+typedef struct qos_record_send_walk_ctx_t_
+{
+ vl_api_registration_t *reg;
+ u32 context;
+} qos_record_send_walk_ctx_t;
+
+static walk_rc_t
+send_qos_record_details (u32 sw_if_index, qos_source_t input_source, void *c)
+{
+ qos_record_send_walk_ctx_t *ctx;
+ vl_api_qos_record_details_t *mp;
+
+ ctx = c;
+ mp = vl_msg_api_alloc_zero (sizeof (*mp));
+
+ mp->_vl_msg_id = ntohs (VL_API_QOS_RECORD_DETAILS);
+ mp->context = ctx->context;
+ mp->record.sw_if_index = htonl (sw_if_index);
+ mp->record.input_source = qos_source_encode (input_source);
+
+ vl_api_send_msg (ctx->reg, (u8 *) mp);
+
+ return (WALK_CONTINUE);
+}
+
+static void
+vl_api_qos_record_dump_t_handler (vl_api_qos_record_dump_t * mp)
+{
+ vl_api_registration_t *reg;
+
+ reg = vl_api_client_index_to_registration (mp->client_index);
+ if (!reg)
+ return;
+
+ qos_record_send_walk_ctx_t ctx = {
+ .reg = reg,
+ .context = mp->context,
+ };
+ qos_record_walk (send_qos_record_details, &ctx);
+}
+
void
vl_api_qos_egress_map_update_t_handler (vl_api_qos_egress_map_update_t * mp)
{
@@ -102,7 +153,8 @@ vl_api_qos_egress_map_update_t_handler (vl_api_qos_egress_map_update_t * mp)
FOR_EACH_QOS_SOURCE (qs)
{
- qos_egress_map_update (ntohl (mp->map_id), qs, &mp->rows[qs].outputs[0]);
+ qos_egress_map_update (ntohl (mp->map.id), qs,
+ &mp->map.rows[qs].outputs[0]);
}
REPLY_MACRO (VL_API_QOS_EGRESS_MAP_UPDATE_REPLY);
@@ -114,33 +166,121 @@ vl_api_qos_egress_map_delete_t_handler (vl_api_qos_egress_map_delete_t * mp)
vl_api_qos_egress_map_delete_reply_t *rmp;
int rv = 0;
- qos_egress_map_delete (ntohl (mp->map_id));
+ qos_egress_map_delete (ntohl (mp->id));
REPLY_MACRO (VL_API_QOS_EGRESS_MAP_DELETE_REPLY);
}
+typedef struct qos_egress_map_send_walk_ctx_t_
+{
+ vl_api_registration_t *reg;
+ u32 context;
+} qos_egress_map_send_walk_ctx_t;
+
+static walk_rc_t
+send_qos_egress_map_details (qos_egress_map_id_t id,
+ const qos_egress_map_t * m, void *c)
+{
+ qos_egress_map_send_walk_ctx_t *ctx;
+ vl_api_qos_egress_map_details_t *mp;
+ u8 ii;
+
+ ctx = c;
+ mp = vl_msg_api_alloc_zero (sizeof (*mp));
+
+ mp->_vl_msg_id = ntohs (VL_API_QOS_EGRESS_MAP_DETAILS);
+ mp->context = ctx->context;
+ mp->map.id = htonl (id);
+
+ for (ii = 0; ii < 4; ii++)
+ clib_memcpy (mp->map.rows[ii].outputs, m->qem_output[ii], 256);
+
+ vl_api_send_msg (ctx->reg, (u8 *) mp);
+
+ return (WALK_CONTINUE);
+}
+
+static void
+vl_api_qos_egress_map_dump_t_handler (vl_api_qos_egress_map_dump_t * mp)
+{
+ vl_api_registration_t *reg;
+
+ reg = vl_api_client_index_to_registration (mp->client_index);
+ if (!reg)
+ return;
+
+ qos_egress_map_send_walk_ctx_t ctx = {
+ .reg = reg,
+ .context = mp->context,
+ };
+ qos_egress_map_walk (send_qos_egress_map_details, &ctx);
+}
+
void
- vl_api_qos_mark_enable_disable_t_handler
- (vl_api_qos_mark_enable_disable_t * mp)
+vl_api_qos_mark_enable_disable_t_handler (vl_api_qos_mark_enable_disable_t *
+ mp)
{
vl_api_qos_mark_enable_disable_reply_t *rmp;
qos_source_t qs;
int rv = 0;
- rv = qos_source_decode (mp->output_source, &qs);
+ rv = qos_source_decode (mp->mark.output_source, &qs);
if (0 == rv)
{
if (mp->enable)
- rv =
- qos_mark_enable (ntohl (mp->sw_if_index), qs, ntohl (mp->map_id));
+ rv = qos_mark_enable (ntohl (mp->mark.sw_if_index),
+ qs, ntohl (mp->mark.map_id));
else
- rv = qos_mark_disable (ntohl (mp->sw_if_index), qs);
+ rv = qos_mark_disable (ntohl (mp->mark.sw_if_index), qs);
}
REPLY_MACRO (VL_API_QOS_MARK_ENABLE_DISABLE_REPLY);
}
+typedef struct qos_mark_send_walk_ctx_t_
+{
+ vl_api_registration_t *reg;
+ u32 context;
+} qos_mark_send_walk_ctx_t;
+
+static walk_rc_t
+send_qos_mark_details (u32 sw_if_index,
+ u32 map_id, qos_source_t output_source, void *c)
+{
+ qos_mark_send_walk_ctx_t *ctx;
+ vl_api_qos_mark_details_t *mp;
+
+ ctx = c;
+ mp = vl_msg_api_alloc_zero (sizeof (*mp));
+
+ mp->_vl_msg_id = ntohs (VL_API_QOS_MARK_DETAILS);
+ mp->context = ctx->context;
+ mp->mark.sw_if_index = htonl (sw_if_index);
+ mp->mark.output_source = qos_source_encode (output_source);
+ mp->mark.map_id = htonl (map_id);
+
+ vl_api_send_msg (ctx->reg, (u8 *) mp);
+
+ return (WALK_CONTINUE);
+}
+
+static void
+vl_api_qos_mark_dump_t_handler (vl_api_qos_mark_dump_t * mp)
+{
+ vl_api_registration_t *reg;
+
+ reg = vl_api_client_index_to_registration (mp->client_index);
+ if (!reg)
+ return;
+
+ qos_mark_send_walk_ctx_t ctx = {
+ .reg = reg,
+ .context = mp->context,
+ };
+ qos_mark_walk (send_qos_mark_details, &ctx);
+}
+
#define vl_msg_name_crc_list
#include <vnet/qos/qos.api.h>
#undef vl_msg_name_crc_list
diff --git a/src/vnet/qos/qos_egress_map.c b/src/vnet/qos/qos_egress_map.c
index 158ff8445c6..7985579d3cf 100644
--- a/src/vnet/qos/qos_egress_map.c
+++ b/src/vnet/qos/qos_egress_map.c
@@ -41,6 +41,23 @@ qos_egress_map_find (qos_egress_map_id_t mid)
return (INDEX_INVALID);
}
+qos_egress_map_id_t
+qos_egress_map_get_id (index_t qemi)
+{
+ qos_egress_map_id_t qid;
+ index_t qmi;
+
+ /* *INDENT-OFF* */
+ hash_foreach(qid, qmi, qem_db,
+ ({
+ if (qmi == qemi)
+ return (qid);
+ }));
+ /* *INDENT-OFF* */
+
+ return (~0);
+}
+
qos_egress_map_t *
qos_egress_map_find_i (qos_egress_map_id_t mid)
{
@@ -106,6 +123,20 @@ qos_egress_map_delete (qos_egress_map_id_t mid)
}
}
+void
+qos_egress_map_walk (qos_egress_map_walk_cb_t fn, void *c)
+{
+ qos_egress_map_id_t qid;
+ index_t qmi;
+
+ /* *INDENT-OFF* */
+ hash_foreach(qid, qmi, qem_db,
+ ({
+ fn(qid, pool_elt_at_index(qem_pool, qmi), c);
+ }));
+ /* *INDENT-OFF* */
+}
+
static clib_error_t *
qos_egress_map_update_cli (vlib_main_t * vm,
unformat_input_t * input, vlib_cli_command_t * cmd)
@@ -159,55 +190,54 @@ VLIB_CLI_COMMAND (qos_egress_map_update_command, static) = {
};
/* *INDENT-ON* */
-u8 *
-format_qos_egress_map (u8 * s, va_list * args)
-{
- qos_egress_map_t *qem = va_arg (*args, qos_egress_map_t *);
- u32 indent = va_arg (*args, u32);
- int qs;
- u32 ii;
-
- FOR_EACH_QOS_SOURCE (qs)
+ u8 *format_qos_egress_map (u8 * s, va_list * args)
{
- s = format (s, "%U%U:[",
- format_white_space, indent, format_qos_source, qs);
-
- for (ii = 0; ii < ARRAY_LEN (qem->qem_output[qs]) - 1; ii++)
- {
- s = format (s, "%d,", qem->qem_output[qs][ii]);
- }
- s = format (s, "%d]\n", qem->qem_output[qs][ii]);
- }
+ qos_egress_map_t *qem = va_arg (*args, qos_egress_map_t *);
+ u32 indent = va_arg (*args, u32);
+ int qs;
+ u32 ii;
- return (s);
-}
-
-static clib_error_t *
-qos_egress_map_show (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- qos_egress_map_id_t map_id;
- qos_egress_map_t *qem;
- clib_error_t *error;
-
- map_id = ~0;
- qem = NULL;
- error = NULL;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ FOR_EACH_QOS_SOURCE (qs)
{
- if (unformat (input, "id %d", &map_id))
- ;
- else
+ s = format (s, "%U%U:[",
+ format_white_space, indent, format_qos_source, qs);
+
+ for (ii = 0; ii < ARRAY_LEN (qem->qem_output[qs]) - 1; ii++)
{
- error = unformat_parse_error (input);
- goto done;
+ s = format (s, "%d,", qem->qem_output[qs][ii]);
}
+ s = format (s, "%d]\n", qem->qem_output[qs][ii]);
}
- if (~0 == map_id)
- {
- index_t qemi;
+ return (s);
+ }
+
+ static clib_error_t *qos_egress_map_show (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+ {
+ qos_egress_map_id_t map_id;
+ qos_egress_map_t *qem;
+ clib_error_t *error;
+
+ map_id = ~0;
+ qem = NULL;
+ error = NULL;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "id %d", &map_id))
+ ;
+ else
+ {
+ error = unformat_parse_error (input);
+ goto done;
+ }
+ }
+
+ if (~0 == map_id)
+ {
+ index_t qemi;
/* *INDENT-OFF* */
hash_foreach(map_id, qemi, qem_db,
@@ -218,25 +248,25 @@ qos_egress_map_show (vlib_main_t * vm,
pool_elt_at_index(qem_pool, qemi), 2);
}));
/* *INDENT-ON* */
- }
- else
- {
- qem = qos_egress_map_find_i (map_id);
-
- if (NULL == qem)
- {
- error = clib_error_return (0, "No Map for ID %d", map_id);
- }
- else
- {
- vlib_cli_output (vm, " Map-ID:%d\n%U",
- map_id, format_qos_egress_map, qem, 2);
- }
- }
+ }
+ else
+ {
+ qem = qos_egress_map_find_i (map_id);
+
+ if (NULL == qem)
+ {
+ error = clib_error_return (0, "No Map for ID %d", map_id);
+ }
+ else
+ {
+ vlib_cli_output (vm, " Map-ID:%d\n%U",
+ map_id, format_qos_egress_map, qem, 2);
+ }
+ }
-done:
- return (error);
-}
+ done:
+ return (error);
+ }
/*?
* Show Egress Qos Maps
diff --git a/src/vnet/qos/qos_egress_map.h b/src/vnet/qos/qos_egress_map.h
index 3b6e0b45a43..0dab7adc2dd 100644
--- a/src/vnet/qos/qos_egress_map.h
+++ b/src/vnet/qos/qos_egress_map.h
@@ -66,6 +66,15 @@ extern void qos_egress_map_delete (qos_egress_map_id_t tid);
* Get the VPP QoS map index from the user's map-ID
*/
extern index_t qos_egress_map_find (qos_egress_map_id_t tid);
+extern qos_egress_map_id_t qos_egress_map_get_id (index_t qemi);
+
+/**
+ * Walk each of the configured maps
+ */
+typedef walk_rc_t (*qos_egress_map_walk_cb_t) (qos_egress_map_id_t id,
+ const qos_egress_map_t * m,
+ void *c);
+void qos_egress_map_walk (qos_egress_map_walk_cb_t fn, void *c);
/**
* Data-plane functions
diff --git a/src/vnet/qos/qos_mark.c b/src/vnet/qos/qos_mark.c
index dcb0f9d1ab3..44bb34bd010 100644
--- a/src/vnet/qos/qos_mark.c
+++ b/src/vnet/qos/qos_mark.c
@@ -117,6 +117,24 @@ qos_mark_disable (u32 sw_if_index, qos_source_t output_source)
return (0);
}
+void
+qos_mark_walk (qos_mark_walk_cb_t fn, void *c)
+{
+ qos_source_t qs;
+
+ FOR_EACH_QOS_SOURCE (qs)
+ {
+ u32 sw_if_index;
+
+ vec_foreach_index (sw_if_index, qos_mark_configs[qs])
+ {
+ if (INDEX_INVALID != qos_mark_configs[qs][sw_if_index])
+ fn (sw_if_index,
+ qos_egress_map_get_id (qos_mark_configs[qs][sw_if_index]), qs, c);
+ }
+ }
+}
+
static clib_error_t *
qos_mark_cli (vlib_main_t * vm,
unformat_input_t * input, vlib_cli_command_t * cmd)
@@ -178,6 +196,90 @@ VLIB_CLI_COMMAND (qos_egress_map_interface_command, static) = {
};
/* *INDENT-ON* */
+static void
+qos_mark_show_one_interface (vlib_main_t * vm, u32 sw_if_index)
+{
+ index_t qemis[QOS_N_SOURCES];
+ qos_source_t qs;
+ bool set;
+
+ set = false;
+ clib_memset_u32 (qemis, INDEX_INVALID, QOS_N_SOURCES);
+
+ FOR_EACH_QOS_SOURCE (qs)
+ {
+ if (vec_len (qos_mark_configs[qs]) <= sw_if_index)
+ continue;
+ if (INDEX_INVALID != (qemis[qs] = qos_mark_configs[qs][sw_if_index]))
+ set = true;
+ }
+
+ if (set)
+ {
+ vlib_cli_output (vm, " %U:", format_vnet_sw_if_index_name,
+ vnet_get_main (), sw_if_index);
+
+ FOR_EACH_QOS_SOURCE (qs)
+ {
+ if (qemis[qs] != INDEX_INVALID)
+ vlib_cli_output (vm, " %U: map:%d", format_qos_source, qs,
+ qemis[qs]);
+ }
+ }
+}
+
+static clib_error_t *
+qos_mark_show (vlib_main_t * vm,
+ unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ qos_source_t qs;
+ u32 sw_if_index;
+
+ sw_if_index = ~0;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "%U", unformat_vnet_sw_interface,
+ vnm, &sw_if_index))
+ ;
+ }
+
+ if (~0 == sw_if_index)
+ {
+ u32 ii, n_ints = 0;
+
+ FOR_EACH_QOS_SOURCE (qs)
+ {
+ n_ints = clib_max (n_ints, vec_len (qos_mark_configs[qs]));
+ }
+
+ for (ii = 0; ii < n_ints; ii++)
+ {
+ qos_mark_show_one_interface (vm, ii);
+ }
+ }
+ else
+ qos_mark_show_one_interface (vm, sw_if_index);
+
+ return (NULL);
+}
+
+/*?
+ * Show Egress Qos Maps
+ *
+ * @cliexpar
+ * @cliexcmd{show qos egress map}
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (qos_mark_show_command, static) = {
+ .path = "show qos mark",
+ .short_help = "show qos mark [interface]",
+ .function = qos_mark_show,
+ .is_mp_safe = 1,
+};
+/* *INDENT-ON* */
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/src/vnet/qos/qos_mark.h b/src/vnet/qos/qos_mark.h
index f1705d1bb33..91e2024af94 100644
--- a/src/vnet/qos/qos_mark.h
+++ b/src/vnet/qos/qos_mark.h
@@ -28,6 +28,12 @@ extern int qos_mark_enable (u32 sw_if_index,
qos_egress_map_id_t tid);
extern int qos_mark_disable (u32 sw_if_index, qos_source_t output_source);
+typedef walk_rc_t (*qos_mark_walk_cb_t) (u32 sw_if_index,
+ u32 map_id,
+ qos_source_t input_source,
+ void *ctx);
+void qos_mark_walk (qos_mark_walk_cb_t fn, void *c);
+
#endif
/*
diff --git a/src/vnet/qos/qos_record.c b/src/vnet/qos/qos_record.c
index 20d0b5bf4f5..40e6b0778bb 100644
--- a/src/vnet/qos/qos_record.c
+++ b/src/vnet/qos/qos_record.c
@@ -100,6 +100,23 @@ qos_record_disable (u32 sw_if_index, qos_source_t input_source)
return (0);
}
+void
+qos_record_walk (qos_record_walk_cb_t fn, void *c)
+{
+ qos_source_t qs;
+
+ FOR_EACH_QOS_SOURCE (qs)
+ {
+ u32 sw_if_index;
+
+ vec_foreach_index (sw_if_index, qos_record_configs[qs])
+ {
+ if (0 != qos_record_configs[qs][sw_if_index])
+ fn (sw_if_index, qs, c);
+ }
+ }
+}
+
/*
* Disable recording feature for all protocols when the interface
* is deleted
@@ -124,7 +141,7 @@ qos_record_ip_interface_add_del (vnet_main_t * vnm,
VNET_SW_INTERFACE_ADD_DEL_FUNCTION (qos_record_ip_interface_add_del);
clib_error_t *
-l2_ip_qos_init (vlib_main_t * vm)
+qos_record_init (vlib_main_t * vm)
{
qos_source_t qs;
vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "l2-ip-qos-record");
@@ -139,7 +156,7 @@ l2_ip_qos_init (vlib_main_t * vm)
return 0;
}
-VLIB_INIT_FUNCTION (l2_ip_qos_init);
+VLIB_INIT_FUNCTION (qos_record_init);
static clib_error_t *
qos_record_cli (vlib_main_t * vm,
@@ -199,6 +216,87 @@ VLIB_CLI_COMMAND (qos_record_command, static) = {
};
/* *INDENT-ON* */
+static void
+qos_record_show_one_interface (vlib_main_t * vm, u32 sw_if_index)
+{
+ u8 n_cfgs[QOS_N_SOURCES] = { };
+ qos_source_t qs;
+ bool set;
+
+ set = false;
+
+ FOR_EACH_QOS_SOURCE (qs)
+ {
+ if (vec_len (qos_record_configs[qs]) <= sw_if_index)
+ continue;
+ if (0 != (n_cfgs[qs] = qos_record_configs[qs][sw_if_index]))
+ set = true;
+ }
+
+ if (set)
+ {
+ vlib_cli_output (vm, " %U:", format_vnet_sw_if_index_name,
+ vnet_get_main (), sw_if_index);
+
+ FOR_EACH_QOS_SOURCE (qs)
+ {
+ if (n_cfgs[qs] != 0)
+ vlib_cli_output (vm, " %U", format_qos_source, qs);
+ }
+ }
+}
+
+static clib_error_t *
+qos_record_show (vlib_main_t * vm,
+ unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ qos_source_t qs;
+ u32 sw_if_index;
+
+ sw_if_index = ~0;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "%U", unformat_vnet_sw_interface,
+ vnm, &sw_if_index))
+ ;
+ }
+
+ if (~0 == sw_if_index)
+ {
+ u32 ii, n_ints = 0;
+
+ FOR_EACH_QOS_SOURCE (qs)
+ {
+ n_ints = clib_max (n_ints, vec_len (qos_record_configs[qs]));
+ }
+
+ for (ii = 0; ii < n_ints; ii++)
+ {
+ qos_record_show_one_interface (vm, ii);
+ }
+ }
+ else
+ qos_record_show_one_interface (vm, sw_if_index);
+
+ return (NULL);
+}
+
+/*?
+ * Show Egress Qos Maps
+ *
+ * @cliexpar
+ * @cliexcmd{show qos egress map}
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (qos_record_show_command, static) = {
+ .path = "show qos record",
+ .short_help = "show qos record [interface]",
+ .function = qos_record_show,
+ .is_mp_safe = 1,
+};
+/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/src/vnet/qos/qos_record.h b/src/vnet/qos/qos_record.h
index e5726d650a7..b80041f3241 100644
--- a/src/vnet/qos/qos_record.h
+++ b/src/vnet/qos/qos_record.h
@@ -21,6 +21,11 @@
extern int qos_record_disable (u32 sw_if_index, qos_source_t input_source);
extern int qos_record_enable (u32 sw_if_index, qos_source_t input_source);
+typedef walk_rc_t (*qos_record_walk_cb_t) (u32 sw_if_index,
+ qos_source_t input_source,
+ void *ctx);
+void qos_record_walk (qos_record_walk_cb_t fn, void *c);
+
#endif
/*
diff --git a/src/vpp/api/custom_dump.c b/src/vpp/api/custom_dump.c
index 840889d6cc3..11ff41aa86c 100644
--- a/src/vpp/api/custom_dump.c
+++ b/src/vpp/api/custom_dump.c
@@ -3765,9 +3765,9 @@ static void *vl_api_qos_record_enable_disable_t_print
u8 *s;
s = format (0, "SCRIPT: qos_record_enable_disable ");
- s = format (s, "sw_if_index %d ", ntohl (mp->sw_if_index));
+ s = format (s, "sw_if_index %d ", ntohl (mp->record.sw_if_index));
s = format (s, "input_source %U ", format_qos_source,
- ntohl (mp->input_source));
+ mp->record.input_source);
if (!mp->enable)
s = format (s, "disable ");