From e6541fdec8b2407e46569147be6887ca3ad4a704 Mon Sep 17 00:00:00 2001 From: Intel Date: Mon, 3 Jun 2013 00:00:00 +0000 Subject: [PATCH] meter: initial import Signed-off-by: Intel --- app/test/Makefile | 1 + app/test/autotest_data.py | 6 + app/test/commands.c | 3 + app/test/test.h | 1 + app/test/test_meter.c | 510 +++++++++++++++++++ config/defconfig_i686-default-linuxapp-gcc | 5 + config/defconfig_i686-default-linuxapp-icc | 5 + config/defconfig_x86_64-default-linuxapp-gcc | 5 + config/defconfig_x86_64-default-linuxapp-icc | 5 + examples/qos_meter/Makefile | 57 +++ examples/qos_meter/main.c | 433 ++++++++++++++++ examples/qos_meter/main.h | 89 ++++ examples/qos_meter/rte_policer.c | 59 +++ examples/qos_meter/rte_policer.h | 65 +++ lib/Makefile | 1 + lib/librte_eal/common/include/rte_log.h | 1 + lib/librte_meter/Makefile | 55 ++ lib/librte_meter/rte_meter.c | 121 +++++ lib/librte_meter/rte_meter.h | 388 ++++++++++++++ mk/rte.app.mk | 4 + 20 files changed, 1814 insertions(+) create mode 100644 app/test/test_meter.c create mode 100644 examples/qos_meter/Makefile create mode 100755 examples/qos_meter/main.c create mode 100755 examples/qos_meter/main.h create mode 100644 examples/qos_meter/rte_policer.c create mode 100644 examples/qos_meter/rte_policer.h create mode 100644 lib/librte_meter/Makefile create mode 100644 lib/librte_meter/rte_meter.c create mode 100644 lib/librte_meter/rte_meter.h diff --git a/app/test/Makefile b/app/test/Makefile index d457ab45dd..6ba18e44e2 100755 --- a/app/test/Makefile +++ b/app/test/Makefile @@ -85,6 +85,7 @@ SRCS-$(CONFIG_RTE_APP_TEST) += test_cmdline_ipaddr.c SRCS-$(CONFIG_RTE_APP_TEST) += test_cmdline_cirbuf.c SRCS-$(CONFIG_RTE_APP_TEST) += test_cmdline_string.c SRCS-$(CONFIG_RTE_APP_TEST) += test_cmdline_lib.c +SRCS-$(CONFIG_RTE_APP_TEST) += test_meter.c SRCS-$(CONFIG_RTE_APP_TEST) += test_pmac_pm.c SRCS-$(CONFIG_RTE_APP_TEST) += test_pmac_acl.c SRCS-$(CONFIG_RTE_APP_TEST) += test_power.c diff --git a/app/test/autotest_data.py b/app/test/autotest_data.py index f64ea9cec2..9bd436bf9c 100755 --- a/app/test/autotest_data.py +++ b/app/test/autotest_data.py @@ -77,6 +77,12 @@ parallel_test_group_list = [ "Func" : default_autotest, "Report" : None, }, + { + "Name" : "Meter autotest", + "Command" : "meter_autotest", + "Func" : default_autotest, + "Report" : None, + }, { "Name" : "Dump log history", "Command" : "dump_log_history", diff --git a/app/test/commands.c b/app/test/commands.c index ae94badafd..2438433cb6 100755 --- a/app/test/commands.c +++ b/app/test/commands.c @@ -167,6 +167,8 @@ static void cmd_autotest_parsed(void *parsed_result, ret |= test_memcpy_perf(); if (all || !strcmp(res->autotest, "func_reentrancy_autotest")) ret |= test_func_reentrancy(); + if (all || !strcmp(res->autotest, "meter_autotest")) + ret |= test_meter(); if (all || !strcmp(res->autotest, "pm_autotest")) ret |= test_pmac_pm(); if (all || !strcmp(res->autotest, "acl_autotest")) @@ -201,6 +203,7 @@ cmdline_parse_token_string_t cmd_autotest_autotest = "version_autotest#eal_fs_autotest#" "cmdline_autotest#func_reentrancy_autotest#" "mempool_perf_autotest#hash_perf_autotest#" + "meter_autotest#" "memcpy_perf_autotest#pm_autotest#" "acl_autotest#power_autotest#" "all_autotests"); diff --git a/app/test/test.h b/app/test/test.h index 632860bfcd..75df8d0064 100755 --- a/app/test/test.h +++ b/app/test/test.h @@ -84,6 +84,7 @@ int test_version(void); int test_eal_fs(void); int test_cmdline(void); int test_func_reentrancy(void); +int test_meter(void); int test_pmac_pm(void); int test_pmac_acl(void); int test_power(void); diff --git a/app/test/test_meter.c b/app/test/test_meter.c new file mode 100644 index 0000000000..3b14906f43 --- /dev/null +++ b/app/test/test_meter.c @@ -0,0 +1,510 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include + +#include + +#include "test.h" + +#ifdef RTE_LIBRTE_METER + +#include +#include + +#define mlog(format, ...) do{\ + printf("Line %d:",__LINE__);\ + printf(format, ##__VA_ARGS__);\ + printf("\n");\ + }while(0); + +#define melog(format, ...) do{\ + printf("Line %d:",__LINE__);\ + printf(format, ##__VA_ARGS__);\ + printf(" failed!\n");\ + return -1;\ + }while(0); + +#define TM_TEST_SRTCM_CIR_DF 46000000 +#define TM_TEST_SRTCM_CBS_DF 2048 +#define TM_TEST_SRTCM_EBS_DF 4096 + +#define TM_TEST_TRTCM_CIR_DF 46000000 +#define TM_TEST_TRTCM_PIR_DF 69000000 +#define TM_TEST_TRTCM_CBS_DF 2048 +#define TM_TEST_TRTCM_PBS_DF 4096 + +static struct rte_meter_srtcm_params sparams = + {.cir = TM_TEST_SRTCM_CIR_DF, + .cbs = TM_TEST_SRTCM_CBS_DF, + .ebs = TM_TEST_SRTCM_EBS_DF,}; + +static struct rte_meter_trtcm_params tparams= + {.cir = TM_TEST_TRTCM_CIR_DF, + .pir = TM_TEST_TRTCM_PIR_DF, + .cbs = TM_TEST_TRTCM_CBS_DF, + .pbs = TM_TEST_TRTCM_PBS_DF,}; + +/** + * functional test for rte_meter_srtcm_config + */ +static inline int +tm_test_srtcm_config(void) +{ +#define SRTCM_CFG_MSG "srtcm_config" + struct rte_meter_srtcm sm; + struct rte_meter_srtcm_params sparams1; + + /* invalid parameter test */ + if(rte_meter_srtcm_config(NULL, NULL) == 0) + melog(SRTCM_CFG_MSG); + if(rte_meter_srtcm_config(&sm, NULL) == 0) + melog(SRTCM_CFG_MSG); + if(rte_meter_srtcm_config(NULL, &sparams) == 0) + melog(SRTCM_CFG_MSG); + + /* cbs and ebs can't both be zero */ + sparams1 = sparams; + sparams1.cbs = 0; + sparams1.ebs = 0; + if(rte_meter_srtcm_config(&sm, &sparams1) == 0) + melog(SRTCM_CFG_MSG); + + /* cir should never be 0 */ + sparams1 = sparams; + sparams1.cir = 0; + if(rte_meter_srtcm_config(&sm, &sparams1) == 0) + melog(SRTCM_CFG_MSG); + + /* one of ebs and cbs can be zero, should be successful */ + sparams1 = sparams; + sparams1.ebs = 0; + if(rte_meter_srtcm_config(&sm, &sparams1) != 0) + melog(SRTCM_CFG_MSG); + + sparams1 = sparams; + sparams1.cbs = 0; + if(rte_meter_srtcm_config(&sm, &sparams1) != 0) + melog(SRTCM_CFG_MSG); + + /* usual parameter, should be successful */ + if(rte_meter_srtcm_config(&sm, &sparams) != 0) + melog(SRTCM_CFG_MSG); + + return 0; + +} + +/** + * functional test for rte_meter_trtcm_config + */ +static inline int +tm_test_trtcm_config(void) +{ + struct rte_meter_trtcm tm; + struct rte_meter_trtcm_params tparams1; +#define TRTCM_CFG_MSG "trtcm_config" + + /* invalid parameter test */ + if(rte_meter_trtcm_config(NULL, NULL) == 0) + melog(TRTCM_CFG_MSG); + if(rte_meter_trtcm_config(&tm, NULL) == 0) + melog(TRTCM_CFG_MSG); + if(rte_meter_trtcm_config(NULL, &tparams) == 0) + melog(TRTCM_CFG_MSG); + + /* cir, cbs, pir and pbs never be zero */ + tparams1 = tparams; + tparams1.cir = 0; + if(rte_meter_trtcm_config(&tm, &tparams1) == 0) + melog(TRTCM_CFG_MSG); + + tparams1 = tparams; + tparams1.cbs = 0; + if(rte_meter_trtcm_config(&tm, &tparams1) == 0) + melog(TRTCM_CFG_MSG); + + tparams1 = tparams; + tparams1.pbs = 0; + if(rte_meter_trtcm_config(&tm, &tparams1) == 0) + melog(TRTCM_CFG_MSG); + + tparams1 = tparams; + tparams1.pir = 0; + if(rte_meter_trtcm_config(&tm, &tparams1) == 0) + melog(TRTCM_CFG_MSG); + + /* pir should be greater or equal to cir */ + tparams1 = tparams; + tparams1.pir = tparams1.cir - 1; + if(rte_meter_trtcm_config(&tm, &tparams1) == 0) + melog(TRTCM_CFG_MSG" pir < cir test"); + + /* usual parameter, should be successful */ + if(rte_meter_trtcm_config(&tm, &tparams) != 0) + melog(TRTCM_CFG_MSG); + + return 0; +} + +/** + * functional test for rte_meter_srtcm_color_blind_check + */ +static inline int +tm_test_srtcm_color_blind_check(void) +{ +#define SRTCM_BLIND_CHECK_MSG "srtcm_blind_check" + struct rte_meter_srtcm sm; + uint64_t time; + uint64_t hz = rte_get_tsc_hz(); + + /* Test green */ + if(rte_meter_srtcm_config(&sm, &sparams) != 0) + melog(SRTCM_BLIND_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_srtcm_color_blind_check( + &sm, time, TM_TEST_SRTCM_CBS_DF - 1) + != e_RTE_METER_GREEN) + melog(SRTCM_BLIND_CHECK_MSG" GREEN"); + + /* Test yellow */ + if(rte_meter_srtcm_config(&sm, &sparams) != 0) + melog(SRTCM_BLIND_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_srtcm_color_blind_check( + &sm, time, TM_TEST_SRTCM_CBS_DF + 1) + != e_RTE_METER_YELLOW) + melog(SRTCM_BLIND_CHECK_MSG" YELLOW"); + + if(rte_meter_srtcm_config(&sm, &sparams) != 0) + melog(SRTCM_BLIND_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_srtcm_color_blind_check( + &sm, time, (uint32_t)sm.ebs - 1) != e_RTE_METER_YELLOW) + melog(SRTCM_BLIND_CHECK_MSG" YELLOW"); + + /* Test red */ + if(rte_meter_srtcm_config(&sm, &sparams) != 0) + melog(SRTCM_BLIND_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_srtcm_color_blind_check( + &sm, time, TM_TEST_SRTCM_EBS_DF + 1) + != e_RTE_METER_RED) + melog(SRTCM_BLIND_CHECK_MSG" RED"); + + return 0; + +} + +/** + * functional test for rte_meter_trtcm_color_blind_check + */ +static inline int +tm_test_trtcm_color_blind_check(void) +{ +#define TRTCM_BLIND_CHECK_MSG "trtcm_blind_check" + + uint64_t time; + struct rte_meter_trtcm tm; + uint64_t hz = rte_get_tsc_hz(); + + /* Test green */ + if(rte_meter_trtcm_config(&tm, &tparams) != 0) + melog(TRTCM_BLIND_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_trtcm_color_blind_check( + &tm, time, TM_TEST_TRTCM_CBS_DF - 1) + != e_RTE_METER_GREEN) + melog(TRTCM_BLIND_CHECK_MSG" GREEN"); + + /* Test yellow */ + if(rte_meter_trtcm_config(&tm, &tparams) != 0) + melog(TRTCM_BLIND_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_trtcm_color_blind_check( + &tm, time, TM_TEST_TRTCM_CBS_DF + 1) + != e_RTE_METER_YELLOW) + melog(TRTCM_BLIND_CHECK_MSG" YELLOW"); + + if(rte_meter_trtcm_config(&tm, &tparams) != 0) + melog(TRTCM_BLIND_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_trtcm_color_blind_check( + &tm, time, TM_TEST_TRTCM_PBS_DF - 1) + != e_RTE_METER_YELLOW) + melog(TRTCM_BLIND_CHECK_MSG" YELLOW"); + + /* Test red */ + if(rte_meter_trtcm_config(&tm, &tparams) != 0) + melog(TRTCM_BLIND_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_trtcm_color_blind_check( + &tm, time, TM_TEST_TRTCM_PBS_DF + 1) + != e_RTE_METER_RED) + melog(TRTCM_BLIND_CHECK_MSG" RED"); + + return 0; +} + + +/** + * @in[4] : the flags packets carries. + * @in[4] : the flags function expect to return. + * It will do blind check at the time of 1 second from beginning. + * At the time, it will use packets length of cbs -1, cbs + 1, + * ebs -1 and ebs +1 with flag in[0], in[1], in[2] and in[3] to do + * aware check, expect flag out[0], out[1], out[2] and out[3] + */ + +static inline int +tm_test_srtcm_aware_check +(enum rte_meter_color in[4], enum rte_meter_color out[4]) +{ +#define SRTCM_AWARE_CHECK_MSG "srtcm_aware_check" + struct rte_meter_srtcm sm; + uint64_t time; + uint64_t hz = rte_get_tsc_hz(); + + if(rte_meter_srtcm_config(&sm, &sparams) != 0) + melog(SRTCM_AWARE_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_srtcm_color_aware_check( + &sm, time, TM_TEST_SRTCM_CBS_DF - 1, in[0]) != out[0]) + melog(SRTCM_AWARE_CHECK_MSG" %u:%u", in[0], out[0]); + + if(rte_meter_srtcm_config(&sm, &sparams) != 0) + melog(SRTCM_AWARE_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_srtcm_color_aware_check( + &sm, time, TM_TEST_SRTCM_CBS_DF + 1, in[1]) != out[1]) + melog(SRTCM_AWARE_CHECK_MSG" %u:%u", in[1], out[1]); + + if(rte_meter_srtcm_config(&sm, &sparams) != 0) + melog(SRTCM_AWARE_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_srtcm_color_aware_check( + &sm, time, TM_TEST_SRTCM_EBS_DF - 1, in[2]) != out[2]) + melog(SRTCM_AWARE_CHECK_MSG" %u:%u", in[2], out[2]); + + if(rte_meter_srtcm_config(&sm, &sparams) != 0) + melog(SRTCM_AWARE_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_srtcm_color_aware_check( + &sm, time, TM_TEST_SRTCM_EBS_DF + 1, in[3]) != out[3]) + melog(SRTCM_AWARE_CHECK_MSG" %u:%u", in[3], out[3]); + + return 0; +} + + +/** + * functional test for rte_meter_srtcm_color_aware_check + */ +static inline int +tm_test_srtcm_color_aware_check(void) +{ + enum rte_meter_color in[4], out[4]; + + /** + * test 4 points that will produce green, yellow, yellow, red flag + * if using blind check + */ + + /* previouly have a green, test points should keep unchanged */ + in[0] = in[1] = in[2] = in[3] = e_RTE_METER_GREEN; + out[0] = e_RTE_METER_GREEN; + out[1] = e_RTE_METER_YELLOW; + out[2] = e_RTE_METER_YELLOW; + out[3] = e_RTE_METER_RED; + if(tm_test_srtcm_aware_check(in, out) != 0) + return -1; + + /** + * previously have a yellow, green & yellow = yellow + * yellow & red = red + */ + in[0] = in[1] = in[2] = in[3] = e_RTE_METER_YELLOW; + out[0] = e_RTE_METER_YELLOW; + out[1] = e_RTE_METER_YELLOW; + out[2] = e_RTE_METER_YELLOW; + out[3] = e_RTE_METER_RED; + if(tm_test_srtcm_aware_check(in, out) != 0) + return -1; + + /** + * previously have a red, red & green = red + * red & yellow = red + */ + in[0] = in[1] = in[2] = in[3] = e_RTE_METER_RED; + out[0] = e_RTE_METER_RED; + out[1] = e_RTE_METER_RED; + out[2] = e_RTE_METER_RED; + out[3] = e_RTE_METER_RED; + if(tm_test_srtcm_aware_check(in, out) != 0) + return -1; + + return 0; +} + +/** + * @in[4] : the flags packets carries. + * @in[4] : the flags function expect to return. + * It will do blind check at the time of 1 second from beginning. + * At the time, it will use packets length of cbs -1, cbs + 1, + * ebs -1 and ebs +1 with flag in[0], in[1], in[2] and in[3] to do + * aware check, expect flag out[0], out[1], out[2] and out[3] + */ +static inline int +tm_test_trtcm_aware_check +(enum rte_meter_color in[4], enum rte_meter_color out[4]) +{ +#define TRTCM_AWARE_CHECK_MSG "trtcm_aware_check" + struct rte_meter_trtcm tm; + uint64_t time; + uint64_t hz = rte_get_tsc_hz(); + + if(rte_meter_trtcm_config(&tm, &tparams) != 0) + melog(TRTCM_AWARE_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_trtcm_color_aware_check( + &tm, time, TM_TEST_TRTCM_CBS_DF - 1, in[0]) != out[0]) + melog(TRTCM_AWARE_CHECK_MSG" %u:%u", in[0], out[0]); + + if(rte_meter_trtcm_config(&tm, &tparams) != 0) + melog(TRTCM_AWARE_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_trtcm_color_aware_check( + &tm, time, TM_TEST_TRTCM_CBS_DF + 1, in[1]) != out[1]) + melog(TRTCM_AWARE_CHECK_MSG" %u:%u", in[1], out[1]); + + if(rte_meter_trtcm_config(&tm, &tparams) != 0) + melog(TRTCM_AWARE_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_trtcm_color_aware_check( + &tm, time, TM_TEST_TRTCM_PBS_DF - 1, in[2]) != out[2]) + melog(TRTCM_AWARE_CHECK_MSG" %u:%u", in[2], out[2]); + + if(rte_meter_trtcm_config(&tm, &tparams) != 0) + melog(TRTCM_AWARE_CHECK_MSG); + time = rte_get_tsc_cycles() + hz; + if(rte_meter_trtcm_color_aware_check( + &tm, time, TM_TEST_TRTCM_PBS_DF + 1, in[3]) != out[3]) + melog(TRTCM_AWARE_CHECK_MSG" %u:%u", in[3], out[3]); + + return 0; +} + + +/** + * functional test for rte_meter_trtcm_color_aware_check + */ + +static inline int +tm_test_trtcm_color_aware_check(void) +{ + enum rte_meter_color in[4], out[4]; + /** + * test 4 points that will produce green, yellow, yellow, red flag + * if using blind check + */ + + /* previouly have a green, test points should keep unchanged */ + in[0] = in[1] = in[2] = in[3] = e_RTE_METER_GREEN; + out[0] = e_RTE_METER_GREEN; + out[1] = e_RTE_METER_YELLOW; + out[2] = e_RTE_METER_YELLOW; + out[3] = e_RTE_METER_RED; + if(tm_test_trtcm_aware_check(in, out) != 0) + return -1; + + in[0] = in[1] = in[2] = in[3] = e_RTE_METER_YELLOW; + out[0] = e_RTE_METER_YELLOW; + out[1] = e_RTE_METER_YELLOW; + out[2] = e_RTE_METER_YELLOW; + out[3] = e_RTE_METER_RED; + if(tm_test_trtcm_aware_check(in, out) != 0) + return -1; + + in[0] = in[1] = in[2] = in[3] = e_RTE_METER_RED; + out[0] = e_RTE_METER_RED; + out[1] = e_RTE_METER_RED; + out[2] = e_RTE_METER_RED; + out[3] = e_RTE_METER_RED; + if(tm_test_trtcm_aware_check(in, out) != 0) + return -1; + + return 0; +} + +/** + * test main entrance for library meter + */ +int +test_meter(void) +{ + if(tm_test_srtcm_config() != 0 ) + return -1; + + if(tm_test_trtcm_config() != 0 ) + return -1; + + if(tm_test_srtcm_color_blind_check() != 0) + return -1; + + if(tm_test_trtcm_color_blind_check()!= 0) + return -1; + + if(tm_test_srtcm_color_aware_check()!= 0) + return -1; + + if(tm_test_trtcm_color_aware_check()!= 0) + return -1; + + return 0; + +} + +#else /* RTE_LIBRTE_METER */ + +int +test_meter(void) +{ + printf("The meter library is not included in this build\n"); + return 0; +} +#endif /* RTE_LIBRTE_METER */ diff --git a/config/defconfig_i686-default-linuxapp-gcc b/config/defconfig_i686-default-linuxapp-gcc index 686f1d15cb..5960e85ff5 100644 --- a/config/defconfig_i686-default-linuxapp-gcc +++ b/config/defconfig_i686-default-linuxapp-gcc @@ -228,6 +228,11 @@ CONFIG_RTE_MAX_LCORE_FREQS=64 # CONFIG_RTE_LIBRTE_NET=y +# +# Compile librte_meter +# +CONFIG_RTE_LIBRTE_METER=y + # # Compile librte_kni # diff --git a/config/defconfig_i686-default-linuxapp-icc b/config/defconfig_i686-default-linuxapp-icc index 5247d5b147..6c6a59d9de 100644 --- a/config/defconfig_i686-default-linuxapp-icc +++ b/config/defconfig_i686-default-linuxapp-icc @@ -229,6 +229,11 @@ CONFIG_RTE_MAX_LCORE_FREQS=64 # CONFIG_RTE_LIBRTE_NET=y +# +# Compile librte_meter +# +CONFIG_RTE_LIBRTE_METER=y + # # Compile librte_kni # diff --git a/config/defconfig_x86_64-default-linuxapp-gcc b/config/defconfig_x86_64-default-linuxapp-gcc index dbb1068013..1dcc8c6486 100644 --- a/config/defconfig_x86_64-default-linuxapp-gcc +++ b/config/defconfig_x86_64-default-linuxapp-gcc @@ -229,6 +229,11 @@ CONFIG_RTE_MAX_LCORE_FREQS=64 # CONFIG_RTE_LIBRTE_NET=y +# +# Compile librte_meter +# +CONFIG_RTE_LIBRTE_METER=y + # # Compile librte_kni # diff --git a/config/defconfig_x86_64-default-linuxapp-icc b/config/defconfig_x86_64-default-linuxapp-icc index 68dd9c3798..7053a1067e 100644 --- a/config/defconfig_x86_64-default-linuxapp-icc +++ b/config/defconfig_x86_64-default-linuxapp-icc @@ -229,6 +229,11 @@ CONFIG_RTE_MAX_LCORE_FREQS=64 # CONFIG_RTE_LIBRTE_NET=y +# +# Compile librte_meter +# +CONFIG_RTE_LIBRTE_METER=y + # # Compile librte_kni # diff --git a/examples/qos_meter/Makefile b/examples/qos_meter/Makefile new file mode 100644 index 0000000000..6ce840a21d --- /dev/null +++ b/examples/qos_meter/Makefile @@ -0,0 +1,57 @@ +# BSD LICENSE +# +# Copyright(c) 2010-2013 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +ifeq ($(RTE_SDK),) +$(error "Please define RTE_SDK environment variable") +endif + +# Default target, can be overriden by command line or environment +RTE_TARGET ?= x86_64-default-linuxapp-gcc + +include $(RTE_SDK)/mk/rte.vars.mk + +# binary name +APP = qos_meter + +# all source are stored in SRCS-y +SRCS-y := main.c rte_policer.c + +CFLAGS += -O3 +CFLAGS += $(WERROR_FLAGS) + +# workaround for a gcc bug with noreturn attribute +# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 +ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) +CFLAGS_main.o += -Wno-return-type +endif + +include $(RTE_SDK)/mk/rte.extapp.mk diff --git a/examples/qos_meter/main.c b/examples/qos_meter/main.c new file mode 100755 index 0000000000..ca1d4ac6ce --- /dev/null +++ b/examples/qos_meter/main.c @@ -0,0 +1,433 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * Traffic metering configuration + * + */ +#define APP_MODE_FWD 0 +#define APP_MODE_SRTCM_COLOR_BLIND 1 +#define APP_MODE_SRTCM_COLOR_AWARE 2 +#define APP_MODE_TRTCM_COLOR_BLIND 3 +#define APP_MODE_TRTCM_COLOR_AWARE 4 + +#define APP_MODE APP_MODE_SRTCM_COLOR_BLIND + + +#include "main.h" + + +#define APP_PKT_FLOW_POS 33 +#define APP_PKT_COLOR_POS 5 + + +#if APP_PKT_FLOW_POS > 64 || APP_PKT_COLOR_POS > 64 +#error Byte offset needs to be less than 64 +#endif + +/* + * Buffer pool configuration + * + ***/ +#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) +#define NB_MBUF 8192 +#define MEMPOOL_CACHE_SIZE 256 + +static struct rte_mempool *pool = NULL; + +/* + * NIC configuration + * + ***/ +static struct rte_eth_conf port_conf = { + .rxmode = { + .max_rx_pkt_len = ETHER_MAX_LEN, + .split_hdr_size = 0, + .header_split = 0, + .hw_ip_checksum = 1, + .hw_vlan_filter = 0, + .jumbo_frame = 0, + .hw_strip_crc = 0, + }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_hf = ETH_RSS_IPV4 | ETH_RSS_IPV6, + }, + }, + .txmode = { + .mq_mode = ETH_DCB_NONE, + }, +}; + +static const struct rte_eth_rxconf rx_conf = { + .rx_thresh = { + .pthresh = 8, /* RX prefetch threshold reg */ + .hthresh = 8, /* RX host threshold reg */ + .wthresh = 4, /* RX write-back threshold reg */ + }, + .rx_free_thresh = 32, +}; + +static const struct rte_eth_txconf tx_conf = { + .tx_thresh = { + .pthresh = 36, /* TX prefetch threshold reg */ + .hthresh = 0, /* TX host threshold reg */ + .wthresh = 0, /* TX write-back threshold reg */ + }, + .tx_free_thresh = 0, + .tx_rs_thresh = 0, + .txq_flags = 0x0, +}; + +#define NIC_RX_QUEUE_DESC 128 +#define NIC_TX_QUEUE_DESC 512 + +#define NIC_RX_QUEUE 0 +#define NIC_TX_QUEUE 0 + +/* + * Packet RX/TX + * + ***/ +#define PKT_RX_BURST_MAX 32 +#define PKT_TX_BURST_MAX 32 +#define TIME_TX_DRAIN 200000ULL + +static uint8_t port_rx; +static uint8_t port_tx; +static struct rte_mbuf *pkts_rx[PKT_RX_BURST_MAX]; +static struct rte_mbuf *pkts_tx[PKT_TX_BURST_MAX]; +static uint16_t pkts_tx_len = 0; + + +struct rte_meter_srtcm_params app_srtcm_params[] = { + {.cir = 1000000 * 46, .cbs = 2048, .ebs = 2048}, +}; + +struct rte_meter_trtcm_params app_trtcm_params[] = { + {.cir = 1000000 * 46, .pir = 1500000 * 46, .cbs = 2048, .pbs = 2048}, +}; + +#define DIM(a) (sizeof (a) / sizeof ((a)[0])) +#define APP_FLOWS_MAX 256 + +FLOW_METER app_flows[APP_FLOWS_MAX]; + +static void +app_configure_flow_table(void) +{ + uint32_t i, j; + + for (i = 0, j = 0; i < APP_FLOWS_MAX; i ++, j = (j + 1) % DIM(PARAMS)){ + FUNC_CONFIG(&app_flows[i], &PARAMS[j]); + } +} + +static inline void +app_pkt_handle(struct rte_mbuf *pkt, uint64_t time) +{ + uint8_t color; + + uint8_t *pkt_data = rte_pktmbuf_mtod(pkt, uint8_t *); + uint32_t pkt_len = rte_pktmbuf_pkt_len(pkt) - sizeof(struct ether_hdr); + uint8_t flow_id = (uint8_t)(pkt_data[APP_PKT_FLOW_POS] & (APP_FLOWS_MAX - 1)); + color = pkt_data[APP_PKT_COLOR_POS]; + + /* color input is not used for blind modes */ + color = (uint8_t) FUNC_METER(&app_flows[flow_id], time, pkt_len, + (enum rte_meter_color) color); + pkt_data[APP_PKT_COLOR_POS] = color; +} + + +static __attribute__((noreturn)) int +main_loop(__attribute__((unused)) void *dummy) +{ + uint64_t current_time, last_time = rte_rdtsc(); + uint32_t lcore_id = rte_lcore_id(); + + printf("Core %u: port RX = %d, port TX = %d\n", lcore_id, port_rx, port_tx); + + while (1) { + uint64_t time_diff; + int i, nb_rx; + + /* Mechanism to avoid stale packets in the output buffer */ + current_time = rte_rdtsc(); + time_diff = current_time - last_time; + if (unlikely(time_diff > TIME_TX_DRAIN)) { + int ret; + + if (pkts_tx_len == 0) { + last_time = current_time; + + continue; + } + + /* Write packet burst to NIC TX */ + ret = rte_eth_tx_burst(port_tx, NIC_TX_QUEUE, pkts_tx, pkts_tx_len); + + /* Free buffers for any packets not written successfully */ + if (unlikely(ret < pkts_tx_len)) { + for ( ; ret < pkts_tx_len; ret ++) { + rte_pktmbuf_free(pkts_tx[ret]); + } + } + + /* Empty the output buffer */ + pkts_tx_len = 0; + + last_time = current_time; + } + + /* Read packet burst from NIC RX */ + nb_rx = rte_eth_rx_burst(port_rx, NIC_RX_QUEUE, pkts_rx, PKT_RX_BURST_MAX); + + /* Handle packets */ + for (i = 0; i < nb_rx; i ++) { + struct rte_mbuf *pkt = pkts_rx[i]; + + /* Handle current packet*/ + app_pkt_handle(pkt, current_time); + + /* Write current packet in the output buffer */ + pkts_tx[pkts_tx_len] = pkt; + pkts_tx_len ++; + + /* Write packets from output buffer to NIC TX when full burst is available */ + if (unlikely(pkts_tx_len == PKT_TX_BURST_MAX)) { + /* Write packet burst to NIC TX */ + int ret = rte_eth_tx_burst(port_tx, NIC_TX_QUEUE, pkts_tx, PKT_TX_BURST_MAX); + + /* Free buffers for any packets not written successfully */ + if (unlikely(ret < PKT_TX_BURST_MAX)) { + for ( ; ret < PKT_TX_BURST_MAX; ret ++) { + rte_pktmbuf_free(pkts_tx[ret]); + } + } + + /* Empty the output buffer */ + pkts_tx_len = 0; + } + } + } +} + +static void +print_usage(const char *prgname) +{ + printf ("%s [EAL options] -- -p PORTMASK\n" + " -p PORTMASK: hexadecimal bitmask of ports to configure\n", + prgname); +} + +static int +parse_portmask(const char *portmask) +{ + char *end = NULL; + unsigned long pm; + + /* parse hexadecimal string */ + pm = strtoul(portmask, &end, 16); + if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) + return -1; + + if (pm == 0) + return -1; + + return pm; +} + +/* Parse the argument given in the command line of the application */ +static int +parse_args(int argc, char **argv) +{ + int opt; + char **argvopt; + int option_index; + char *prgname = argv[0]; + static struct option lgopts[] = { + {NULL, 0, 0, 0} + }; + uint64_t port_mask, i, mask; + + argvopt = argv; + + while ((opt = getopt_long(argc, argvopt, "p:", lgopts, &option_index)) != EOF) { + switch (opt) { + case 'p': + port_mask = parse_portmask(optarg); + if (port_mask == 0) { + printf("invalid port mask (null port mask)\n"); + print_usage(prgname); + return -1; + } + + for (i = 0, mask = 1; i < 64; i ++, mask <<= 1){ + if (mask & port_mask){ + port_rx = i; + port_mask &= ~ mask; + break; + } + } + + for (i = 0, mask = 1; i < 64; i ++, mask <<= 1){ + if (mask & port_mask){ + port_tx = i; + port_mask &= ~ mask; + break; + } + } + + if (port_mask != 0) { + printf("invalid port mask (more than 2 ports)\n"); + print_usage(prgname); + return -1; + } + break; + + default: + print_usage(prgname); + return -1; + } + } + + if (optind <= 1) { + print_usage(prgname); + return -1; + } + + argv[optind-1] = prgname; + + optind = 0; /* reset getopt lib */ + return 0; +} + +int +MAIN(int argc, char **argv) +{ + uint32_t lcore_id; + int ret; + + /* EAL init */ + ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); + argc -= ret; + argv += ret; + if (rte_lcore_count() != 1) { + rte_exit(EXIT_FAILURE, "This application does not accept more than one core. " + "Please adjust the \"-c COREMASK\" parameter accordingly.\n"); + } + + /* Application non-EAL arguments parse */ + ret = parse_args(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid input arguments\n"); + + /* Buffer pool init */ + pool = rte_mempool_create("pool", NB_MBUF, MBUF_SIZE, MEMPOOL_CACHE_SIZE, + sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, + rte_pktmbuf_init, NULL, rte_socket_id(), 0); + if (pool == NULL) + rte_exit(EXIT_FAILURE, "Buffer pool creation error\n"); + + /* PMD init */ + if (rte_pmd_init_all() < 0) + rte_exit(EXIT_FAILURE, "PMD init error\n"); + + if (rte_eal_pci_probe() < 0) + rte_exit(EXIT_FAILURE, "PCI probe error\n"); + + /* NIC init */ + ret = rte_eth_dev_configure(port_rx, 1, 1, &port_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Port %d configuration error (%d)\n", port_rx, ret); + + ret = rte_eth_rx_queue_setup(port_rx, NIC_RX_QUEUE, NIC_RX_QUEUE_DESC, rte_eth_dev_socket_id(port_rx), &rx_conf, pool); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Port %d RX queue setup error (%d)\n", port_rx, ret); + + ret = rte_eth_tx_queue_setup(port_rx, NIC_TX_QUEUE, NIC_TX_QUEUE_DESC, rte_eth_dev_socket_id(port_rx), &tx_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Port %d TX queue setup error (%d)\n", port_rx, ret); + + ret = rte_eth_dev_configure(port_tx, 1, 1, &port_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Port %d configuration error (%d)\n", port_tx, ret); + + ret = rte_eth_rx_queue_setup(port_tx, NIC_RX_QUEUE, NIC_RX_QUEUE_DESC, rte_eth_dev_socket_id(port_tx), &rx_conf, pool); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Port %d RX queue setup error (%d)\n", port_tx, ret); + + ret = rte_eth_tx_queue_setup(port_tx, NIC_TX_QUEUE, NIC_TX_QUEUE_DESC, rte_eth_dev_socket_id(port_tx), &tx_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Port %d TX queue setup error (%d)\n", port_tx, ret); + + ret = rte_eth_dev_start(port_rx); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Port %d start error (%d)\n", port_rx, ret); + + ret = rte_eth_dev_start(port_tx); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Port %d start error (%d)\n", port_tx, ret); + + rte_eth_promiscuous_enable(port_rx); + + rte_eth_promiscuous_enable(port_tx); + + /* App configuration */ + app_configure_flow_table(); + + /* Launch per-lcore init on every lcore */ + rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + if (rte_eal_wait_lcore(lcore_id) < 0) + return -1; + } + + return 0; +} diff --git a/examples/qos_meter/main.h b/examples/qos_meter/main.h new file mode 100755 index 0000000000..7a848559e0 --- /dev/null +++ b/examples/qos_meter/main.h @@ -0,0 +1,89 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _MAIN_H_ +#define _MAIN_H_ + +#ifdef RTE_EXEC_ENV_BAREMETAL +#define MAIN _main +#else +#define MAIN main +#endif + +int MAIN(int argc, char **argv); + + +#if APP_MODE == APP_MODE_FWD + +#define FUNC_METER(a,b,c,d) color, flow_id=flow_id, pkt_len=pkt_len, time=time +#define FUNC_CONFIG(a,b) +#define PARAMS app_srtcm_params +#define FLOW_METER int + +#elif APP_MODE == APP_MODE_SRTCM_COLOR_BLIND + +#define FUNC_METER(a,b,c,d) rte_meter_srtcm_color_blind_check(a,b,c) +#define FUNC_CONFIG rte_meter_srtcm_config +#define PARAMS app_srtcm_params +#define FLOW_METER struct rte_meter_srtcm + +#elif (APP_MODE == APP_MODE_SRTCM_COLOR_AWARE) + +#define FUNC_METER rte_meter_srtcm_color_aware_check +#define FUNC_CONFIG rte_meter_srtcm_config +#define PARAMS app_srtcm_params +#define FLOW_METER struct rte_meter_srtcm + +#elif (APP_MODE == APP_MODE_TRTCM_COLOR_BLIND) + +#define FUNC_METER(a,b,c,d) rte_meter_trtcm_color_blind_check(a,b,c) +#define FUNC_CONFIG rte_meter_trtcm_config +#define PARAMS app_trtcm_params +#define FLOW_METER struct rte_meter_trtcm + +#elif (APP_MODE == APP_MODE_TRTCM_COLOR_AWARE) + +#define FUNC_METER rte_meter_trtcm_color_aware_check +#define FUNC_CONFIG rte_meter_trtcm_config +#define PARAMS app_trtcm_params +#define FLOW_METER struct rte_meter_trtcm + +#else +#error Invalid value for APP_MODE +#endif + + + + +#endif /* _MAIN_H_ */ diff --git a/examples/qos_meter/rte_policer.c b/examples/qos_meter/rte_policer.c new file mode 100644 index 0000000000..1f2ac47aa3 --- /dev/null +++ b/examples/qos_meter/rte_policer.c @@ -0,0 +1,59 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include "rte_policer.h" + +int +rte_phb_config(struct rte_phb *phb_table, uint32_t phb_table_index, + enum rte_meter_color pre_meter, enum rte_meter_color post_meter, enum rte_phb_action action) +{ + struct rte_phb *phb = NULL; + + /* User argument checking */ + if (phb_table == NULL) { + return -1; + } + + if ((pre_meter > e_RTE_METER_RED) || (post_meter > e_RTE_METER_RED) || (pre_meter > post_meter)) { + return -2; + } + + /* Set action in PHB table entry */ + phb = &phb_table[phb_table_index]; + phb->actions[pre_meter][post_meter] = action; + + + return 0; +} diff --git a/examples/qos_meter/rte_policer.h b/examples/qos_meter/rte_policer.h new file mode 100644 index 0000000000..7eb6b2774e --- /dev/null +++ b/examples/qos_meter/rte_policer.h @@ -0,0 +1,65 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __INCLUDE_RTE_POLICER_H__ +#define __INCLUDE_RTE_POLICER_H__ + +#include +#include + +enum rte_phb_action { + e_RTE_PHB_ACTION_GREEN = e_RTE_METER_GREEN, + e_RTE_PHB_ACTION_YELLOW = e_RTE_METER_YELLOW, + e_RTE_PHB_ACTION_RED = e_RTE_METER_RED, + e_RTE_PHB_ACTION_DROP = 3, +}; + +struct rte_phb { + enum rte_phb_action actions[e_RTE_METER_COLORS][e_RTE_METER_COLORS]; +}; + +int +rte_phb_config(struct rte_phb *phb_table, uint32_t phb_table_index, + enum rte_meter_color pre_meter, enum rte_meter_color post_meter, enum rte_phb_action action); + +static inline enum rte_phb_action +policer_run(struct rte_phb *phb_table, uint32_t phb_table_index, enum rte_meter_color pre_meter, enum rte_meter_color post_meter) +{ + struct rte_phb *phb = &phb_table[phb_table_index]; + enum rte_phb_action action = phb->actions[pre_meter][post_meter]; + + return action; +} + +#endif diff --git a/lib/Makefile b/lib/Makefile index 82ed571e97..122ba42f29 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -47,6 +47,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm DIRS-$(CONFIG_RTE_LIBRTE_NET) += librte_net DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power +DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter DIRS-$(CONFIG_RTE_LIBRTE_PMAC) += librte_pmac ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) diff --git a/lib/librte_eal/common/include/rte_log.h b/lib/librte_eal/common/include/rte_log.h index 5e886c09dc..b0c735f171 100644 --- a/lib/librte_eal/common/include/rte_log.h +++ b/lib/librte_eal/common/include/rte_log.h @@ -73,6 +73,7 @@ extern struct rte_logs rte_logs; #define RTE_LOGTYPE_KNI 0X00000100 /**< Log related to KNI. */ #define RTE_LOGTYPE_PMAC 0x00000200 /**< Log related to PMAC. */ #define RTE_LOGTYPE_POWER 0x00000400 /**< Log related to power. */ +#define RTE_LOGTYPE_METER 0x00000800 /**< Log related to QoS meter. */ /* these log types can be used in an application */ #define RTE_LOGTYPE_USER1 0x01000000 /**< User-defined log type 1. */ diff --git a/lib/librte_meter/Makefile b/lib/librte_meter/Makefile new file mode 100644 index 0000000000..46f70050e4 --- /dev/null +++ b/lib/librte_meter/Makefile @@ -0,0 +1,55 @@ +# BSD LICENSE +# +# Copyright(c) 2010-2013 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +include $(RTE_SDK)/mk/rte.vars.mk + +# +# library name +# +LIB = librte_meter.a + +CFLAGS += -O3 +CFLAGS += -g +CFLAGS += $(WERROR_FLAGS) + +# +# all source are stored in SRCS-y +# +SRCS-$(CONFIG_RTE_LIBRTE_METER) := rte_meter.c + +# install includes +SYMLINK-$(CONFIG_RTE_LIBRTE_METER)-include := rte_meter.h + +# this lib depends upon: +DEPDIRS-$(CONFIG_RTE_LIBRTE_METER) += lib/librte_eal + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_meter/rte_meter.c b/lib/librte_meter/rte_meter.c new file mode 100644 index 0000000000..8e0e2bc94c --- /dev/null +++ b/lib/librte_meter/rte_meter.c @@ -0,0 +1,121 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include + +#include +#include +#include + +#include "rte_meter.h" + +#ifndef RTE_METER_TB_PERIOD_MIN +#define RTE_METER_TB_PERIOD_MIN 100 +#endif + +static void +rte_meter_get_tb_params(uint64_t hz, uint64_t rate, uint64_t *tb_period, uint64_t *tb_bytes_per_period) +{ + double period = ((double) hz) / ((double) rate); + + if (period >= RTE_METER_TB_PERIOD_MIN) { + *tb_bytes_per_period = 1; + *tb_period = (uint64_t) period; + } else { + *tb_bytes_per_period = (uint64_t) ceil(RTE_METER_TB_PERIOD_MIN / period); + *tb_period = (hz * (*tb_bytes_per_period)) / rate; + } +} + +int +rte_meter_srtcm_config(struct rte_meter_srtcm *m, struct rte_meter_srtcm_params *params) +{ + uint64_t hz; + + /* Check input parameters */ + if ((m == NULL) || (params == NULL)) { + return -1; + } + + if ((params->cir == 0) || ((params->cbs == 0) && (params->ebs == 0))) { + return -2; + } + + /* Initialize srTCM run-time structure */ + hz = rte_get_tsc_hz(); + m->time = rte_get_tsc_cycles(); + m->tc = m->cbs = params->cbs; + m->te = m->ebs = params->ebs; + rte_meter_get_tb_params(hz, params->cir, &m->cir_period, &m->cir_bytes_per_period); + + RTE_LOG(INFO, METER, "Low level srTCM config: \n" + "\tCIR period = %" PRIu64 ", CIR bytes per period = %" PRIu64 "\n", + m->cir_period, m->cir_bytes_per_period); + + return 0; +} + +int +rte_meter_trtcm_config(struct rte_meter_trtcm *m, struct rte_meter_trtcm_params *params) +{ + uint64_t hz; + + /* Check input parameters */ + if ((m == NULL) || (params == NULL)) { + return -1; + } + + if ((params->cir == 0) || (params->pir == 0) || (params->pir < params->cir) || + (params->cbs == 0) || (params->pbs == 0)) { + return -2; + } + + /* Initialize trTCM run-time structure */ + hz = rte_get_tsc_hz(); + m->time_tc = m->time_tp = rte_get_tsc_cycles(); + m->tc = m->cbs = params->cbs; + m->tp = m->pbs = params->pbs; + rte_meter_get_tb_params(hz, params->cir, &m->cir_period, &m->cir_bytes_per_period); + rte_meter_get_tb_params(hz, params->pir, &m->pir_period, &m->pir_bytes_per_period); + + RTE_LOG(INFO, METER, "Low level trTCM config: \n" + "\tCIR period = %" PRIu64 ", CIR bytes per period = %" PRIu64 "\n" + "\tPIR period = %" PRIu64 ", PIR bytes per period = %" PRIu64 "\n", + m->cir_period, m->cir_bytes_per_period, + m->pir_period, m->pir_bytes_per_period); + + return 0; +} diff --git a/lib/librte_meter/rte_meter.h b/lib/librte_meter/rte_meter.h new file mode 100644 index 0000000000..eb4a825277 --- /dev/null +++ b/lib/librte_meter/rte_meter.h @@ -0,0 +1,388 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __INCLUDE_RTE_METER_H__ +#define __INCLUDE_RTE_METER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * RTE Traffic Metering + * + * Traffic metering algorithms: + * 1. Single Rate Three Color Marker (srTCM): defined by IETF RFC 2697 + * 2. Two Rate Three Color Marker (trTCM): defined by IETF RFC 2698 + * + ***/ + +#include + +/* + * Application Programmer's Interface (API) + * + ***/ + +/** Packet Color Set */ +enum rte_meter_color { + e_RTE_METER_GREEN = 0, /**< Green */ + e_RTE_METER_YELLOW, /**< Yellow */ + e_RTE_METER_RED, /**< Red */ + e_RTE_METER_COLORS /**< Number of available colors */ +}; + +/** srTCM parameters per metered traffic flow. The CIR, CBS and EBS parameters only +count bytes of IP packets and do not include link specific headers. At least one of +the CBS or EBS parameters has to be greater than zero. */ +struct rte_meter_srtcm_params { + uint64_t cir; /**< Committed Information Rate (CIR). Measured in bytes per second. */ + uint64_t cbs; /**< Committed Burst Size (CBS). Measured in bytes. */ + uint64_t ebs; /**< Excess Burst Size (EBS). Measured in bytes. */ +}; + +/** trTCM parameters per metered traffic flow. The CIR, PIR, CBS and PBS parameters +only count bytes of IP packets and do not include link specific headers. PIR has to +be greater than or equal to CIR. Both CBS or EBS have to be greater than zero. */ +struct rte_meter_trtcm_params { + uint64_t cir; /**< Committed Information Rate (CIR). Measured in bytes per second. */ + uint64_t pir; /**< Peak Information Rate (PIR). Measured in bytes per second. */ + uint64_t cbs; /**< Committed Burst Size (CBS). Measured in byes. */ + uint64_t pbs; /**< Peak Burst Size (PBS). Measured in bytes. */ +}; + +/** Internal data structure storing the srTCM run-time context per metered traffic flow. */ +struct rte_meter_srtcm; + +/** Internal data structure storing the trTCM run-time context per metered traffic flow. */ +struct rte_meter_trtcm; + +/** + * srTCM configuration per metered traffic flow + * + * @param m + * Pointer to pre-allocated srTCM data structure + * @param params + * User parameters per srTCM metered traffic flow + * @return + * 0 upon success, error code otherwise + */ +int +rte_meter_srtcm_config(struct rte_meter_srtcm *m, + struct rte_meter_srtcm_params *params); + +/** + * trTCM configuration per metered traffic flow + * + * @param m + * Pointer to pre-allocated trTCM data structure + * @param params + * User parameters per trTCM metered traffic flow + * @return + * 0 upon success, error code otherwise + */ +int +rte_meter_trtcm_config(struct rte_meter_trtcm *m, + struct rte_meter_trtcm_params *params); + +/** + * srTCM color blind traffic metering + * + * @param m + * Handle to srTCM instance + * @param time + * Current CPU time stamp (measured in CPU cycles) + * @param pkt_length + * Length of the current IP packet (measured in bytes) + * @return + * Color assigned to the current IP packet + */ +static inline enum rte_meter_color +rte_meter_srtcm_color_blind_check(struct rte_meter_srtcm *m, + uint64_t time, + uint32_t pkt_len); + +/** + * srTCM color aware traffic metering + * + * @param m + * Handle to srTCM instance + * @param time + * Current CPU time stamp (measured in CPU cycles) + * @param pkt_length + * Length of the current IP packet (measured in bytes) + * @param pkt_color + * Input color of the current IP packet + * @return + * Color assigned to the current IP packet + */ +static inline enum rte_meter_color +rte_meter_srtcm_color_aware_check(struct rte_meter_srtcm *m, + uint64_t time, + uint32_t pkt_len, + enum rte_meter_color pkt_color); + +/** + * trTCM color blind traffic metering + * + * @param m + * Handle to trTCM instance + * @param time + * Current CPU time stamp (measured in CPU cycles) + * @param pkt_length + * Length of the current IP packet (measured in bytes) + * @return + * Color assigned to the current IP packet + */ +static inline enum rte_meter_color +rte_meter_trtcm_color_blind_check(struct rte_meter_trtcm *m, + uint64_t time, + uint32_t pkt_len); + +/** + * trTCM color aware traffic metering + * + * @param m + * Handle to trTCM instance + * @param time + * Current CPU time stamp (measured in CPU cycles) + * @param pkt_length + * Length of the current IP packet (measured in bytes) + * @param pkt_color + * Input color of the current IP packet + * @return + * Color assigned to the current IP packet + */ +static inline enum rte_meter_color +rte_meter_trtcm_color_aware_check(struct rte_meter_trtcm *m, + uint64_t time, + uint32_t pkt_len, + enum rte_meter_color pkt_color); + +/* + * Inline implementation of run-time methods + * + ***/ + +/* Internal data structure storing the srTCM run-time context per metered traffic flow. */ +struct rte_meter_srtcm { + uint64_t time; /* Time of latest update of C and E token buckets */ + uint64_t tc; /* Number of bytes currently available in the committed (C) token bucket */ + uint64_t te; /* Number of bytes currently available in the excess (E) token bucket */ + uint64_t cbs; /* Upper limit for C token bucket */ + uint64_t ebs; /* Upper limit for E token bucket */ + uint64_t cir_period; /* Number of CPU cycles for one update of C and E token buckets */ + uint64_t cir_bytes_per_period; /* Number of bytes to add to C and E token buckets on each update */ +}; + +/* Internal data structure storing the trTCM run-time context per metered traffic flow. */ +struct rte_meter_trtcm { + uint64_t time_tc; /* Time of latest update of C token bucket */ + uint64_t time_tp; /* Time of latest update of E token bucket */ + uint64_t tc; /* Number of bytes currently available in the committed (C) token bucket */ + uint64_t tp; /* Number of bytes currently available in the peak (P) token bucket */ + uint64_t cbs; /* Upper limit for C token bucket */ + uint64_t pbs; /* Upper limit for P token bucket */ + uint64_t cir_period; /* Number of CPU cycles for one update of C token bucket */ + uint64_t cir_bytes_per_period; /* Number of bytes to add to C token bucket on each update */ + uint64_t pir_period; /* Number of CPU cycles for one update of P token bucket */ + uint64_t pir_bytes_per_period; /* Number of bytes to add to P token bucket on each update */ +}; + +static inline enum rte_meter_color +rte_meter_srtcm_color_blind_check(struct rte_meter_srtcm *m, + uint64_t time, + uint32_t pkt_len) +{ + uint64_t time_diff, n_periods, tc, te; + + /* Bucket update */ + time_diff = time - m->time; + n_periods = time_diff / m->cir_period; + m->time += n_periods * m->cir_period; + + tc = m->tc + n_periods * m->cir_bytes_per_period; + if (tc > m->cbs) + tc = m->cbs; + + te = m->te + n_periods * m->cir_bytes_per_period; + if (te > m->ebs) + te = m->ebs; + + /* Color logic */ + if (tc >= pkt_len) { + m->tc = tc - pkt_len; + m->te = te; + return e_RTE_METER_GREEN; + } + + if (te >= pkt_len) { + m->tc = tc; + m->te = te - pkt_len; + return e_RTE_METER_YELLOW; + } + + m->tc = tc; + m->te = te; + return e_RTE_METER_RED; +} + +static inline enum rte_meter_color +rte_meter_srtcm_color_aware_check(struct rte_meter_srtcm *m, + uint64_t time, + uint32_t pkt_len, + enum rte_meter_color pkt_color) +{ + uint64_t time_diff, n_periods, tc, te; + + /* Bucket update */ + time_diff = time - m->time; + n_periods = time_diff / m->cir_period; + m->time += n_periods * m->cir_period; + + tc = m->tc + n_periods * m->cir_bytes_per_period; + if (tc > m->cbs) + tc = m->cbs; + + te = m->te + n_periods * m->cir_bytes_per_period; + if (te > m->ebs) + te = m->ebs; + + /* Color logic */ + if ((pkt_color == e_RTE_METER_GREEN) && (tc >= pkt_len)) { + m->tc = tc - pkt_len; + m->te = te; + return e_RTE_METER_GREEN; + } + + if ((pkt_color != e_RTE_METER_RED) && (te >= pkt_len)) { + m->tc = tc; + m->te = te - pkt_len; + return e_RTE_METER_YELLOW; + } + + m->tc = tc; + m->te = te; + return e_RTE_METER_RED; +} + +static inline enum rte_meter_color +rte_meter_trtcm_color_blind_check(struct rte_meter_trtcm *m, + uint64_t time, + uint32_t pkt_len) +{ + uint64_t time_diff_tc, time_diff_tp, n_periods_tc, n_periods_tp, tc, tp; + + /* Bucket update */ + time_diff_tc = time - m->time_tc; + time_diff_tp = time - m->time_tp; + n_periods_tc = time_diff_tc / m->cir_period; + n_periods_tp = time_diff_tp / m->pir_period; + m->time_tc += n_periods_tc * m->cir_period; + m->time_tp += n_periods_tp * m->pir_period; + + tc = m->tc + n_periods_tc * m->cir_bytes_per_period; + if (tc > m->cbs) + tc = m->cbs; + + tp = m->tp + n_periods_tp * m->pir_bytes_per_period; + if (tp > m->pbs) + tp = m->pbs; + + /* Color logic */ + if (tp < pkt_len) { + m->tc = tc; + m->tp = tp; + return e_RTE_METER_RED; + } + + if (tc < pkt_len) { + m->tc = tc; + m->tp = tp - pkt_len; + return e_RTE_METER_YELLOW; + } + + m->tc = tc - pkt_len; + m->tp = tp - pkt_len; + return e_RTE_METER_GREEN; +} + +static inline enum rte_meter_color +rte_meter_trtcm_color_aware_check(struct rte_meter_trtcm *m, + uint64_t time, + uint32_t pkt_len, + enum rte_meter_color pkt_color) +{ + uint64_t time_diff_tc, time_diff_tp, n_periods_tc, n_periods_tp, tc, tp; + + /* Bucket update */ + time_diff_tc = time - m->time_tc; + time_diff_tp = time - m->time_tp; + n_periods_tc = time_diff_tc / m->cir_period; + n_periods_tp = time_diff_tp / m->pir_period; + m->time_tc += n_periods_tc * m->cir_period; + m->time_tp += n_periods_tp * m->pir_period; + + tc = m->tc + n_periods_tc * m->cir_bytes_per_period; + if (tc > m->cbs) + tc = m->cbs; + + tp = m->tp + n_periods_tp * m->pir_bytes_per_period; + if (tp > m->pbs) + tp = m->pbs; + + /* Color logic */ + if ((pkt_color == e_RTE_METER_RED) || (tp < pkt_len)) { + m->tc = tc; + m->tp = tp; + return e_RTE_METER_RED; + } + + if ((pkt_color == e_RTE_METER_YELLOW) || (tc < pkt_len)) { + m->tc = tc; + m->tp = tp - pkt_len; + return e_RTE_METER_YELLOW; + } + + m->tc = tc - pkt_len; + m->tp = tp - pkt_len; + return e_RTE_METER_GREEN; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_RTE_METER_H__ */ diff --git a/mk/rte.app.mk b/mk/rte.app.mk index f8f265741d..8eb45d863d 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -101,6 +101,10 @@ ifeq ($(CONFIG_RTE_LIBRTE_PMAC),y) LDLIBS += -lrte_pmac endif +ifeq ($(CONFIG_RTE_LIBRTE_METER),y) +LDLIBS += -lrte_meter +endif + LDLIBS += --start-group ifeq ($(CONFIG_RTE_LIBRTE_ETHER),y) -- 2.20.1