From 039cbfe254be998f7311bc4638bb262b44efac19 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Tue, 27 Feb 2018 03:45:38 -0800 Subject: QoS recording and marking Change-Id: Ie5a50def4ec1e4a3b3404a8b6ab9ec248bc16744 Signed-off-by: Neale Ranns --- src/vnet/qos/qos_egress_map.c | 262 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 src/vnet/qos/qos_egress_map.c (limited to 'src/vnet/qos/qos_egress_map.c') diff --git a/src/vnet/qos/qos_egress_map.c b/src/vnet/qos/qos_egress_map.c new file mode 100644 index 00000000000..365643995ba --- /dev/null +++ b/src/vnet/qos/qos_egress_map.c @@ -0,0 +1,262 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2018 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#include +#include + +/** + * Pool from which to allocate table + */ +qos_egress_map_t *qem_pool; + +/** + * DB to map user table-IDs to internal table indicies. + */ +uword *qem_db; + +index_t +qos_egress_map_find (qos_egress_map_id_t mid) +{ + uword *p = NULL; + + p = hash_get (qem_db, mid); + + if (NULL != p) + return p[0]; + + return (INDEX_INVALID); +} + +qos_egress_map_t * +qos_egress_map_find_i (qos_egress_map_id_t mid) +{ + index_t qemi; + + qemi = qos_egress_map_find (mid); + + if (INDEX_INVALID != qemi) + { + return (pool_elt_at_index (qem_pool, qemi)); + } + + return (NULL); +} + +static qos_egress_map_t * +qos_egress_map_find_or_create (qos_egress_map_id_t mid) +{ + qos_egress_map_t *qem; + + /* + * Find the existing or create a new table + */ + qem = qos_egress_map_find_i (mid); + + if (NULL == qem) + { + index_t qemi; + + pool_get_aligned (qem_pool, qem, CLIB_CACHE_LINE_BYTES); + qemi = qem - qem_pool; + + memset (qem, 0, sizeof (*qem)); + hash_set (qem_db, mid, qemi); + } + + return (qem); +} + +void +qos_egress_map_update (qos_egress_map_id_t mid, + qos_source_t input_source, qos_bits_t * values) +{ + qos_egress_map_t *qem; + + qem = qos_egress_map_find_or_create (mid); + + clib_memcpy (qem->qem_output[input_source], + values, sizeof (qem->qem_output[input_source])); +} + +void +qos_egress_map_delete (qos_egress_map_id_t mid) +{ + qos_egress_map_t *qem; + + qem = qos_egress_map_find_i (mid); + hash_unset (qem_db, mid); + + if (NULL != qem) + { + pool_put (qem_pool, qem); + } +} + +static clib_error_t * +qos_egress_map_update_cli (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; + u8 add; + + add = 1; + map_id = ~0; + qem = NULL; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "delete") || unformat (input, "del")) + add = 0; + else if (unformat (input, "id %d", &map_id)) + qem = qos_egress_map_find_or_create (map_id); + else + { + int qs, qi, qo; + + if (NULL == qem) + return clib_error_return (0, "map-id must be specified"); + + while (unformat + (input, "[%U][%d]=%d", unformat_qos_source, &qs, &qi, &qo)) + qem->qem_output[qs][qi] = qo; + break; + } + } + + if (!add) + qos_egress_map_delete (map_id); + + return (NULL); +} + +/*? + * Update a Egress Qos Map table + * + * @cliexpar + * @cliexcmd{qos egress map id 0 [ip][4]=4} + ?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (qos_egress_map_update_command, static) = { + .path = "qos egress map", + .short_help = "qos egress map id %d [delete] {[SOURCE][INPUT]=OUTPUT}", + .function = qos_egress_map_update_cli, + .is_mp_safe = 1, +}; +/* *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) + { + 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]); + } + + 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, + ({ + vlib_cli_output (vm, " Map-ID:%d\n%U", + map_id, + format_qos_egress_map, + 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); + } + } + +done: + return (error); +} + +/*? + * Show Egress Qos Maps + * + * @cliexpar + * @cliexcmd{show qos egress map} + ?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (qos_egress_map_show_command, static) = { + .path = "show qos egress map", + .short_help = "show qos egress map id %d", + .function = qos_egress_map_show, + .is_mp_safe = 1, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- cgit 1.2.3-korg