From 87ebb5f92e62fce4e254cebe1b65f9ab78cd994d Mon Sep 17 00:00:00 2001 From: Lu Qiuwen Date: Sun, 14 Apr 2024 15:27:56 +0800 Subject: support tx meter and df calculate. --- service/include/sc_devmgr.h | 15 +++ service/src/devmgr.c | 71 ++++++++++++++- service/src/node_phydev.c | 216 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 280 insertions(+), 22 deletions(-) diff --git a/service/include/sc_devmgr.h b/service/include/sc_devmgr.h index 3787fe9..d6ad8ee 100644 --- a/service/include/sc_devmgr.h +++ b/service/include/sc_devmgr.h @@ -177,6 +177,21 @@ struct dpdk_dev #define __DEV_MAX_DEFAULT_FLOWS 256 struct rte_flow * default_flow_handles[__DEV_MAX_DEFAULT_FLOWS]; unsigned int nr_default_flow_handles; + + /* rx meter */ + unsigned int en_rx_meter; + struct rte_meter_srtcm_profile * rx_meter_profile[MR_SID_MAX]; + struct rte_meter_srtcm * rx_meter[MR_SID_MAX]; + + /* tx meter */ + unsigned int en_tx_meter; + uint64_t tx_meter_cir; + uint64_t tx_meter_cbs; + uint64_t tx_meter_ebs; + unsigned int tx_meter_yellow_pkt_delay_us; + + struct rte_meter_srtcm_profile * tx_meter_profile[MR_SID_MAX]; + struct rte_meter_srtcm * tx_meter[MR_SID_MAX]; }; struct mr_dev_desc_qid_map diff --git a/service/src/devmgr.c b/service/src/devmgr.c index 634a015..4bd54d6 100644 --- a/service/src/devmgr.c +++ b/service/src/devmgr.c @@ -1199,6 +1199,42 @@ static int gen_dpdk_dev_ethconf(struct dpdk_dev * dev, unsigned nr_rxq_use, stru return 0; } +static int dpdk_dev_tx_meter_setup(struct dpdk_dev * dev, unsigned int nr_txq, uint64_t cir, uint64_t cbs, uint64_t ebs) +{ + for (unsigned int txq = 0; txq < nr_txq; txq++) + { + dev->tx_meter_profile[txq] = ZMALLOC(sizeof(struct rte_meter_srtcm_profile)); + MR_VERIFY_MALLOC(dev->tx_meter_profile[txq]); + + dev->tx_meter[txq] = ZMALLOC(sizeof(struct rte_meter_srtcm)); + MR_VERIFY_MALLOC(dev->tx_meter[txq]); + + struct rte_meter_srtcm_profile * profile = dev->tx_meter_profile[txq]; + struct rte_meter_srtcm_params params = { + .cir = cir / nr_txq, + .cbs = cbs / nr_txq, + .ebs = ebs / nr_txq, + }; + + int ret = rte_meter_srtcm_profile_config(profile, ¶ms); + if (ret < 0) + { + MR_ERROR("Failed at setting up tx meter config for device %s, errno = %d", dev->symbol, ret); + return ret; + } + + ret = rte_meter_srtcm_config(dev->tx_meter[txq], profile); + if (ret < 0) + { + MR_ERROR("Failed at setting up tx meter for device %s, errno = %d", dev->symbol, ret); + return ret; + } + } + + MR_INFO("dpdk device %s: tx_meter enable, cir=%lu, cbs=%lu, ebs=%lu", dev->symbol, cir, cbs, ebs); + return 0; +} + static int dpdk_dev_queue_setup_rss(struct dpdk_dev * dev, cpu_set_t * rx_cpu_set, cpu_set_t * tx_cpu_set, unsigned int rxq_index_begin, unsigned int txq_index_begin) { @@ -1489,6 +1525,16 @@ static int dpdk_dev_setup_common(struct devmgr_main * devmgr_main, struct dpdk_d return RT_ERR; } + + if(dev->en_tx_meter) + { + ret = dpdk_dev_tx_meter_setup(dev, nr_txq_use, dev->tx_meter_cir, dev->tx_meter_cbs, dev->tx_meter_ebs); + if (ret < 0) + { + return RT_ERR; + } + } + nr_rxq_index += dev->nr_rxq; nr_txq_index += dev->nr_txq; @@ -1627,8 +1673,25 @@ void dpdk_dev_config_load(struct dpdk_dev * dev_dpdk, const char * cfg) MESA_load_profile_uint_def(cfg, str_section, "promisc", &dev_dpdk->promisc, 0); // MULTICAST MESA_load_profile_uint_def(cfg, str_section, "allmulticast", &dev_dpdk->allmulticast, 0); - // SMARTOFFLOAD - MESA_load_profile_uint_def(cfg, str_section, "en_smartoffload", &dev_dpdk->en_smartoffload, 0); + + /* tx meter */ + MESA_load_profile_uint_def(cfg, str_section, "en_tx_meter", &dev_dpdk->en_tx_meter, 0); + if(dev_dpdk->en_tx_meter) + { + unsigned int tx_meter_cir_in_Kbps = 0; + unsigned int tx_meter_cbs_in_KB = 0; + unsigned int tx_meter_ebs_in_KB = 0; + + MESA_load_profile_uint_def(cfg, str_section, "tx_meter_cir_in_Kbps", &tx_meter_cir_in_Kbps, 0); + MESA_load_profile_uint_def(cfg, str_section, "tx_meter_cbs_in_KB", &tx_meter_cbs_in_KB, 0); + MESA_load_profile_uint_def(cfg, str_section, "tx_meter_ebs_in_KB", &tx_meter_ebs_in_KB, 0); + MESA_load_profile_uint_def(cfg, str_section, "tx_meter_yellow_pkt_delay_in_us", + &dev_dpdk->tx_meter_yellow_pkt_delay_us, 1); + + dev_dpdk->tx_meter_cir = (uint64_t)tx_meter_cir_in_Kbps * 1000 / 8; + dev_dpdk->tx_meter_cbs = (uint64_t)tx_meter_cbs_in_KB * 1024; + dev_dpdk->tx_meter_ebs = (uint64_t)tx_meter_ebs_in_KB * 1024; + } // which mempool used memset(dev_dpdk->str_direct_pool, 0, sizeof(dev_dpdk->str_direct_pool)); @@ -2330,12 +2393,12 @@ static cJSON * dpdk_dev_monit_stats(struct dpdk_dev * dev) for (int i = 0; i < RTE_DIM(_dpdk_dev_stat.tx_drop_counter); i++) { - user_rx_drop_total += _dpdk_dev_stat.tx_drop_counter[i]; + user_tx_drop_total += _dpdk_dev_stat.tx_drop_counter[i]; } for (int i = 0; i < RTE_DIM(_dpdk_dev_stat_last.tx_drop_counter); i++) { - user_rx_drop_last += _dpdk_dev_stat_last.tx_drop_counter[i]; + user_tx_drop_last += _dpdk_dev_stat_last.tx_drop_counter[i]; } cJSON_AddNumberToObject(j_device_value, "ipackets", _eth_stat.ipackets); diff --git a/service/src/node_phydev.c b/service/src/node_phydev.c index 0cb5a9d..155ab02 100644 --- a/service/src/node_phydev.c +++ b/service/src/node_phydev.c @@ -1,4 +1,3 @@ -#include "common.h" #include #include #include @@ -25,6 +24,16 @@ struct dev_node_main TAILQ_HEAD(dev_node_elem_head, dev_node_elem) elems_head; }; +struct df_stat_counters +{ + volatile uint64_t df_last_tsc; + volatile uint64_t df_sum_Sj; + volatile uint64_t df_VB_pre; + volatile uint64_t df_VB_post; + volatile uint64_t df_VB_max; + volatile uint64_t df_VB_min; +}; + struct phydev_stat_per_core { volatile uint64_t total_rx_pkts; @@ -34,6 +43,21 @@ struct phydev_stat_per_core volatile uint32_t rx_zero_iterations; volatile uint32_t rx_non_zero_iterations; + + /* https://www.rfc-editor.org/rfc/rfc4445.html, Section 3.1 Delay Factor + VB(i,pre) = sum (Sj) - MR * Ti; where j=1..i-1 + VB(i,post) = VB(i,pre) + Si + */ + + /* DF calculate */ + struct df_stat_counters rx_df; + struct df_stat_counters tx_df; + + /* meter */ + volatile uint64_t tx_meter_red; + volatile uint64_t tx_meter_yellow; + volatile uint64_t tx_meter_green; + } __rte_cache_aligned; static struct phydev_stat_per_core phydev_stat[RTE_MAX_LCORE]; @@ -41,6 +65,7 @@ static struct phydev_stat_per_core phydev_stat[RTE_MAX_LCORE]; static struct dev_node_main st_dev_node_main; static struct dev_node_main * p_dev_node_main = &st_dev_node_main; +#define DF_MR_DEFAULT 50000 static_assert(sizeof(struct dev_node_ctx) <= RTE_NODE_CTX_SZ, "dev_node_ctx size must smaller than RTE_NODE_CTX_SZ"); int mbuf_object_deserialize_from_msgpack(struct sc_main * sc, struct rte_mbuf * mbuf, const char * buf, @@ -320,6 +345,55 @@ static unsigned int mbufs_msgpack_decode(struct rte_mbuf ** mbufs, unsigned int return out_nr_mbufs; } + +void df_calculate_packet_input(struct df_stat_counters * df_counters, unsigned int MR, + struct rte_mbuf * mbufs[], unsigned int nr_mbufs) +{ + /* now tsc */ + uint64_t now_tsc = rte_get_timer_cycles(); + + /* total bytes */ + uint64_t Sj = 0; + for (unsigned int i = 0; i < nr_mbufs; i++) + { + Sj += mbufs[i]->pkt_len; + } + + if(Sj == 0) + { + return; + } + + /* calculate the delay factor */ + uint64_t delta_tsc = now_tsc - df_counters->df_last_tsc; + uint64_t delta_tsc_in_us = delta_tsc / (rte_get_timer_hz() / US_PER_S); + + uint64_t VB_pre = df_counters->df_VB_pre + Sj - MR * delta_tsc_in_us; + uint64_t VB_post = VB_pre + Sj; + + /* update the counters */ + df_counters->df_last_tsc = now_tsc; + df_counters->df_sum_Sj += Sj; + df_counters->df_VB_pre = VB_pre; + df_counters->df_VB_post = VB_post; + df_counters->df_VB_max = RTE_MAX(df_counters->df_VB_max, VB_post); + df_counters->df_VB_min = RTE_MIN(df_counters->df_VB_min, VB_pre); +} + +uint64_t df_calculate_get_result(struct df_stat_counters * df_counters, uint64_t MR) +{ + uint64_t df = (df_counters->df_VB_max - df_counters->df_VB_min) / MR; + + /* clear the counters */ + df_counters->df_VB_max = df_counters->df_VB_post; + df_counters->df_VB_min = df_counters->df_VB_post; + df_counters->df_VB_pre = 0; + df_counters->df_VB_post = 0; + df_counters->df_sum_Sj = 0; + + return df; +} + static __rte_always_inline uint16_t dpdk_msgpack_dev_rx_node_process(struct rte_graph * graph, struct rte_node * node, void ** objs, uint16_t cnt) { @@ -379,6 +453,10 @@ static __rte_always_inline uint16_t dpdk_dev_rx_node_process(struct rte_graph * stat_per_core->total_rx_pkts+= nr_mbufs; } +#if MR_PHYDEV_ENABLE_DF_CALCULATE + df_calculate_packet_input(&stat_per_core->rx_df, DF_MR_DEFAULT, (struct rte_mbuf **)node->objs, nr_mbufs); +#endif + /* hash calculate */ node->idx = nr_mbufs; @@ -476,26 +554,98 @@ static __rte_always_inline uint16_t dpdk_msgpack_dev_tx_node_process(struct rte_ return tx_nr_mbufs; } +#define MR_PHYDEV_RETRY_WHEN_TX_FAILED 1 + +static __rte_always_inline void do_tx_burst(struct rte_graph * graph, struct rte_node * node, struct mr_dev_desc * dev_desc, + struct rte_mbuf ** mbufs_to_send, unsigned int nr_mbufs_to_send) +{ + unsigned int tx_nr_mbufs = 0; + while (tx_nr_mbufs < nr_mbufs_to_send) + { + struct rte_mbuf ** mbuf_ptr = mbufs_to_send + tx_nr_mbufs; + unsigned int tx_cnt = nr_mbufs_to_send - tx_nr_mbufs; + tx_nr_mbufs += rte_eth_tx_burst(dev_desc->port_id, graph->id, mbuf_ptr, tx_cnt); + } +} + static __rte_always_inline uint16_t dpdk_dev_tx_node_process(struct rte_graph * graph, struct rte_node * node, void ** objs, uint16_t cnt) { struct dev_node_ctx * ctx = (struct dev_node_ctx *)node->ctx; struct mr_dev_desc * dev_desc = ctx->dev_desc; - struct dpdk_dev_stats * dev_stat = &ctx->dev_desc->dpdk_dev_desc->stat; + struct dpdk_dev * dpdk_dev_desc = dev_desc->dpdk_dev_desc; struct phydev_stat_per_core * stat_per_core = &phydev_stat[graph->id]; - unsigned int tx_nr_mbufs = rte_eth_tx_burst(dev_desc->port_id, graph->id, (struct rte_mbuf **)objs, cnt); - if (unlikely(tx_nr_mbufs != cnt)) + + /* do CF calculate */ +#if MR_PHYDEV_ENABLE_DF_CALCULATE + df_calculate_packet_input(&stat_per_core->tx_df, DF_MR_DEFAULT, (struct rte_mbuf **)objs, cnt); +#endif + + struct rte_mbuf * mbufs_to_send[RTE_GRAPH_BURST_SIZE]; + unsigned int nr_mbufs_to_send = 0; + + struct rte_mbuf * mbufs_to_drop[RTE_GRAPH_BURST_SIZE]; + unsigned int nr_mbufs_to_drop = 0; + + unsigned int counter_tx_meter_green = 0; + unsigned int counter_tx_meter_yellow = 0; + unsigned int counter_tx_meter_red = 0; + + if (dpdk_dev_desc->en_tx_meter) { - /* redirect unsent packets to drop node */ - stat_per_core->total_tx_drop_pkts += cnt - tx_nr_mbufs; - dev_stat->tx_drop_counter[graph->id] += cnt - tx_nr_mbufs; + struct rte_meter_srtcm * meter = dpdk_dev_desc->tx_meter[graph->id]; + struct rte_meter_srtcm_profile * profile = dpdk_dev_desc->tx_meter_profile[graph->id]; + for (unsigned int i = 0; i < cnt; i++) + { + struct rte_mbuf * mbuf = (struct rte_mbuf *)objs[i]; + uint64_t tsc = rte_get_timer_cycles(); + enum rte_color color = rte_meter_srtcm_color_blind_check(meter, profile, tsc, mbuf->pkt_len); - /* stat for dpdk dev */ - rte_node_enqueue(graph, node, 0, &objs[tx_nr_mbufs], cnt - tx_nr_mbufs); + switch (color) + { + case RTE_COLORS: + case RTE_COLOR_GREEN: + mbufs_to_send[nr_mbufs_to_send++] = mbuf; + counter_tx_meter_green++; + break; + + case RTE_COLOR_YELLOW: + mbufs_to_send[nr_mbufs_to_send++] = mbuf; + do_tx_burst(graph, node, dev_desc, mbufs_to_send, nr_mbufs_to_send); + nr_mbufs_to_send = 0; + + rte_delay_us_block(dpdk_dev_desc->tx_meter_yellow_pkt_delay_us); + counter_tx_meter_yellow++; + break; + + case RTE_COLOR_RED: + stat_per_core->tx_meter_red++; + mbufs_to_drop[nr_mbufs_to_drop++] = mbuf; + break; + } + } + } + else + { + rte_memcpy(mbufs_to_send, objs, cnt * sizeof(void *)); + nr_mbufs_to_send = cnt; + } + + do_tx_burst(graph, node, dev_desc, mbufs_to_send, nr_mbufs_to_send); + + /* enqueue drop packet to next node */ + if (nr_mbufs_to_drop > 0) + { + rte_node_enqueue(graph, node, 0, (void **)mbufs_to_drop, nr_mbufs_to_drop); } - stat_per_core->total_tx_pkts += tx_nr_mbufs; + /* stat */ + stat_per_core->tx_meter_red += counter_tx_meter_red; + stat_per_core->tx_meter_yellow += counter_tx_meter_yellow; + stat_per_core->tx_meter_green += counter_tx_meter_green; + stat_per_core->total_tx_pkts += nr_mbufs_to_send; + stat_per_core->total_tx_drop_pkts += nr_mbufs_to_drop; return cnt; } @@ -580,11 +730,11 @@ static struct rte_node_register dpdk_dev_tx_node_base = { }, }; -static struct rte_node_register dpdk_dev_tx_node_periodical = { - .process = dpdk_dev_tx_periodical_process, - .name = "dpdk_dev_tx_node_periodical", - .flags = RTE_NODE_SOURCE_F, +static struct rte_node_register dpdk_dev_rx_node_periodical = { + .process = dpdk_dev_rx_periodical_process, + .name = "dpdk_dev_rx_node_periodical", .init = dev_node_init, + .flags = RTE_NODE_SOURCE_F, .nb_edges = 1, .next_nodes = { @@ -592,11 +742,11 @@ static struct rte_node_register dpdk_dev_tx_node_periodical = { }, }; -static struct rte_node_register dpdk_dev_rx_node_periodical = { - .process = dpdk_dev_rx_periodical_process, - .name = "dpdk_dev_rx_node_periodical", - .init = dev_node_init, +static struct rte_node_register dpdk_dev_tx_node_periodical = { + .process = dpdk_dev_tx_periodical_process, + .name = "dpdk_dev_tx_node_periodical", .flags = RTE_NODE_SOURCE_F, + .init = dev_node_init, .nb_edges = 1, .next_nodes = { @@ -809,6 +959,12 @@ cJSON * phydev_rx_node_monit_loop(struct sc_main * sc) uint64_t total_tx_drop_pkts[RTE_MAX_LCORE]; double rx_spin_time[RTE_MAX_LCORE]; + uint64_t df_rx[RTE_MAX_LCORE]; + uint64_t df_tx[RTE_MAX_LCORE]; + + uint64_t total_tx_meter_red[RTE_MAX_LCORE]; + uint64_t total_tx_meter_yellow[RTE_MAX_LCORE]; + uint64_t total_tx_meter_green[RTE_MAX_LCORE]; for (unsigned int i = 0; i < nr_graphs; i++) { @@ -817,6 +973,10 @@ cJSON * phydev_rx_node_monit_loop(struct sc_main * sc) total_rx_drop_pkts[i] = phydev_stat[i].total_rx_drop_pkts; total_tx_drop_pkts[i] = phydev_stat[i].total_tx_drop_pkts; + total_tx_meter_green[i] = phydev_stat[i].tx_meter_green; + total_tx_meter_yellow[i] = phydev_stat[i].tx_meter_yellow; + total_tx_meter_red[i] = phydev_stat[i].tx_meter_red; + /* calculate the spin time */ uint32_t rx_zero_iterations = phydev_stat[i].rx_zero_iterations; uint32_t rx_non_zero_iterations = phydev_stat[i].rx_non_zero_iterations; @@ -832,6 +992,10 @@ cJSON * phydev_rx_node_monit_loop(struct sc_main * sc) { rx_spin_time[i] = 0; } + + /* DF calculate */ + df_rx[i] = df_calculate_get_result(&phydev_stat[i].rx_df, DF_MR_DEFAULT); + df_tx[i] = df_calculate_get_result(&phydev_stat[i].tx_df, DF_MR_DEFAULT); } cJSON * json_total_rx_pkts = create_uint64_array(total_rx_pkts, nr_graphs); @@ -846,8 +1010,24 @@ cJSON * phydev_rx_node_monit_loop(struct sc_main * sc) cJSON * json_total_tx_drop_pkts = create_uint64_array(total_tx_drop_pkts, nr_graphs); cJSON_AddItemToObject(json_root, "total_tx_drop_pkts", json_total_tx_drop_pkts); + cJSON * json_total_tx_meter_red = create_uint64_array(total_tx_meter_red, nr_graphs); + cJSON_AddItemToObject(json_root, "total_tx_meter_red", json_total_tx_meter_red); + + cJSON * json_total_tx_meter_yellow = create_uint64_array(total_tx_meter_yellow, nr_graphs); + cJSON_AddItemToObject(json_root, "total_tx_meter_yellow", json_total_tx_meter_yellow); + + cJSON * json_total_tx_meter_green = create_uint64_array(total_tx_meter_green, nr_graphs); + cJSON_AddItemToObject(json_root, "total_tx_meter_green", json_total_tx_meter_green); + cJSON * json_rx_spin_time = cJSON_CreateDoubleArray(rx_spin_time, (int)nr_graphs); cJSON_AddItemToObject(json_root, "rx_spin_time", json_rx_spin_time); + + cJSON * json_df_rx = create_uint64_array(df_rx, nr_graphs); + cJSON_AddItemToObject(json_root, "df_rx", json_df_rx); + + cJSON * json_df_tx = create_uint64_array(df_tx, nr_graphs); + cJSON_AddItemToObject(json_root, "df_tx", json_df_tx); + return json_root; } -- cgit v1.2.3