From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail04.ics.ntt-tx.co.jp (mail05.ics.ntt-tx.co.jp [210.232.35.69]) by dpdk.org (Postfix) with ESMTP id 1C05D2B9A for ; Thu, 28 Dec 2017 05:56:11 +0100 (CET) Received: from gwchk03.silk.ntt-tx.co.jp (gwchk03.silk.ntt-tx.co.jp [10.107.0.111]) by mail04.ics.ntt-tx.co.jp (unknown) with ESMTP id vBS4uAo5025209 for unknown; Thu, 28 Dec 2017 13:56:10 +0900 Received: (from root@localhost) by gwchk03.silk.ntt-tx.co.jp (unknown) id vBS4u9S2027453 for unknown; Thu, 28 Dec 2017 13:56:09 +0900 Received: from gwchk.silk.ntt-tx.co.jp [10.107.0.110] by gwchk03.silk.ntt-tx.co.jp with ESMTP id PAA27443; Thu, 28 Dec 2017 13:56:08 +0900 Received: from imss03.silk.ntt-tx.co.jp (localhost [127.0.0.1]) by imss03.silk.ntt-tx.co.jp (unknown) with ESMTP id vBS4u8OV011190 for unknown; Thu, 28 Dec 2017 13:56:08 +0900 Received: from mgate01.silk.ntt-tx.co.jp (smtp02.silk.ntt-tx.co.jp [10.107.0.37]) by imss03.silk.ntt-tx.co.jp (unknown) with ESMTP id vBS4u8tM011161 for unknown; Thu, 28 Dec 2017 13:56:08 +0900 Message-Id: <201712280456.vBS4u8tM011161@imss03.silk.ntt-tx.co.jp> Received: from localhost by mgate01.silk.ntt-tx.co.jp (unknown) id vBS4u4bS025622 ; Thu, 28 Dec 2017 13:56:07 +0900 From: x-fn-spp@sl.ntt-tx.co.jp To: spp@dpdk.org Date: Thu, 28 Dec 2017 13:56:01 +0900 X-Mailer: git-send-email 1.9.1 In-Reply-To: <4aae78ff-3b6c-cdfe-a8b7-24ec08b73935@lab.ntt.co.jp> References: <4aae78ff-3b6c-cdfe-a8b7-24ec08b73935@lab.ntt.co.jp> X-TM-AS-MML: No Subject: [spp] [PATCH 54/57] spp_vf: support new command X-BeenThere: spp@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Soft Patch Panel List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 Dec 2017 04:56:14 -0000 From: Hiroyuki Nakamura Newly support 'component' command. * 'component' command provides start/stop function for component such as forwarder, classifier etc. * Support naming function for 'component' and its name can be used for later command operations. * Support core selection function for 'component'. Newly support 'port' command. * 'port' command provides function for creating port such as ring, vhost, phy. * Also provides function for assigning port to 'component'. This can be done by specifying the name of 'component'. * 'port' command initializes the port to be used for the first time. Newly support 'exit' command. * 'exit' command provides stop function for spp_vf process. And modify 'classifier_table' command. * Add operation types. (add/del) * Add wait procedure for initialization to complete. Also, to support above commands, the structure of management data has been changed. Signed-off-by: Kentaro Watanabe Signed-off-by: Yasufum Ogawa --- src/spp_vf.py | 6 +- src/vf/Makefile | 2 +- src/vf/classifier_mac.c | 251 ++++++---- src/vf/classifier_mac.h | 14 +- src/vf/command_dec.c | 400 +++++++++++++-- src/vf/command_dec.h | 52 +- src/vf/command_proc.c | 36 +- src/vf/command_proc.h | 3 +- src/vf/spp_config.c | 26 +- src/vf/spp_forward.c | 199 +++++--- src/vf/spp_forward.h | 9 +- src/vf/spp_vf.c | 1269 ++++++++++++++++++++++++++++++----------------- src/vf/spp_vf.h | 199 +++++++- 13 files changed, 1718 insertions(+), 748 deletions(-) diff --git a/src/spp_vf.py b/src/spp_vf.py index 40310db..505a142 100755 --- a/src/spp_vf.py +++ b/src/spp_vf.py @@ -60,7 +60,7 @@ def connectionthread(name, client_id, conn, m2s, s2m): #Receiving from secondary try: - data = conn.recv(1024) # 1024 stands for bytes of data to be received + data = conn.recv(2048) # 2048 stands for bytes of data to be received if data: s2m.put("recv:" + str(conn.fileno()) + ":" + "{" + data + "}") else: @@ -212,7 +212,7 @@ def primarythread(sock, main2primary, primary2main): #Receiving from primary try: - data = conn.recv(1024) # 1024 stands for bytes of data to be received + data = conn.recv(2048) # 2048 stands for bytes of data to be received if data: primary2main.put("recv:" + str(addr) + ":" + "{" + data + "}") else: @@ -228,8 +228,6 @@ def primarythread(sock, main2primary, primary2main): def close_all_secondary(): """Exit all secondary processes""" - return; - global SECONDARY_COUNT tmp_list = [] diff --git a/src/vf/Makefile b/src/vf/Makefile index 1284733..a2ac128 100644 --- a/src/vf/Makefile +++ b/src/vf/Makefile @@ -40,7 +40,7 @@ include $(RTE_SDK)/mk/rte.vars.mk APP = spp_vf # all source are stored in SRCS-y -SRCS-y := spp_vf.c spp_config.c classifier_mac.c spp_forward.c string_buffer.c command_conn.c command_dec.c command_proc.c ringlatencystats.c ../shared/common.c +SRCS-y := spp_vf.c classifier_mac.c spp_forward.c string_buffer.c command_conn.c command_dec.c command_proc.c ringlatencystats.c ../shared/common.c CFLAGS += $(WERROR_FLAGS) -O3 CFLAGS += -I$(SRCDIR)/../shared diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c index e2aa715..937a8c0 100644 --- a/src/vf/classifier_mac.c +++ b/src/vf/classifier_mac.c @@ -40,7 +40,7 @@ /* interval that wait untill change update index micro second */ -#define CHANGE_UPDATE_INDEX_WAIT_INTERVAL 10 +#define CHANGE_UPDATE_INDEX_WAIT_INTERVAL SPP_CHANGE_UPDATE_INTERVAL /* interval that transmit burst packet, if buffer is not filled. nano second */ @@ -65,12 +65,12 @@ static const size_t ETHER_ADDR_STR_BUF_SZ = /* classified data (destination port, target packets, etc) */ struct classified_data { - enum port_type if_type; - int if_no; - int if_no_global; - uint8_t tx_port; - uint16_t num_pkt; - struct rte_mbuf *pkts[MAX_PKT_BURST]; + enum port_type if_type; /* interface type (see "enum port_type") */ + int if_no; /* index of ports handled by classifier */ + int if_no_global; /* interface number */ + uint8_t port; /* port number used by dpdk */ + uint16_t num_pkt; /* the number of packets in pkts[] */ + struct rte_mbuf *pkts[MAX_PKT_BURST]; /* packet array to be classified */ }; /* classifier information */ @@ -79,6 +79,9 @@ struct classifier_mac_info { int num_active_classified; int active_classifieds[RTE_MAX_ETHPORTS]; int default_classified; + int n_classified_data_tx; + struct classified_data classified_data_rx; + struct classified_data classified_data_tx[RTE_MAX_ETHPORTS]; }; /* classifier management information */ @@ -86,7 +89,6 @@ struct classifier_mac_mng_info { struct classifier_mac_info info[NUM_CLASSIFIER_MAC_INFO]; volatile int ref_index; volatile int upd_index; - struct classified_data classified_data[RTE_MAX_ETHPORTS]; }; /* classifier information per lcore */ @@ -109,20 +111,40 @@ is_used_mng_info(const struct classifier_mac_mng_info *mng_info) /* initialize classifier information. */ static int init_classifier_info(struct classifier_mac_info *classifier_info, - const struct spp_core_info *core_info) + const struct spp_component_info *component_info) { int ret = -1; int i; struct rte_hash **classifier_table = &classifier_info->classifier_table; struct ether_addr eth_addr; char mac_addr_str[ETHER_ADDR_STR_BUF_SZ]; + struct classified_data *classified_data_rx = &classifier_info->classified_data_rx; + struct classified_data *classified_data_tx = classifier_info->classified_data_tx; + struct spp_port_info *tx_port = NULL; rte_hash_reset(*classifier_table); classifier_info->num_active_classified = 0; classifier_info->default_classified = -1; + classifier_info->n_classified_data_tx = component_info->num_tx_port; + if (component_info->num_rx_port != 0) { + classified_data_rx->if_type = component_info->rx_ports[0]->if_type; + classified_data_rx->if_no = 0; + classified_data_rx->if_no_global = component_info->rx_ports[0]->if_no; + classified_data_rx->port = component_info->rx_ports[0]->dpdk_port; + classified_data_rx->num_pkt = 0; + } + + for (i = 0; i < component_info->num_tx_port; i++) { + tx_port = component_info->tx_ports[i]; - for (i = 0; i < core_info->num_tx_port; i++) { - if (core_info->tx_ports[i].mac_addr == 0) { + /* store ports information */ + classified_data_tx[i].if_type = tx_port->if_type; + classified_data_tx[i].if_no = i; + classified_data_tx[i].if_no_global = tx_port->if_no; + classified_data_tx[i].port = tx_port->dpdk_port; + classified_data_tx[i].num_pkt = 0; + + if (component_info->tx_ports[i]->mac_addr == 0) { continue; } @@ -131,19 +153,19 @@ init_classifier_info(struct classifier_mac_info *classifier_info, num_active_classified++] = i; /* store default classified */ - if (unlikely(core_info->tx_ports[i].mac_addr == - SPP_CONFIG_DEFAULT_CLASSIFIED_DMY_ADDR)) { + if (unlikely(tx_port->mac_addr == + SPP_DEFAULT_CLASSIFIED_DMY_ADDR)) { classifier_info->default_classified = i; RTE_LOG(INFO, SPP_CLASSIFIER_MAC, "default classified. " "if_type=%d, if_no=%d, dpdk_port=%d\n", - core_info->tx_ports[i].if_type, - core_info->tx_ports[i].if_no, - core_info->tx_ports[i].dpdk_port); + tx_port->if_type, + tx_port->if_no, + tx_port->dpdk_port); continue; } /* add entry to classifier mac table */ - rte_memcpy(ð_addr, &core_info->tx_ports[i].mac_addr, ETHER_ADDR_LEN); + rte_memcpy(ð_addr, &tx_port->mac_addr, ETHER_ADDR_LEN); ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð_addr); ret = rte_hash_add_key_data(*classifier_table, @@ -160,9 +182,9 @@ init_classifier_info(struct classifier_mac_info *classifier_info, RTE_LOG(INFO, SPP_CLASSIFIER_MAC, "Add entry to classifier mac table. " "mac_addr=%s, if_type=%d, if_no=%d, dpdk_port=%d\n", mac_addr_str, - core_info->tx_ports[i].if_type, - core_info->tx_ports[i].if_no, - core_info->tx_ports[i].dpdk_port); + tx_port->if_type, + tx_port->if_no, + tx_port->dpdk_port); } return 0; @@ -170,19 +192,25 @@ init_classifier_info(struct classifier_mac_info *classifier_info, /* initialize classifier. */ static int -init_classifier(const struct spp_core_info *core_info, - struct classifier_mac_mng_info *classifier_mng_info, - struct classified_data *classified_data) +init_classifier(struct classifier_mac_mng_info *classifier_mng_info) { int ret = -1; int i; char hash_table_name[HASH_TABLE_NAME_BUF_SZ]; struct rte_hash **classifier_mac_table = NULL; + struct spp_component_info component_info; memset(classifier_mng_info, 0, sizeof(struct classifier_mac_mng_info)); + /* + * Set the same value for "ref_index" and "upd_index" + * so that it will not be changed from others during initialization, + * and update "upd_index" after initialization is completed. + * Therefore, this setting is consciously described. + */ classifier_mng_info->ref_index = 0; - classifier_mng_info->upd_index = classifier_mng_info->ref_index + 1; + classifier_mng_info->upd_index = 0; + memset(&component_info, 0x00, sizeof(component_info)); #ifdef RTE_MACHINE_CPUFLAG_SSE4_2 RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, "Enabled SSE4.2. use crc hash.\n"); @@ -222,21 +250,15 @@ init_classifier(const struct spp_core_info *core_info, /* populate the classifier information at reference */ ret = init_classifier_info(&classifier_mng_info-> - info[classifier_mng_info->ref_index], core_info); + info[classifier_mng_info->ref_index], &component_info); if (unlikely(ret != 0)) { RTE_LOG(ERR, SPP_CLASSIFIER_MAC, "Cannot initialize classifer mac table. ret=%d\n", ret); return -1; } - /* store ports information */ - for (i = 0; i < core_info->num_tx_port; i++) { - classified_data[i].if_type = core_info->tx_ports[i].if_type; - classified_data[i].if_no = i; - classified_data[i].if_no_global = core_info->tx_ports[i].if_no; - classified_data[i].tx_port = core_info->tx_ports[i].dpdk_port; - classified_data[i].num_pkt = 0; - } + /* updating side can be set by completion of initialization. */ + classifier_mng_info->upd_index = classifier_mng_info->ref_index + 1; return 0; } @@ -270,7 +292,7 @@ transmit_packet(struct classified_data *classified_data) #endif /* transmit packets */ - n_tx = rte_eth_tx_burst(classified_data->tx_port, 0, + n_tx = rte_eth_tx_burst(classified_data->port, 0, classified_data->pkts, classified_data->num_pkt); /* free cannnot transmit packets */ @@ -279,12 +301,32 @@ transmit_packet(struct classified_data *classified_data) rte_pktmbuf_free(classified_data->pkts[i]); RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, "drop packets(tx). num=%hu, dpdk_port=%hhu\n", - classified_data->num_pkt - n_tx, classified_data->tx_port); + classified_data->num_pkt - n_tx, classified_data->port); } classified_data->num_pkt = 0; } +/* transmit packet to one destination. */ +static inline void +transmit_all_packet(struct classifier_mac_info *classifier_info) +{ + int i; + struct classified_data *classified_data_tx = classifier_info->classified_data_tx; + + for (i = 0; i < classifier_info->n_classified_data_tx; i++) { + if (unlikely(classified_data_tx[i].num_pkt != 0)) { + RTE_LOG(INFO, SPP_CLASSIFIER_MAC, + "transimit all packets (drain). " + "index=%d, " + "num_pkt=%hu\n", + i, + classified_data_tx[i].num_pkt); + transmit_packet(&classified_data_tx[i]); + } + } +} + /* set mbuf pointer to tx buffer and transmit packet, if buffer is filled */ static inline void @@ -300,7 +342,7 @@ push_packet(struct rte_mbuf *pkt, struct classified_data *classified_data) classified_data->if_type, classified_data->if_no_global, classified_data->if_no, - classified_data->tx_port, + classified_data->port, classified_data->num_pkt); transmit_packet(classified_data); } @@ -383,13 +425,18 @@ classify_packet(struct rte_mbuf **rx_pkts, uint16_t n_rx, /* change update index at classifier management information */ static inline void -change_update_index(struct classifier_mac_mng_info *classifier_mng_info, unsigned int lcore_id) +change_update_index(struct classifier_mac_mng_info *classifier_mng_info, int id) { if (unlikely(classifier_mng_info->ref_index == classifier_mng_info->upd_index)) { + + /* Transmit all packets for switching the using data. */ + transmit_all_packet(classifier_mng_info->info + + classifier_mng_info->ref_index); + RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, - "Core[%u] Change update index.\n", lcore_id); - classifier_mng_info->upd_index = + "Core[%u] Change update index.\n", id); + classifier_mng_info->ref_index = (classifier_mng_info->upd_index + 1) % NUM_CLASSIFIER_MAC_INFO; } @@ -406,22 +453,26 @@ spp_classifier_mac_init(void) /* classifier(mac address) update component info. */ int -spp_classifier_mac_update(struct spp_core_info *core_info) +spp_classifier_mac_update(struct spp_component_info *component_info) { int ret = -1; - unsigned int lcore_id = core_info->lcore_id; - + int id = component_info->component_id; struct classifier_mac_mng_info *classifier_mng_info = - g_classifier_mng_info + lcore_id; + g_classifier_mng_info + id; - struct classifier_mac_info *classifier_info = - classifier_mng_info->info + classifier_mng_info->upd_index; + struct classifier_mac_info *classifier_info = NULL; RTE_LOG(INFO, SPP_CLASSIFIER_MAC, - "Core[%u] Start update component.\n", lcore_id); + "Component[%u] Start update component.\n", id); + + /* wait until no longer access the new update side */ + while(likely(classifier_mng_info->ref_index == classifier_mng_info->upd_index)) + rte_delay_us_block(CHANGE_UPDATE_INDEX_WAIT_INTERVAL); + + classifier_info = classifier_mng_info->info + classifier_mng_info->upd_index; /* initialize update side classifier information */ - ret = init_classifier_info(classifier_info, core_info); + ret = init_classifier_info(classifier_info, component_info); if (unlikely(ret != 0)) { RTE_LOG(ERR, SPP_CLASSIFIER_MAC, "Cannot update classifer mac. ret=%d\n", ret); @@ -429,105 +480,96 @@ spp_classifier_mac_update(struct spp_core_info *core_info) } /* change index of reference side */ - classifier_mng_info->ref_index = classifier_mng_info->upd_index; + classifier_mng_info->upd_index = classifier_mng_info->ref_index; /* wait until no longer access the new update side */ while(likely(classifier_mng_info->ref_index == classifier_mng_info->upd_index)) rte_delay_us_block(CHANGE_UPDATE_INDEX_WAIT_INTERVAL); RTE_LOG(INFO, SPP_CLASSIFIER_MAC, - "Core[%u] Complete update component.\n", lcore_id); + "Component[%u] Complete update component.\n", id); return 0; } /* classifier(mac address) thread function. */ int -spp_classifier_mac_do(void *arg) +spp_classifier_mac_do(int id) { int ret = -1; int i; int n_rx; unsigned int lcore_id = rte_lcore_id(); - struct spp_core_info *core_info = (struct spp_core_info *)arg; struct classifier_mac_mng_info *classifier_mng_info = - g_classifier_mng_info + rte_lcore_id(); + g_classifier_mng_info + id; struct classifier_mac_info *classifier_info = NULL; struct rte_mbuf *rx_pkts[MAX_PKT_BURST]; - const int n_classified_data = core_info->num_tx_port; - struct classified_data *classified_data = classifier_mng_info->classified_data; + struct classified_data *classified_data_rx = NULL; + struct classified_data *classified_data_tx = NULL; uint64_t cur_tsc, prev_tsc = 0; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * DRAIN_TX_PACKET_INTERVAL; /* initialize */ - ret = init_classifier(core_info, classifier_mng_info, classified_data); + ret = init_classifier(classifier_mng_info); if (unlikely(ret != 0)) return ret; - /* to idle */ - core_info->status = SPP_CORE_IDLE; - RTE_LOG(INFO, SPP_CLASSIFIER_MAC, "Core[%u] Start. (type = %d)\n", - lcore_id, core_info->type); - - while(likely(core_info->status == SPP_CORE_IDLE) || - likely(core_info->status == SPP_CORE_FORWARD)) { - - while(likely(core_info->status == SPP_CORE_FORWARD)) { - /* change index of update side */ - change_update_index(classifier_mng_info, lcore_id); - - /* decide classifier infomation of the current cycle */ - classifier_info = classifier_mng_info->info + - classifier_mng_info->ref_index; - - /* drain tx packets, if buffer is not filled for interval */ - cur_tsc = rte_rdtsc(); - if (unlikely(cur_tsc - prev_tsc > drain_tsc)) { - for (i = 0; i < n_classified_data; i++) { - if (unlikely(classified_data[i].num_pkt != 0)) { - RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, - "transimit packets (drain). " - "index=%d, " - "num_pkt=%hu, " - "interval=%lu\n", - i, - classified_data[i].num_pkt, - cur_tsc - prev_tsc); - transmit_packet(&classified_data[i]); - } + while(likely(spp_get_core_status(lcore_id) == SPP_CORE_FORWARD) && + likely(spp_check_core_index(lcore_id) == 0)) { + /* change index of update side */ + change_update_index(classifier_mng_info, id); + + /* decide classifier infomation of the current cycle */ + classifier_info = classifier_mng_info->info + + classifier_mng_info->ref_index; + classified_data_rx = &classifier_info->classified_data_rx; + classified_data_tx = classifier_info->classified_data_tx; + + /* drain tx packets, if buffer is not filled for interval */ + cur_tsc = rte_rdtsc(); + if (unlikely(cur_tsc - prev_tsc > drain_tsc)) { + for (i = 0; i < classifier_info->n_classified_data_tx; i++) { + if (unlikely(classified_data_tx[i].num_pkt != 0)) { + RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, + "transimit packets (drain). " + "index=%d, " + "num_pkt=%hu, " + "interval=%lu\n", + i, + classified_data_tx[i].num_pkt, + cur_tsc - prev_tsc); + transmit_packet(&classified_data_tx[i]); } - prev_tsc = cur_tsc; } + prev_tsc = cur_tsc; + } - /* retrieve packets */ - n_rx = rte_eth_rx_burst(core_info->rx_ports[0].dpdk_port, 0, - rx_pkts, MAX_PKT_BURST); - if (unlikely(n_rx == 0)) - continue; + /* retrieve packets */ + n_rx = rte_eth_rx_burst(classified_data_rx->port, 0, + rx_pkts, MAX_PKT_BURST); + if (unlikely(n_rx == 0)) + continue; #ifdef SPP_RINGLATENCYSTATS_ENABLE - if (core_info->rx_ports[0].if_type == RING) - spp_ringlatencystats_calculate_latency( - core_info->rx_ports[0].if_no, rx_pkts, n_rx); + if (classified_data_rx->if_type == RING) + spp_ringlatencystats_calculate_latency( + classified_data_rx->if_no, rx_pkts, n_rx); #endif - /* classify and transmit (filled) */ - classify_packet(rx_pkts, n_rx, classifier_info, classified_data); - } + /* classify and transmit (filled) */ + classify_packet(rx_pkts, n_rx, classifier_info, classified_data_tx); } /* just in case */ - change_update_index(classifier_mng_info, lcore_id); + change_update_index(classifier_mng_info, id); /* uninitialize */ uninit_classifier(classifier_mng_info); - core_info->status = SPP_CORE_STOP; - return 0; } @@ -542,7 +584,7 @@ int spp_classifier_mac_iterate_table( struct classifier_mac_mng_info *classifier_mng_info; struct classifier_mac_info *classifier_info; struct classified_data *classified_data; - struct spp_config_port_info port; + struct spp_port_index port; char mac_addr_str[ETHER_ADDR_STR_BUF_SZ]; for (i = 0; i < RTE_MAX_LCORE; i++) { @@ -553,7 +595,7 @@ int spp_classifier_mac_iterate_table( classifier_info = classifier_mng_info->info + classifier_mng_info->ref_index; - classified_data = classifier_mng_info->classified_data; + classified_data = classifier_info->classified_data_tx; RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, "Core[%u] Start iterate classifier table.\n", i); @@ -565,10 +607,11 @@ int spp_classifier_mac_iterate_table( (*params->element_proc)( params->opaque, SPP_CLASSIFIER_TYPE_MAC, - SPP_CONFIG_DEFAULT_CLASSIFIED_SPEC_STR, + SPP_DEFAULT_CLASSIFIED_SPEC_STR, &port); } + next = 0; while(1) { ret = rte_hash_iterate(classifier_info->classifier_table, &key, &data, &next); diff --git a/src/vf/classifier_mac.h b/src/vf/classifier_mac.h index b1d0198..f182668 100644 --- a/src/vf/classifier_mac.h +++ b/src/vf/classifier_mac.h @@ -2,7 +2,7 @@ #define _CLASSIFIER_MAC_H_ /* forward declaration */ -struct spp_core_info; +struct spp_component_info; struct spp_iterate_classifier_table_params; /** @@ -13,21 +13,21 @@ int spp_classifier_mac_init(void); /** * classifier(mac address) update component info. * - * @param core_info - * point to struct spp_core_info. + * @param component_info + * point to struct spp_component_info. * * @ret_val 0 succeeded. * @ret_val -1 failed. */ -int spp_classifier_mac_update(struct spp_core_info *core_info); +int spp_classifier_mac_update(struct spp_component_info *component_info); /** * classifier(mac address) thread function. * - * @param arg - * pointer to struct spp_core_info. + * @param id + * unique component ID. */ -int spp_classifier_mac_do(void *arg); +int spp_classifier_mac_do(int id); /** * classifier(mac address) iterate classifier table. diff --git a/src/vf/command_dec.c b/src/vf/command_dec.c index 9363b8f..166901c 100644 --- a/src/vf/command_dec.c +++ b/src/vf/command_dec.c @@ -5,7 +5,6 @@ #include #include "spp_vf.h" -#include "spp_config.h" #include "command_dec.h" #define RTE_LOGTYPE_SPP_COMMAND_PROC RTE_LOGTYPE_USER1 @@ -19,6 +18,28 @@ static const char *CLASSIFILER_TYPE_STRINGS[] = { /* termination */ "", }; +/* command action type string list + do it same as the order of enum spp_command_action (spp_vf.h) */ +static const char *COMMAND_ACTION_STRINGS[] = { + "none", + "start", + "stop", + "add", + "del", + + /* termination */ "", +}; + +/* port rxtx string list + do it same as the order of enum spp_port_rxtx (spp_vf.h) */ +static const char *PORT_RXTX_STRINGS[] = { + "none", + "rx", + "tx", + + /* termination */ "", +}; + /* set decode error */ inline int set_decode_error(struct spp_command_decode_error *error, @@ -75,13 +96,44 @@ get_arrary_index(const char *match, const char *list[]) return -1; } +/* Get unsigned int type value */ +static int +get_uint_value( unsigned int *output, + const char *arg_val, + unsigned int min, + unsigned int max) +{ + unsigned int ret = 0; + char *endptr = NULL; + ret = strtoul(arg_val, &endptr, 0); + if (unlikely(endptr == arg_val) || unlikely(*endptr != '\0')) + return -1; + + if (unlikely(ret < min) || unlikely(ret > max)) + return -1; + + *output = ret; + return 0; +} + +/* decoding procedure of string */ +static int +decode_str_value(char *output, const char *arg_val) +{ + if (strlen(arg_val) >= SPP_CMD_VALUE_BUFSZ) + return -1; + + strcpy(output, arg_val); + return 0; +} + /* decoding procedure of port */ static int decode_port_value(void *output, const char *arg_val) { int ret = 0; - struct spp_config_port_info *port = output; - ret = spp_config_get_if_info(arg_val, &port->if_type, &port->if_no); + struct spp_port_index *port = output; + ret = spp_get_if_info(arg_val, &port->if_type, &port->if_no); if (unlikely(ret != 0)) { RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad port. val=%s\n", arg_val); return -1; @@ -90,6 +142,188 @@ decode_port_value(void *output, const char *arg_val) return 0; } +/* decoding procedure of core */ +static int +decode_core_value(void *output, const char *arg_val) +{ + int ret = 0; + ret = get_uint_value(output, arg_val, 0, RTE_MAX_LCORE-1); + if (unlikely(ret < 0)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad core id. val=%s\n", arg_val); + return -1; + } + + return 0; +} + +/* decoding procedure of action for component command */ +static int +decode_component_action_value(void *output, const char *arg_val) +{ + int ret = 0; + ret = get_arrary_index(arg_val, COMMAND_ACTION_STRINGS); + if (unlikely(ret <= 0)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown component action. val=%s\n", arg_val); + return -1; + } + + if (unlikely(ret != SPP_CMD_ACTION_START) && unlikely(ret != SPP_CMD_ACTION_STOP)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown component action. val=%s\n", arg_val); + return -1; + } + + *(int *)output = ret; + return 0; +} + +/* decoding procedure of action for component command */ +static int +decode_component_name_value(void *output, const char *arg_val) +{ + int ret = 0; + struct spp_command_component *component = output; + + /* "stop" has no core ID parameter. */ + if (component->action == SPP_CMD_ACTION_START) { + ret = spp_get_component_id(arg_val); + if (unlikely(ret >= 0)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, + "Component name in used. val=%s\n", + arg_val); + return -1; + } + } + + return decode_str_value(component->name, arg_val); +} + +/* decoding procedure of core id for component command */ +static int +decode_component_core_value(void *output, const char *arg_val) +{ + struct spp_command_component *component = output; + + /* "stop" has no core ID parameter. */ + if (component->action != SPP_CMD_ACTION_START) + return 0; + + return decode_core_value(&component->core, arg_val); +} + +/* decoding procedure of type for component command */ +static int +decode_component_type_value(void *output, const char *arg_val) +{ + enum spp_component_type org_type, set_type; + struct spp_command_component *component = output; + + /* "stop" has no type parameter. */ + if (component->action != SPP_CMD_ACTION_START) + return 0; + + set_type = spp_change_component_type(arg_val); + if (unlikely(set_type <= 0)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, + "Unknown component type. val=%s\n", + arg_val); + return -1; + } + + org_type = spp_get_component_type_update(component->core); + if ((org_type != SPP_COMPONENT_UNUSE) && (org_type != set_type)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, + "Component type does not match. val=%s (org=%d, new=%d)\n", + arg_val, org_type, set_type); + return -1; + } + + component->type = set_type; + return 0; +} + +/* decoding procedure of action for port command */ +static int +decode_port_action_value(void *output, const char *arg_val) +{ + int ret = 0; + ret = get_arrary_index(arg_val, COMMAND_ACTION_STRINGS); + if (unlikely(ret <= 0)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown port action. val=%s\n", arg_val); + return -1; + } + + if (unlikely(ret != SPP_CMD_ACTION_ADD) && unlikely(ret != SPP_CMD_ACTION_DEL)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown port action. val=%s\n", arg_val); + return -1; + } + + *(int *)output = ret; + return 0; +} + +/* decoding procedure of port for port command */ +static int +decode_port_port_value(void *output, const char *arg_val) +{ + int ret = -1; + struct spp_port_index tmp_port; + struct spp_command_port *port = output; + + ret = decode_port_value(&tmp_port, arg_val); + if (ret < 0) + return -1; + + if ((port->action == SPP_CMD_ACTION_ADD) && + (spp_check_used_port(tmp_port.if_type, tmp_port.if_no, SPP_PORT_RXTX_RX) >= 0) && + (spp_check_used_port(tmp_port.if_type, tmp_port.if_no, SPP_PORT_RXTX_TX) >= 0)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Port in used. (port command) val=%s\n", arg_val); + return -1; + } + + port->port.if_type = tmp_port.if_type; + port->port.if_no = tmp_port.if_no; + return 0; +} + +/* decoding procedure of rxtx type for port command */ +static int +decode_port_rxtx_value(void *output, const char *arg_val) +{ + int ret = 0; + struct spp_command_port *port = output; + + ret = get_arrary_index(arg_val, PORT_RXTX_STRINGS); + if (unlikely(ret <= 0)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown port rxtx. val=%s\n", arg_val); + return -1; + } + + if ((port->action == SPP_CMD_ACTION_ADD) && + (spp_check_used_port(port->port.if_type, port->port.if_no, ret) >= 0)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Port in used. (port command) val=%s\n", arg_val); + return -1; + } + + port->rxtx = ret; + return 0; +} + +/* decoding procedure of component name for port command */ +static int +decode_port_name_value(void *output, const char *arg_val) +{ + int ret = 0; + + ret = spp_get_component_id(arg_val); + if (unlikely(ret < 0)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown component name. val=%s\n", + arg_val); + return -1; + } + + return decode_str_value(output, arg_val); +} + /* decoding procedure of mac address string */ static int decode_mac_addr_str_value(void *output, const char *arg_val) @@ -98,10 +332,10 @@ decode_mac_addr_str_value(void *output, const char *arg_val) const char *str_val = arg_val; /* if default specification, convert to internal dummy address */ - if (unlikely(strcmp(str_val, SPP_CONFIG_DEFAULT_CLASSIFIED_SPEC_STR) == 0)) - str_val = SPP_CONFIG_DEFAULT_CLASSIFIED_DMY_ADDR_STR; + if (unlikely(strcmp(str_val, SPP_DEFAULT_CLASSIFIED_SPEC_STR) == 0)) + str_val = SPP_DEFAULT_CLASSIFIED_DMY_ADDR_STR; - ret = spp_config_change_mac_str_to_int64(str_val); + ret = spp_change_mac_str_to_int64(str_val); if (unlikely(ret < 0)) { RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad mac address string. val=%s\n", str_val); @@ -112,26 +346,46 @@ decode_mac_addr_str_value(void *output, const char *arg_val) return 0; } -/* decoding procedure of classifier type */ +/* decoding procedure of action for classifier_table command */ +static int +decode_classifier_action_value(void *output, const char *arg_val) +{ + int ret = 0; + ret = get_arrary_index(arg_val, COMMAND_ACTION_STRINGS); + if (unlikely(ret <= 0)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown port action. val=%s\n", arg_val); + return -1; + } + + if (unlikely(ret != SPP_CMD_ACTION_ADD) && unlikely(ret != SPP_CMD_ACTION_DEL)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown port action. val=%s\n", arg_val); + return -1; + } + + *(int *)output = ret; + return 0; +} + +/* decoding procedure of type for classifier_table command */ static int decode_classifier_type_value(void *output, const char *arg_val) { - int ret = 0; + int ret = 0; ret = get_arrary_index(arg_val, CLASSIFILER_TYPE_STRINGS); - if (unlikely(ret <= 0)) { - RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown classifier type. val=%s\n", arg_val); - return -1; - } + if (unlikely(ret <= 0)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown classifier type. val=%s\n", arg_val); + return -1; + } - *(int *)output = ret; - return 0; + *(int *)output = ret; + return 0; } -/* decode procedure for classifier value */ +/* decoding procedure of value for classifier_table command */ static int decode_classifier_value_value(void *output, const char *arg_val) { - int ret = -1; + int ret = -1; struct spp_command_classifier_table *classifier_table = output; switch(classifier_table->type) { case SPP_CLASSIFIER_TYPE_MAC: @@ -140,37 +394,70 @@ decode_classifier_value_value(void *output, const char *arg_val) default: break; } - return ret; + return ret; } -/* decode procedure for classifier port */ +/* decoding procedure of port for classifier_table command */ static int decode_classifier_port_value(void *output, const char *arg_val) { - struct spp_config_port_info *port = output; + int ret = 0; + struct spp_command_classifier_table *classifier_table = output; + struct spp_port_index tmp_port; + int64_t mac_addr = 0; + + ret = decode_port_value(&tmp_port, arg_val); + if (ret < 0) + return -1; + + if (spp_check_added_port(tmp_port.if_type, tmp_port.if_no) == 0) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Port not added. val=%s\n", arg_val); + return -1; + } + + if (unlikely(classifier_table->action == SPP_CMD_ACTION_ADD)) { + if (!spp_check_mac_used_port(0, tmp_port.if_type, tmp_port.if_no)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, + "Port in used. (classifier_table command) val=%s\n", + arg_val); + return -1; + } + } else if (unlikely(classifier_table->action == SPP_CMD_ACTION_DEL)) { + mac_addr = spp_change_mac_str_to_int64(classifier_table->value); + if (mac_addr < 0) + return -1; - if (strcmp(arg_val, SPP_CMD_UNUSE) == 0) { - port->if_type = UNDEF; - port->if_no = 0; - return 0; - } + if (!spp_check_mac_used_port((uint64_t)mac_addr, tmp_port.if_type, tmp_port.if_no)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, + "Port in used. (classifier_table command) val=%s\n", + arg_val); + return -1; + } + } - return decode_port_value(port, arg_val); + classifier_table->port.if_type = tmp_port.if_type; + classifier_table->port.if_no = tmp_port.if_no; + return 0; } #define DECODE_PARAMETER_LIST_EMPTY { NULL, 0, NULL } /* parameter list for decoding */ struct decode_parameter_list { - const char *name; - size_t offset; - int (*func)(void *output, const char *arg_val); + const char *name; + size_t offset; + int (*func)(void *output, const char *arg_val); }; /* parameter list for each command */ static struct decode_parameter_list parameter_list[][SPP_CMD_MAX_PARAMETERS] = { { /* classifier_table */ { + .name = "action", + .offset = offsetof(struct spp_command, spec.classifier_table.action), + .func = decode_classifier_action_value + }, + { .name = "type", .offset = offsetof(struct spp_command, spec.classifier_table.type), .func = decode_classifier_type_value @@ -182,7 +469,7 @@ static struct decode_parameter_list parameter_list[][SPP_CMD_MAX_PARAMETERS] = { }, { .name = "port", - .offset = offsetof(struct spp_command, spec.classifier_table.port), + .offset = offsetof(struct spp_command, spec.classifier_table), .func = decode_classifier_port_value }, DECODE_PARAMETER_LIST_EMPTY, @@ -190,6 +477,53 @@ static struct decode_parameter_list parameter_list[][SPP_CMD_MAX_PARAMETERS] = { { DECODE_PARAMETER_LIST_EMPTY }, /* flush */ { DECODE_PARAMETER_LIST_EMPTY }, /* _get_client_id */ { DECODE_PARAMETER_LIST_EMPTY }, /* status */ + { DECODE_PARAMETER_LIST_EMPTY }, /* exit */ + { /* component */ + { + .name = "action", + .offset = offsetof(struct spp_command, spec.component.action), + .func = decode_component_action_value + }, + { + .name = "component name", + .offset = offsetof(struct spp_command, spec.component), + .func = decode_component_name_value + }, + { + .name = "core", + .offset = offsetof(struct spp_command, spec.component), + .func = decode_component_core_value + }, + { + .name = "component type", + .offset = offsetof(struct spp_command, spec.component), + .func = decode_component_type_value + }, + DECODE_PARAMETER_LIST_EMPTY, + }, + { /* port */ + { + .name = "action", + .offset = offsetof(struct spp_command, spec.port.action), + .func = decode_port_action_value + }, + { + .name = "port", + .offset = offsetof(struct spp_command, spec.port), + .func = decode_port_port_value + }, + { + .name = "port rxtx", + .offset = offsetof(struct spp_command, spec.port), + .func = decode_port_rxtx_value + }, + { + .name = "component name", + .offset = offsetof(struct spp_command, spec.port.name), + .func = decode_port_name_value + }, + DECODE_PARAMETER_LIST_EMPTY, + }, { DECODE_PARAMETER_LIST_EMPTY }, /* termination */ }; @@ -227,10 +561,13 @@ struct decode_command_list { /* command list */ static struct decode_command_list command_list[] = { - { "classifier_table", 4, 4, decode_comand_parameter_in_list }, /* classifier_table */ + { "classifier_table", 5, 5, decode_comand_parameter_in_list }, /* classifier_table */ { "flush", 1, 1, NULL }, /* flush */ { "_get_client_id", 1, 1, NULL }, /* _get_client_id */ { "status", 1, 1, NULL }, /* status */ + { "exit", 1, 1, NULL }, /* exit */ + { "component", 3, 5, decode_comand_parameter_in_list }, /* port */ + { "port", 5, 5, decode_comand_parameter_in_list }, /* port */ { "", 0, 0, NULL } /* termination */ }; @@ -310,6 +647,9 @@ spp_command_decode_request(struct spp_command_request *request, const char *requ case SPP_CMDTYPE_STATUS: request->is_requested_status = 1; break; + case SPP_CMDTYPE_EXIT: + request->is_requested_exit = 1; + break; default: /* nothing to do */ break; diff --git a/src/vf/command_dec.h b/src/vf/command_dec.h index 8850485..359f5e5 100644 --- a/src/vf/command_dec.h +++ b/src/vf/command_dec.h @@ -1,6 +1,8 @@ #ifndef _COMMAND_DEC_H_ #define _COMMAND_DEC_H_ +//#include "spp_vf.h" + /* max number of command per request */ #define SPP_CMD_MAX_COMMANDS 32 @@ -16,9 +18,6 @@ /* string that specify unused */ #define SPP_CMD_UNUSE "unuse" -/* component type */ -#define spp_component_type spp_core_type - /* decode error code */ enum spp_command_decode_error_code { /* not use 0, in general 0 is ok */ @@ -36,31 +35,17 @@ enum spp_command_type { SPP_CMDTYPE_FLUSH, SPP_CMDTYPE_CLIENT_ID, SPP_CMDTYPE_STATUS, + SPP_CMDTYPE_EXIT, + SPP_CMDTYPE_COMPONENT, + SPP_CMDTYPE_PORT, }; -#if 0 /* not supported yet */ -/* "add" command parameters */ -struct spp_command_add { - int num_port; - struct spp_config_port_info ports[RTE_MAX_ETHPORTS]; -}; - -/* "component" command specific parameters */ -struct spp_command_component { - enum spp_component_type type; - unsigned int core_id; - int num_rx_port; - int num_tx_port; - struct spp_config_port_info rx_ports[RTE_MAX_ETHPORTS]; - struct spp_config_port_info tx_ports[RTE_MAX_ETHPORTS]; -}; -#endif - /* "classifier_table" command specific parameters */ struct spp_command_classifier_table { + enum spp_command_action action; enum spp_classifier_type type; char value[SPP_CMD_VALUE_BUFSZ]; - struct spp_config_port_info port; + struct spp_port_index port; }; /* "flush" command specific parameters */ @@ -68,17 +53,31 @@ struct spp_command_flush { /* nothing specific */ }; +/* "component" command parameters */ +struct spp_command_component { + enum spp_command_action action; + char name[SPP_CMD_NAME_BUFSZ]; + unsigned int core; + enum spp_component_type type; +}; + +/* "port" command parameters */ +struct spp_command_port { + enum spp_command_action action; + struct spp_port_index port; + enum spp_port_rxtx rxtx; + char name[SPP_CMD_NAME_BUFSZ]; +}; + /* command parameters */ struct spp_command { enum spp_command_type type; union { -#if 0 /* not supported yet */ - struct spp_command_add add; - struct spp_command_component component; -#endif struct spp_command_classifier_table classifier_table; struct spp_command_flush flush; + struct spp_command_component component; + struct spp_command_port port; } spec; }; @@ -90,6 +89,7 @@ struct spp_command_request { int is_requested_client_id; int is_requested_status; + int is_requested_exit; }; /* decode error information */ diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c index ef1ae81..0a45874 100644 --- a/src/vf/command_proc.c +++ b/src/vf/command_proc.c @@ -7,7 +7,6 @@ #include #include "spp_vf.h" -#include "spp_config.h" #include "string_buffer.h" #include "command_conn.h" #include "command_dec.h" @@ -40,6 +39,7 @@ execute_command(const struct spp_command *command) case SPP_CMDTYPE_CLASSIFIER_TABLE: RTE_LOG(INFO, SPP_COMMAND_PROC, "Execute classifier_table command.\n"); ret = spp_update_classifier_table( + command->spec.classifier_table.action, command->spec.classifier_table.type, command->spec.classifier_table.value, &command->spec.classifier_table.port); @@ -50,6 +50,25 @@ execute_command(const struct spp_command *command) ret = spp_flush(); break; + case SPP_CMDTYPE_COMPONENT: + RTE_LOG(INFO, SPP_COMMAND_PROC, "Execute component command.\n"); + ret = spp_update_component( + command->spec.component.action, + command->spec.component.name, + command->spec.component.core, + command->spec.component.type); + break; + + case SPP_CMDTYPE_PORT: + RTE_LOG(INFO, SPP_COMMAND_PROC, "Execute port command. (act = %d)\n", + command->spec.port.action); + ret = spp_update_port( + command->spec.port.action, + &command->spec.port.port, + command->spec.port.rxtx, + command->spec.port.name); + break; + default: RTE_LOG(INFO, SPP_COMMAND_PROC, "Execute other command. type=%d\n", command->type); /* nothing to do here */ @@ -230,12 +249,12 @@ int append_classifier_element_value( void *opaque, __rte_unused enum spp_classifier_type type, const char *data, - const struct spp_config_port_info *port) + const struct spp_port_index *port) { json_t *parent_obj = (json_t *)opaque; char port_str[64]; - spp_config_format_port_string(port_str, port->if_type, port->if_no); + spp_format_port_string(port_str, port->if_type, port->if_no); json_array_append_new(parent_obj, json_pack( "{ssssss}", @@ -416,7 +435,7 @@ process_request(int *sock, const char *request_str, size_t request_str_len) /* send error response */ send_decode_error_response(sock, &request, &decode_error); RTE_LOG(DEBUG, SPP_COMMAND_PROC, "End command request processing.\n"); - return ret; + return 0; } RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Command request is valid. " @@ -438,6 +457,13 @@ process_request(int *sock, const char *request_str, size_t request_str_len) command_results[i].code = CRES_SUCCESS; } + if (request.is_requested_exit) { + /* Terminated by process exit command. */ + /* Other route is normal end because it responds to command. */ + RTE_LOG(INFO, SPP_COMMAND_PROC, "No response with process exit command."); + return -1; + } + /* send response */ send_command_result_response(sock, &request, command_results); @@ -489,5 +515,5 @@ spp_command_proc_do(void) ret = process_request(&sock, msgbuf, msg_ret); spp_strbuf_remove_front(msgbuf, msg_ret); - return 0; + return ret; } diff --git a/src/vf/command_proc.h b/src/vf/command_proc.h index 37e55ad..05cb1f1 100644 --- a/src/vf/command_proc.h +++ b/src/vf/command_proc.h @@ -20,7 +20,8 @@ spp_command_proc_init(const char *controller_ip, int controller_port); * process command from controller. * * @retval 0 succeeded. - * @retval -1 failed. + * @retval -1 process termination is required. + * (occurred connection failure, or received exit command) */ int spp_command_proc_do(void); diff --git a/src/vf/spp_config.c b/src/vf/spp_config.c index 55129ac..9170281 100644 --- a/src/vf/spp_config.c +++ b/src/vf/spp_config.c @@ -136,11 +136,11 @@ config_get_str_value(const json_t *obj, const char *path, char *value) static void config_init_data(struct spp_config_area *config) { - /* Clear config area with zero */ + /* Clear config area with zero */ memset(config, 0x00, sizeof(struct spp_config_area)); int core_cnt, port_cnt, table_cnt; - /* Set all of interface type of ports and mac tables to UNDEF */ + /* Set all of interface type of ports and mac tables to UNDEF */ for (core_cnt = 0; core_cnt < SPP_CONFIG_CORE_MAX; core_cnt++) { for (port_cnt = 0; port_cnt < RTE_MAX_ETHPORTS; port_cnt++) { config->proc.functions[core_cnt].rx_ports[port_cnt].if_type = UNDEF; @@ -188,7 +188,7 @@ spp_config_get_if_info(const char *port, enum port_type *if_type, int *if_no) return -1; } - /* Change type of number of interface */ + /* Change type of number of interface */ int ret_no = strtol(no_str, &endptr, 0); if (unlikely(no_str == endptr) || unlikely(*endptr != '\0')) { /* No IF number */ @@ -321,7 +321,7 @@ config_load_classifier_table(const json_t *obj, } classifier_table->num_table = array_num; - /* Setup for each of mac tables */ + /* Setup for each of mac tables */ struct spp_config_mac_table_element *tmp_table = NULL; char if_str[SPP_CONFIG_STR_LEN]; int table_cnt = 0; @@ -346,10 +346,10 @@ config_load_classifier_table(const json_t *obj, return -1; } - /** - * If mac address is set to 'default', replace it to reserved - * dummy address for validation. - */ + /** + * If mac address is set to 'default', replace it to reserved + * dummy address for validation. + */ if (unlikely(strcmp(tmp_table->mac_addr_str, SPP_CONFIG_DEFAULT_CLASSIFIED_SPEC_STR) == 0)) strcpy(tmp_table->mac_addr_str, @@ -375,7 +375,7 @@ config_load_classifier_table(const json_t *obj, table_cnt, JSONPATH_PORT); return -1; } - /* And separate it to type and number */ + /* And separate it to type and number */ int ret_if = spp_config_get_if_info(if_str, &tmp_table->port.if_type, &tmp_table->port.if_no); if (unlikely(ret_if != 0)) { @@ -433,7 +433,7 @@ config_set_rx_port(enum spp_core_type type, json_t *obj, return -1; } - /* Check if the size of array is not over RTE_MAX_ETHPORTS */ + /* Check if the size of array is not over RTE_MAX_ETHPORTS */ int port_num = json_array_size(array_obj); if (unlikely(port_num <= 0) || unlikely(port_num > RTE_MAX_ETHPORTS)) { @@ -557,7 +557,7 @@ config_set_tx_port(enum spp_core_type type, json_t *obj, return -1; } - /* Check if the size of array is not over RTE_MAX_ETHPORTS */ + /* Check if the size of array is not over RTE_MAX_ETHPORTS */ int port_num = json_array_size(array_obj); if (unlikely(port_num <= 0) || unlikely(port_num > RTE_MAX_ETHPORTS)) { @@ -579,7 +579,7 @@ config_set_tx_port(enum spp_core_type type, json_t *obj, return -1; } - /* Get sending port */ + /* Get sending port */ if (unlikely(!json_is_string(elements_obj))) { RTE_LOG(ERR, APP, "Not a string. (path = %s, No = %d, route = classifier)\n", JSONPATH_TX_PORT, array_cnt); @@ -587,7 +587,7 @@ config_set_tx_port(enum spp_core_type type, json_t *obj, } strcpy(if_str, json_string_value(elements_obj)); - /* Separate it to interface type and number */ + /* Separate it to interface type and number */ int ret_if = spp_config_get_if_info(if_str, &tmp_tx_port->if_type, &tmp_tx_port->if_no); if (unlikely(ret_if != 0)) { diff --git a/src/vf/spp_forward.c b/src/vf/spp_forward.c index afe7c03..8a0980a 100644 --- a/src/vf/spp_forward.c +++ b/src/vf/spp_forward.c @@ -1,3 +1,5 @@ +#include + #include "spp_vf.h" #include "ringlatencystats.h" #include "spp_forward.h" @@ -5,21 +7,106 @@ #define RTE_LOGTYPE_FORWARD RTE_LOGTYPE_USER1 /* A set of port info of rx and tx */ -struct rxtx { - struct spp_core_port_info rx; - struct spp_core_port_info tx; +struct forward_rxtx { + struct spp_port_info rx; + struct spp_port_info tx; +}; + +struct forward_path { + int num; + struct forward_rxtx ports[RTE_MAX_ETHPORTS]; +}; + +struct forward_info { + enum spp_component_type type; + volatile int ref_index; + volatile int upd_index; + struct forward_path path[SPP_INFO_AREA_MAX]; }; -/* Set destination port as source */ +struct forward_info g_forward_info[RTE_MAX_LCORE]; + +/* Clear info */ +void +spp_forward_init(void) +{ + int cnt = 0; + memset(&g_forward_info, 0x00, sizeof(g_forward_info)); + for (cnt = 0; cnt < RTE_MAX_LCORE; cnt++) { + g_forward_info[cnt].ref_index = 0; + g_forward_info[cnt].upd_index = 1; + } +} + +/* Clear info for one element. */ static void -set_use_interface(struct spp_core_port_info *dst, - struct spp_core_port_info *src) +clear_forward_info(int id) { - dst->if_type = src->if_type; - dst->if_no = src->if_no; - dst->dpdk_port = src->dpdk_port; + struct forward_info *info = &g_forward_info[id]; + info->type = SPP_COMPONENT_UNUSE; + memset(&g_forward_info[id].path, 0x00, sizeof(struct forward_path)); } +/* Update forward info */ +int +spp_forward_update(struct spp_component_info *component) +{ + int cnt = 0; + int num_rx = component->num_rx_port; + int num_tx = component->num_tx_port; + int max = (num_rx > num_tx)?num_rx*num_tx:num_tx; + struct forward_info *info = &g_forward_info[component->component_id]; + struct forward_path *path = &info->path[info->upd_index]; + + /* Forward component allows only one receiving port. */ + if ((component->type == SPP_COMPONENT_FORWARD) && unlikely(num_rx > 1)) { + RTE_LOG(ERR, FORWARD, "Component[%d] Setting error. (type = %d, rx = %d)\n", + component->component_id, component->type, num_rx); + return -1; + } + + /* Component allows only one transmit port. */ + if (unlikely(num_tx != 0) && unlikely(num_tx != 1)) { + RTE_LOG(ERR, FORWARD, "Component[%d] Setting error. (type = %d, tx = %d)\n", + component->component_id, component->type, num_tx); + return -1; + } + + clear_forward_info(component->component_id); + + RTE_LOG(INFO, FORWARD, + "Component[%d] Start update component. (type = %d)\n", + component->component_id, component->type); + + info->type = component->type; + path->num = component->num_rx_port; + for (cnt = 0; cnt < num_rx; cnt++) + memcpy(&path->ports[cnt].rx, component->rx_ports[cnt], + sizeof(struct spp_port_info)); + + /* Transmit port is set according with larger num_rx / num_tx. */ + for (cnt = 0; cnt < max; cnt++) + memcpy(&path->ports[cnt].tx, component->tx_ports[0], + sizeof(struct spp_port_info)); + + info->upd_index = info->ref_index; + while(likely(info->ref_index == info->upd_index)) + rte_delay_us_block(SPP_CHANGE_UPDATE_INTERVAL); + + RTE_LOG(INFO, FORWARD, "Component[%d] Complete update component. (type = %d)\n", + component->component_id, component->type); + + return 0; +} + +/* Change index of forward info */ +static inline void +change_forward_index(int id) +{ + struct forward_info *info = &g_forward_info[id]; + if (info->ref_index == info->upd_index) + info->ref_index = (info->upd_index+1)%SPP_INFO_AREA_MAX; +} /** * Forwarding packets as forwarder or merger * @@ -27,75 +114,49 @@ set_use_interface(struct spp_core_port_info *dst, * as an argument of void and typecasted to spp_config_info. */ int -spp_forward(void *arg) +spp_forward(int id) { - unsigned int lcore_id = rte_lcore_id(); - struct spp_core_info *core_info = (struct spp_core_info *)arg; - int if_cnt, rxtx_num = 0; - struct rxtx patch[RTE_MAX_ETHPORTS]; - - /* Decide the destination of forwarding */ - rxtx_num = core_info->num_rx_port; - for (if_cnt = 0; if_cnt < rxtx_num; if_cnt++) { - set_use_interface(&patch[if_cnt].rx, - &core_info->rx_ports[if_cnt]); - /* Forwarding type is supposed to forwarder or merger */ - if (core_info->type == SPP_CONFIG_FORWARD) { - set_use_interface(&patch[if_cnt].tx, - &core_info->tx_ports[if_cnt]); - } else { - set_use_interface(&patch[if_cnt].tx, - &core_info->tx_ports[0]); - } - } + int cnt, num, buf; + int nb_rx = 0; + int nb_tx = 0; + struct forward_info *info = &g_forward_info[id]; + struct forward_path *path = NULL; + struct spp_port_info *rx; + struct spp_port_info *tx; + struct rte_mbuf *bufs[MAX_PKT_BURST]; - core_info->status = SPP_CORE_IDLE; - RTE_LOG(INFO, FORWARD, "Core[%d] Start. (type = %d)\n", lcore_id, - core_info->type); + change_forward_index(id); + path = &info->path[info->ref_index]; + num = path->num; - int cnt, nb_rx, nb_tx, buf; - struct spp_core_port_info *rx; - struct spp_core_port_info *tx; - struct rte_mbuf *bufs[MAX_PKT_BURST]; - while (likely(core_info->status == SPP_CORE_IDLE) || - likely(core_info->status == SPP_CORE_FORWARD)) { - while (likely(core_info->status == SPP_CORE_FORWARD)) { - for (cnt = 0; cnt < rxtx_num; cnt++) { - rx = &patch[cnt].rx; - tx = &patch[cnt].tx; - - /* Receive packets */ - nb_rx = rte_eth_rx_burst(rx->dpdk_port, 0, bufs, MAX_PKT_BURST); - if (unlikely(nb_rx == 0)) { - continue; - } + for (cnt = 0; cnt < num; cnt++) { + rx = &path->ports[cnt].rx; + tx = &path->ports[cnt].tx; + + /* Receive packets */ + nb_rx = rte_eth_rx_burst(rx->dpdk_port, 0, bufs, MAX_PKT_BURST); + if (unlikely(nb_rx == 0)) + continue; #ifdef SPP_RINGLATENCYSTATS_ENABLE - if (rx->if_type == RING) { - spp_ringlatencystats_calculate_latency(rx->if_no, - bufs, nb_rx); - } - if (tx->if_type == RING) { - spp_ringlatencystats_add_time_stamp(tx->if_no, - bufs, nb_rx); - } + if (rx->if_type == RING) + spp_ringlatencystats_calculate_latency(rx->if_no, + bufs, nb_rx); + + if (tx->if_type == RING) + spp_ringlatencystats_add_time_stamp(tx->if_no, + bufs, nb_rx); #endif /* SPP_RINGLATENCYSTATS_ENABLE */ - /* Send packets */ - nb_tx = rte_eth_tx_burst(tx->dpdk_port, 0, bufs, nb_rx); + /* Send packets */ + if (tx->dpdk_port >= 0) + nb_tx = rte_eth_tx_burst(tx->dpdk_port, 0, bufs, nb_rx); - /* Discard remained packets to release mbuf */ - if (unlikely(nb_tx < nb_rx)) { - for (buf = nb_tx; buf < nb_rx; buf++) { - rte_pktmbuf_free(bufs[buf]); - } - } - } + /* Discard remained packets to release mbuf */ + if (unlikely(nb_tx < nb_rx)) { + for (buf = nb_tx; buf < nb_rx; buf++) + rte_pktmbuf_free(bufs[buf]); } } - - RTE_LOG(INFO, FORWARD, "Core[%d] End. (type = %d)\n", lcore_id, - core_info->type); - core_info->status = SPP_CORE_STOP; return 0; } diff --git a/src/vf/spp_forward.h b/src/vf/spp_forward.h index 33208bf..729dbe8 100644 --- a/src/vf/spp_forward.h +++ b/src/vf/spp_forward.h @@ -1,9 +1,16 @@ #ifndef __SPP_FORWARD_H__ #define __SPP_FORWARD_H__ + +void spp_forward_init(void); + +void spp_forward_init_info(int id); + +int spp_forward_update(struct spp_component_info *component); + /* * Merge/Forward */ -int spp_forward(void *arg); +int spp_forward(int id); #endif /* __SPP_FORWARD_H__ */ diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c index c7268e5..d6eb7b2 100644 --- a/src/vf/spp_vf.c +++ b/src/vf/spp_vf.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "spp_vf.h" #include "ringlatencystats.h" @@ -16,13 +17,16 @@ #define SPP_CORE_STATUS_CHECK_MAX 5 #define SPP_RING_LATENCY_STATS_SAMPLING_INTERVAL 1000000 +#define CORE_TYPE_CLASSIFIER_MAC_STR "classifier_mac" +#define CORE_TYPE_MERGE_STR "merge" +#define CORE_TYPE_FORWARD_STR "forward" + /* getopt_long return value for long option */ enum SPP_LONGOPT_RETVAL { SPP_LONGOPT_RETVAL__ = 127, /* add below */ /* TODO(yasufum) add description what and why add below */ - SPP_LONGOPT_RETVAL_CONFIG, SPP_LONGOPT_RETVAL_CLIENT_ID, SPP_LONGOPT_RETVAL_VHOST_CLIENT }; @@ -35,37 +39,41 @@ struct startup_param { int vhost_client; }; -/* Status of patch and its cores, mac address assinged for it and port info */ -struct patch_info { - int use_flg; - int dpdk_port; /* TODO(yasufum) add desc for what is this */ - int rx_core_no; - int tx_core_no; - char mac_addr_str[SPP_CONFIG_STR_LEN]; - uint64_t mac_addr; - struct spp_core_port_info *rx_core; - struct spp_core_port_info *tx_core; -}; - -/* Manage number of interfaces and patch information as global variable */ +/* Manage number of interfaces and port information as global variable */ /* TODO(yasufum) refactor, change if to iface */ struct if_info { int num_nic; int num_vhost; int num_ring; - struct patch_info nic_patchs[RTE_MAX_ETHPORTS]; - struct patch_info vhost_patchs[RTE_MAX_ETHPORTS]; - struct patch_info ring_patchs[RTE_MAX_ETHPORTS]; + struct spp_port_info nic[RTE_MAX_ETHPORTS]; + struct spp_port_info vhost[RTE_MAX_ETHPORTS]; + struct spp_port_info ring[RTE_MAX_ETHPORTS]; +}; + +/* Manage component running in core as global variable */ +struct core_info { + volatile enum spp_component_type type; + int num; + int id[RTE_MAX_LCORE]; +}; + +/* Manage core status and component information as global variable */ +struct core_mng_info { + volatile enum spp_core_status status; + volatile int ref_index; + volatile int upd_index; + struct core_info core[SPP_INFO_AREA_MAX]; }; /* Declare global variables */ -static struct spp_config_area g_config; -static struct startup_param g_startup_param; -static struct if_info g_if_info; -static struct spp_core_info g_core_info[SPP_CONFIG_CORE_MAX]; -static int g_change_core[SPP_CONFIG_CORE_MAX]; /* TODO(yasufum) add desc how it is used and why changed core is kept */ +static unsigned int g_main_lcore_id = 0xffffffff; +static struct startup_param g_startup_param; +static struct if_info g_if_info; +static struct spp_component_info g_component_info[RTE_MAX_LCORE]; +static struct core_mng_info g_core_info[RTE_MAX_LCORE]; -static char config_file_path[PATH_MAX]; +static int g_change_core[RTE_MAX_LCORE]; /* TODO(yasufum) add desc how it is used and why changed component is kept */ +static int g_change_component[RTE_MAX_LCORE]; /* Print help message */ static void @@ -73,11 +81,9 @@ usage(const char *progname) { RTE_LOG(INFO, APP, "Usage: %s [EAL args] --" " --client-id CLIENT_ID" - " [--config CONFIG_FILE_PATH]" " -s SERVER_IP:SERVER_PORT" " [--vhost-client]\n" " --client-id CLIENT_ID : My client ID\n" - " --config CONFIG_FILE_PATH : specific config file path\n" " -s SERVER_IP:SERVER_PORT : Access information to the server\n" " --vhost-client : Run vhost on client\n" , progname); @@ -99,8 +105,8 @@ add_ring_pmd(int ring_id) /* Create ring pmd */ ring_port_id = rte_eth_from_ring(ring); - RTE_LOG(DEBUG, APP, "ring port id %d\n", ring_port_id); - + RTE_LOG(INFO, APP, "ring port add. (no = %d / port = %d)\n", + ring_id, ring_port_id); return ring_port_id; } @@ -178,26 +184,30 @@ add_vhost_pmd(int index, int client) return ret; } - RTE_LOG(DEBUG, APP, "vhost port id %d\n", vhost_port_id); - + RTE_LOG(INFO, APP, "vhost port add. (no = %d / port = %d)\n", + index, vhost_port_id); return vhost_port_id; } +/* Get core status */ +enum spp_core_status +spp_get_core_status(unsigned int lcore_id) +{ + return g_core_info[lcore_id].status; +} + /** * Check status of all of cores is same as given * * It returns -1 as status mismatch if status is not same. - * If status is SPP_CONFIG_UNUSE, check is skipped. + * If core is in use, status will be checked. */ static int check_core_status(enum spp_core_status status) { - int cnt; /* increment core id */ - for (cnt = 0; cnt < SPP_CONFIG_CORE_MAX; cnt++) { - if (g_core_info[cnt].type == SPP_CONFIG_UNUSE) { - continue; - } - if (g_core_info[cnt].status != status) { + unsigned int lcore_id = 0; + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + if (g_core_info[lcore_id].status != status) { /* Status is mismatched */ return -1; } @@ -225,18 +235,26 @@ check_core_status_wait(enum spp_core_status status) return -1; } +/* Set core status */ +static void +set_core_status(unsigned int lcore_id, + enum spp_core_status status) +{ + g_core_info[lcore_id].status = status; +} + /* Set all core to given status */ static void -set_core_status(enum spp_core_status status) +set_all_core_status(enum spp_core_status status) { - int core_cnt = 0; /* increment core id */ - for(core_cnt = 0; core_cnt < SPP_CONFIG_CORE_MAX; core_cnt++) { - g_core_info[core_cnt].status = status; + unsigned int lcore_id = 0; + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + g_core_info[lcore_id].status = status; } } /** - * Set all of core status to SPP_CORE_STOP_REQUEST if received signal + * Set all of component status to SPP_CORE_STOP_REQUEST if received signal * is SIGTERM or SIGINT */ static void @@ -246,7 +264,8 @@ stop_process(int signal) { return; } - set_core_status(SPP_CORE_STOP_REQUEST); + g_core_info[g_main_lcore_id].status = SPP_CORE_STOP_REQUEST; + set_all_core_status(SPP_CORE_STOP_REQUEST); } /** @@ -265,7 +284,7 @@ parse_app_client_id(const char *client_id_str, int *client_id) if (unlikely(client_id_str == endptr) || unlikely(*endptr != '\0')) return -1; - if (id >= SPP_CLIENT_MAX) + if (id >= RTE_MAX_LCORE) return -1; *client_id = id; @@ -310,7 +329,6 @@ parse_app_args(int argc, char *argv[]) char *argvopt[argcopt]; const char *progname = argv[0]; static struct option lgopts[] = { - { "config", required_argument, NULL, SPP_LONGOPT_RETVAL_CONFIG }, { "client-id", required_argument, NULL, SPP_LONGOPT_RETVAL_CLIENT_ID }, { "vhost-client", no_argument, NULL, SPP_LONGOPT_RETVAL_VHOST_CLIENT }, { 0 }, @@ -333,13 +351,6 @@ parse_app_args(int argc, char *argv[]) while ((opt = getopt_long(argc, argvopt, "s:", lgopts, &option_index)) != EOF) { switch (opt) { - case SPP_LONGOPT_RETVAL_CONFIG: - if (optarg[0] == '\0' || strlen(optarg) >= sizeof(config_file_path)) { - usage(progname); - return -1; - } - strcpy(config_file_path, optarg); - break; case SPP_LONGOPT_RETVAL_CLIENT_ID: if (parse_app_client_id(optarg, &g_startup_param.client_id) != 0) { usage(progname); @@ -371,9 +382,8 @@ parse_app_args(int argc, char *argv[]) return -1; } RTE_LOG(INFO, APP, - "app opts (client_id=%d,config=%s,server=%s:%d,vhost_client=%d)\n", + "app opts (client_id=%d,server=%s:%d,vhost_client=%d)\n", g_startup_param.client_id, - config_file_path, g_startup_param.server_ip, g_startup_param.server_port, g_startup_param.vhost_client); @@ -381,25 +391,25 @@ parse_app_args(int argc, char *argv[]) } /** - * Return patch info of given type and num of interface + * Return port info of given type and num of interface * * It returns NULL value if given type is invalid. * * TODO(yasufum) refactor name of func to be more understandable (area?) * TODO(yasufum) refactor, change if to iface. */ -static struct patch_info * +static struct spp_port_info * get_if_area(enum port_type if_type, int if_no) { switch (if_type) { case PHY: - return &g_if_info.nic_patchs[if_no]; + return &g_if_info.nic[if_no]; break; case VHOST: - return &g_if_info.vhost_patchs[if_no]; + return &g_if_info.vhost[if_no]; break; case RING: - return &g_if_info.ring_patchs[if_no]; + return &g_if_info.ring[if_no]; break; default: return NULL; @@ -408,8 +418,9 @@ get_if_area(enum port_type if_type, int if_no) } /** - * Initialize all of patch info by assingning -1 + * Initialize g_if_info * + * Clear g_if_info and set initial value. * TODO(yasufum) refactor, change if to iface. */ static void @@ -418,336 +429,90 @@ init_if_info(void) int port_cnt; /* increment ether ports */ memset(&g_if_info, 0x00, sizeof(g_if_info)); for (port_cnt = 0; port_cnt < RTE_MAX_ETHPORTS; port_cnt++) { - g_if_info.nic_patchs[port_cnt].rx_core_no = -1; - g_if_info.nic_patchs[port_cnt].tx_core_no = -1; - g_if_info.vhost_patchs[port_cnt].rx_core_no = -1; - g_if_info.vhost_patchs[port_cnt].tx_core_no = -1; - g_if_info.ring_patchs[port_cnt].rx_core_no = -1; - g_if_info.ring_patchs[port_cnt].tx_core_no = -1; + g_if_info.nic[port_cnt].if_type = UNDEF; + g_if_info.nic[port_cnt].if_no = port_cnt; + g_if_info.nic[port_cnt].dpdk_port = -1; + g_if_info.vhost[port_cnt].if_type = UNDEF; + g_if_info.vhost[port_cnt].if_no = port_cnt; + g_if_info.vhost[port_cnt].dpdk_port = -1; + g_if_info.ring[port_cnt].if_type = UNDEF; + g_if_info.ring[port_cnt].if_no = port_cnt; + g_if_info.ring[port_cnt].dpdk_port = -1; } } /** - * Initialize g_core_info and its port info - * - * Clear g_core_info and set interface type of its port info to UNDEF. - * TODO(yasufum) refactor, change if to iface. + * Initialize g_component_info */ static void -init_core_info(void) +init_component_info(void) { - memset(&g_core_info, 0x00, sizeof(g_core_info)); - int core_cnt, port_cnt; - for (core_cnt = 0; core_cnt < SPP_CONFIG_CORE_MAX; core_cnt++) { - g_core_info[core_cnt].lcore_id = core_cnt; - for (port_cnt = 0; port_cnt < RTE_MAX_ETHPORTS; port_cnt++) { - g_core_info[core_cnt].rx_ports[port_cnt].if_type = UNDEF; - g_core_info[core_cnt].tx_ports[port_cnt].if_type = UNDEF; - } + int cnt; + memset(&g_component_info, 0x00, sizeof(g_component_info)); + for (cnt = 0; cnt < RTE_MAX_LCORE; cnt++) { + g_component_info[cnt].component_id = cnt; } - memset(g_change_core, 0x00, sizeof(g_change_core)); + memset(g_change_component, 0x00, sizeof(g_change_component)); } /** - * Set properties of g_core_info from config - * - * TODO(yasufum) refactor, change if to iface. + * Initialize g_core_info */ -static int -set_from_proc_info(struct spp_config_area *config) +static void +init_core_info(void) { - int core_cnt, rx_start, rx_cnt, tx_start, tx_cnt; - enum port_type if_type; - int if_no; - struct spp_config_functions *core_func = NULL; - struct spp_core_info *core_info = NULL; - struct patch_info *patch_info = NULL; - for (core_cnt = 0; core_cnt < config->proc.num_func; core_cnt++) { - core_func = &config->proc.functions[core_cnt]; - core_info = &g_core_info[core_func->core_no]; - - if (core_func->type == SPP_CONFIG_UNUSE) { - continue; - } - - /* Check if type of core_info is SPP_CONFIG_FORWARD because this - * this type is only available for several settings. - */ - if ((core_info->type != SPP_CONFIG_UNUSE) && - ((core_info->type != SPP_CONFIG_FORWARD) || - (core_func->type != SPP_CONFIG_FORWARD))) { - RTE_LOG(ERR, APP, "Core in use. (core = %d, type = %d/%d)\n", - core_func->core_no, - core_func->type, core_info->type); - return -1; - } - - core_info->type = core_func->type; - if (!rte_lcore_is_enabled(core_func->core_no)) { - /* CPU mismatch */ - RTE_LOG(ERR, APP, "CPU mismatch (cpu = %u)\n", - core_func->core_no); - return -1; - } - - rx_start = core_info->num_rx_port; - core_info->num_rx_port += core_func->num_rx_port; - for (rx_cnt = 0; rx_cnt < core_func->num_rx_port; rx_cnt++) { - if_type = core_func->rx_ports[rx_cnt].if_type; - if_no = core_func->rx_ports[rx_cnt].if_no; - - core_info->rx_ports[rx_start + rx_cnt].if_type = if_type; - core_info->rx_ports[rx_start + rx_cnt].if_no = if_no; - - /* Retrieve patch corresponding to type and number of the interface */ - patch_info = get_if_area(if_type, if_no); - - patch_info->use_flg = 1; - if (unlikely(patch_info->rx_core != NULL)) { - RTE_LOG(ERR, APP, "Used RX port (core = %d, if_type = %d, if_no = %d)\n", - core_func->core_no, if_type, if_no); - return -1; - } - - /* Hold core info is to be referred for updating this information */ - patch_info->rx_core_no = core_func->core_no; - patch_info->rx_core = &core_info->rx_ports[rx_start + rx_cnt]; - } - - /* Set TX port */ - tx_start = core_info->num_tx_port; - core_info->num_tx_port += core_func->num_tx_port; - for (tx_cnt = 0; tx_cnt < core_func->num_tx_port; tx_cnt++) { - if_type = core_func->tx_ports[tx_cnt].if_type; - if_no = core_func->tx_ports[tx_cnt].if_no; - - core_info->tx_ports[tx_start + tx_cnt].if_type = if_type; - core_info->tx_ports[tx_start + tx_cnt].if_no = if_no; - - patch_info = get_if_area(if_type, if_no); - - patch_info->use_flg = 1; - if (unlikely(patch_info->tx_core != NULL)) { - RTE_LOG(ERR, APP, "Used TX port (core = %d, if_type = %d, if_no = %d)\n", - core_func->core_no, if_type, if_no); - return -1; - } - - /* Hold core info is to be referred for updating this information */ - patch_info->tx_core_no = core_func->core_no; - patch_info->tx_core = &core_info->tx_ports[tx_start + tx_cnt]; - } + int cnt = 0; + memset(&g_core_info, 0x00, sizeof(g_core_info)); + set_all_core_status(SPP_CORE_STOP); + for (cnt = 0; cnt < RTE_MAX_LCORE; cnt++) { + g_core_info[cnt].ref_index = 0; + g_core_info[cnt].upd_index = 1; } - - return 0; + memset(g_change_core, 0x00, sizeof(g_change_core)); } /** - * Load mac table entries from config and setup patches + * Setup port info of port on host * * TODO(yasufum) refactor, change if to iface. */ static int -set_from_classifier_table(struct spp_config_area *config) +set_nic_interface(void) { - enum port_type if_type; - int if_no = 0; - int mac_cnt = 0; - struct spp_config_mac_table_element *mac_table = NULL; - struct patch_info *patch_info = NULL; - for (mac_cnt = 0; mac_cnt < config->classifier_table.num_table; mac_cnt++) { - mac_table = &config->classifier_table.mac_tables[mac_cnt]; - - if_type = mac_table->port.if_type; - if_no = mac_table->port.if_no; - - /* Retrieve patch corresponding to type and number of the interface */ - patch_info = get_if_area(if_type, if_no); - - if (unlikely(patch_info->use_flg == 0)) { - RTE_LOG(ERR, APP, "Not used interface (if_type = %d, if_no = %d)\n", - if_type, if_no); - return -1; - } + int nic_cnt = 0; - /* Set mac address from the table for destination tx, not need for rx */ - patch_info->mac_addr = mac_table->mac_addr; - strcpy(patch_info->mac_addr_str, mac_table->mac_addr_str); - if (unlikely(patch_info->tx_core != NULL)) { - patch_info->tx_core->mac_addr = mac_table->mac_addr; - strcpy(patch_info->tx_core->mac_addr_str, mac_table->mac_addr_str); - } - } - return 0; -} - -/** - * Setup patch info of port on host - * - * TODO(yasufum) refactor, change if to iface. - */ -static int -set_nic_interface(struct spp_config_area *config __attribute__ ((unused))) -{ /* NIC Setting */ g_if_info.num_nic = rte_eth_dev_count(); if (g_if_info.num_nic > RTE_MAX_ETHPORTS) { g_if_info.num_nic = RTE_MAX_ETHPORTS; } - int nic_cnt, nic_num = 0; - struct patch_info *patch_info = NULL; - for (nic_cnt = 0; nic_cnt < RTE_MAX_ETHPORTS; nic_cnt++) { - patch_info = &g_if_info.nic_patchs[nic_cnt]; - patch_info->dpdk_port = nic_cnt; - - /* Skip for no used nic */ - if (patch_info->use_flg == 0) { - continue; - } - - if (patch_info->rx_core != NULL) { - patch_info->rx_core->dpdk_port = nic_cnt; - } - if (patch_info->tx_core != NULL) { - patch_info->tx_core->dpdk_port = nic_cnt; - } - - nic_num++; - } - - if (unlikely(nic_num > g_if_info.num_nic)) { - RTE_LOG(ERR, APP, "NIC Setting mismatch. (IF = %d, config = %d)\n", - nic_num, g_if_info.num_nic); - return -1; + for (nic_cnt = 0; nic_cnt < g_if_info.num_nic; nic_cnt++) { + g_if_info.nic[nic_cnt].dpdk_port = nic_cnt; } return 0; } /** - * Setup vhost interfaces from config - * - * TODO(yasufum) refactor, change if to iface. - */ -static int -set_vhost_interface(struct spp_config_area *config) -{ - int vhost_cnt, vhost_num = 0; - g_if_info.num_vhost = config->proc.num_vhost; - struct patch_info *patch_info = NULL; - for (vhost_cnt = 0; vhost_cnt < RTE_MAX_ETHPORTS; vhost_cnt++) { - patch_info = &g_if_info.vhost_patchs[vhost_cnt]; - if (patch_info->use_flg == 0) { - /* Not Used */ - continue; - } - - int dpdk_port = add_vhost_pmd(vhost_cnt, g_startup_param.vhost_client); - if (unlikely(dpdk_port < 0)) { - RTE_LOG(ERR, APP, "VHOST add failed. (no = %d)\n", - vhost_cnt); - return -1; - } - patch_info->dpdk_port = dpdk_port; - - if (patch_info->rx_core != NULL) { - patch_info->rx_core->dpdk_port = dpdk_port; - } - if (patch_info->tx_core != NULL) { - patch_info->tx_core->dpdk_port = dpdk_port; - } - vhost_num++; - } - if (unlikely(vhost_num > g_if_info.num_vhost)) { - RTE_LOG(ERR, APP, "VHOST Setting mismatch. (IF = %d, config = %d)\n", - vhost_num, g_if_info.num_vhost); - return -1; - } - return 0; -} - -/** - * Setup ring interfaces from config - * - * TODO(yasufum) refactor, change if to iface. - */ -static int -set_ring_interface(struct spp_config_area *config) -{ - int ring_cnt, ring_num = 0; - g_if_info.num_ring = config->proc.num_ring; - struct patch_info *patch_info = NULL; - for (ring_cnt = 0; ring_cnt < RTE_MAX_ETHPORTS; ring_cnt++) { - patch_info = &g_if_info.ring_patchs[ring_cnt]; - - if (patch_info->use_flg == 0) { - /* Skip for no used nic */ - continue; - } - - int dpdk_port = add_ring_pmd(ring_cnt); - if (unlikely(dpdk_port < 0)) { - RTE_LOG(ERR, APP, "RING add failed. (no = %d)\n", - ring_cnt); - return -1; - } - patch_info->dpdk_port = dpdk_port; - - if (patch_info->rx_core != NULL) { - patch_info->rx_core->dpdk_port = dpdk_port; - } - if (patch_info->tx_core != NULL) { - patch_info->tx_core->dpdk_port = dpdk_port; - } - ring_num++; - } - if (unlikely(ring_num > g_if_info.num_ring)) { - RTE_LOG(ERR, APP, "RING Setting mismatch. (IF = %d, config = %d)\n", - ring_num, g_if_info.num_ring); - return -1; - } - return 0; -} - -/** * Setup management info for spp_vf * * TODO(yasufum) refactor, change if to iface. * TODO(yasufum) refactor, change function name from manage to mng or management */ static int -init_manage_data(struct spp_config_area *config) +init_manage_data(void) { /* Initialize interface and core infomation */ init_if_info(); init_core_info(); + init_component_info(); - /* Load config for resource assingment and network configuration */ - int ret_proc = set_from_proc_info(config); - if (unlikely(ret_proc != 0)) { - return -1; - } - int ret_classifier = set_from_classifier_table(config); - if (unlikely(ret_classifier != 0)) { - return -1; - } - - int ret_nic = set_nic_interface(config); + int ret_nic = set_nic_interface(); if (unlikely(ret_nic != 0)) { return -1; } - int ret_vhost = set_vhost_interface(config); - if (unlikely(ret_vhost != 0)) { - return -1; - } - - int ret_ring = set_ring_interface(config); - if (unlikely(ret_ring != 0)) { - return -1; - } - return 0; } @@ -772,7 +537,7 @@ print_ring_latency_stats(void) printf("RING Latency\n"); printf(" RING"); for (ring_cnt = 0; ring_cnt < RTE_MAX_ETHPORTS; ring_cnt++) { - if (g_if_info.ring_patchs[ring_cnt].use_flg == 0) { + if (g_if_info.ring[ring_cnt].if_type == UNDEF) { continue; } spp_ringlatencystats_get_stats(ring_cnt, &stats[ring_cnt]); @@ -783,7 +548,7 @@ print_ring_latency_stats(void) for (stats_cnt = 0; stats_cnt < SPP_RINGLATENCYSTATS_STATS_SLOT_COUNT; stats_cnt++) { printf("%3dns", stats_cnt); for (ring_cnt = 0; ring_cnt < RTE_MAX_ETHPORTS; ring_cnt++) { - if (g_if_info.ring_patchs[ring_cnt].use_flg == 0) { + if (g_if_info.ring[ring_cnt].if_type == UNDEF) { continue; } @@ -800,7 +565,7 @@ print_ring_latency_stats(void) * Remove sock file */ static void -del_vhost_sockfile(struct patch_info *vhost_patchs) +del_vhost_sockfile(struct spp_port_info *vhost) { int cnt; @@ -809,7 +574,7 @@ del_vhost_sockfile(struct patch_info *vhost_patchs) return; for (cnt = 0; cnt < RTE_MAX_ETHPORTS; cnt++) { - if (likely(vhost_patchs[cnt].use_flg == 0)) { + if (likely(vhost[cnt].if_type == UNDEF)) { /* Skip removing if it is not using vhost */ continue; } @@ -818,6 +583,95 @@ del_vhost_sockfile(struct patch_info *vhost_patchs) } } +/* Get component type of target core */ +enum spp_component_type +spp_get_component_type(unsigned int lcore_id) +{ + struct core_mng_info *info = &g_core_info[lcore_id]; + return info->core[info->ref_index].type; +} + +/* Get component type being updated on target core */ +enum spp_component_type +spp_get_component_type_update(unsigned int lcore_id) +{ + struct core_mng_info *info = &g_core_info[lcore_id]; + return info->core[info->upd_index].type; +} + +/* Get core ID of target component */ +unsigned int +spp_get_component_core(int component_id) +{ + struct spp_component_info *info = &g_component_info[component_id]; + return info->lcore_id; +} + +/* Get usage area of target core */ +static struct core_info * +get_core_info(unsigned int lcore_id) +{ + struct core_mng_info *info = &g_core_info[lcore_id]; + return &(info->core[info->ref_index]); +} + +/* Check core index change */ +int +spp_check_core_index(unsigned int lcore_id) +{ + struct core_mng_info *info = &g_core_info[lcore_id]; + return info->ref_index == info->upd_index; +} + +/* Main process of slave core */ +static int +slave_main(void *arg __attribute__ ((unused))) +{ + int ret = 0; + int cnt = 0; + unsigned int lcore_id = rte_lcore_id(); + enum spp_core_status status = SPP_CORE_STOP; + struct core_mng_info *info = &g_core_info[lcore_id]; + struct core_info *core = get_core_info(lcore_id); + + RTE_LOG(INFO, APP, "Core[%d] Start.\n", lcore_id); + set_core_status(lcore_id, SPP_CORE_IDLE); + + while((status = spp_get_core_status(lcore_id)) != SPP_CORE_STOP_REQUEST) { + if (status != SPP_CORE_FORWARD) + continue; + + if (spp_check_core_index(lcore_id)) { + /* Setting with the flush command trigger. */ + info->ref_index = (info->upd_index+1)%SPP_INFO_AREA_MAX; + core = get_core_info(lcore_id); + } + + for (cnt = 0; cnt < core->num; cnt++) { + if (spp_get_component_type(lcore_id) == SPP_COMPONENT_CLASSIFIER_MAC) { + /* Classifier loops inside the function. */ + ret = spp_classifier_mac_do(core->id[cnt]); + break; + } else { + /* Forward / Merge returns at once. */ + /* It is for processing multiple components. */ + ret = spp_forward(core->id[cnt]); + if (unlikely(ret != 0)) + break; + } + } + if (unlikely(ret != 0)) { + RTE_LOG(ERR, APP, "Core[%d] Component Error. (id = %d)\n", + lcore_id, core->id[cnt]); + break; + } + } + + set_core_status(lcore_id, SPP_CORE_STOP); + RTE_LOG(INFO, APP, "Core[%d] End.\n", lcore_id); + return ret; +} + /* TODO(yasufum) refactor, change if to iface. */ /* TODO(yasufum) change test using ut_main(), or add desccription for what and why use it */ /* TODO(yasufum) change to return -1 explicity if error is occured. */ @@ -842,10 +696,6 @@ ut_main(int argc, char *argv[]) signal(SIGTERM, stop_process); signal(SIGINT, stop_process); - /* Setup config wiht default file path */ - strcpy(config_file_path, SPP_CONFIG_FILE_PATH); - - unsigned int main_lcore_id = 0xffffffff; while(1) { int ret_dpdk = rte_eal_init(argc, argv); if (unlikely(ret_dpdk < 0)) { @@ -864,17 +714,10 @@ ut_main(int argc, char *argv[]) break; } - RTE_LOG(INFO, APP, "Load config file(%s)\n", config_file_path); - - int ret_config = spp_config_load_file(config_file_path, 0, &g_config); - if (unlikely(ret_config != 0)) { - break; - } - /* Get lcore id of main thread to set its status after */ - main_lcore_id = rte_lcore_id(); + g_main_lcore_id = rte_lcore_id(); - int ret_manage = init_manage_data(&g_config); + int ret_manage = init_manage_data(); if (unlikely(ret_manage != 0)) { break; } @@ -884,7 +727,9 @@ ut_main(int argc, char *argv[]) break; } - /* Setup connection for accepting commands from controller */ + spp_forward_init(); + + /* Setup connection for accepting commands from controller */ int ret_command_init = spp_command_proc_init( g_startup_param.server_ip, g_startup_param.server_port); @@ -903,37 +748,29 @@ ut_main(int argc, char *argv[]) /* Start worker threads of classifier and forwarder */ unsigned int lcore_id = 0; RTE_LCORE_FOREACH_SLAVE(lcore_id) { - if (g_core_info[lcore_id].type == SPP_CONFIG_CLASSIFIER_MAC) { - rte_eal_remote_launch(spp_classifier_mac_do, - (void *)&g_core_info[lcore_id], - lcore_id); - } else { - rte_eal_remote_launch(spp_forward, - (void *)&g_core_info[lcore_id], - lcore_id); - } + rte_eal_remote_launch(slave_main, NULL, lcore_id); } - /* Set the status of main thread to idle */ - g_core_info[main_lcore_id].status = SPP_CORE_IDLE; + /* Set the status of main thread to idle */ + g_core_info[g_main_lcore_id].status = SPP_CORE_IDLE; int ret_wait = check_core_status_wait(SPP_CORE_IDLE); if (unlikely(ret_wait != 0)) { break; } /* Start forwarding */ - set_core_status(SPP_CORE_FORWARD); + set_all_core_status(SPP_CORE_FORWARD); RTE_LOG(INFO, APP, "My ID %d start handling message\n", 0); RTE_LOG(INFO, APP, "[Press Ctrl-C to quit ...]\n"); /* Enter loop for accepting commands */ int ret_do = 0; #ifndef USE_UT_SPP_VF - while(likely(g_core_info[main_lcore_id].status != SPP_CORE_STOP_REQUEST)) { + while(likely(g_core_info[g_main_lcore_id].status != SPP_CORE_STOP_REQUEST)) { #else { #endif - /* Receive command */ + /* Receive command */ ret_do = spp_command_proc_do(); if (unlikely(ret_do != 0)) { break; @@ -947,6 +784,7 @@ ut_main(int argc, char *argv[]) } if (unlikely(ret_do != 0)) { + set_all_core_status(SPP_CORE_STOP_REQUEST); break; } @@ -955,16 +793,16 @@ ut_main(int argc, char *argv[]) } /* Finalize to exit */ - if (main_lcore_id == rte_lcore_id()) + if (g_main_lcore_id == rte_lcore_id()) { - g_core_info[main_lcore_id].status = SPP_CORE_STOP; + g_core_info[g_main_lcore_id].status = SPP_CORE_STOP; int ret_core_end = check_core_status_wait(SPP_CORE_STOP); if (unlikely(ret_core_end != 0)) { RTE_LOG(ERR, APP, "Core did not stop.\n"); } /* Remove vhost sock file if it is not running in vhost-client mode */ - del_vhost_sockfile(g_if_info.vhost_patchs); + del_vhost_sockfile(g_if_info.vhost); } #ifdef SPP_RINGLATENCYSTATS_ENABLE @@ -982,123 +820,478 @@ spp_get_client_id(void) } /** - * Check mac address used on the interface for registering or removing + * Check mac address used on the port for registering or removing * * TODO(yasufum) refactor, change if to iface. */ -static int -check_mac_used_interface(uint64_t mac_addr, enum port_type *if_type, int *if_no) +int +spp_check_mac_used_port(uint64_t mac_addr, enum port_type if_type, int if_no) { - int cnt = 0; - for (cnt = 0; cnt < RTE_MAX_ETHPORTS; cnt++) { - if (unlikely(g_if_info.nic_patchs[cnt].mac_addr == mac_addr)) { - *if_type = PHY; - *if_no = cnt; - return 0; - } - if (unlikely(g_if_info.vhost_patchs[cnt].mac_addr == mac_addr)) { - *if_type = VHOST; - *if_no = cnt; - return 0; + struct spp_port_info *port_info = get_if_area(if_type, if_no); + return (mac_addr == port_info->mac_addr); +} + +/* + * Check if port has been added. + */ +int +spp_check_added_port(enum port_type if_type, int if_no) +{ + struct spp_port_info *port = get_if_area(if_type, if_no); + return port->if_type != UNDEF; +} + +/* + * Check if component is using port. + */ +int +spp_check_used_port(enum port_type if_type, int if_no, enum spp_port_rxtx rxtx) +{ + int cnt, port_cnt, max = 0; + struct spp_component_info *component = NULL; + struct spp_port_info **port_array = NULL; + struct spp_port_info *port = get_if_area(if_type, if_no); + + if (port == NULL) + return SPP_RET_NG; + + for (cnt = 0; cnt < RTE_MAX_LCORE; cnt++) { + component = &g_component_info[cnt]; + if (component->type == SPP_COMPONENT_UNUSE) + continue; + + if (rxtx == SPP_PORT_RXTX_RX) { + max = component->num_rx_port; + port_array = component->rx_ports; + } else if (rxtx == SPP_PORT_RXTX_TX) { + max = component->num_tx_port; + port_array = component->tx_ports; } - if (unlikely(g_if_info.ring_patchs[cnt].mac_addr == mac_addr)) { - *if_type = RING; - *if_no = cnt; - return 0; + for (port_cnt = 0; port_cnt < max; port_cnt++) { + if (unlikely(port_array[port_cnt] == port)) + return cnt; } } - return -1; + + return SPP_RET_NG; +} + +/* + * Set port change to component. + */ +static void +set_component_change_port(struct spp_port_info *port, enum spp_port_rxtx rxtx) +{ + int ret = 0; + if ((rxtx == SPP_PORT_RXTX_RX) || (rxtx == SPP_PORT_RXTX_ALL)) { + ret = spp_check_used_port(port->if_type, port->if_no, SPP_PORT_RXTX_RX); + if (ret >= 0) + g_change_component[ret] = 1; + } + + if ((rxtx == SPP_PORT_RXTX_TX) || (rxtx == SPP_PORT_RXTX_ALL)) { + ret = spp_check_used_port(port->if_type, port->if_no, SPP_PORT_RXTX_TX); + if (ret >= 0) + g_change_component[ret] = 1; + } } int spp_update_classifier_table( + enum spp_command_action action, enum spp_classifier_type type, const char *data, - const struct spp_config_port_info *port) + const struct spp_port_index *port) { - enum port_type if_type = UNDEF; - int if_no = 0; - struct patch_info *patch_info = NULL; + struct spp_port_info *port_info = NULL; int64_t ret_mac = 0; uint64_t mac_addr = 0; - int ret_used = 0; if (type == SPP_CLASSIFIER_TYPE_MAC) { RTE_LOG(DEBUG, APP, "update_classifier_table ( type = mac, data = %s, port = %d:%d )\n", data, port->if_type, port->if_no); - ret_mac = spp_config_change_mac_str_to_int64(data); + ret_mac = spp_change_mac_str_to_int64(data); if (unlikely(ret_mac == -1)) { RTE_LOG(ERR, APP, "MAC address format error. ( mac = %s )\n", data); return SPP_RET_NG; } - mac_addr = (uint64_t)ret_mac; - ret_used = check_mac_used_interface(mac_addr, &if_type, &if_no); - if (port->if_type == UNDEF) { - /* Delete(unuse) */ - if (ret_used < 0) { - RTE_LOG(DEBUG, APP, "No MAC address. ( mac = %s )\n", data); - return SPP_RET_OK; - } + port_info = get_if_area(port->if_type, port->if_no); + if (unlikely(port_info == NULL)) { + RTE_LOG(ERR, APP, "No port. ( port = %d:%d )\n", + port->if_type, port->if_no); + return SPP_RET_NG; + } + if (unlikely(port_info->if_type == UNDEF)) { + RTE_LOG(ERR, APP, "Port not added. ( port = %d:%d )\n", + port->if_type, port->if_no); + return SPP_RET_NG; + } - patch_info = get_if_area(if_type, if_no); - if (unlikely(patch_info == NULL)) { - RTE_LOG(ERR, APP, "No port. ( port = %d:%d )\n", port->if_type, port->if_no); + if (action == SPP_CMD_ACTION_DEL) { + /* Delete */ + if ((port_info->mac_addr != 0) && + unlikely(port_info->mac_addr != mac_addr)) { + RTE_LOG(ERR, APP, "MAC address is different. ( mac = %s )\n", + data); return SPP_RET_NG; } - patch_info->mac_addr = 0; - memset(patch_info->mac_addr_str, 0x00, SPP_CONFIG_STR_LEN); - if (patch_info->tx_core != NULL) { - patch_info->tx_core->mac_addr = 0; - memset(patch_info->tx_core->mac_addr_str, 0x00, SPP_CONFIG_STR_LEN); - } + port_info->mac_addr = 0; + memset(port_info->mac_addr_str, 0x00, SPP_MIN_STR_LEN); } - else - { + else if (action == SPP_CMD_ACTION_ADD) { /* Setting */ - if (unlikely(ret_used == 0)) { - if (likely(port->if_type == if_type) && likely(port->if_no == if_no)) { - RTE_LOG(DEBUG, APP, "Same MAC address and port. ( mac = %s, port = %d:%d )\n", - data, if_type, if_no); - return SPP_RET_OK; - } - else - { - RTE_LOG(ERR, APP, "MAC address in used. ( mac = %s )\n", data); - return SPP_RET_USED_MAC; - } + if (unlikely(port_info->mac_addr != 0)) { + RTE_LOG(ERR, APP, "Port in used. ( port = %d:%d )\n", + port->if_type, port->if_no); + return SPP_RET_NG; } - patch_info = get_if_area(port->if_type, port->if_no); - if (unlikely(patch_info == NULL)) { - RTE_LOG(ERR, APP, "No port. ( port = %d:%d )\n", port->if_type, port->if_no); + port_info->mac_addr = mac_addr; + strcpy(port_info->mac_addr_str, data); + } + } + + /* TODO(yasufum) add desc how it is used and why changed core is kept */ + set_component_change_port(port_info, SPP_PORT_RXTX_TX); + return SPP_RET_OK; +} + +/* Get free component */ +static int +get_free_component(void) +{ + int cnt = 0; + for (cnt = 0; cnt < RTE_MAX_LCORE; cnt++) { + if (g_component_info[cnt].type == SPP_COMPONENT_UNUSE) + return cnt; + } + return -1; +} + +/* Get name matching component */ +int +spp_get_component_id(const char *name) +{ + int cnt = 0; + if (name[0] == '\0') + return SPP_RET_NG; + + for (cnt = 0; cnt < RTE_MAX_LCORE; cnt++) { + if (strcmp(name, g_component_info[cnt].name) == 0) + return cnt; + } + return SPP_RET_NG; +} + +static int +get_del_core_element(int info, int num, int *array) +{ + int cnt; + int match = -1; + int max = num; + + for (cnt = 0; cnt < max; cnt++) { + if (info == array[cnt]) + match = cnt; + } + + if (match < 0) + return -1; + + /* Last element is excluded from movement. */ + max--; + + for (cnt = match; cnt < max; cnt++) { + array[cnt] = array[cnt+1]; + } + + /* Last element is cleared. */ + array[cnt] = 0; + return 0; +} + +/* Component command to execute it */ +int +spp_update_component( + enum spp_command_action action, + const char *name, + unsigned int lcore_id, + enum spp_component_type type) +{ + int ret = SPP_RET_NG; + int ret_del = -1; + int component_id = 0; + unsigned int tmp_lcore_id = 0; + struct spp_component_info *component = NULL; + struct core_info *core = NULL; + struct core_mng_info *info = NULL; + + switch (action) { + case SPP_CMD_ACTION_START: + info = &g_core_info[lcore_id]; + if (info->status == SPP_CORE_UNUSE) { + RTE_LOG(ERR, APP, "Core unavailable.\n"); + return SPP_RET_NG; + } + + component_id = spp_get_component_id(name); + if (component_id >= 0) { + RTE_LOG(ERR, APP, "Component name in used.\n"); + return SPP_RET_NG; + } + + component_id = get_free_component(); + if (component_id < 0) { + RTE_LOG(ERR, APP, "Component upper limit is over.\n"); + return SPP_RET_NG; + } + + core = &info->core[info->upd_index]; + if ((core->type != SPP_COMPONENT_UNUSE) && (core->type != type)) { + RTE_LOG(ERR, APP, "Component type is error.\n"); + return SPP_RET_NG; + } + + component = &g_component_info[component_id]; + memset(component, 0x00, sizeof(struct spp_component_info)); + strcpy(component->name, name); + component->type = type; + component->lcore_id = lcore_id; + component->component_id = component_id; + + core->type = type; + core->id[core->num] = component_id; + core->num++; + ret = SPP_RET_OK; + tmp_lcore_id = lcore_id; + break; + + case SPP_CMD_ACTION_STOP: + component_id = spp_get_component_id(name); + if (component_id < 0) + return SPP_RET_OK; + + component = &g_component_info[component_id]; + tmp_lcore_id = component->lcore_id; + memset(component, 0x00, sizeof(struct spp_component_info)); + + info = &g_core_info[tmp_lcore_id]; + core = &info->core[info->upd_index]; + ret_del = get_del_core_element(component_id, + core->num, core->id); + if (ret_del >= 0) + /* If deleted, decrement number. */ + core->num--; + + if (core->num == 0) + core->type = SPP_COMPONENT_UNUSE; + + ret = SPP_RET_OK; + break; + + default: + break; + } + + g_change_core[tmp_lcore_id] = 1; + return ret; +} + +static int +check_port_element( + struct spp_port_info *info, + int num, + struct spp_port_info *array[]) +{ + int cnt = 0; + int match = -1; + for (cnt = 0; cnt < num; cnt++) { + if (info == array[cnt]) + match = cnt; + } + return match; +} + +static int +get_del_port_element( + struct spp_port_info *info, + int num, + struct spp_port_info *array[]) +{ + int cnt = 0; + int match = -1; + int max = num; + + match = check_port_element(info, num, array); + if (match < 0) + return -1; + + /* Last element is excluded from movement. */ + max--; + + for (cnt = match; cnt < max; cnt++) { + array[cnt] = array[cnt+1]; + } + + /* Last element is cleared. */ + array[cnt] = NULL; + return 0; +} + +/* Port add or del to execute it */ +int +spp_update_port(enum spp_command_action action, + const struct spp_port_index *port, + enum spp_port_rxtx rxtx, + const char *name) +{ + int ret = SPP_RET_NG; + int ret_check = -1; + int ret_del = -1; + int component_id = 0; + struct spp_component_info *component = NULL; + struct spp_port_info *port_info = NULL; + int *num = NULL; + struct spp_port_info **ports = NULL; + + component_id = spp_get_component_id(name); + if (component_id < 0) { + RTE_LOG(ERR, APP, "Unknown component by port command. (component = %s)\n", + name); + return SPP_RET_NG; + } + + component = &g_component_info[component_id]; + port_info = get_if_area(port->if_type, port->if_no); + if (rxtx == SPP_PORT_RXTX_RX) { + num = &component->num_rx_port; + ports = component->rx_ports; + } else { + num = &component->num_tx_port; + ports = component->tx_ports; + } + + switch (action) { + case SPP_CMD_ACTION_ADD: + ret_check = check_port_element(port_info, *num, ports); + if (ret_check >= 0) + return SPP_RET_OK; + + if (*num >= RTE_MAX_ETHPORTS) { + RTE_LOG(ERR, APP, "Port upper limit is over.\n"); + break; + } + + port_info->if_type = port->if_type; + ports[*num] = port_info; + (*num)++; + + ret = SPP_RET_OK; + break; + + case SPP_CMD_ACTION_DEL: + ret_del = get_del_port_element(port_info, *num, ports); + if (ret_del == 0) + (*num)--; /* If deleted, decrement number. */ + ret = SPP_RET_OK; + break; + default: + break; + } + + g_change_component[component_id] = 1; + return ret; +} + +/* Flush initial setting of each interface. */ +static int +flush_port(void) +{ + int ret = 0; + int cnt = 0; + struct spp_port_info *port = NULL; + + /* Initialize added vhost. */ + for (cnt = 0; cnt < RTE_MAX_ETHPORTS; cnt++) { + port = &g_if_info.vhost[cnt]; + if ((port->if_type != UNDEF) && (port->dpdk_port < 0)) { + ret = add_vhost_pmd(port->if_no, g_startup_param.vhost_client); + if (ret < 0) return SPP_RET_NG; - } + port->dpdk_port = ret; + } + } - if (unlikely(patch_info->use_flg == 0)) { - RTE_LOG(ERR, APP, "Port not added. ( port = %d:%d )\n", port->if_type, port->if_no); - return SPP_RET_NOT_ADD_PORT; - } + /* Initialize added ring. */ + for (cnt = 0; cnt < RTE_MAX_ETHPORTS; cnt++) { + port = &g_if_info.ring[cnt]; + if ((port->if_type != UNDEF) && (port->dpdk_port < 0)) { + ret = add_ring_pmd(port->if_no); + if (ret < 0) + return SPP_RET_NG; + port->dpdk_port = ret; + } + } + return SPP_RET_OK; +} - if (unlikely(patch_info->mac_addr != 0)) { - RTE_LOG(ERR, APP, "Port in used. ( port = %d:%d )\n", port->if_type, port->if_no); - return SPP_RET_USED_PORT; - } +/* Flush changed core. */ +static void +flush_core(void) +{ + int cnt = 0; + struct core_mng_info *info = NULL; - patch_info->mac_addr = mac_addr; - strcpy(patch_info->mac_addr_str, data); - if (patch_info->tx_core != NULL) { - patch_info->tx_core->mac_addr = mac_addr; - strcpy(patch_info->tx_core->mac_addr_str, data); - } + /* Changed core has changed index. */ + for (cnt = 0; cnt < RTE_MAX_LCORE; cnt++) { + if (g_change_core[cnt] != 0) { + info = &g_core_info[cnt]; + info->upd_index = info->ref_index; + } + } + + /* Waiting for changed core change. */ + for (cnt = 0; cnt < RTE_MAX_LCORE; cnt++) { + if (g_change_core[cnt] != 0) { + info = &g_core_info[cnt]; + while(likely(info->ref_index == info->upd_index)) + rte_delay_us_block(SPP_CHANGE_UPDATE_INTERVAL); + + memcpy(&info->core[info->upd_index], + &info->core[info->ref_index], + sizeof(struct core_info)); } } +} - /* TODO(yasufum) add desc how it is used and why changed core is kept */ - g_change_core[patch_info->tx_core_no] = 1; +/* Flush chagned component */ +static int +flush_component(void) +{ + int ret = 0; + int cnt = 0; + struct spp_component_info *component_info = NULL; + + for(cnt = 0; cnt < RTE_MAX_LCORE; cnt++) { + if (g_change_component[cnt] == 0) + continue; + + component_info = &g_component_info[cnt]; + if (component_info->type == SPP_COMPONENT_CLASSIFIER_MAC) { + ret = spp_classifier_mac_update(component_info); + } else { + ret = spp_forward_update(component_info); + } + if (unlikely(ret < 0)) { + RTE_LOG(ERR, APP, "Flush error. ( component = %s, type = %d)\n", + component_info->name, component_info->type); + return SPP_RET_NG; + } + } return SPP_RET_OK; } @@ -1106,26 +1299,24 @@ spp_update_classifier_table( int spp_flush(void) { - int core_cnt = 0; /* increment core id */ - int ret_classifier = 0; - struct spp_core_info *core_info = NULL; + int ret = -1; - for(core_cnt = 0; core_cnt < SPP_CONFIG_CORE_MAX; core_cnt++) { - if (g_change_core[core_cnt] == 0) - continue; + /* Initial setting of each interface. */ + ret = flush_port(); + if (ret < 0) + return ret; - core_info = &g_core_info[core_cnt]; - if (core_info->type == SPP_CONFIG_CLASSIFIER_MAC) { - ret_classifier = spp_classifier_mac_update(core_info); - if (unlikely(ret_classifier < 0)) { - RTE_LOG(ERR, APP, "Flush error. ( component = classifier_mac)\n"); - return SPP_RET_NG; - } - } - } + /* Flush of core index. */ + flush_core(); + memset(g_change_core, 0x00, sizeof(g_change_core)); + + /* Flush of component */ + ret = flush_component(); + if (ret < 0) + return ret; /* Finally, zero-clear g_change_core */ - memset(g_change_core, 0x00, sizeof(g_change_core)); + memset(g_change_component, 0x00, sizeof(g_change_component)); return SPP_RET_OK; } @@ -1143,3 +1334,151 @@ spp_iterate_classifier_table( return SPP_RET_OK; } + +/** + * Sepeparate port id of combination of iface type and number and + * assign to given argment, if_type and if_no. + * + * For instance, 'ring:0' is separated to 'ring' and '0'. + * + * TODO(yasufum) change if to iface + */ +int +spp_get_if_info(const char *port, enum port_type *if_type, int *if_no) +{ + enum port_type type = UNDEF; + const char *no_str = NULL; + char *endptr = NULL; + + /* Find out which type of interface from port */ + if (strncmp(port, SPP_IFTYPE_NIC_STR ":", strlen(SPP_IFTYPE_NIC_STR)+1) == 0) { + /* NIC */ + type = PHY; + no_str = &port[strlen(SPP_IFTYPE_NIC_STR)+1]; + } else if (strncmp(port, SPP_IFTYPE_VHOST_STR ":", strlen(SPP_IFTYPE_VHOST_STR)+1) == 0) { + /* VHOST */ + type = VHOST; + no_str = &port[strlen(SPP_IFTYPE_VHOST_STR)+1]; + } else if (strncmp(port, SPP_IFTYPE_RING_STR ":", strlen(SPP_IFTYPE_RING_STR)+1) == 0) { + /* RING */ + type = RING; + no_str = &port[strlen(SPP_IFTYPE_RING_STR)+1]; + } else { + /* OTHER */ + RTE_LOG(ERR, APP, "Unknown interface type. (port = %s)\n", port); + return -1; + } + + /* Change type of number of interface */ + int ret_no = strtol(no_str, &endptr, 0); + if (unlikely(no_str == endptr) || unlikely(*endptr != '\0')) { + /* No IF number */ + RTE_LOG(ERR, APP, "No interface number. (port = %s)\n", port); + return -1; + } + + *if_type = type; + *if_no = ret_no; + + RTE_LOG(DEBUG, APP, "Port = %s => Type = %d No = %d\n", + port, *if_type, *if_no); + return 0; +} + +/** + * Generate a formatted string of conbination from interface type and + * number and assign to given 'port' + */ +int spp_format_port_string(char *port, enum port_type if_type, int if_no) +{ + const char* if_type_str; + + switch (if_type) { + case PHY: + if_type_str = SPP_IFTYPE_NIC_STR; + break; + case RING: + if_type_str = SPP_IFTYPE_RING_STR; + break; + case VHOST: + if_type_str = SPP_IFTYPE_VHOST_STR; + break; + default: + return -1; + } + + sprintf(port, "%s:%d", if_type_str, if_no); + + return 0; +} + +/** + * Change mac address of 'aa:bb:cc:dd:ee:ff' to int64 and return it + */ +int64_t +spp_change_mac_str_to_int64(const char *mac) +{ + int64_t ret_mac = 0; + int64_t token_val = 0; + int token_cnt = 0; + char tmp_mac[SPP_MIN_STR_LEN]; + char *str = tmp_mac; + char *saveptr = NULL; + char *endptr = NULL; + + RTE_LOG(DEBUG, APP, "MAC address change. (mac = %s)\n", mac); + + strcpy(tmp_mac, mac); + while(1) { + /* Split by colon(':') */ + char *ret_tok = strtok_r(str, ":", &saveptr); + if (unlikely(ret_tok == NULL)) { + break; + } + + /* Check for mal-formatted address */ + if (unlikely(token_cnt >= ETHER_ADDR_LEN)) { + RTE_LOG(ERR, APP, "MAC address format error. (mac = %s)\n", + mac); + return -1; + } + + /* Convert string to hex value */ + int ret_tol = strtol(ret_tok, &endptr, 16); + if (unlikely(ret_tok == endptr) || unlikely(*endptr != '\0')) { + break; + } + + /* Append separated value to the result */ + token_val = (int64_t)ret_tol; + ret_mac |= token_val << (token_cnt * 8); + token_cnt++; + str = NULL; + } + + RTE_LOG(DEBUG, APP, "MAC address change. (mac = %s => 0x%08lx)\n", + mac, ret_mac); + return ret_mac; +} + +/** + * Return the type of forwarder as a member of enum of spp_component_type + */ +enum spp_component_type +spp_change_component_type(const char *type_str) +{ + if(strncmp(type_str, CORE_TYPE_CLASSIFIER_MAC_STR, + strlen(CORE_TYPE_CLASSIFIER_MAC_STR)+1) == 0) { + /* Classifier */ + return SPP_COMPONENT_CLASSIFIER_MAC; + } else if (strncmp(type_str, CORE_TYPE_MERGE_STR, + strlen(CORE_TYPE_MERGE_STR)+1) == 0) { + /* Merger */ + return SPP_COMPONENT_MERGE; + } else if (strncmp(type_str, CORE_TYPE_FORWARD_STR, + strlen(CORE_TYPE_FORWARD_STR)+1) == 0) { + /* Forwarder */ + return SPP_COMPONENT_FORWARD; + } + return SPP_COMPONENT_UNUSE; +} diff --git a/src/vf/spp_vf.h b/src/vf/spp_vf.h index b0da048..90a2886 100644 --- a/src/vf/spp_vf.h +++ b/src/vf/spp_vf.h @@ -2,18 +2,42 @@ #define __SPP_VF_H__ #include "common.h" -#include "spp_config.h" -#define SPP_CLIENT_MAX 128 +#define SPP_IFTYPE_NIC_STR "phy" +#define SPP_IFTYPE_VHOST_STR "vhost" +#define SPP_IFTYPE_RING_STR "ring" + +#define SPP_CLIENT_MAX 128 +#define SPP_INFO_AREA_MAX 2 +#define SPP_MIN_STR_LEN 32 +#define SPP_NAME_STR_LEN 128 + +#define SPP_CHANGE_UPDATE_INTERVAL 10 + +#define SPP_DEFAULT_CLASSIFIED_SPEC_STR "default" +#define SPP_DEFAULT_CLASSIFIED_DMY_ADDR_STR "00:00:00:00:00:01" +#define SPP_DEFAULT_CLASSIFIED_DMY_ADDR 0x010000000000 /* - * State on core + * State on component */ enum spp_core_status { + SPP_CORE_UNUSE, SPP_CORE_STOP, SPP_CORE_IDLE, SPP_CORE_FORWARD, - SPP_CORE_STOP_REQUEST + SPP_CORE_STOP_REQUEST, + SPP_CORE_IDLE_REQUEST +}; + +/* + * Process type for each component + */ +enum spp_component_type { + SPP_COMPONENT_UNUSE, + SPP_COMPONENT_CLASSIFIER_MAC, + SPP_COMPONENT_MERGE, + SPP_COMPONENT_FORWARD, }; /* @@ -30,34 +54,68 @@ enum spp_classifier_type { enum spp_return_value { SPP_RET_OK = 0, SPP_RET_NG = -1, - SPP_RET_USED_MAC = -2, - SPP_RET_NOT_ADD_PORT = -3, - SPP_RET_USED_PORT = -4 +}; + +/* Port type (rx or tx) */ +enum spp_port_rxtx { + SPP_PORT_RXTX_NONE, + SPP_PORT_RXTX_RX, + SPP_PORT_RXTX_TX, + SPP_PORT_RXTX_ALL, +}; + +/* command setting type */ +enum spp_command_action { + SPP_CMD_ACTION_NONE, + SPP_CMD_ACTION_START, + SPP_CMD_ACTION_STOP, + SPP_CMD_ACTION_ADD, + SPP_CMD_ACTION_DEL, +}; + +/* + * Interface information structure + */ +struct spp_port_index { + enum port_type if_type; + int if_no; }; /* - * Port info on core + * Port info */ -struct spp_core_port_info { +struct spp_port_info { enum port_type if_type; int if_no; int dpdk_port; uint64_t mac_addr; - char mac_addr_str[SPP_CONFIG_STR_LEN]; + char mac_addr_str[SPP_MIN_STR_LEN]; }; /* + * Component info + */ +struct spp_component_info { + char name[SPP_NAME_STR_LEN]; + enum spp_component_type type; + unsigned int lcore_id; + int component_id; + int num_rx_port; + int num_tx_port; + struct spp_port_info *rx_ports[RTE_MAX_ETHPORTS]; + struct spp_port_info *tx_ports[RTE_MAX_ETHPORTS]; +}; + +#if 0 +/* * Core info */ struct spp_core_info { - unsigned int lcore_id; - volatile enum spp_core_status status; - enum spp_core_type type; - int num_rx_port; - int num_tx_port; - struct spp_core_port_info rx_ports[RTE_MAX_ETHPORTS]; - struct spp_core_port_info tx_ports[RTE_MAX_ETHPORTS]; + enum spp_core_status status; + int num_component; + int component_id[SPP_CONFIG_CORE_MAX]; }; +#endif /* * Get client ID @@ -69,11 +127,33 @@ int spp_get_client_id(void); * Update Classifier_table * OK : SPP_RET_OK(0) * NG : SPP_RET_NG(-1) - * : SPP_RET_USED_MAC(-2) - * : SPP_RET_NOT_ADD_PORT(-3) - * : SPP_RET_USED_PORT(-4) */ -int spp_update_classifier_table(enum spp_classifier_type type, const char *data, const struct spp_config_port_info *port); +int spp_update_classifier_table( + enum spp_command_action action, + enum spp_classifier_type type, + const char *data, + const struct spp_port_index *port); + +/* + * Update component + * OK : SPP_RET_OK(0) + * NG : SPP_RET_NG(-1) + */ +int spp_update_component( + enum spp_command_action action, + const char *name, unsigned int lcore_id, + enum spp_component_type type); + +/* + * Update port + * OK : SPP_RET_OK(0) + * NG : SPP_RET_NG(-1) + */ +int spp_update_port( + enum spp_command_action action, + const struct spp_port_index *port, + enum spp_port_rxtx rxtx, + const char *name); /* * Flush SPP component @@ -87,7 +167,7 @@ typedef int (*spp_iterate_classifier_element_proc)( void *opaque, enum spp_classifier_type type, const char *data, - const struct spp_config_port_info *port); + const struct spp_port_index *port); /* iterate classifier table parameters */ struct spp_iterate_classifier_table_params { @@ -100,4 +180,79 @@ struct spp_iterate_classifier_table_params { */ int spp_iterate_classifier_table(struct spp_iterate_classifier_table_params *params); +/* Get core status */ +enum spp_core_status spp_get_core_status(unsigned int lcore_id); + +/* Get component type of target core */ +enum spp_component_type spp_get_component_type(unsigned int lcore_id); + +/* Get component type being updated on target core */ +enum spp_component_type spp_get_component_type_update(unsigned int lcore_id); + +/* + * Get core ID of target component + * RETURN : core ID + */ +unsigned int spp_get_component_core(int component_id); + +/* + * Check core index change + * RETURN : True if index has changed. + */ +int spp_check_core_index(unsigned int lcore_id); + +/* + * Get name matching component ID + * OK : component ID + * NG : SPP_RET_NG + */ +int spp_get_component_id(const char *name); + +/** + * Check mac address used on the port for registering or removing + * RETURN : True if target MAC address matches MAC address of port. + */ +int spp_check_mac_used_port(uint64_t mac_addr, enum port_type if_type, int if_no); + +/* + * Check if port has been added. + * RETURN : True if port has been added. + */ +int spp_check_added_port(enum port_type if_type, int if_no); + +/* + * Check if component is using port. + * OK : match component ID + * NG : SPP_RET_NG + */ +int spp_check_used_port(enum port_type if_type, int if_no, enum spp_port_rxtx rxtx); + +/* + * Change mac address string to int64 + * OK : int64 that store mac address + * NG : -1 + */ +int64_t spp_change_mac_str_to_int64(const char *mac); + +/* + * Extract if-type/if-number from port string + * + * OK : 0 + * NG : -1 + */ +int spp_get_if_info(const char *port, enum port_type *if_type, int *if_no); + +/* + * Format port string form if-type/if-number + * + * OK : 0 + * NG : -1 + */ +int spp_format_port_string(char *port, enum port_type if_type, int if_no); + +/* + * Change component type from string to type value. + */ +enum spp_component_type spp_change_component_type(const char *type_str); + #endif /* __SPP_VF_H__ */ -- 1.9.1