summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsongyanchao <[email protected]>2024-04-30 09:58:10 +0000
committersongyanchao <[email protected]>2024-05-15 02:06:25 +0000
commit4465a1ce74f4a6109bacff3e475a55f3ea1990d7 (patch)
treeb3ba9c125c124fcb27554c4a54cc9da52b3ca813
parent7fa3de16bd8cc266a99279e23baea532a4a3e4c3 (diff)
✨ feat(DPISDN-42): Add 'link_aware_injector' node.
Add 'link_aware_injector' node.
-rw-r--r--include/internal/adapter_define.h2
-rw-r--r--infra/include/link_db.h3
-rw-r--r--infra/src/link_db.c30
-rw-r--r--infra/test/TestLinkDb.cc36
-rw-r--r--service/CMakeLists.txt2
-rw-r--r--service/include/sc_node_common.h2
-rw-r--r--service/src/monit.c2
-rw-r--r--service/src/node_etherfabric.c7
-rw-r--r--service/src/node_forwarder.c34
-rw-r--r--service/src/node_link_aware_injector.c343
-rw-r--r--service/src/node_vwire.c6
11 files changed, 417 insertions, 50 deletions
diff --git a/include/internal/adapter_define.h b/include/internal/adapter_define.h
index 5e6e131..c103cb3 100644
--- a/include/internal/adapter_define.h
+++ b/include/internal/adapter_define.h
@@ -14,6 +14,8 @@ enum adapter_type
unsigned int nr_max_vwires_get();
unsigned int nr_max_ef_adapters_get();
unsigned int nr_max_tera_adapters_get();
+uint32_t vwire_sid_start_get();
+uint32_t ef_sid_start_get();
int ef_adapter_id_check(uint32_t ef_adapter_id);
int vwire_id_check(uint32_t vwire_id);
int tera_adapter_id_check(uint32_t tera_adapter_id);
diff --git a/infra/include/link_db.h b/infra/include/link_db.h
index 198a1ef..3affd77 100644
--- a/infra/include/link_db.h
+++ b/infra/include/link_db.h
@@ -29,6 +29,7 @@ struct link_db_reverse_result
{
enum link_db_type type;
uint16_t adapter_id;
+ int match_result;
};
struct link_db_ctx;
@@ -37,5 +38,5 @@ struct link_db_ctx * link_db_create(enum link_db_type type, uint32_t max_entries
int link_db_config_parse(const char * cfgfile, struct link_db_ctx * ctx);
void link_db_match(struct link_db_ctx * ctx, struct link_db_match_field match_field[], uint16_t nr_mbufs,
uint16_t result[]);
-int link_db_reverse_match(struct link_db_ctx * ctx, uint16_t link_id, struct link_db_reverse_result * result);
+void link_db_reverse_match(struct link_db_ctx * ctx, uint16_t link_id, struct link_db_reverse_result * result);
void link_db_destroy(struct link_db_ctx ** ctx);
diff --git a/infra/src/link_db.c b/infra/src/link_db.c
index d823e6f..ae42ec5 100644
--- a/infra/src/link_db.c
+++ b/infra/src/link_db.c
@@ -35,6 +35,8 @@ struct link_db_ctx
link_db_match_func match_func;
};
+const char * link_db_type_str[LINK_DB_TYPE_MAX] = {"etherfabric", "vwire", "tera", "all"};
+
/* Link db ctx item create */
struct link_db_ctx * link_db_create(enum link_db_type type, uint32_t max_entries)
{
@@ -96,25 +98,9 @@ void link_db_destroy(struct link_db_ctx ** ctx)
void link_db_ctx_dump(struct link_db_ctx * ctx)
{
assert(ctx != NULL);
- char str_type[MR_STRING_MAX];
-
- switch (ctx->type)
- {
- case LINK_DB_TYPE_EF:
- snprintf(str_type, sizeof(str_type) - 1, "%u(etherfabric)", ctx->type);
- break;
- case LINK_DB_TYPE_VWIRE:
- snprintf(str_type, sizeof(str_type) - 1, "%u(vwire)", ctx->type);
- break;
- case LINK_DB_TYPE_TERA:
- snprintf(str_type, sizeof(str_type) - 1, "%u(tera)", ctx->type);
- break;
- default:
- snprintf(str_type, sizeof(str_type) - 1, "%u(unknow)", ctx->type);
- break;
- }
- MR_INFO("Link db, max entries:%u, nr entries:%u, type:%s", ctx->max_entries, ctx->nr_entries, str_type);
+ MR_INFO("Link db, max entries:%u, nr entries:%u, type:%s", ctx->max_entries, ctx->nr_entries,
+ link_db_type_str[ctx->type]);
for (int index = 0; index < ctx->nr_entries; index++)
{
@@ -332,9 +318,10 @@ void link_db_match(struct link_db_ctx * ctx, struct link_db_match_field match_fi
}
/* Link db reverse match */
-int link_db_reverse_match(struct link_db_ctx * ctx, uint16_t link_id, struct link_db_reverse_result * result)
+void link_db_reverse_match(struct link_db_ctx * ctx, uint16_t link_id, struct link_db_reverse_result * result)
{
assert(ctx != NULL);
+ result->match_result = RT_ERR;
for (int index = 0; index < ctx->nr_entries; index++)
{
@@ -358,9 +345,10 @@ int link_db_reverse_match(struct link_db_ctx * ctx, uint16_t link_id, struct lin
break;
}
- return RT_SUCCESS;
+ result->match_result = RT_SUCCESS;
+ return;
}
}
- return RT_ERR;
+ return;
}
diff --git a/infra/test/TestLinkDb.cc b/infra/test/TestLinkDb.cc
index eb0f6c2..86bb0d2 100644
--- a/infra/test/TestLinkDb.cc
+++ b/infra/test/TestLinkDb.cc
@@ -296,14 +296,14 @@ TEST(TestCaseLinkDb, TypeAllReverseMatch)
struct link_db_reverse_result reverse_result;
- int ret = link_db_reverse_match(all_ctx, result[0], &reverse_result);
- ASSERT_EQ(ret, -1);
+ link_db_reverse_match(all_ctx, result[0], &reverse_result);
+ ASSERT_EQ(reverse_result.match_result, -1);
- ret = link_db_reverse_match(all_ctx, result[1], &reverse_result);
- ASSERT_EQ(ret, -1);
+ link_db_reverse_match(all_ctx, result[1], &reverse_result);
+ ASSERT_EQ(reverse_result.match_result, -1);
- ret = link_db_reverse_match(all_ctx, result[2], &reverse_result);
- ASSERT_EQ(ret, 0);
+ link_db_reverse_match(all_ctx, result[2], &reverse_result);
+ ASSERT_EQ(reverse_result.match_result, 0);
ASSERT_EQ(reverse_result.type, LINK_DB_TYPE_EF);
ASSERT_EQ(reverse_result.adapter_id, 16);
@@ -318,14 +318,14 @@ TEST(TestCaseLinkDb, TypeAllReverseMatch)
ASSERT_EQ(result[1], UINT16_MAX);
ASSERT_EQ(result[2], 54321);
- ret = link_db_reverse_match(all_ctx, result[0], &reverse_result);
- ASSERT_EQ(ret, -1);
+ link_db_reverse_match(all_ctx, result[0], &reverse_result);
+ ASSERT_EQ(reverse_result.match_result, -1);
- ret = link_db_reverse_match(all_ctx, result[1], &reverse_result);
- ASSERT_EQ(ret, -1);
+ link_db_reverse_match(all_ctx, result[1], &reverse_result);
+ ASSERT_EQ(reverse_result.match_result, -1);
- ret = link_db_reverse_match(all_ctx, result[2], &reverse_result);
- ASSERT_EQ(ret, 0);
+ link_db_reverse_match(all_ctx, result[2], &reverse_result);
+ ASSERT_EQ(reverse_result.match_result, 0);
ASSERT_EQ(reverse_result.type, LINK_DB_TYPE_VWIRE);
ASSERT_EQ(reverse_result.adapter_id, 17);
@@ -340,14 +340,14 @@ TEST(TestCaseLinkDb, TypeAllReverseMatch)
ASSERT_EQ(result[1], UINT16_MAX);
ASSERT_EQ(result[2], 6000);
- ret = link_db_reverse_match(all_ctx, result[0], &reverse_result);
- ASSERT_EQ(ret, -1);
+ link_db_reverse_match(all_ctx, result[0], &reverse_result);
+ ASSERT_EQ(reverse_result.match_result, -1);
- ret = link_db_reverse_match(all_ctx, result[1], &reverse_result);
- ASSERT_EQ(ret, -1);
+ link_db_reverse_match(all_ctx, result[1], &reverse_result);
+ ASSERT_EQ(reverse_result.match_result, -1);
- ret = link_db_reverse_match(all_ctx, result[2], &reverse_result);
- ASSERT_EQ(ret, 0);
+ link_db_reverse_match(all_ctx, result[2], &reverse_result);
+ ASSERT_EQ(reverse_result.match_result, 0);
ASSERT_EQ(reverse_result.type, LINK_DB_TYPE_TERA);
ASSERT_EQ(reverse_result.adapter_id, 18);
diff --git a/service/CMakeLists.txt b/service/CMakeLists.txt
index 5ca2dcf..22dcb4c 100644
--- a/service/CMakeLists.txt
+++ b/service/CMakeLists.txt
@@ -7,7 +7,7 @@ add_executable(mrzcpd src/core.c src/devmgr.c src/mrb.c src/hwinfo.c src/vdev.c
src/node_phydev.c src/node_lb.c src/node_classifier.c src/node_etherfabric.c src/node_tera.c
src/node_eth_ingress.c src/node_eth_egress.c src/node_bfd.c src/node_vwire.c
src/node_health_check.c src/node_forwarder.c src/node_bridge.c src/pdump.c src/olp.c src/olp_6500.c
- src/http_serv.c src/classifier_rule_parser.c src/mpack.c src/dp_trace.c)
+ src/http_serv.c src/classifier_rule_parser.c src/mpack.c src/dp_trace.c src/node_link_aware_injector.c)
target_link_libraries(mrzcpd MESA_prof_load_static libdpdk ${SYSTEMD_LIBRARIES})
target_link_libraries(mrzcpd rt pthread dl infra z elf)
diff --git a/service/include/sc_node_common.h b/service/include/sc_node_common.h
index 2c34c7c..1f8dc7f 100644
--- a/service/include/sc_node_common.h
+++ b/service/include/sc_node_common.h
@@ -22,6 +22,7 @@ enum
FORWARDER_TYPE_VWIRE,
FORWARDER_TYPE_EF,
FORWARDER_TYPE_TERA,
+ FORWARDER_TYPE_LAI,
FORWARDER_TYPE_HEALTH_CHECK,
FORWARDER_TYPE_MAX
};
@@ -119,7 +120,6 @@ static inline int mr_is_local_addr(struct mr_dev_desc * dev_desc, struct mr_gene
(x[0] == 0xFF && x[1] == 0x02 && x[2] == 0x00 && x[3] == 0x00 && x[4] == 0x00 && x[5] == 0x00 && x[6] == 0x00 && \
x[7] == 0x00 && x[8] == 0x00 && x[9] == 0x00 && x[10] == 0x00 && x[11] == 0x01 && x[12] == 0xFF)
-
static inline cJSON * create_uint64_array(const uint64_t * value, unsigned int nr_value)
{
struct cJSON * uint64_array = cJSON_CreateArray();
diff --git a/service/src/monit.c b/service/src/monit.c
index d758c64..08263fd 100644
--- a/service/src/monit.c
+++ b/service/src/monit.c
@@ -224,6 +224,7 @@ extern cJSON * tera_egress_node_monit_loop(struct sc_main * sc);
extern cJSON * devmgr_monit_loop(struct sc_main * sc);
extern cJSON * dp_trace_monit_loop(struct sc_main * sc);
extern cJSON * phydev_rx_node_monit_loop(struct sc_main * sc);
+extern cJSON * lai_node_monit_loop(struct sc_main * sc);
static cJSON * monit_root(struct sc_main * sc)
{
@@ -249,6 +250,7 @@ static cJSON * monit_root(struct sc_main * sc)
cJSON_AddItemToObject(j_root, "bfd", bfd_node_monit_loop(sc));
cJSON_AddItemToObject(j_root, "classifier", classifier_node_monit_loop(sc));
cJSON_AddItemToObject(j_root, "forwarder", forwarder_node_monit_loop(sc));
+ cJSON_AddItemToObject(j_root, "link-aware-injector", lai_node_monit_loop(sc));
cJSON_AddItemToObject(j_root, "vwire-egress", vwire_egress_node_monit_loop(sc));
cJSON_AddItemToObject(j_root, "lb", lb_node_monit_loop(sc));
cJSON_AddItemToObject(j_root, "ef-egress", ef_egress_node_monit_loop(sc));
diff --git a/service/src/node_etherfabric.c b/service/src/node_etherfabric.c
index e0c32e3..00adade 100644
--- a/service/src/node_etherfabric.c
+++ b/service/src/node_etherfabric.c
@@ -140,6 +140,13 @@ unsigned int nr_max_ef_adapters_get()
return nr_max_ef_adapters;
}
+/* Etherfabric start sid get */
+uint32_t ef_sid_start_get()
+{
+ struct node_ef_main * ef_main = node_ef_main_get();
+ return ef_main->sid_start;
+}
+
/* Set the pkt offset */
const static int ef_encap_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) +
sizeof(struct rte_udp_hdr) + sizeof(struct g_vxlan_hdr);
diff --git a/service/src/node_forwarder.c b/service/src/node_forwarder.c
index ba5aee3..87a3124 100644
--- a/service/src/node_forwarder.c
+++ b/service/src/node_forwarder.c
@@ -16,6 +16,7 @@ enum
FORWARDER_VWIRE_EGRESS,
FORWARDER_EF_EGRESS,
FORWARDER_TERA_EGRESS,
+ FORWARDER_LAI,
FORWARDER_NEXT_MAX
};
@@ -39,6 +40,7 @@ struct forwarder_stats
volatile uint64_t to_vwire_egress;
volatile uint64_t to_ef_egress;
volatile uint64_t to_tera_egress;
+ volatile uint64_t to_lai;
volatile uint64_t drop_reason[FORWARDER_DROP_RSN_MAX];
} __rte_cache_aligned;
@@ -96,7 +98,12 @@ void forwarder_table_inserter(uint16_t sid, uint16_t type)
forwarder_main->forwarder_table[sid] = FORWARDER_TERA_EGRESS;
len += snprintf(str_forwarder + len, sizeof(str_forwarder) - len, ", next_services=tera egress");
break;
+ case FORWARDER_TYPE_LAI:
+ forwarder_main->forwarder_table[sid] = FORWARDER_LAI;
+ len += snprintf(str_forwarder + len, sizeof(str_forwarder) - len, ", next_services=link aware injector");
+ break;
}
+
forwarder_main->nr_rules++;
MR_INFO("%s", str_forwarder);
}
@@ -236,6 +243,7 @@ static __rte_always_inline uint16_t forwarder_node_process(struct rte_graph * gr
graph_stats->to_vwire_egress += next_node_index_counters[FORWARDER_VWIRE_EGRESS];
graph_stats->to_ef_egress += next_node_index_counters[FORWARDER_EF_EGRESS];
graph_stats->to_tera_egress += next_node_index_counters[FORWARDER_TERA_EGRESS];
+ graph_stats->to_lai += next_node_index_counters[FORWARDER_LAI];
for (uint16_t i = 0; i < FORWARDER_DROP_RSN_MAX; i++)
{
@@ -264,6 +272,7 @@ static struct rte_node_register forwarder_node_base = {
[FORWARDER_VWIRE_EGRESS] = "vwire_egress",
[FORWARDER_EF_EGRESS] = "ef_egress",
[FORWARDER_TERA_EGRESS] = "tera_egress",
+ [FORWARDER_LAI] = "link_aware_injector",
},
};
@@ -281,6 +290,7 @@ cJSON * forwarder_node_monit_loop(struct sc_main * sc)
uint64_t to_vwire_egress[nr_graphs];
uint64_t to_ef_egress[nr_graphs];
uint64_t to_tera_egress[nr_graphs];
+ uint64_t to_lai[nr_graphs];
uint64_t drop_reason[nr_graphs][FORWARDER_DROP_RSN_MAX];
for (uint32_t graph_id = 0; graph_id < nr_graphs; graph_id++)
@@ -294,6 +304,7 @@ cJSON * forwarder_node_monit_loop(struct sc_main * sc)
to_vwire_egress[graph_id] = 0;
to_ef_egress[graph_id] = 0;
to_tera_egress[graph_id] = 0;
+ to_lai[graph_id] = 0;
memset(drop_reason[graph_id], 0, sizeof(drop_reason[graph_id]));
continue;
@@ -305,6 +316,7 @@ cJSON * forwarder_node_monit_loop(struct sc_main * sc)
to_vwire_egress[graph_id] = stats->to_vwire_egress;
to_ef_egress[graph_id] = stats->to_ef_egress;
to_tera_egress[graph_id] = stats->to_tera_egress;
+ to_lai[graph_id] = stats->to_lai;
for (int i = 0; i < FORWARDER_DROP_RSN_MAX; i++)
{
@@ -330,6 +342,9 @@ cJSON * forwarder_node_monit_loop(struct sc_main * sc)
cJSON * json_to_tera_egress = create_uint64_array(to_tera_egress, nr_graphs);
cJSON_AddItemToObject(json_root, "forwarder, to_tera_egress", json_to_tera_egress);
+ cJSON * json_to_lai = create_uint64_array(to_lai, nr_graphs);
+ cJSON_AddItemToObject(json_root, "forwarder, to_link_aware_injector", json_to_lai);
+
for (int i = 0; i < FORWARDER_DROP_RSN_MAX; i++)
{
char str_title[MR_STRING_MAX];
@@ -353,31 +368,34 @@ cJSON * forwarder_table_monit_loop(struct sc_main * sc)
if (forwarder_main->forwarder_table[index] == 0)
continue;
- cJSON * item_obj = cJSON_CreateObject();
+ char str_info[MR_STRING_MAX] = {};
+ int len = snprintf(str_info, sizeof(str_info), "Sid:%u, ", index);
- cJSON_AddNumberToObject(item_obj, "Sid", index);
switch (forwarder_main->forwarder_table[index])
{
case FORWARDER_NEXT_LB:
- cJSON_AddStringToObject(item_obj, "Next Services", "LB");
+ len += snprintf(str_info + len, sizeof(str_info) - len, "Next Services: LB");
break;
case FORWARDER_VWIRE_EGRESS:
- cJSON_AddStringToObject(item_obj, "Next Services", "Vwire");
+ len += snprintf(str_info + len, sizeof(str_info) - len, "Next Services: Vwire");
break;
case FORWARDER_EF_EGRESS:
- cJSON_AddStringToObject(item_obj, "Next Services", "Etherfabric");
+ len += snprintf(str_info + len, sizeof(str_info) - len, "Next Services: Etherfabric");
break;
case FORWARDER_TERA_EGRESS:
- cJSON_AddStringToObject(item_obj, "Next Services", "Tera");
+ len += snprintf(str_info + len, sizeof(str_info) - len, "Next Services: Tera");
+ break;
+ case FORWARDER_LAI:
+ len += snprintf(str_info + len, sizeof(str_info) - len, "Next Services: Link Aware Injector");
break;
default:
- cJSON_AddStringToObject(item_obj, "Next Services", "Unknown");
+ len += snprintf(str_info + len, sizeof(str_info) - len, "Next Services: Unknown");
break;
}
char str_idx[MR_STRING_MAX] = {};
snprintf(str_idx, sizeof(str_idx) - 1, "index:%u", nr_items);
- cJSON_AddItemToObject(json_root, str_idx, item_obj);
+ cJSON_AddStringToObject(json_root, str_idx, str_info);
nr_items++;
}
diff --git a/service/src/node_link_aware_injector.c b/service/src/node_link_aware_injector.c
new file mode 100644
index 0000000..1b7f5d4
--- /dev/null
+++ b/service/src/node_link_aware_injector.c
@@ -0,0 +1,343 @@
+#include <MESA_prof_load.h>
+#include <link_db.h>
+#include <rte_branch_prediction.h>
+#include <sc_node.h>
+#include <sc_node_common.h>
+#include <sc_trace.h>
+
+#include <rte_graph.h>
+#include <rte_graph_worker.h>
+
+/* Link aware injector next node */
+enum
+{
+ LAI_NEXT_PKT_DROP = 0,
+ LAI_NEXT_EF_EGRESS,
+ LAI_NEXT_VWIRE_EGRESS,
+ LAI_NEXT_MAX
+};
+
+/* Link aware injector drop reason*/
+enum lai_drop_reason
+{
+ LAI_DROP_RSN_TLID_MISS = 0,
+ LAI_DROP_RSN_INVALID_ADAPTER_TYPE,
+ LAI_DROP_RSN_MAX
+};
+
+/* Link aware injector drop reason string */
+char * lai_drop_rsn_str[LAI_DROP_RSN_MAX] = {"traffic link id miss", "invalid adapter type"};
+
+/* Link aware injector stats struct */
+struct lai_stats
+{
+ volatile uint64_t total_pkts;
+ volatile uint64_t pkts_per_batch;
+ volatile uint64_t to_eth_egress;
+ volatile uint64_t to_vwire_egress;
+ volatile uint64_t drop_reason[LAI_DROP_RSN_MAX];
+} __rte_cache_aligned;
+
+/* Link aware injector main struct */
+struct node_lai_main
+{
+ uint32_t lai_sid;
+ uint32_t ef_sid_start;
+ uint32_t vwire_sid_start;
+ struct link_db_ctx * link_db_ctx;
+};
+
+/* Link aware injector node context */
+struct lai_node_ctx
+{
+ /* Cached next index */
+ uint16_t next_index;
+};
+
+#define LAI_NODE_LAST_NEXT(ctx) (((struct lai_node_ctx *)ctx)->next_index)
+
+/* Global variable */
+static struct node_lai_main g_lai_main = {};
+static struct lai_stats lai_stats_per_graph[RTE_MAX_LCORE] = {};
+
+static inline struct node_lai_main * node_lai_main_get()
+{
+ return &g_lai_main;
+}
+
+/* Init Link aware injector */
+int lai_init(struct sc_main * sc)
+{
+ struct node_lai_main * lai_main = node_lai_main_get();
+ memset(lai_main, 0, sizeof(struct node_lai_main));
+
+ /* Get Link aware injector sid */
+ MESA_load_profile_uint_def(sc->local_cfgfile, "feature_sids", "lai", &lai_main->lai_sid, 900);
+
+ /* Link db ctx create */
+ uint32_t max_entries;
+ MESA_load_profile_uint_def(sc->local_cfgfile, "limits", "nr_max_link_dbs", &max_entries, 64);
+ max_entries = max_entries * LINK_DB_TYPE_ALL;
+
+ lai_main->link_db_ctx = link_db_create(LINK_DB_TYPE_EF, max_entries);
+ if (lai_main->link_db_ctx == NULL)
+ {
+ MR_ERROR("In link aware injector node, link db ctx create failed.");
+ return RT_ERR;
+ }
+
+ if (link_db_config_parse(sc->local_cfgfile, lai_main->link_db_ctx) == RT_ERR)
+ {
+ MR_ERROR("In link aware injector node, link db config parse failed.");
+ return RT_ERR;
+ }
+
+ /* Get ef and vwire sid start */
+ lai_main->ef_sid_start = ef_sid_start_get();
+ lai_main->vwire_sid_start = vwire_sid_start_get();
+
+ if (lai_main->ef_sid_start == 0)
+ {
+ MR_ERROR("In link aware injector node, ef sid start get failed.");
+ return RT_ERR;
+ }
+ else if (lai_main->vwire_sid_start == 0)
+ {
+ MR_ERROR("In link aware injector node, vwire sid start get failed.");
+ return RT_ERR;
+ }
+
+ /* Inserter sid to forwarder table */
+ forwarder_table_inserter(lai_main->lai_sid, FORWARDER_TYPE_LAI);
+
+ MR_INFO("Link aware injector node init success,link aware injector sid:%u, ef sid start: %u, vwire sid start: %u",
+ lai_main->lai_sid, lai_main->ef_sid_start, lai_main->vwire_sid_start);
+
+ return RT_SUCCESS;
+}
+
+/* Generate and store the trace information */
+static __rte_always_inline void gen_store_trace_info(struct rte_node * node, struct rte_mbuf * mbuf,
+ uint16_t next_node_index, enum lai_drop_reason drop_reason)
+{
+ /* Populate the next node infomation */
+ char str_record[MR_STRING_MAX];
+ int len = snprintf(str_record, sizeof(str_record), "next node:%s", node->nodes[next_node_index]->name);
+
+ /* Populate the drop reason */
+ if (next_node_index == LAI_NEXT_PKT_DROP)
+ {
+ assert(drop_reason < LAI_DROP_RSN_MAX);
+ len += snprintf(str_record + len, sizeof(str_record) - len, ", rsn:%s", lai_drop_rsn_str[drop_reason]);
+ }
+
+ struct mrb_metadata * mrb_meta = mrbuf_cz_data(mbuf, MR_NODE_CTRLZONE_ID);
+ len += snprintf(str_record + len, sizeof(str_record) - len, ", trf lk id:%u, cur sid:%u", mrb_meta->traffic_link_id,
+ mrb_meta->cur_sid);
+
+ /* Emit the trace record */
+ struct dp_trace_record_meta meta = {
+ .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE, .appsym = MR_TRACE_APPSYM, .module = node->name};
+ dp_trace_record_emit_str(sc_main_get()->trace, mbuf, rte_lcore_id(), &meta, str_record);
+}
+
+/* Link aware injector node process function */
+static __rte_always_inline uint16_t lai_node_process(struct rte_graph * graph, struct rte_node * node, void ** objs,
+ uint16_t nb_objs)
+{
+ void ** batch_pkts = objs;
+ struct rte_mbuf ** mbufs = (struct rte_mbuf **)objs;
+
+ /* prefetch the mbuf and it's content */
+ rte_prefetch0(mbufs[0]);
+ rte_prefetch0(mrbuf_cz_data(mbufs[0], MR_NODE_CTRLZONE_ID));
+
+ uint16_t last_spec = 0;
+ uint16_t n_left_from = nb_objs;
+ uint16_t batch_next_node_index = LAI_NODE_LAST_NEXT(node->ctx);
+ uint32_t last_traffic_link_id = UINT32_MAX;
+ enum lai_drop_reason drop_reason = LAI_DROP_RSN_TLID_MISS;
+ struct lai_stats stats = {};
+ struct node_lai_main * lai_main = node_lai_main_get();
+ struct link_db_reverse_result result = {.match_result = RT_ERR};
+
+ while (n_left_from > 0)
+ {
+ struct rte_mbuf * mbuf = mbufs[0];
+ mbufs += 1;
+ n_left_from -= 1;
+
+ /* prefetch next mbuf */
+ if (n_left_from > 0)
+ {
+ rte_prefetch0(mbufs[0]);
+ rte_prefetch0(mrbuf_cz_data(mbufs[0], MR_NODE_CTRLZONE_ID));
+ }
+
+ /* Get metadata */
+ uint16_t next_node_index;
+ struct mrb_metadata * mrb_meta = mrbuf_cz_data(mbuf, MR_NODE_CTRLZONE_ID);
+
+ /* Link db reverse match */
+ if (last_traffic_link_id != mrb_meta->traffic_link_id)
+ {
+ last_traffic_link_id = mrb_meta->traffic_link_id;
+ link_db_reverse_match(lai_main->link_db_ctx, last_traffic_link_id, &result);
+ }
+
+ /* Check the match result */
+ if (unlikely(result.match_result != RT_SUCCESS))
+ {
+ drop_reason = LAI_DROP_RSN_TLID_MISS;
+ stats.drop_reason[drop_reason]++;
+ next_node_index = LAI_NEXT_PKT_DROP;
+ goto node_enqueue;
+ }
+
+ /* Set the next node index */
+ if (result.type == LINK_DB_TYPE_EF)
+ {
+ mrb_meta->cur_sid = lai_main->ef_sid_start + result.adapter_id;
+ next_node_index = LAI_NEXT_EF_EGRESS;
+ stats.to_eth_egress++;
+ }
+ else if (result.type == LINK_DB_TYPE_VWIRE)
+ {
+ mrb_meta->cur_sid = lai_main->vwire_sid_start + result.adapter_id;
+ next_node_index = LAI_NEXT_VWIRE_EGRESS;
+ stats.to_vwire_egress++;
+ }
+ else
+ {
+ drop_reason = LAI_DROP_RSN_INVALID_ADAPTER_TYPE;
+ stats.drop_reason[drop_reason]++;
+ next_node_index = LAI_NEXT_PKT_DROP;
+ }
+
+ node_enqueue:
+
+ /* Check if tracing is enabled for the current Mbuf */
+ if (unlikely(dp_trace_record_can_emit(mbuf, DP_TRACE_MEASUREMENT_TYPE_TRACE)))
+ {
+ gen_store_trace_info(node, mbuf, next_node_index, drop_reason);
+ }
+
+ /* Check if the next index needs to be changed */
+ if (unlikely(batch_next_node_index != next_node_index))
+ {
+ /* Enqueue the last packets if the next index has changed */
+ rte_node_enqueue(graph, node, batch_next_node_index, batch_pkts, last_spec);
+ batch_pkts += last_spec;
+ last_spec = 1;
+ batch_next_node_index = next_node_index;
+ }
+ else
+ {
+ /* If the next index hasn't changed, update the last packets */
+ last_spec++;
+ }
+ }
+
+ /* Process any remaining packets */
+ if (likely(last_spec > 0))
+ rte_node_enqueue(graph, node, batch_next_node_index, batch_pkts, last_spec);
+
+ /* Update last next index */
+ LAI_NODE_LAST_NEXT(node->ctx) = batch_next_node_index;
+
+ /* Update stats */
+ struct lai_stats * graph_stats = &lai_stats_per_graph[graph->id];
+ graph_stats->total_pkts += nb_objs;
+ graph_stats->pkts_per_batch = nb_objs;
+ graph_stats->to_eth_egress += stats.to_eth_egress;
+ graph_stats->to_vwire_egress += stats.to_vwire_egress;
+ for (int i = 0; i < LAI_DROP_RSN_MAX; i++)
+ {
+ graph_stats->drop_reason[i] += stats.drop_reason[i];
+ }
+
+ return nb_objs;
+}
+
+/* Link aware injector node init function */
+static int lai_node_init(const struct rte_graph * graph, struct rte_node * node)
+{
+ LAI_NODE_LAST_NEXT(node->ctx) = LAI_NEXT_EF_EGRESS;
+ return 0;
+}
+
+/* Link aware injector node base */
+static struct rte_node_register lai_node_base = {
+ .process = lai_node_process,
+ .name = "link_aware_injector",
+ .init = lai_node_init,
+ .nb_edges = LAI_NEXT_MAX,
+ .next_nodes =
+ {
+ [LAI_NEXT_PKT_DROP] = "pkt_drop_trap",
+ [LAI_NEXT_EF_EGRESS] = "ef_egress",
+ [LAI_NEXT_VWIRE_EGRESS] = "vwire_egress",
+ },
+};
+
+RTE_NODE_REGISTER(lai_node_base);
+
+cJSON * lai_node_monit_loop(struct sc_main * sc)
+{
+ cJSON * json_root = cJSON_CreateObject();
+ unsigned int nr_graphs = sc->nr_io_thread;
+
+ uint64_t total_pkts[nr_graphs];
+ uint64_t pkts_per_batch[nr_graphs];
+ uint64_t to_eth_egress[nr_graphs];
+ uint64_t to_vwire_egress[nr_graphs];
+ uint64_t drop_reason[LAI_DROP_RSN_MAX][nr_graphs];
+
+ for (uint32_t graph_id = 0; graph_id < nr_graphs; graph_id++)
+ {
+ struct lai_stats * stats = &lai_stats_per_graph[graph_id];
+ if (stats->total_pkts == 0)
+ {
+ total_pkts[graph_id] = 0;
+ pkts_per_batch[graph_id] = 0;
+ to_eth_egress[graph_id] = 0;
+ to_vwire_egress[graph_id] = 0;
+ for (int i = 0; i < LAI_DROP_RSN_MAX; i++)
+ {
+ drop_reason[i][graph_id] = 0;
+ }
+ continue;
+ }
+
+ total_pkts[graph_id] = stats->total_pkts;
+ pkts_per_batch[graph_id] = stats->pkts_per_batch;
+ to_eth_egress[graph_id] = stats->to_eth_egress;
+ to_vwire_egress[graph_id] = stats->to_vwire_egress;
+ for (int i = 0; i < LAI_DROP_RSN_MAX; i++)
+ {
+ drop_reason[i][graph_id] = stats->drop_reason[i];
+ }
+ }
+
+ cJSON * json_total_pkts = create_uint64_array(total_pkts, nr_graphs);
+ cJSON_AddItemToObject(json_root, "lai, total_pkts", json_total_pkts);
+
+ cJSON * json_pkts_per_batch = create_uint64_array(pkts_per_batch, nr_graphs);
+ cJSON_AddItemToObject(json_root, "lai, pkts_per_batch", json_pkts_per_batch);
+
+ cJSON * json_to_eth_egress = create_uint64_array(to_eth_egress, nr_graphs);
+ cJSON_AddItemToObject(json_root, "lai, to_eth_egress", json_to_eth_egress);
+
+ cJSON * json_to_vwire_egress = create_uint64_array(to_vwire_egress, nr_graphs);
+ cJSON_AddItemToObject(json_root, "lai, to_vwire_egress", json_to_vwire_egress);
+ for (int i = 0; i < LAI_DROP_RSN_MAX; i++)
+ {
+ char str_title[MR_STRING_MAX];
+ snprintf(str_title, sizeof(str_title), "lai, %s", lai_drop_rsn_str[i]);
+
+ cJSON * json_drop_reason = create_uint64_array(drop_reason[i], nr_graphs);
+ cJSON_AddItemToObject(json_root, str_title, json_drop_reason);
+ }
+
+ return json_root;
+}
diff --git a/service/src/node_vwire.c b/service/src/node_vwire.c
index 4197085..1b57073 100644
--- a/service/src/node_vwire.c
+++ b/service/src/node_vwire.c
@@ -90,6 +90,12 @@ unsigned int nr_max_vwires_get()
return nr_max_vwires;
}
+/* Get max vwires start sid */
+uint32_t vwire_sid_start_get()
+{
+ return p_vwire_node_main->sid_start;
+}
+
/* Vwire service id check */
int vwire_id_check(uint32_t vwire_id)
{