diff options
| author | songyanchao <[email protected]> | 2022-08-31 02:13:59 +0000 |
|---|---|---|
| committer | songyanchao <[email protected]> | 2022-08-31 02:13:59 +0000 |
| commit | 2a835d0bdf6d8ede385bbd65b416316af2af1e4c (patch) | |
| tree | 0995da0e43aedb65fa3eeca39c371b68138c1916 | |
| parent | 0170accae0b5b32ea22d3595488d94a4ba17dd3e (diff) | |
✨ feat(TSG-11819): 添加新功能 “vlan_flipping_adapter”
添加新功能 “vlan_flipping_adapter”
| -rw-r--r-- | conf/classifier.conf | 28 | ||||
| -rw-r--r-- | conf/etherfabric.conf | 22 | ||||
| -rw-r--r-- | conf/lb.conf | 21 | ||||
| -rw-r--r-- | conf/mrglobal.conf | 9 | ||||
| -rw-r--r-- | service/include/sc_node_common.h | 14 | ||||
| -rw-r--r-- | service/src/core.c | 8 | ||||
| -rw-r--r-- | service/src/monit.c | 4 | ||||
| -rw-r--r-- | service/src/node_eth_ingress.c | 1 | ||||
| -rw-r--r-- | service/src/node_etherfabric.c | 226 | ||||
| -rw-r--r-- | service/src/node_lb.c | 157 | ||||
| -rw-r--r-- | service/src/node_shmdev.c | 441 |
11 files changed, 682 insertions, 249 deletions
diff --git a/conf/classifier.conf b/conf/classifier.conf index 014b39a..01b63ea 100644 --- a/conf/classifier.conf +++ b/conf/classifier.conf @@ -1,30 +1,18 @@ #[classifier_rule] -#rule_num=2 +#rule_num=1 # #[classifier_rule:1] #ip_version=ipv4 -#src_ip_v4=192.168.0.100 -#src_mask_v4=32 -#dst_ip_v4=192.168.0.1 -#dst_mask_v4=32 -#src_port_low=0 -#src_port_high=65535 -#dst_port_low=0 -#dst_port_high=65535 -#proto=tcp -#action=drop -#priority=1 -# -#[classifier_rule:2] -#src_ip=192.168.0.101 -#src_mask=32 -#dst_ip=192.168.0.1 -#dst_mask=32 +#src_ip_v4=172.16.22.0 +#src_mask_v4=0 +#dst_ip_v4=172.16.22.0 +#dst_mask_v4=24 #src_port_low=0 #src_port_high=65535 #dst_port_low=0 #dst_port_high=65535 #proto=tcp +#si=0 #action=nf_steering -#nf_name=ens6f1np1 -#priority=1 +#next_group=0 +#priority=1
\ No newline at end of file diff --git a/conf/etherfabric.conf b/conf/etherfabric.conf index fbd3f8e..f4bbd42 100644 --- a/conf/etherfabric.conf +++ b/conf/etherfabric.conf @@ -1,25 +1,19 @@ #[service_conf] #rule_num=1 - +# #[etherfabric_service:0] #name=etherfabric_ingress_eth0_0 #type=etherfabric #mode=virtual-wire -#listen_ip=10.0.0.1 +#listen_device=ens4f0np0 +#listen_ip=10.254.22.1 #listen_port=4789 - -#[etherfabric_service:1] -#name=etherfabric_ingress_eth1_1 -#type=etherfabric -#mode=tap -#listen_ip=10.0.0.2 -#listen_port=4789 - +# #[link_conf] #rule_num=1 - +# #[etherfabric_link:0] -#etherfabric_link_id=1 +#etherfabric_link_id=26 #virtual_wire_id=100 -#etherfabric_ip=10.10.1.40 -#etherfabric_mac=10:70:fd:03:c0:bd
\ No newline at end of file +#etherfabric_ip=10.10.1.36 +#etherfabric_mac=0a:0a:0a:0a:01:24
\ No newline at end of file diff --git a/conf/lb.conf b/conf/lb.conf index f2e7db6..70191d2 100644 --- a/conf/lb.conf +++ b/conf/lb.conf @@ -1,18 +1,3 @@ -#[group] -#group_num=2 - -#[group:0] -#group_mode=single_mode -#vdev_num=1 - -#[group:0:vdev:0] -#type=normal -#name=ens6f0np0 - -#[group:1] -#group_mode=single_mode -#vdev_num=1 - -#[group:1:vdev:0] -#type=normal -#name=ens6f1np1
\ No newline at end of file +#[load_balance_0] +#mode=balance +#devices=nf_0,normal
\ No newline at end of file diff --git a/conf/mrglobal.conf b/conf/mrglobal.conf index a783a5f..ba08fa8 100644 --- a/conf/mrglobal.conf +++ b/conf/mrglobal.conf @@ -43,4 +43,11 @@ check_spinlock=1 create_mode=3 sz_direct_pktmbuf=4194304 sz_indirect_pktmbuf=8192 -sz_cache=256
\ No newline at end of file +sz_cache=256 + +#[vlan_flipping_adapter] +#enable=1 +#enable_devices=nf_0 +#etherfabric_vlan_range_start=1000 +#etherfabric_vlan_range_end=3047 +#default_si_table_0=nf_0,0
\ No newline at end of file diff --git a/service/include/sc_node_common.h b/service/include/sc_node_common.h index 7e6cf69..2b581fa 100644 --- a/service/include/sc_node_common.h +++ b/service/include/sc_node_common.h @@ -10,6 +10,14 @@ #define MR_NODE_COMMON_ORIGINAL_PKT 1 #endif +#ifndef MR_NODE_COMMON_VLAN_FLIPPING_DEFAULT_ARG_NUM +#define MR_NODE_COMMON_VLAN_FLIPPING_DEFAULT_ARG_NUM 2 +#endif + +#ifndef MR_NODE_COMMON_MAX_SI_ID +#define MR_NODE_COMMON_MAX_SI_ID 1024 +#endif + #ifndef MR_NODE_COMMON_ETHERFABRIC_PKT_OFFSET #define MR_NODE_COMMON_ETHERFABRIC_PKT_OFFSET sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_udp_hdr) + sizeof(struct g_vxlan_hdr) #endif @@ -25,7 +33,8 @@ enum { /* Service Type */ enum { - MR_NODE_COMMON_ETHERFABRIC_SERVICE, + MR_NODE_COMMON_ETHERFABRIC_SERVICE = 0, + MR_NODE_COMMON_MAX_SERVICE, }; /* Ip Version */ @@ -65,8 +74,7 @@ struct pkt_head_info struct etherfabric_service_tag { uint8_t dir; - uint16_t link_index; - uint16_t service_index; + uint16_t fwd_table_index; }; /* Mbuf Private Date */ diff --git a/service/src/core.c b/service/src/core.c index a712c85..245adf4 100644 --- a/service/src/core.c +++ b/service/src/core.c @@ -954,6 +954,7 @@ extern int classifier_init(struct sc_main * sc); extern int lb_init(struct sc_main * sc); extern int etherfabric_init(struct sc_main * sc); extern int bfd_init(struct sc_main * sc); +extern int vlan_flipping_adapter_init(struct sc_main * sc); int main(int argc, char * argv[]) { @@ -1180,6 +1181,13 @@ int main(int argc, char * argv[]) goto quit; } + if (vlan_flipping_adapter_init(sc) != RT_SUCCESS) + { + MR_ERROR("Vlan Flipping Adapter initialization failed. "); + ret = EXIT_FAILURE; + goto quit; + } + sc_config_dump(sc); vdev_dump(sc); sw_fwd_dump(sc); diff --git a/service/src/monit.c b/service/src/monit.c index c09a938..84e5f16 100644 --- a/service/src/monit.c +++ b/service/src/monit.c @@ -269,6 +269,8 @@ extern cJSON * etherfabric_ingress_node_monit_loop(struct sc_main * sc); extern cJSON * etherfabric_egress_node_monit_loop(struct sc_main * sc); extern cJSON * eth_ingress_node_monit_loop(struct sc_main * sc); extern cJSON * bfd_node_monit_loop(struct sc_main * sc); +extern cJSON * shmdev_tx_node_monit_loop(struct sc_main * sc); +extern cJSON * shmdev_rx_node_monit_loop(struct sc_main * sc); static cJSON * monit_root(struct sc_main * sc) { @@ -286,6 +288,8 @@ static cJSON * monit_root(struct sc_main * sc) cJSON_AddItemToObject(j_root, "etherfabric-ingress", etherfabric_ingress_node_monit_loop(sc)); cJSON_AddItemToObject(j_root, "classifier", classifier_node_monit_loop(sc)); cJSON_AddItemToObject(j_root, "lb", lb_node_monit_loop(sc)); + cJSON_AddItemToObject(j_root, "shmdev_tx", shmdev_tx_node_monit_loop(sc)); + cJSON_AddItemToObject(j_root, "shmdev_rx", shmdev_rx_node_monit_loop(sc)); cJSON_AddItemToObject(j_root, "etherfabric-egress", etherfabric_egress_node_monit_loop(sc)); return j_root; } diff --git a/service/src/node_eth_ingress.c b/service/src/node_eth_ingress.c index 1e2df91..6ece1a1 100644 --- a/service/src/node_eth_ingress.c +++ b/service/src/node_eth_ingress.c @@ -1,4 +1,3 @@ -#include "rte_branch_prediction.h" #include <common.h> #include <netinet/in.h> #include <sys/socket.h> diff --git a/service/src/node_etherfabric.c b/service/src/node_etherfabric.c index 2aa2388..2f7bd1b 100644 --- a/service/src/node_etherfabric.c +++ b/service/src/node_etherfabric.c @@ -31,6 +31,10 @@ #define MR_ETHERFABRIC_LAYER_OFFSET_V4 4 #endif +#ifndef MR_ETHERFABRIC_INVALID_SERVICE_INDEX +#define MR_ETHERFABRIC_INVALID_SERVICE_INDEX 65535 +#endif + #define MR_ETHERFABRIC_INGRESS_STAT_ADD(st, graph_id, counter, value) \ do \ { \ @@ -64,19 +68,21 @@ enum { }; /* Service Rule Struct */ -struct etherfabric_service_rule +struct etherfabric_service_config { uint8_t mode; uint16_t listen_port; + uint16_t listen_device_port_id; uint32_t listen_ip_v4; char name[MR_SYMBOL_MAX]; }; /* Link Rule Struct */ -struct etherfabric_link_rule +struct etherfabric_fwd_table { uint16_t etherfabric_link_id; uint16_t virtual_wire_id; + uint16_t etherfabric_service_index; uint32_t etherfabric_ip_v4; struct rte_ether_addr etherfabric_mac_addr; }; @@ -87,8 +93,8 @@ struct etherfabric_management uint16_t es_rule_num; uint16_t el_rule_num; uint16_t port_tx_map[MR_PHYDEV_MAX]; - struct etherfabric_service_rule es_rule_array[MR_ETHERFABRIC_MAX_RULE]; - struct etherfabric_link_rule el_rule_array[MR_ETHERFABRIC_MAX_RULE]; + struct etherfabric_service_config etherfabric_service_array[MR_ETHERFABRIC_MAX_RULE]; + struct etherfabric_fwd_table etherfabric_fwd_array[MR_ETHERFABRIC_MAX_RULE]; }; /* Etherfabric Ingress Stat Struct */ @@ -108,8 +114,8 @@ struct etherfabric_egress_stat_per_lcore { volatile uint64_t total_pkts; volatile uint64_t invalid_pkts; - volatile uint64_t ipv4_no_set_tag; - volatile uint64_t ipv4_set_tag; + volatile uint64_t ipv4_original_pkt; + volatile uint64_t ipv4_new_create_pkt; volatile uint64_t no_suport_pkt; volatile uint64_t link_index_invalid; volatile uint64_t service_index_invalid; @@ -127,6 +133,27 @@ struct node_etherfabric_main static struct node_etherfabric_main * global_etherfabric_main = NULL; extern int eth_ingress_update_ip_listen_num(uint16_t num,uint32_t * listen_ip); +struct etherfabric_fwd_table * etherfabric_get_fwd_item_for_id(uint16_t fwd_table_index) +{ + struct etherfabric_fwd_table * etherfabric_fwd_item = NULL; + etherfabric_fwd_item = &global_etherfabric_main->etherfabric_manage.etherfabric_fwd_array[fwd_table_index]; + return etherfabric_fwd_item; +} + +uint16_t etherfabric_get_service_index_for_fwd_id(uint16_t fwd_table_index) +{ + uint16_t etherfabric_service_index = 0; + etherfabric_service_index = global_etherfabric_main->etherfabric_manage.etherfabric_fwd_array[fwd_table_index].etherfabric_service_index; + return etherfabric_service_index; +} + +uint16_t etherfabric_get_port_index_for_service_id(uint16_t service_index) +{ + uint16_t listen_device_port_id = 0; + listen_device_port_id = global_etherfabric_main->etherfabric_manage.etherfabric_service_array[service_index].listen_device_port_id; + return listen_device_port_id; +} + /************************************* Etherfabric Config **************************************/ /* String to mac */ int etherfabric_string_to_mac(char *s,struct rte_ether_addr * addr ) @@ -170,6 +197,7 @@ int parser_etherfabric_service_conf(struct sc_main * sc, struct etherfabric_mana char rule_str_section[MR_STRING_MAX]; char str_ip_addr[MR_STRING_MAX]; char tx_node_name[MR_SYMBOL_MAX]; + char str_listen_device[MR_STRING_MAX]; char **next_edges = NULL; /* Parsing Service Rule Num */ @@ -178,7 +206,7 @@ int parser_etherfabric_service_conf(struct sc_main * sc, struct etherfabric_mana if (ret < 0) { /* No Config The Etherfabric Service Rule Num */ - MR_INFO("No Config The Etherfabric Rule Num !!!!"); + MR_INFO("No Config The Etherfabric Rule Num.!"); return RT_SUCCESS; } @@ -196,41 +224,41 @@ int parser_etherfabric_service_conf(struct sc_main * sc, struct etherfabric_mana for (int i = 0; i < es_rule_num; i++) { snprintf(rule_str_section, sizeof(rule_str_section), "etherfabric_service:%d", i); - ret = MESA_load_profile_string_nodef(MR_ETHERFABRIC_DEFAULT_CFG, rule_str_section, "name", ðerfabric_manage->es_rule_array[i].name, MR_ETHERFABRIC_INVALID_RULE_STRING_ARG); + ret = MESA_load_profile_string_nodef(MR_ETHERFABRIC_DEFAULT_CFG, rule_str_section, "name", ðerfabric_manage->etherfabric_service_array[i].name, MR_ETHERFABRIC_INVALID_RULE_STRING_ARG); if (ret < 0) { - MR_ERROR("The : %s ,No Config The 'name' !!!",rule_str_section); + MR_ERROR("The : %s ,No Config The 'name'.",rule_str_section); return RT_ERR; } ret = MESA_load_profile_string_nodef(MR_ETHERFABRIC_DEFAULT_CFG, rule_str_section, "type", &str_buf, MR_ETHERFABRIC_INVALID_RULE_STRING_ARG); if (ret < 0) { - MR_ERROR("The : %s ,No Config The 'type' !!!",rule_str_section); + MR_ERROR("The : %s ,No Config The 'type'.",rule_str_section); return RT_ERR; } ret = MESA_load_profile_string_nodef(MR_ETHERFABRIC_DEFAULT_CFG, rule_str_section, "mode", &str_buf, MR_ETHERFABRIC_INVALID_RULE_STRING_ARG); if (ret < 0) { - MR_ERROR("The : %s ,No Config The 'mode' !!!",rule_str_section); + MR_ERROR("The : %s ,No Config The 'mode'.",rule_str_section); return RT_ERR; } /* Save mode */ if (strcmp(str_buf, "virtual-wire") == 0) { - etherfabric_manage->es_rule_array[i].mode = MODE_VIRTUAL_WIRE; + etherfabric_manage->etherfabric_service_array[i].mode = MODE_VIRTUAL_WIRE; } else { - MR_ERROR("The Rule '%s' 'mode' Invalid,Current Only Support 'virtual-wire' !!! ",rule_str_section); + MR_ERROR("The Rule '%s' 'mode' Invalid,Current Only Support 'virtual-wire'. ",rule_str_section); return RT_ERR; } ret = MESA_load_profile_string_nodef(MR_ETHERFABRIC_DEFAULT_CFG, rule_str_section, "listen_ip", &str_ip_addr, MR_ETHERFABRIC_INVALID_RULE_STRING_ARG); if (ret < 0) { - MR_ERROR("The : %s ,No Config The 'listen_ip' !!!",rule_str_section); + MR_ERROR("The : %s ,No Config The 'listen_ip'.",rule_str_section); return RT_ERR; } @@ -242,11 +270,11 @@ int parser_etherfabric_service_conf(struct sc_main * sc, struct etherfabric_mana } /* Save listen_ip */ - etherfabric_manage->es_rule_array[i].listen_ip_v4 = ip_addr.s_addr; + etherfabric_manage->etherfabric_service_array[i].listen_ip_v4 = ip_addr.s_addr; ret = MESA_load_profile_uint_def(MR_ETHERFABRIC_DEFAULT_CFG, rule_str_section, "listen_port", &listen_port, MR_ETHERFABRIC_INVALID_RULE_ARG); if (ret < 0) { - MR_ERROR("The : %s ,No Config The 'listen_port' !!!",rule_str_section); + MR_ERROR("The : %s ,No Config The 'listen_port'.",rule_str_section); return RT_ERR; } @@ -257,7 +285,25 @@ int parser_etherfabric_service_conf(struct sc_main * sc, struct etherfabric_mana } /* Save listen_port */ - etherfabric_manage->es_rule_array[i].listen_port = htons((uint16_t)listen_port); + etherfabric_manage->etherfabric_service_array[i].listen_port = htons((uint16_t)listen_port); + + /* Parsing listen_device */ + ret = MESA_load_profile_string_nodef(MR_ETHERFABRIC_DEFAULT_CFG, rule_str_section, "listen_device", &str_listen_device, MR_ETHERFABRIC_INVALID_RULE_STRING_ARG); + if (ret < 0) + { + MR_ERROR("The : %s ,No Config The 'listen_device'.",rule_str_section); + return RT_ERR; + } + + struct phydev * phydev = phydev_lookup(sc->phydev_main, str_listen_device); + if (phydev == NULL) + { + MR_ERROR("The : %s 'listen_device' Is Invalid: %s",rule_str_section,str_listen_device); + return RT_ERR; + } + + /* Save The Listen Device Port Index */ + etherfabric_manage->etherfabric_service_array[i].listen_device_port_id = phydev->port_id; } /* Create 'Port Id To Tx Node Index' Table */ @@ -298,7 +344,7 @@ int parser_etherfabric_link_conf(struct sc_main * sc, struct etherfabric_managem if (ret < 0) { /* No Config The Etherfabric Link Rule Num */ - MR_INFO("No Config The Etherfabric Link Num !!!!"); + MR_INFO("No Config The Etherfabric Link Num."); return RT_SUCCESS; } @@ -315,26 +361,26 @@ int parser_etherfabric_link_conf(struct sc_main * sc, struct etherfabric_managem /* Parsing All Link Rule Config */ for (int i = 0; i < rule_num; i++) { - struct etherfabric_link_rule * el_rule_item = ðerfabric_manage->el_rule_array[i]; + struct etherfabric_fwd_table * etherfabric_fwd_item = ðerfabric_manage->etherfabric_fwd_array[i]; snprintf(rule_str_section, sizeof(rule_str_section), "etherfabric_link:%d", i); ret = MESA_load_profile_uint_def(MR_ETHERFABRIC_DEFAULT_CFG, rule_str_section, "etherfabric_link_id", ðerfabric_link_id, MR_ETHERFABRIC_INVALID_RULE_ARG); if (ret < 0) { - MR_ERROR("The : %s ,No Config The 'etherfabric_link_id' !!!",rule_str_section); + MR_ERROR("The : %s ,No Config The 'etherfabric_link_id'.",rule_str_section); return RT_ERR; } ret = MESA_load_profile_uint_def(MR_ETHERFABRIC_DEFAULT_CFG, rule_str_section, "virtual_wire_id", &virtual_wire_id, MR_ETHERFABRIC_INVALID_RULE_ARG); if (ret < 0) { - MR_ERROR("The : %s ,No Config The 'virtual_wire_id' !!!",rule_str_section); + MR_ERROR("The : %s ,No Config The 'virtual_wire_id'.",rule_str_section); return RT_ERR; } ret = MESA_load_profile_string_nodef(MR_ETHERFABRIC_DEFAULT_CFG, rule_str_section, "etherfabric_ip", &str_ip_addr, MR_ETHERFABRIC_INVALID_RULE_STRING_ARG); if (ret < 0) { - MR_ERROR("The : %s ,No Config The 'etherfabric_ip' !!!",rule_str_section); + MR_ERROR("The : %s ,No Config The 'etherfabric_ip'.",rule_str_section); return RT_ERR; } @@ -348,19 +394,20 @@ int parser_etherfabric_link_conf(struct sc_main * sc, struct etherfabric_managem ret = MESA_load_profile_string_nodef(MR_ETHERFABRIC_DEFAULT_CFG, rule_str_section, "etherfabric_mac", &str_mac_addr, MR_ETHERFABRIC_INVALID_RULE_STRING_ARG); if (ret < 0) { - MR_ERROR("The : %s ,No Config The 'str_mac_addr' !!!",rule_str_section); + MR_ERROR("The : %s ,No Config The 'str_mac_addr'.",rule_str_section); return RT_ERR; } - if(etherfabric_string_to_mac(str_mac_addr,&el_rule_item->etherfabric_mac_addr) == RT_ERR) + if(etherfabric_string_to_mac(str_mac_addr,ðerfabric_fwd_item->etherfabric_mac_addr) == RT_ERR) { MR_ERROR("The : %s 'etherfabric_mac' Is Invalid: %s",rule_str_section,str_mac_addr); return RT_ERR; } - el_rule_item->etherfabric_link_id = (uint16_t)etherfabric_link_id; - el_rule_item->virtual_wire_id = (uint16_t)virtual_wire_id; - el_rule_item->etherfabric_ip_v4 = ip_addr.s_addr; + etherfabric_fwd_item->etherfabric_link_id = (uint16_t)etherfabric_link_id; + etherfabric_fwd_item->virtual_wire_id = (uint16_t)virtual_wire_id; + etherfabric_fwd_item->etherfabric_service_index = MR_ETHERFABRIC_INVALID_SERVICE_INDEX; + etherfabric_fwd_item->etherfabric_ip_v4 = ip_addr.s_addr; } return RT_SUCCESS; } @@ -376,14 +423,14 @@ void dump_etherfabric_service_config(struct etherfabric_management * etherfabric for (int i = 0; i < etherfabric_manage->es_rule_num; i++) { - struct etherfabric_service_rule * es_rule_item = ðerfabric_manage->es_rule_array[i]; - listen_addr.s_addr = es_rule_item->listen_ip_v4; + struct etherfabric_service_config * etherfabric_service_item = ðerfabric_manage->etherfabric_service_array[i]; + listen_addr.s_addr = etherfabric_service_item->listen_ip_v4; MR_INFO(" "); MR_INFO(" Rule Id : %d",i); - MR_INFO(" Rule Name : %s",es_rule_item->name); + MR_INFO(" Rule Name : %s",etherfabric_service_item->name); - switch (es_rule_item->mode) + switch (etherfabric_service_item->mode) { case MODE_VIRTUAL_WIRE: MR_INFO(" Rule Mode : virtual-wire"); @@ -395,7 +442,7 @@ void dump_etherfabric_service_config(struct etherfabric_management * etherfabric } MR_INFO(" Listen Ip : %s", inet_ntoa(listen_addr)); - MR_INFO(" Listen Port : %u",htons(es_rule_item->listen_port)); + MR_INFO(" Listen Port : %u",htons(etherfabric_service_item->listen_port)); } } @@ -411,14 +458,14 @@ void dump_etherfabric_link_config(struct etherfabric_management * etherfabric_ma for (int i = 0; i < etherfabric_manage->el_rule_num; i++) { - struct etherfabric_link_rule * el_rule_item = ðerfabric_manage->el_rule_array[i]; - etherfabric_ip_v4.s_addr = el_rule_item->etherfabric_ip_v4; - etherfabric_mac_to_string(mac_addr, sizeof(mac_addr), &el_rule_item->etherfabric_mac_addr); + struct etherfabric_fwd_table * etherfabric_fwd_item = ðerfabric_manage->etherfabric_fwd_array[i]; + etherfabric_ip_v4.s_addr = etherfabric_fwd_item->etherfabric_ip_v4; + etherfabric_mac_to_string(mac_addr, sizeof(mac_addr), ðerfabric_fwd_item->etherfabric_mac_addr); MR_INFO(" "); MR_INFO(" Rule Id : %d",i); - MR_INFO(" Link Id : %u",el_rule_item->etherfabric_link_id); - MR_INFO(" Virtual Wire Id : %u",el_rule_item->virtual_wire_id); + MR_INFO(" Link Id : %u",etherfabric_fwd_item->etherfabric_link_id); + MR_INFO(" Virtual Wire Id : %u",etherfabric_fwd_item->virtual_wire_id); MR_INFO(" Etherfabric IP : %s",inet_ntoa(etherfabric_ip_v4)); MR_INFO(" Etherfabric Mac : %s",mac_addr); } @@ -430,6 +477,7 @@ int etherfabric_init(struct sc_main * sc) int ret = RT_SUCCESS; struct etherfabric_management * etherfabric_manage; struct node_etherfabric_main * etherfabric_main = ZMALLOC(sizeof(struct node_etherfabric_main)); + uint32_t listen_ip_v4[MR_ETHERFABRIC_MAX_RULE]; MR_VERIFY_MALLOC(etherfabric_main); global_etherfabric_main = etherfabric_main; @@ -440,19 +488,19 @@ int etherfabric_init(struct sc_main * sc) ret = parser_etherfabric_service_conf(sc,etherfabric_manage); /* Dump The Config And Update Ip Listen Num */ - if (ret != RT_ERR) + if (ret == RT_ERR) { - uint32_t listen_ip_v4[MR_ETHERFABRIC_MAX_RULE]; - - for (int i = 0; i < etherfabric_manage->es_rule_num; i++) - { - listen_ip_v4[i] = etherfabric_manage->es_rule_array[i].listen_ip_v4; - } + return ret; + } - dump_etherfabric_service_config(etherfabric_manage); - eth_ingress_update_ip_listen_num(etherfabric_manage->es_rule_num,listen_ip_v4); + for (int i = 0; i < etherfabric_manage->es_rule_num; i++) + { + listen_ip_v4[i] = etherfabric_manage->etherfabric_service_array[i].listen_ip_v4; } + dump_etherfabric_service_config(etherfabric_manage); + eth_ingress_update_ip_listen_num(etherfabric_manage->es_rule_num,listen_ip_v4); + ret = parser_etherfabric_link_conf(sc,etherfabric_manage); if (ret != RT_ERR) { @@ -464,17 +512,17 @@ int etherfabric_init(struct sc_main * sc) /************************************** Etherfabric Node **************************************/ /* Match Etherfabric Service Rule */ -struct etherfabric_service_rule * match_etherfabric_service_rule(struct etherfabric_management * etherfabric_manage,struct rte_ipv4_hdr * ipv4_hdr,struct rte_udp_hdr * udp_hdr,uint16_t * service_index) +struct etherfabric_service_config * match_etherfabric_service_rule(struct etherfabric_management * etherfabric_manage,struct rte_ipv4_hdr * ipv4_hdr,struct rte_udp_hdr * udp_hdr,uint16_t * service_index) { - struct etherfabric_service_rule * es_rule_item = NULL; + struct etherfabric_service_config * etherfabric_service_item = NULL; for (int i = 0; i < etherfabric_manage->es_rule_num; i++) { - es_rule_item = ðerfabric_manage->es_rule_array[i]; - if ((es_rule_item->listen_port == udp_hdr->dst_port) && (es_rule_item->listen_ip_v4 == ipv4_hdr->dst_addr)) + etherfabric_service_item = ðerfabric_manage->etherfabric_service_array[i]; + if ((etherfabric_service_item->listen_port == udp_hdr->dst_port) && (etherfabric_service_item->listen_ip_v4 == ipv4_hdr->dst_addr)) { *service_index = i; - return es_rule_item; + return etherfabric_service_item; } } @@ -482,22 +530,22 @@ struct etherfabric_service_rule * match_etherfabric_service_rule(struct etherfab } /* Match Etherfabric Link Rule */ -int match_etherfabric_link_rule(struct etherfabric_management * etherfabric_manage,struct rte_ether_hdr * ether_hdr,struct rte_ipv4_hdr * ipv4_hdr,uint16_t * link_index) +struct etherfabric_fwd_table * match_etherfabric_link_rule(struct etherfabric_management * etherfabric_manage,struct rte_ether_hdr * ether_hdr,struct rte_ipv4_hdr * ipv4_hdr,uint16_t * fwd_table_index) { - struct etherfabric_link_rule * el_rule_item = NULL; + struct etherfabric_fwd_table * etherfabric_fwd_item = NULL; for (int i = 0; etherfabric_manage->el_rule_num; i++) { - el_rule_item = ðerfabric_manage->el_rule_array[i]; - if (el_rule_item->etherfabric_ip_v4 == ipv4_hdr->src_addr) + etherfabric_fwd_item = ðerfabric_manage->etherfabric_fwd_array[i]; + if (etherfabric_fwd_item->etherfabric_ip_v4 == ipv4_hdr->src_addr) { - if (memcmp(&el_rule_item->etherfabric_mac_addr, ðer_hdr->src_addr, sizeof(struct rte_ether_addr)) == 0) + if (memcmp(ðerfabric_fwd_item->etherfabric_mac_addr, ðer_hdr->src_addr, sizeof(struct rte_ether_addr)) == 0) { - *link_index = i; - return RT_SUCCESS; + *fwd_table_index = i; + return etherfabric_fwd_item; } } } - return RT_ERR; + return NULL; } /* Etherfabric Node Init Function */ @@ -529,11 +577,14 @@ static __rte_always_inline uint16_t etherfabric_ingress_node_process(struct rte_ /* Single Packet Processing */ while (n_left_from > 0) { + + uint16_t service_index = MR_ETHERFABRIC_INVALID_SERVICE_INDEX; uint32_t head_flg = MR_PARSE_NONE; int ret = RT_SUCCESS; struct pkt_parser * pkt_parser_ptr = NULL; struct etherfabric_service_tag * service_tag_item = NULL; - struct etherfabric_service_rule * es_rule_item = NULL; + struct etherfabric_service_config * etherfabric_service_item = NULL; + struct etherfabric_fwd_table * etherfabric_fwd_item = NULL; struct private_data * private_ctrlzone = NULL; struct pkt_head_info pkt_head_info_item = {}; @@ -571,20 +622,26 @@ static __rte_always_inline uint16_t etherfabric_ingress_node_process(struct rte_ } /* Match Etherfabric Service Rule */ - es_rule_item = match_etherfabric_service_rule(etherfabric_manage,pkt_head_info_item._ipv4_hdr,pkt_head_info_item._udp_hdr,&service_tag_item->service_index); - if (unlikely(es_rule_item == NULL)) + etherfabric_service_item = match_etherfabric_service_rule(etherfabric_manage,pkt_head_info_item._ipv4_hdr,pkt_head_info_item._udp_hdr,&service_index); + if (unlikely(etherfabric_service_item == NULL)) { MR_ETHERFABRIC_INGRESS_STAT_ADD(etherfabric_main,graph_id,no_match_service_pkts,1); goto exception_handling; } /* Match Etherfabric Link Rule */ - if (unlikely(match_etherfabric_link_rule(etherfabric_manage,pkt_head_info_item._ether_hdr,pkt_head_info_item._ipv4_hdr,&service_tag_item->link_index) == RT_ERR)) + etherfabric_fwd_item = match_etherfabric_link_rule(etherfabric_manage,pkt_head_info_item._ether_hdr,pkt_head_info_item._ipv4_hdr,&service_tag_item->fwd_table_index); + if (unlikely(etherfabric_fwd_item == NULL)) { MR_ETHERFABRIC_INGRESS_STAT_ADD(etherfabric_main,graph_id,no_match_link_pkts,1); goto exception_handling; } + if (unlikely(etherfabric_fwd_item->etherfabric_service_index == MR_ETHERFABRIC_INVALID_SERVICE_INDEX)) + { + etherfabric_fwd_item->etherfabric_service_index = service_index; + } + /* Fill Etherfabric Tag,And Save The Etherfabric Tag Ctrlzone,Current Not Support IPv6 */ private_ctrlzone->service_type = MR_NODE_COMMON_ETHERFABRIC_SERVICE; pkt_parser_ptr->layer_offset += MR_ETHERFABRIC_LAYER_OFFSET_V4; @@ -670,21 +727,15 @@ void fill_ipv4_pkt_for_original_packet(struct rte_mbuf *mbuf) } /* Fill Ether IPv4 Udp Vxlan Hdr For The Constructed Packet */ -void fill_ipv4_pkt_for_constructed_packet(struct sc_main * sc,struct etherfabric_service_tag * service_tag_item,struct rte_mbuf *mbuf,uint16_t port_ingress) +void fill_ipv4_pkt_for_constructed_packet(struct sc_main * sc,struct rte_mbuf *mbuf,uint16_t port_ingress,uint8_t dir, + struct etherfabric_fwd_table * etherfabric_fwd_item,struct etherfabric_service_config * etherfabric_service_item) { struct rte_ether_hdr * eth_hdr = NULL; struct rte_ipv4_hdr * ip_hdr = NULL; struct rte_udp_hdr * udp_hdr = NULL; struct g_vxlan_hdr * g_vxlan_hdr = NULL; struct rte_ipv4_hdr * ip_hdr_inner = NULL; - struct node_etherfabric_main * etherfabric_node_main = NULL; - struct etherfabric_service_rule * es_rule_item = NULL; - struct etherfabric_link_rule * el_rule_item = NULL; - struct phydev * dev = phydev_lookup_id(sc->phydev_main,port_ingress); - etherfabric_node_main = sc->etherfabric_node_main; - es_rule_item = ðerfabric_node_main->etherfabric_manage.es_rule_array[service_tag_item->service_index]; - el_rule_item = ðerfabric_node_main->etherfabric_manage.el_rule_array[service_tag_item->link_index]; eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *); ip_hdr = rte_pktmbuf_mtod_offset(mbuf,struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr)); @@ -693,7 +744,7 @@ void fill_ipv4_pkt_for_constructed_packet(struct sc_main * sc,struct etherfabric ip_hdr_inner = rte_pktmbuf_mtod_offset(mbuf,struct rte_ipv4_hdr *, 2*sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_udp_hdr) + sizeof(struct g_vxlan_hdr)); /* Fill eth_hdr */ - rte_ether_addr_copy(&el_rule_item->etherfabric_mac_addr, ð_hdr->dst_addr); + rte_ether_addr_copy(ðerfabric_fwd_item->etherfabric_mac_addr, ð_hdr->dst_addr); rte_ether_addr_copy(&dev->ether_addr, ð_hdr->src_addr); eth_hdr->ether_type = 0x08; @@ -704,8 +755,8 @@ void fill_ipv4_pkt_for_constructed_packet(struct sc_main * sc,struct etherfabric ip_hdr->fragment_offset = 0x0000; ip_hdr->time_to_live = 0x40; ip_hdr->next_proto_id = IPPROTO_UDP; - ip_hdr->src_addr = es_rule_item->listen_ip_v4; - ip_hdr->dst_addr = el_rule_item->etherfabric_ip_v4; + ip_hdr->src_addr = etherfabric_service_item->listen_ip_v4; + ip_hdr->dst_addr = etherfabric_fwd_item->etherfabric_ip_v4; ip_hdr->total_length = ip_hdr_inner->total_length + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_udp_hdr) + sizeof(struct g_vxlan_hdr) + sizeof(struct rte_ether_hdr); ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr); @@ -723,8 +774,8 @@ void fill_ipv4_pkt_for_constructed_packet(struct sc_main * sc,struct etherfabric g_vxlan_hdr->vlan_id_half_high = 0x00; g_vxlan_hdr->link_layer_type = 0x00; g_vxlan_hdr->vlan_id_half_low = 0x00; - g_vxlan_hdr->dir = service_tag_item->dir; - g_vxlan_hdr->link_id = el_rule_item->etherfabric_link_id; + g_vxlan_hdr->dir = dir; + g_vxlan_hdr->link_id = etherfabric_fwd_item->etherfabric_link_id; g_vxlan_hdr->online_test = 0x00; g_vxlan_hdr->r7 = 0x00; g_vxlan_hdr->r6 = 0x00; @@ -768,6 +819,8 @@ static __rte_always_inline uint16_t etherfabric_egress_node_process(struct rte_g struct pkt_parser * pkt_parser_ptr = NULL; struct private_data * private_ctrlzone = NULL; struct etherfabric_service_tag * service_tag_item = NULL; + struct etherfabric_fwd_table * etherfabric_fwd_item = NULL; + struct etherfabric_service_config * etherfabric_service_item = NULL; struct pkt_head_info pkt_head_info_item = {}; mbuf = pkts[0]; @@ -799,27 +852,30 @@ static __rte_always_inline uint16_t etherfabric_egress_node_process(struct rte_g if (likely(private_ctrlzone->original_packet_flag == MR_NODE_COMMON_ORIGINAL_PKT)) { fill_ipv4_pkt_for_original_packet(mbuf); - MR_ETHERFABRIC_EGRESS_STAT_ADD(etherfabric_main,graph_id,ipv4_no_set_tag,1); + MR_ETHERFABRIC_EGRESS_STAT_ADD(etherfabric_main,graph_id,ipv4_original_pkt,1); /* From Port Id Get Next Node Index */ next_node_index = etherfabric_manage->port_tx_map[port_ingress]; goto node_enqueue; } else { - if (unlikely((service_tag_item->link_index >= MR_ETHERFABRIC_MAX_RULE))) + if (unlikely((service_tag_item->fwd_table_index >= MR_ETHERFABRIC_MAX_RULE))) { MR_ETHERFABRIC_EGRESS_STAT_ADD(etherfabric_main,graph_id,link_index_invalid,1); goto exception_handling; } - if (unlikely((service_tag_item->service_index >= MR_ETHERFABRIC_MAX_RULE))) + etherfabric_fwd_item = ðerfabric_main->etherfabric_manage.etherfabric_fwd_array[service_tag_item->fwd_table_index]; + etherfabric_service_item = ðerfabric_main->etherfabric_manage.etherfabric_service_array[etherfabric_fwd_item->etherfabric_service_index]; + + if (unlikely((etherfabric_fwd_item->etherfabric_service_index >= MR_ETHERFABRIC_MAX_RULE))) { MR_ETHERFABRIC_EGRESS_STAT_ADD(etherfabric_main,graph_id,service_index_invalid,1); goto exception_handling; } - fill_ipv4_pkt_for_constructed_packet(sc,service_tag_item,mbuf,port_ingress); - MR_ETHERFABRIC_EGRESS_STAT_ADD(etherfabric_main,graph_id,ipv4_set_tag,1); + fill_ipv4_pkt_for_constructed_packet(sc,mbuf,port_ingress,service_tag_item->dir,etherfabric_fwd_item,etherfabric_service_item); + MR_ETHERFABRIC_EGRESS_STAT_ADD(etherfabric_main,graph_id,ipv4_new_create_pkt,1); /* From Port Id Get Next Node Index */ next_node_index = etherfabric_manage->port_tx_map[port_ingress]; goto node_enqueue; @@ -950,10 +1006,10 @@ cJSON * etherfabric_egress_node_monit_loop(struct sc_main * sc) cJSON_AddNumberToObject(graph_obj, "total_pkts", stats); stats = stat_item->invalid_pkts; cJSON_AddNumberToObject(graph_obj, "invalid_pkts", stats); - stats = stat_item->ipv4_no_set_tag; - cJSON_AddNumberToObject(graph_obj, "ipv4_no_set_tag", stats); - stats = stat_item->ipv4_set_tag; - cJSON_AddNumberToObject(graph_obj, "ipv4_set_tag", stats); + stats = stat_item->ipv4_original_pkt; + cJSON_AddNumberToObject(graph_obj, "ipv4_original_pkt", stats); + stats = stat_item->ipv4_new_create_pkt; + cJSON_AddNumberToObject(graph_obj, "ipv4_new_create_pkt", stats); stats = stat_item->no_suport_pkt; cJSON_AddNumberToObject(graph_obj, "no_suport_pkt", stats); } diff --git a/service/src/node_lb.c b/service/src/node_lb.c index 38b4c04..b8e42db 100644 --- a/service/src/node_lb.c +++ b/service/src/node_lb.c @@ -385,132 +385,80 @@ uint16_t get_lb_item_index_from_group_id(struct lb_management * lb_manage,uint16 /* Parser The Local LB Config */ int parser_local_lb_conf(struct sc_main * sc, struct lb_management * lb_manage) { - uint64_t group_num = 0,vdev_num = 0; - char str_buf[MR_STRING_MAX]; - char group_str_section[MR_STRING_MAX]; - char vdev_str_section[MR_STRING_MAX]; - - /* 1. Parsing Group Num */ - int ret = MESA_load_profile_uint_def(MR_LB_DEFAULT_CFG, "group", "group_num", &group_num, MR_LB_INVALID_RULE_ARG); - - if ((ret < 0) || (group_num == MR_LB_INVALID_RULE_ARG)) - { - /* No Config The LB Group,Returen Error */ - MR_INFO("No Config The LB Group Num !"); - lb_manage->group_num = MR_LB_INVALID_RULE_ARG; - return RT_SUCCESS; - } - - /* 2. Check The LB Group Num */ - if (group_num > MR_LB_MAX_GROUP) - { - MR_ERROR("The LB Group Num: %lu Is Invalid,The Group Num Range From 0 to '%u' ",group_num,MR_LB_MAX_GROUP); - return RT_ERR; - } - - /* 3. Save The Group Num */ - lb_manage->group_num = group_num; - - /* 4. Parsing All Group Config */ - for (int i = 0; i < group_num; i++) + int ret = RT_SUCCESS; + uint64_t group_num = 0; + char str_mode[MR_STRING_MAX]; + char str_section[MR_STRING_MAX]; + char str_devices[MR_STRING_MAX]; + char * str_tokens[MR_TOKENS_MAX]; + struct lb_group * lb_group_item = NULL; + + for (int index = 0; index < MR_LB_MAX_GROUP; index ++) { uint16_t item_id = 0; - struct lb_group * lb_group_item = NULL; + uint64_t vdev_num = 0; - /* Get Free Group Item */ - if (get_free_group_item_id(lb_manage,&item_id) == RT_ERR) + snprintf(str_section, sizeof(str_section), "load_balance_%d", index); + ret = MESA_load_profile_string_nodef(MR_LB_DEFAULT_CFG, str_section, "mode", &str_mode, MR_LB_INVALID_RULE_STRING_ARG); + if (ret < 0) { - MR_ERROR("The : %s ,Dont Have Free Group Item !!!",group_str_section); - return RT_ERR; + continue; } - lb_group_item = &lb_manage->lb_groups[item_id]; - lb_group_item->group_status = GROUP_STATUS_IN_USE; - lb_group_item->group_id = i; - - snprintf(group_str_section, sizeof(group_str_section), "group:%d", i); - ret = MESA_load_profile_string_nodef(MR_LB_DEFAULT_CFG, group_str_section, "group_mode", &str_buf, MR_LB_INVALID_RULE_STRING_ARG); + ret = MESA_load_profile_string_nodef(MR_LB_DEFAULT_CFG, str_section, "devices", str_devices,sizeof(str_devices)); if (ret < 0) { - MR_ERROR("The : %s ,No Config The 'group_mode' !!!",group_str_section); + MR_ERROR("Load Balance Config : %s No Config 'devices' .",str_section); + return RT_ERR; + } + + /* Get Free Group Item */ + if (get_free_group_item_id(lb_manage,&item_id) == RT_ERR) + { + MR_ERROR("Load Balance Config : %s ,Dont Have Free Group Item .",str_section); return RT_ERR; } + lb_group_item = &lb_manage->lb_groups[item_id]; /* Save Mode */ - if (strcmp(str_buf, "balance_mode") == 0) + if (strcmp(str_mode, "balance") == 0) { lb_group_item->group_mode = GROUP_MODE_BALANCE; lb_group_item->dispatch_func = (lb_dispatch_func)load_balance; } else { - MR_ERROR("The Group '%s' 'group_mode' Invalid,Current Only Support 'balance_mode' !!! ",group_str_section); - return RT_ERR; - } - - ret = MESA_load_profile_uint_def(MR_LB_DEFAULT_CFG, group_str_section, "vdev_num", &vdev_num, MR_LB_INVALID_RULE_ARG); - if (ret < 0) - { - MR_ERROR("The Group '%s' No Config 'vdev_num' !!!",group_str_section); + MR_ERROR("Load Balance Config : %s 'mode' Invalid,Current Only Support 'balance' . ",str_section); return RT_ERR; } - /* Check The Dev Num */ - if ((vdev_num == MR_LB_INVALID_RULE_ARG) || (vdev_num > MR_LB_MAX_DEV_FOR_SINGLE_GROUP)) + int nr_str_tokens = rte_strsplit(str_devices, sizeof(str_devices), str_tokens, MR_TOKENS_MAX, ','); + if (nr_str_tokens %2) { - MR_ERROR("The Group '%s' Dev Num: %lu Is Invalid,The Dev Num Range From 1 to '%u' ",group_str_section,vdev_num,MR_LB_MAX_DEV_FOR_SINGLE_GROUP); + MR_ERROR("Load Balance Config : %s 'devices' Invalid Arg Num.",str_section); return RT_ERR; } - /* Save Dev Num */ - lb_group_item->vdev_num = vdev_num; - - /* Parsing All Dev */ - for (int j = 0; j < vdev_num; j++) + for (int i = 0; i < nr_str_tokens; i += 2) { uint32_t count; char **next_edges; char tx_node_name[MR_SYMBOL_MAX]; int vdev_flg = MR_LB_DEV_INVALID; - snprintf(vdev_str_section, sizeof(vdev_str_section), "group:%d:vdev:%d", i,j); - ret = MESA_load_profile_string_nodef(MR_LB_DEFAULT_CFG, vdev_str_section, "type", &str_buf, MR_LB_INVALID_RULE_STRING_ARG); - if (ret < 0) - { - MR_ERROR("The : %s ,No Config The 'type' !!!",vdev_str_section); - return RT_ERR; - } - - /* Save Type */ - if (strcmp(str_buf, "normal") == 0) - { - lb_group_item->vdev_array[j].vdev_type = DEV_TYPE_NORMAL; - } - else - { - MR_ERROR("The '%s' 'type' Invalid,Current Only Support 'normal' !!! ",vdev_str_section); - return RT_ERR; - } - - ret = MESA_load_profile_string_nodef(MR_LB_DEFAULT_CFG, vdev_str_section, "name", &lb_group_item->vdev_array[j].vdevsym, MR_LB_INVALID_RULE_STRING_ARG); - if (ret < 0) - { - MR_ERROR("The %s ,No Config The 'name' !!!",vdev_str_section); - return RT_ERR; - } - + snprintf(lb_group_item->vdev_array[vdev_num].vdevsym, sizeof(lb_group_item->vdev_array[vdev_num].vdevsym), "%s", str_tokens[i]); /* Check The Dev Name */ - snprintf(tx_node_name, sizeof(tx_node_name), "shmdev_tx-%s",lb_group_item->vdev_array[j].vdevsym); + snprintf(tx_node_name, sizeof(tx_node_name), "shmdev_tx-%s",lb_group_item->vdev_array[vdev_num].vdevsym); rte_node_t node_id = rte_node_from_name("lb"); count = rte_node_edge_get(node_id, NULL); next_edges = malloc(count); count = rte_node_edge_get(node_id, next_edges); - for (int ni = 0; ni < count; ni++) + for (int next_edges_index = 0; next_edges_index < count; next_edges_index++) { - if (strncmp(next_edges[ni],tx_node_name,sizeof(tx_node_name)) == 0) + if (strncmp(next_edges[next_edges_index],tx_node_name,sizeof(tx_node_name)) == 0) { - lb_group_item->vdev_array[j].tx_node_index = ni; + lb_group_item->vdev_array[vdev_num].tx_node_index = next_edges_index; vdev_flg = MR_LB_DEV_NEXT_NODE_VALID; break; } @@ -520,23 +468,42 @@ int parser_local_lb_conf(struct sc_main * sc, struct lb_management * lb_manage) if (vdev_flg != MR_LB_DEV_NEXT_NODE_VALID) { - MR_ERROR("The %s ,Not Find Tx Node Index !!!",vdev_str_section); + MR_ERROR("Load Balance Config : %s The %s ,Not Find Tx Node Index .",str_section,lb_group_item->vdev_array[vdev_num].vdevsym); return RT_ERR; } - struct vdev * vdev = vdev_lookup(sc->vdev_main, lb_group_item->vdev_array[j].vdevsym); + struct vdev * vdev = vdev_lookup(sc->vdev_main, lb_group_item->vdev_array[vdev_num].vdevsym); if (vdev == NULL) { - MR_ERROR("The %s ,Dev Name '%s' Is Invalid !!!",vdev_str_section,lb_group_item->vdev_array[j].vdevsym); + MR_ERROR("Load Balance Config : %s ,Dev Name '%s' Is Invalid .",str_section,lb_group_item->vdev_array[vdev_num].vdevsym); return RT_ERR; } /* Save The vdev */ - lb_group_item->vdev_array[j].vdev = vdev; - lb_group_item->vdev_array[j].vdev_flag = DEV_ENABLE; + lb_group_item->vdev_array[vdev_num].vdev = vdev; + lb_group_item->vdev_array[vdev_num].vdev_flag = DEV_ENABLE; + + /* Save Type */ + if (strcmp(str_tokens[i+1], "normal") == 0) + { + lb_group_item->vdev_array[vdev_num].vdev_type = DEV_TYPE_NORMAL; + } + else + { + MR_ERROR("Load Balance Config : %s 'type' Invalid,Current Only Support 'normal' . ",str_section); + return RT_ERR; + } + + vdev_num ++; } + + lb_group_item->group_status = GROUP_STATUS_IN_USE; + lb_group_item->group_id = index; + lb_group_item->vdev_num = vdev_num; + group_num ++; } + lb_manage->group_num = group_num; return RT_SUCCESS; } @@ -1009,7 +976,7 @@ static __rte_always_inline uint16_t lb_node_process(struct rte_graph * graph, st /* Single Packet Processing */ while (n_left_from > 0) { - uint16_t graph_id = 0,group_item_id = MR_LB_GROUP_ITEM_ID_INVALID; + uint16_t group_id = 0,group_item_id = MR_LB_GROUP_ITEM_ID_INVALID; struct private_data * private_ctrlzone = NULL; struct lb_group * lb_group_item = NULL; @@ -1018,10 +985,10 @@ static __rte_always_inline uint16_t lb_node_process(struct rte_graph * graph, st n_left_from -= 1; private_ctrlzone = mrbuf_cz_data(mbuf, 0); - graph_id = private_ctrlzone->lb_group_id; + group_id = private_ctrlzone->lb_group_id; MR_LB_STAT_ADD(lb_main,graph_id,total_pkts,1); - group_item_id = get_lb_item_index_from_group_id(lb_main->lb_manage,graph_id); + group_item_id = get_lb_item_index_from_group_id(lb_main->lb_manage,group_id); if (likely(group_item_id == MR_LB_GROUP_ITEM_ID_INVALID)) { /* Group Id Is Invalid,Sent To Classifier */ diff --git a/service/src/node_shmdev.c b/service/src/node_shmdev.c index 14afd2a..ab471ce 100644 --- a/service/src/node_shmdev.c +++ b/service/src/node_shmdev.c @@ -9,6 +9,54 @@ #include <sc_vdev.h> #include <mrb_define.h> #include <sc_node_common.h> +#include <sys/ucontext.h> +#include <cJSON.h> + +#ifndef MR_VLAN_FLIPPING_ADAPTER_DISABLE +#define MR_VLAN_FLIPPING_ADAPTER_DISABLE 0 +#endif + +#ifndef MR_VLAN_FLIPPING_ADAPTER_ENABLE +#define MR_VLAN_FLIPPING_ADAPTER_ENABLE 1 +#endif + +#ifndef MR_VLAN_FLIPPING_ADAPTER_DEVICE_DISABLE +#define MR_VLAN_FLIPPING_ADAPTER_DEVICE_DISABLE MR_VLAN_FLIPPING_ADAPTER_DISABLE +#endif + +#ifndef MR_VLAN_FLIPPING_ADAPTER_DEVICE_ENABLE +#define MR_VLAN_FLIPPING_ADAPTER_DEVICE_ENABLE MR_VLAN_FLIPPING_ADAPTER_ENABLE +#endif + +#ifndef MR_VLAN_FLIPPING_ADAPTER_SI_TABLE_UNINITIALIZED +#define MR_VLAN_FLIPPING_ADAPTER_SI_TABLE_UNINITIALIZED MR_VLAN_FLIPPING_ADAPTER_DISABLE +#endif + +#ifndef MR_VLAN_FLIPPING_ADAPTER_SI_TABLE_INITIALIZED +#define MR_VLAN_FLIPPING_ADAPTER_SI_TABLE_INITIALIZED MR_VLAN_FLIPPING_ADAPTER_ENABLE +#endif + +#ifndef DEFAULT_ETHERFABRIC_VLAN_RANGE_START +#define DEFAULT_ETHERFABRIC_VLAN_RANGE_START 1000 +#endif + +#ifndef DEFAULT_ETHERFABRIC_VLAN_RANGE_END +#define DEFAULT_ETHERFABRIC_VLAN_RANGE_END 3047 +#endif + +#ifndef DEFAULT_VIRTUAL_WIRE_VLAN_RANGE_START +#define DEFAULT_VIRTUAL_WIRE_VLAN_RANGE_START 4000 +#endif + +#ifndef DEFAULT_VIRTUAL_WIRE_VLAN_RANGE_END +#define DEFAULT_VIRTUAL_WIRE_VLAN_RANGE_END 6047 +#endif + +#define MR_SHMDEV_STAT_ADD(st, graph_id, counter, value) \ +do \ +{ \ + st[graph_id].counter += value; \ +} while(0) \ struct shmdev_rx_node_ctx { @@ -44,20 +92,275 @@ struct shmdev_tx_node_main TAILQ_HEAD(shmdev_tx_node_elem_head, shmdev_tx_node_elem) elems_head; }; +struct default_si_table +{ + uint8_t vdev_enable; + uint8_t init_flg; + uint16_t default_si; +}; + +struct vlan_flipping_adapter +{ + uint8_t enable; + uint16_t etherfabric_vlan_range_start; + uint16_t etherfabric_vlan_range_end; + uint16_t virtual_wire_vlan_range_start; + uint16_t virtual_wire_vlan_range_end; + struct default_si_table default_si_table_array[MR_VDEV_MAX]; +}; + +struct shmdev_stat_per_lcore +{ + volatile uint64_t total_tx_pkts; + volatile uint64_t total_rx_pkts; + volatile uint64_t original_pkt; + volatile uint64_t new_create_pkt; +}; + + struct shmdev_stat_per_lcore shmdev_graph_stat[RTE_MAX_LCORE]; + static struct shmdev_rx_node_main __shmdev_rx_node_main; static struct shmdev_tx_node_main __shmdev_tx_node_main; static struct shmdev_rx_node_main * p_shmdev_rx_node_main = &__shmdev_rx_node_main; static struct shmdev_tx_node_main * p_shmdev_tx_node_main = &__shmdev_tx_node_main; +static struct vlan_flipping_adapter * _global_vlan_flipping_adapter = NULL; static_assert(sizeof(struct shmdev_rx_node_ctx) <= RTE_NODE_CTX_SZ, "shmdev_rx_node_ctx size must smaller than RTE_NODE_CTX_SZ"); static_assert(sizeof(struct shmdev_tx_node_ctx) <= RTE_NODE_CTX_SZ, "shmdev_tx_node_ctx size must smaller than RTE_NODE_CTX_SZ"); +extern uint16_t etherfabric_get_service_index_for_fwd_id(uint16_t fwd_table_index); +extern uint16_t etherfabric_get_port_index_for_service_id(uint16_t service_index); + +/* + * 功能:字符串转uint + */ +static int str2uint(const char *str, unsigned int *val) +{ + unsigned int tmpval; + char *tmp_str=(char *)str; + char check_str[16]={0}; + if(tmp_str==NULL||strlen(tmp_str)<=0||strlen(tmp_str)>11||*tmp_str=='-') + return -1; + tmpval=(unsigned int)strtoul(str,NULL,0); + //tmpval=(unsigned int)atoi(tmp_str); + sprintf(check_str,"%u",tmpval); + if(*str=='+') + tmp_str++; + if(strncasecmp(tmp_str,check_str,strlen(tmp_str))==0) + { + *val=tmpval; + return 0; + } + else + { + return -1; + } +} + +/* Parsing The Vlan Flipping Adapter Config */ +int parser_vlan_flipping_adapter_conf(struct sc_main * sc, struct vlan_flipping_adapter * _vlan_flipping_adapter) +{ + int ret = RT_SUCCESS; + uint32_t default_si = 0; + unsigned int adapter_enable = MR_VLAN_FLIPPING_ADAPTER_DISABLE; + unsigned int etherfabric_vlan_range_start ,etherfabric_vlan_range_end ,virtual_wire_vlan_range_start,virtual_wire_vlan_range_end; + char str_section[MR_STRING_MAX]; + char str_default_si_table[MR_STRING_MAX]; + char str_enable_devices[MR_STRING_MAX]; + struct vdev * vdev = NULL; + struct default_si_table * _default_si_table_item = NULL; + + for (int index = 0; index < MR_VDEV_MAX; index ++) + { + char * str_tokens[MR_TOKENS_MAX]; + snprintf(str_section, sizeof(str_section), "default_si_table_%d", index); + ret = MESA_load_profile_string_nodef(sc->local_cfgfile, "vlan_flipping_adapter", str_section, str_default_si_table,sizeof(str_default_si_table)); + if (ret < 0) + { + continue; + } + + int nr_str_tokens = rte_strsplit(str_default_si_table, sizeof(str_default_si_table), str_tokens, MR_TOKENS_MAX, ','); + if (nr_str_tokens != MR_NODE_COMMON_VLAN_FLIPPING_DEFAULT_ARG_NUM) + { + MR_ERROR("Vlan Flipping Adapter : %s Invalid Arg Num.",str_section); + return RT_ERR; + } + + vdev = vdev_lookup(sc->vdev_main, str_tokens[0]); + if (vdev == NULL) + { + MR_ERROR("Vlan Flipping Adapter : %s Invalid Device Name %s.",str_section,str_tokens[0]); + return RT_ERR; + } + + if(str2uint(str_tokens[1],&default_si)<0) + { + MR_ERROR("Vlan Flipping Adapter : %s Invalid Si %s.",str_section,str_tokens[1]); + return RT_ERR; + } + + if (default_si > MR_NODE_COMMON_MAX_SI_ID) + { + MR_ERROR("Vlan Flipping Adapter : %s Invalid Si %u.",str_section,default_si); + return RT_ERR; + } + + _default_si_table_item = &_vlan_flipping_adapter->default_si_table_array[vdev->port_id]; + if (_default_si_table_item->init_flg == MR_VLAN_FLIPPING_ADAPTER_SI_TABLE_INITIALIZED) + { + MR_ERROR("Vlan Flipping Adapter : %s Repeat Configuration.",str_section); + return RT_ERR; + } + + _default_si_table_item->init_flg = MR_VLAN_FLIPPING_ADAPTER_SI_TABLE_INITIALIZED; + _default_si_table_item->default_si = (uint16_t)default_si; + } + + ret = MESA_load_profile_string_nodef(sc->local_cfgfile, "vlan_flipping_adapter", "enable_devices", str_enable_devices,sizeof(str_enable_devices)); + if (ret >= 0) + { + char * str_devices[MR_TOKENS_MAX]; + int nr_str_tokens = rte_strsplit(str_enable_devices, sizeof(str_enable_devices), str_devices, MR_TOKENS_MAX, ','); + + for (int device_index = 0; device_index < nr_str_tokens; device_index++) + { + vdev = vdev_lookup(sc->vdev_main, str_devices[device_index]); + if (vdev == NULL) + { + MR_ERROR("Vlan Flipping Adapter : 'enable_devices' Invalid Device Name :%s.",str_devices[device_index]); + return RT_ERR; + } + _default_si_table_item = &_vlan_flipping_adapter->default_si_table_array[vdev->port_id]; + if (_default_si_table_item->init_flg != MR_VLAN_FLIPPING_ADAPTER_SI_TABLE_INITIALIZED) + { + MR_ERROR("Vlan Flipping Adapter :'enable_devices' The Device '%s' No Config 'default_si_table'.",str_devices[device_index]); + return RT_ERR; + } + _default_si_table_item->vdev_enable = MR_VLAN_FLIPPING_ADAPTER_DEVICE_ENABLE; + } + } + + ret = MESA_load_profile_uint_def(sc->local_cfgfile, "vlan_flipping_adapter", "enable", &adapter_enable, MR_VLAN_FLIPPING_ADAPTER_DISABLE); + if (ret < 0) + { + _vlan_flipping_adapter->enable = MR_VLAN_FLIPPING_ADAPTER_DISABLE; + } + else + { + _vlan_flipping_adapter->enable = (adapter_enable == MR_VLAN_FLIPPING_ADAPTER_ENABLE) ? MR_VLAN_FLIPPING_ADAPTER_ENABLE : MR_VLAN_FLIPPING_ADAPTER_DISABLE; + } + + ret = MESA_load_profile_uint_def(sc->local_cfgfile, "vlan_flipping_adapter", "etherfabric_vlan_range_start", ðerfabric_vlan_range_start, DEFAULT_ETHERFABRIC_VLAN_RANGE_START); + if (ret < 0) + { + _vlan_flipping_adapter->etherfabric_vlan_range_start = DEFAULT_ETHERFABRIC_VLAN_RANGE_START; + } + else + { + _vlan_flipping_adapter->etherfabric_vlan_range_start = etherfabric_vlan_range_start; + } + + ret = MESA_load_profile_uint_def(sc->local_cfgfile, "vlan_flipping_adapter", "etherfabric_vlan_range_end", ðerfabric_vlan_range_end, DEFAULT_ETHERFABRIC_VLAN_RANGE_END); + if (ret < 0) + { + if (etherfabric_vlan_range_start != DEFAULT_ETHERFABRIC_VLAN_RANGE_START) + { + MR_ERROR("Vlan Flipping Adapter : 'etherfabric_vlan_range_end' No Config."); + return RT_ERR; + } + _vlan_flipping_adapter->etherfabric_vlan_range_end = DEFAULT_ETHERFABRIC_VLAN_RANGE_END; + } + else + { + _vlan_flipping_adapter->etherfabric_vlan_range_end = etherfabric_vlan_range_end; + } + + ret = MESA_load_profile_uint_def(sc->local_cfgfile, "vlan_flipping_adapter", "virtual_wire_vlan_range_start", &virtual_wire_vlan_range_start, DEFAULT_VIRTUAL_WIRE_VLAN_RANGE_START); + if (ret < 0) + { + _vlan_flipping_adapter->virtual_wire_vlan_range_start = DEFAULT_VIRTUAL_WIRE_VLAN_RANGE_START; + } + else + { + _vlan_flipping_adapter->virtual_wire_vlan_range_start = virtual_wire_vlan_range_start; + } + + ret = MESA_load_profile_uint_def(sc->local_cfgfile, "vlan_flipping_adapter", "virtual_wire_vlan_range_end", &virtual_wire_vlan_range_end, DEFAULT_VIRTUAL_WIRE_VLAN_RANGE_END); + if (ret < 0) + { + if (virtual_wire_vlan_range_start != DEFAULT_VIRTUAL_WIRE_VLAN_RANGE_START) + { + MR_ERROR("Vlan Flipping Adapter : 'virtual_wire_vlan_range_end' No Config."); + return RT_ERR; + } + _vlan_flipping_adapter->virtual_wire_vlan_range_end = DEFAULT_VIRTUAL_WIRE_VLAN_RANGE_END; + } + else + { + _vlan_flipping_adapter->virtual_wire_vlan_range_end = virtual_wire_vlan_range_end; + } + return RT_SUCCESS; +} + +int vlan_flipping_adapter_init(struct sc_main * sc) +{ + int ret = RT_SUCCESS; + struct vlan_flipping_adapter * _vlan_flipping_adapter = ZMALLOC(sizeof(struct vlan_flipping_adapter)); + MR_VERIFY_MALLOC(_vlan_flipping_adapter); + + _global_vlan_flipping_adapter = _vlan_flipping_adapter; + ret = parser_vlan_flipping_adapter_conf(sc,_vlan_flipping_adapter); + return ret; +} + +uint16_t vlan_flipping_adapter_encode(uint8_t dir,uint16_t fwd_table_index,uint16_t vlan_range_start) +{ + uint16_t vlan_id = 0 ; + + vlan_id = ((fwd_table_index * 2) + dir + vlan_range_start); + return vlan_id; +} + +void etherfabric_vlan_id_decode(struct private_data * private_ctrlzone,uint16_t vlan_id,struct default_si_table * _default_si_table_item) +{ + uint8_t dir = 0, service_type = MR_NODE_COMMON_MAX_SERVICE; + uint16_t fwd_table_index = 0, service_index = 0,vlan_range_start = 0,port_ingress = 0; + + if ((vlan_id >= _global_vlan_flipping_adapter->etherfabric_vlan_range_start) && (vlan_id <= _global_vlan_flipping_adapter->etherfabric_vlan_range_end)) + { + vlan_range_start = _global_vlan_flipping_adapter->etherfabric_vlan_range_start; + service_type = MR_NODE_COMMON_ETHERFABRIC_SERVICE; + } + + dir = (vlan_id - vlan_range_start) % 2; + fwd_table_index =((vlan_id - vlan_range_start) - (vlan_id - vlan_range_start) % 2) / 2; + + switch (service_type) + { + case MR_NODE_COMMON_ETHERFABRIC_SERVICE: + { + service_index = etherfabric_get_service_index_for_fwd_id(fwd_table_index); + port_ingress = etherfabric_get_port_index_for_service_id(service_index); + private_ctrlzone->tag.etherfabric.fwd_table_index = fwd_table_index; + private_ctrlzone->tag.etherfabric.dir = dir; + } + break; + } + + private_ctrlzone->service_type = service_type; + private_ctrlzone->port_ingress = port_ingress; + private_ctrlzone->si = _default_si_table_item->default_si + 1; +} + static __rte_always_inline uint16_t shmdev_rx_node_process(struct rte_graph * graph, struct rte_node * node, void ** objs, uint16_t cnt) { struct shmdev_rx_node_ctx * ctx = (struct shmdev_rx_node_ctx *)node->ctx; + struct default_si_table * _default_si_table_item = &_global_vlan_flipping_adapter->default_si_table_array[ctx->vdev->port_id]; + struct rte_mbuf ** mbufs = (struct rte_mbuf **)node->objs; RTE_SET_USED(objs); RTE_SET_USED(cnt); @@ -70,24 +373,29 @@ static __rte_always_inline uint16_t shmdev_rx_node_process(struct rte_graph * gr return 0; } - struct rte_mbuf ** mbufs = (struct rte_mbuf **)node->objs; + MR_SHMDEV_STAT_ADD(shmdev_graph_stat,graph->id,total_rx_pkts,rx_nr_mbufs); for (int i = 0; i < rx_nr_mbufs; i++) { - struct private_data * private_ctrlzone = mrbuf_cz_data(mbufs[i], 0); - if (unlikely(private_ctrlzone->original_packet_flag != MR_NODE_COMMON_ORIGINAL_PKT)) { struct pkt_parser * pkt_parser_ptr = &private_ctrlzone->pkt_parser; - private_ctrlzone->lb_group_id = 65535; - private_ctrlzone->si = 0; - pkt_parser_init(pkt_parser_ptr, LAYER_TYPE_ALL, MR_PKT_PARSE_RESULT_MAX); complex_parser_ether(pkt_parser_ptr, rte_pktmbuf_mtod(mbufs[i],const char *)); - } - mbufs[i]->ol_flags = 0; - mbufs[i]->vlan_tci = 0; + if ((_global_vlan_flipping_adapter->enable == MR_VLAN_FLIPPING_ADAPTER_ENABLE) && (_default_si_table_item->vdev_enable == MR_VLAN_FLIPPING_ADAPTER_DEVICE_ENABLE)) + { + uint16_t vlan_id = mbufs[i]->vlan_tci; + etherfabric_vlan_id_decode(private_ctrlzone,vlan_id,_default_si_table_item); + mbufs[i]->ol_flags = 0; + mbufs[i]->vlan_tci = 0; + } + MR_SHMDEV_STAT_ADD(shmdev_graph_stat,graph->id,new_create_pkt,1); + } + else + { + MR_SHMDEV_STAT_ADD(shmdev_graph_stat,graph->id,original_pkt,1); + } } node->idx = rx_nr_mbufs; @@ -100,13 +408,35 @@ static __rte_always_inline uint16_t shmdev_tx_node_process(struct rte_graph * gr { struct shmdev_tx_node_ctx * ctx = (struct shmdev_tx_node_ctx *)node->ctx; struct rte_mbuf ** mbufs = (struct rte_mbuf **)objs; + struct default_si_table * _default_si_table_item = &_global_vlan_flipping_adapter->default_si_table_array[ctx->vdev->port_id]; - for (int i = 0; i < cnt; i++) + if ((_global_vlan_flipping_adapter->enable == MR_VLAN_FLIPPING_ADAPTER_ENABLE) && (_default_si_table_item->vdev_enable == MR_VLAN_FLIPPING_ADAPTER_DEVICE_ENABLE)) { - mbufs[i]->ol_flags = PKT_RX_VLAN; - mbufs[i]->vlan_tci = 1000; + uint8_t dir = 0; + uint16_t fwd_table_index = 0; + uint16_t vlan_id = 0, vlan_range_start = 0; + + for (int i = 0; i < cnt; i++) + { + struct private_data * private_ctrlzone = mrbuf_cz_data(mbufs[i], 0); + switch (private_ctrlzone->service_type) + { + case MR_NODE_COMMON_ETHERFABRIC_SERVICE: + { + fwd_table_index = private_ctrlzone->tag.etherfabric.fwd_table_index; + dir = private_ctrlzone->tag.etherfabric.dir; + vlan_range_start = _global_vlan_flipping_adapter->etherfabric_vlan_range_start; + } + break; + } + + vlan_id = vlan_flipping_adapter_encode(dir,fwd_table_index,vlan_range_start); + mbufs[i]->ol_flags = PKT_RX_VLAN; + mbufs[i]->vlan_tci = vlan_id; + } } + MR_SHMDEV_STAT_ADD(shmdev_graph_stat,graph->id,total_tx_pkts,cnt); vdev_dispatch(ctx->vdev, graph->id, mbufs, cnt, 0); return cnt; } @@ -228,4 +558,91 @@ int node_manager_shmdev_init(struct sc_main * sc, struct node_manager_main * nod int node_manager_shmdev_deinit(struct node_manager_main * node_mgr_main) { return 0; +} + +/************************************** Shmdev Statistics **************************************/ +cJSON * shmdev_tx_node_monit_loop(struct sc_main * sc) +{ + uint32_t graph_id = 0,graph_num = 0; + cJSON * json_root = NULL,* graph_obj = NULL; + unsigned int nr_io_thread = sc->nr_io_thread; + + json_root = cJSON_CreateObject(); + + for (graph_id = 0; graph_id < nr_io_thread; graph_id++) + { + char graph_index[MR_STRING_MAX]; + uint64_t stats = 0; + graph_obj = cJSON_CreateObject(); + + struct shmdev_stat_per_lcore * stat_item = &shmdev_graph_stat[graph_id]; + + stats = stat_item->total_tx_pkts; + + if (stats > 0) + { + cJSON_AddNumberToObject(graph_obj, "total_tx_pkts", stats); + } + else + { + cJSON_Delete(graph_obj); + continue; + } + + cJSON_AddNumberToObject(graph_obj, "graph_id", graph_id); + + sprintf(graph_index,"graph-%u",graph_num); + cJSON_AddItemToObject(json_root,graph_index,graph_obj); + + graph_num ++; + } + + cJSON_AddNumberToObject(json_root, "total_graph_num", graph_num); + + return json_root; +} + +cJSON * shmdev_rx_node_monit_loop(struct sc_main * sc) +{ + uint32_t graph_id = 0,graph_num = 0; + cJSON * json_root = NULL,* graph_obj = NULL; + unsigned int nr_io_thread = sc->nr_io_thread; + + json_root = cJSON_CreateObject(); + + for (graph_id = 0; graph_id < nr_io_thread; graph_id++) + { + char graph_index[MR_STRING_MAX]; + uint64_t stats = 0; + graph_obj = cJSON_CreateObject(); + + struct shmdev_stat_per_lcore * stat_item = &shmdev_graph_stat[graph_id]; + + stats = stat_item->total_rx_pkts; + + if (stats > 0) + { + cJSON_AddNumberToObject(graph_obj, "total_rx_pkts", stats); + stats = stat_item->original_pkt; + cJSON_AddNumberToObject(graph_obj, "original_pkt", stats); + stats = stat_item->new_create_pkt; + cJSON_AddNumberToObject(graph_obj, "new_create_pkt", stats); + } + else + { + cJSON_Delete(graph_obj); + continue; + } + + cJSON_AddNumberToObject(graph_obj, "graph_id", graph_id); + + sprintf(graph_index,"graph-%u",graph_num); + cJSON_AddItemToObject(json_root,graph_index,graph_obj); + + graph_num ++; + } + + cJSON_AddNumberToObject(json_root, "total_graph_num", graph_num); + + return json_root; }
\ No newline at end of file |
