* [spp] [PATCH 01/57] spp_vf: add vf functions
2017-12-26 1:54 ` Yasufumi Ogawa
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 8:49 ` Yasufumi Ogawa
2017-12-28 4:55 ` [spp] [PATCH 02/57] spp_vf: support multi process x-fn-spp
` (55 subsequent siblings)
56 siblings, 1 reply; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Hi everyone,
This the first patch of series for spp_vf. Some of them might not comply
with coding style for whitespace or indenting and I would like to send
patches to fix it later.
I also would like to send another series of patches for documentation after
you accept first series.
Thanks,
* Classifier by MAC address
* Forwarder
* Merger
Signed-off-by: Tomoyuki Mizuguchi <mizuguchi.tomoyuki@po.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/Makefile | 1 +
src/vf/Makefile | 56 ++++
src/vf/classifier_mac.c | 233 ++++++++++++++
src/vf/classifier_mac.h | 12 +
src/vf/ringlatencystats.c | 147 +++++++++
src/vf/ringlatencystats.h | 69 ++++
src/vf/spp_config.c | 669 ++++++++++++++++++++++++++++++++++++++
src/vf/spp_config.h | 90 ++++++
src/vf/spp_forward.c | 106 +++++++
src/vf/spp_forward.h | 9 +
src/vf/spp_vf.c | 794 ++++++++++++++++++++++++++++++++++++++++++++++
src/vf/spp_vf.h | 40 +++
12 files changed, 2226 insertions(+)
create mode 100644 src/vf/Makefile
create mode 100644 src/vf/classifier_mac.c
create mode 100644 src/vf/classifier_mac.h
create mode 100644 src/vf/ringlatencystats.c
create mode 100644 src/vf/ringlatencystats.h
create mode 100644 src/vf/spp_config.c
create mode 100644 src/vf/spp_config.h
create mode 100644 src/vf/spp_forward.c
create mode 100644 src/vf/spp_forward.h
create mode 100644 src/vf/spp_vf.c
create mode 100644 src/vf/spp_vf.h
diff --git a/src/Makefile b/src/Makefile
index 6fd24b8..d2eb9b6 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -41,5 +41,6 @@ include $(RTE_SDK)/mk/rte.vars.mk
DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += nfv
DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += primary
DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += vm
+DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += vf
include $(RTE_SDK)/mk/rte.extsubdir.mk
diff --git a/src/vf/Makefile b/src/vf/Makefile
new file mode 100644
index 0000000..4961d2e
--- /dev/null
+++ b/src/vf/Makefile
@@ -0,0 +1,56 @@
+# BSD LICENSE
+#
+# Copyright(c) 2015-2016 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, can be overriden by command line or environment
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# binary name
+APP = spp_vf
+
+# all source are stored in SRCS-y
+SRCS-y := spp_vf.c spp_config.c classifier_mac.c spp_forward.c ringlatencystats.c ../shared/common.c
+
+CFLAGS += $(WERROR_FLAGS) -O3
+CFLAGS += -I$(SRCDIR)/../shared
+#CFLAGS += -DSPP_DEMONIZE
+#CFLAGS += -DSPP_RINGLATENCYSTATS_ENABLE
+
+LDLIBS += -ljansson
+ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
+LDLIBS += -lrte_pmd_ring
+LDLIBS += -lrte_pmd_vhost
+endif
+
+include $(RTE_SDK)/mk/rte.extapp.mk
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
new file mode 100644
index 0000000..da03905
--- /dev/null
+++ b/src/vf/classifier_mac.c
@@ -0,0 +1,233 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <math.h>
+
+#include <rte_mbuf.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_random.h>
+#include <rte_byteorder.h>
+#include <rte_per_lcore.h>
+#include <rte_eal.h>
+#include <rte_launch.h>
+#include <rte_hash.h>
+
+#include "spp_vf.h"
+#include "ringlatencystats.h"
+#include "classifier_mac.h"
+
+#define RTE_LOGTYPE_SPP_CLASSIFIER_MAC RTE_LOGTYPE_USER1
+
+#ifdef RTE_MACHINE_CPUFLAG_SSE4_2
+#include <rte_hash_crc.h>
+#define DEFAULT_HASH_FUNC rte_hash_crc
+#else
+#include <rte_jhash.h>
+#define DEFAULT_HASH_FUNC rte_jhash
+#endif
+
+/* number of classifier mac table entry */
+#define NUM_CLASSIFIER_MAC_TABLE_ENTRY 128
+
+/* interval that transmit burst packet, if buffer is not filled.
+ nano second */
+#define DRAIN_TX_PACKET_INTERVAL 100
+
+/* mac address string(xx:xx:xx:xx:xx:xx) buffer size */
+static const size_t ETHER_ADDR_STR_BUF_SZ =
+ ETHER_ADDR_LEN * 2 + (ETHER_ADDR_LEN - 1) + 1;
+
+/* classified data (destination port, target packets, etc) */
+struct classified_data {
+ int if_no;
+ uint8_t tx_port;
+ uint16_t num_pkt;
+ struct rte_mbuf *pkts[MAX_PKT_BURST];
+};
+
+/* initialize classifier. */
+static int
+init_classifier(const struct spp_core_info *core_info,
+ struct rte_hash **classifier_mac_table, struct classified_data *classified_data)
+{
+ int ret = -1;
+ int i;
+ struct ether_addr eth_addr;
+ char mac_addr_str[ETHER_ADDR_STR_BUF_SZ];
+
+ /* set hash creating parameters */
+ struct rte_hash_parameters hash_params = {
+ .name = "classifier_mac_table",
+ .entries = NUM_CLASSIFIER_MAC_TABLE_ENTRY,
+ .key_len = sizeof(struct ether_addr),
+ .hash_func = DEFAULT_HASH_FUNC,
+ .hash_func_init_val = 0,
+ .socket_id = rte_socket_id(),
+ };
+
+#ifdef RTE_MACHINE_CPUFLAG_SSE4_2
+ RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, "Enabled SSE4.2. use crc hash.\n");
+#else
+ RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, "Disabled SSE4.2. use jenkins hash.\n");
+#endif
+
+ /* create classifier mac table (hash table) */
+ *classifier_mac_table = rte_hash_create(&hash_params);
+ if (unlikely(*classifier_mac_table == NULL)) {
+ RTE_LOG(ERR, SPP_CLASSIFIER_MAC, "Cannot create classifier mac table\n");
+ return -1;
+ }
+
+ /* populate the hash */
+ for (i = 0; i < core_info->num_tx_port; i++) {
+ rte_memcpy(ð_addr, &core_info->tx_ports[i].mac_addr, ETHER_ADDR_LEN);
+
+ /* add entry to classifier mac table */
+ ret = rte_hash_add_key_data(*classifier_mac_table, (void*)ð_addr, (void*)(long)i);
+ if (unlikely(ret < 0)) {
+ ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð_addr);
+ RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
+ "Cannot add entry to classifier mac table. "
+ "ret=%d, mac_addr=%s\n", ret, mac_addr_str);
+ rte_hash_free(*classifier_mac_table);
+ *classifier_mac_table = NULL;
+ return -1;
+ }
+
+ /* set value */
+ classified_data[i].if_no = i;
+ classified_data[i].tx_port = core_info->tx_ports[i].dpdk_port;
+ classified_data[i].num_pkt = 0;
+ }
+
+ return 0;
+}
+
+/* transimit packet to one destination. */
+static inline void
+transimit_packet(struct classified_data *classified_data)
+{
+ int i;
+ uint16_t n_tx;
+
+ /* set ringlatencystats */
+ spp_ringlatencystats_add_time_stamp(classified_data->if_no,
+ classified_data->pkts, classified_data->num_pkt);
+
+ /* transimit packets */
+ n_tx = rte_eth_tx_burst(classified_data->tx_port, 0,
+ classified_data->pkts, classified_data->num_pkt);
+
+ /* free cannnot transiit packets */
+ if (unlikely(n_tx != classified_data->num_pkt)) {
+ for (i = n_tx; i < classified_data->num_pkt; i++)
+ 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 = 0;
+}
+
+/* classify packet by destination mac address,
+ and transimit packet (conditional). */
+static inline void
+classify_packet(struct rte_mbuf **rx_pkts, uint16_t n_rx,
+ struct rte_hash *classifier_mac_table, struct classified_data *classified_data)
+{
+ int ret;
+ int i;
+ struct ether_hdr *eth;
+ struct classified_data *cd;
+ void *lookup_data;
+ char mac_addr_str[ETHER_ADDR_STR_BUF_SZ];
+
+ for (i = 0; i < n_rx; i++) {
+ eth = rte_pktmbuf_mtod(rx_pkts[i], struct ether_hdr *);
+
+ /* find in table (by destination mac address)*/
+ ret = rte_hash_lookup_data(classifier_mac_table,
+ (const void*)ð->d_addr, &lookup_data);
+ if (unlikely(ret < 0)) {
+ ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð->d_addr);
+ RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
+ "unknown mac address. ret=%d, mac_addr=%s\n", ret, mac_addr_str);
+ rte_pktmbuf_free(rx_pkts[i]);
+ continue;
+ }
+
+ /* set mbuf pointer to tx buffer */
+ cd = classified_data + (long)lookup_data;
+ cd->pkts[cd->num_pkt++] = rx_pkts[i];
+
+ /* transimit packet, if buffer is filled */
+ if (unlikely(cd->num_pkt == MAX_PKT_BURST))
+ transimit_packet(cd);
+ }
+}
+
+/* classifier(mac address) thread function. */
+int
+spp_classifier_mac_do(void *arg)
+{
+ int ret = -1;
+ int i;
+ int n_rx;
+ struct spp_core_info *core_info = (struct spp_core_info *)arg;
+ struct rte_mbuf *rx_pkts[MAX_PKT_BURST];
+
+ struct rte_hash *classifier_mac_table = NULL;
+ const int n_classified_data = core_info->num_tx_port;
+ struct classified_data classified_data[n_classified_data];
+
+ 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_mac_table, classified_data);
+ if (unlikely(ret != 0))
+ return ret;
+
+ /* to idle */
+ core_info->status = SPP_CORE_IDLE;
+ while(likely(core_info->status == SPP_CORE_IDLE) ||
+ likely(core_info->status == SPP_CORE_FORWARD)) {
+
+ while(likely(core_info->status == SPP_CORE_FORWARD)) {
+ /* 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))
+ transimit_packet(&classified_data[i]);
+ }
+ 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;
+
+ /* classify and transimit (filled) */
+ classify_packet(rx_pkts, n_rx, classifier_mac_table, classified_data);
+ }
+ }
+
+ /* uninitialize */
+ if (classifier_mac_table != NULL) {
+ rte_hash_free(classifier_mac_table);
+ classifier_mac_table = NULL;
+ }
+ core_info->status = SPP_CORE_STOP;
+
+ return 0;
+}
diff --git a/src/vf/classifier_mac.h b/src/vf/classifier_mac.h
new file mode 100644
index 0000000..2661206
--- /dev/null
+++ b/src/vf/classifier_mac.h
@@ -0,0 +1,12 @@
+#ifndef _CLASSIFIER_MAC_H_
+#define _CLASSIFIER_MAC_H_
+
+/**
+ * classifier(mac address) thread function.
+ *
+ * @param arg
+ * pointer to struct spp_core_info.
+ */
+int spp_classifier_mac_do(void *arg);
+
+#endif /* _CLASSIFIER_MAC_H_ */
diff --git a/src/vf/ringlatencystats.c b/src/vf/ringlatencystats.c
new file mode 100644
index 0000000..8f44020
--- /dev/null
+++ b/src/vf/ringlatencystats.c
@@ -0,0 +1,147 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <math.h>
+
+#include <rte_mbuf.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+
+#include "ringlatencystats.h"
+
+#define NS_PER_SEC 1E9
+
+#define RTE_LOGTYPE_SPP_RING_LATENCY_STATS RTE_LOGTYPE_USER1
+
+#ifdef SPP_RINGLATENCYSTATS_ENABLE
+
+/** ring latency statistics information */
+struct ring_latency_stats_info {
+ uint64_t timer_tsc; /**< sampling interval counter */
+ uint64_t prev_tsc; /**< previous time */
+ struct spp_ringlatencystats_ring_latency_stats stats; /**< ring latency statistics list */
+};
+
+/** sampling interval */
+static uint64_t g_samp_intvl = 0;
+
+/** ring latency statistics information instance */
+static struct ring_latency_stats_info *g_stats_info = NULL;
+
+/** number of ring latency statisics */
+static uint16_t g_stats_count = 0;
+
+/* clock cycles per nano second */
+static inline uint64_t
+cycles_per_ns(void)
+{
+ return rte_get_timer_hz() / NS_PER_SEC;
+}
+
+int
+spp_ringlatencystats_init(uint64_t samp_intvl, uint16_t stats_count)
+{
+ /* allocate memory for ring latency statisics infromation */
+ g_stats_info = rte_zmalloc(
+ "global ring_latency_stats_info",
+ sizeof(struct ring_latency_stats_info) * stats_count, 0);
+ if (unlikely(g_stats_info == NULL)) {
+ RTE_LOG(ERR, SPP_RING_LATENCY_STATS,
+ "Cannot allocate memory for ring latency stats info\n");
+ return -1;
+ }
+
+ /* store global information for ring latency statistics */
+ g_samp_intvl = samp_intvl * cycles_per_ns();
+ g_stats_count = stats_count;
+
+ RTE_LOG(DEBUG, SPP_RING_LATENCY_STATS,
+ "g_samp_intvl=%lu, g_stats_count=%hu, cpns=%lu\n",
+ g_samp_intvl, g_stats_count, cycles_per_ns());
+
+ return 0;
+}
+
+void
+spp_ringlatencystats_uninit(void)
+{
+ /* free memory for ring latency statisics infromation */
+ if (likely(g_stats_info != NULL)) {
+ rte_free(g_stats_info);
+ g_stats_count = 0;
+ }
+}
+
+void
+spp_ringlatencystats_add_time_stamp(int ring_id,
+ struct rte_mbuf **pkts, uint16_t nb_pkts)
+{
+ unsigned int i;
+ uint64_t diff_tsc, now;
+ struct ring_latency_stats_info *stats_info = &g_stats_info[ring_id];
+
+ for (i = 0; i < nb_pkts; i++) {
+
+ /* get tsc now */
+ now = rte_rdtsc();
+
+ /* calculate difference from the previous processing time */
+ diff_tsc = now - stats_info->prev_tsc;
+ stats_info->timer_tsc += diff_tsc;
+
+ /* when it is over sampling interval */
+ /* set tsc to mbuf::timestamp */
+ if (unlikely(stats_info->timer_tsc >= g_samp_intvl)) {
+ pkts[i]->timestamp = now;
+ stats_info->timer_tsc = 0;
+ }
+
+ /* update previus tsc */
+ stats_info->prev_tsc = now;
+ }
+}
+
+void
+spp_ringlatencystats_calculate_latency(int ring_id,
+ struct rte_mbuf **pkts, uint16_t nb_pkts)
+{
+ unsigned int i;
+ uint64_t now;
+ int64_t latency;
+ struct ring_latency_stats_info *stats_info = &g_stats_info[ring_id];
+
+ now = rte_rdtsc();
+ for (i = 0; i < nb_pkts; i++) {
+ if (likely(pkts[i]->timestamp == 0))
+ continue;
+
+ /* when mbuf::timestamp is not zero */
+ /* calculate latency */
+ latency = (uint64_t)floor((now - pkts[i]->timestamp) / cycles_per_ns());
+ if (likely(latency < SPP_RINGLATENCYSTATS_STATS_SLOT_COUNT-1))
+ stats_info->stats.slot[latency]++;
+ else
+ stats_info->stats.slot[SPP_RINGLATENCYSTATS_STATS_SLOT_COUNT-1]++;
+ }
+}
+
+int
+spp_ringlatencystats_get_count(void)
+{
+ return g_stats_count;
+}
+
+void
+spp_ringlatencystats_get_stats(int ring_id,
+ struct spp_ringlatencystats_ring_latency_stats *stats)
+{
+ struct ring_latency_stats_info *stats_info = &g_stats_info[ring_id];
+
+ rte_memcpy(stats, &stats_info->stats,
+ sizeof(struct spp_ringlatencystats_ring_latency_stats));
+}
+
+#endif /* SPP_RINGLATENCYSTATS_ENABLE */
diff --git a/src/vf/ringlatencystats.h b/src/vf/ringlatencystats.h
new file mode 100644
index 0000000..bc47699
--- /dev/null
+++ b/src/vf/ringlatencystats.h
@@ -0,0 +1,69 @@
+#ifndef _RINGLATENCYSTATS_H_
+#define _RINGLATENCYSTATS_H_
+
+#include <rte_mbuf.h>
+
+/** number of slots to save latency. 0ns~99ns and 100ns over */
+#define SPP_RINGLATENCYSTATS_STATS_SLOT_COUNT 101
+
+/** ring latency statistics */
+struct spp_ringlatencystats_ring_latency_stats {
+ uint64_t slot[SPP_RINGLATENCYSTATS_STATS_SLOT_COUNT]; /**< slots to save latency */
+};
+
+
+#ifdef SPP_RINGLATENCYSTATS_ENABLE
+/**
+ * initialize ring latency statisics.
+ *
+ * @retval 0: succeeded.
+ * @retval -1: failed.
+ */
+int spp_ringlatencystats_init(uint64_t samp_intvl, uint16_t stats_count);
+
+/**
+ *uninitialize ring latency statisics.
+ */
+void spp_ringlatencystats_uninit(void);
+
+/**
+ * add time-stamp to mbuf's member.
+ *
+ * call at enqueue.
+ */
+void spp_ringlatencystats_add_time_stamp(int ring_id,
+ struct rte_mbuf **pkts, uint16_t nb_pkts);
+
+/**
+ * calculate latency.
+ *
+ * call at dequeue.
+ */
+void spp_ringlatencystats_calculate_latency(int ring_id,
+ struct rte_mbuf **pkts, uint16_t nb_pkts);
+
+/**
+ * get number of ring latency statisics.
+ *
+ * @return spp_ringlatencystats_init's parameter "stats_count"
+ */
+int spp_ringlatencystats_get_count(void);
+
+/**
+ *get specific ring latency statisics.
+ */
+void spp_ringlatencystats_get_stats(int ring_id,
+ struct spp_ringlatencystats_ring_latency_stats *stats);
+
+#else
+
+#define spp_ringlatencystats_init(arg1, arg2) 0
+#define spp_ringlatencystats_uninit()
+#define spp_ringlatencystats_add_time_stamp(arg1, arg2, arg3)
+#define spp_ringlatencystats_calculate_latency(arg1, arg2, arg3)
+#define spp_ringlatencystats_get_count() 0
+#define spp_ringlatencystats_get_stats(arg1, arg2)
+
+#endif /* SPP_RINGLATENCYSTATS_ENABLE */
+
+#endif /* _RINGLATENCYSTATS_H_ */
diff --git a/src/vf/spp_config.c b/src/vf/spp_config.c
new file mode 100644
index 0000000..63b85f2
--- /dev/null
+++ b/src/vf/spp_config.c
@@ -0,0 +1,669 @@
+#include <sys/types.h>
+#include <jansson.h>
+
+#include <rte_log.h>
+
+#include "spp_config.h"
+
+#define CONFIG_CORE_TYPE_CLASSIFIER_MAC "classifier_mac"
+#define CONFIG_CORE_TYPE_MERGE "merge"
+#define CONFIG_CORE_TYPE_FORWARD "forward"
+
+#define JSONPATH_CLASSIFIER_TABLE "$.classifier_table"
+#define JSONPATH_PROC_TABLE "$.vfs"
+#define JSONPATH_NAME "$.name"
+#define JSONPATH_TABLE "$.table"
+#define JSONPATH_MAC "$.mac"
+#define JSONPATH_PORT "$.port"
+#define JSONPATH_NUM_VHOST "$.num_vhost"
+#define JSONPATH_NUM_RING "$.num_ring"
+#define JSONPATH_FUNCTIONS "$.functions"
+#define JSONPATH_CORE_NO "$.core"
+#define JSONPATH_CORE_TYPE "$.type"
+#define JSONPATH_RX_PORT "$.rx_port"
+#define JSONPATH_TX_PORT "$.tx_port"
+#define JSONPATH_TX_TABLE "$.tx_port_table"
+
+/*
+ * Get integer data from config
+ */
+static int
+config_get_int_value(const json_t *obj, const char *path, int *value)
+{
+ /* 指定パラメータのJsonオブジェクト取得 */
+ json_t *tmp_obj = json_path_get(obj, path);
+ if (unlikely(tmp_obj == NULL)) {
+ /* 必須でないデータを取得する場合を考慮し、DEBUGログとする。 */
+ RTE_LOG(DEBUG, APP, "No parameter. (path = %s)\n", path);
+ return -1;
+ }
+
+ /* Integer type check */
+ if (unlikely(!json_is_integer(tmp_obj))) {
+ /* 必須でないデータを取得する場合を考慮し、DEBUGログとする。 */
+ RTE_LOG(DEBUG, APP, "Not an integer. (path = %s)\n", path);
+ return -1;
+ }
+
+ /* Set to OUT parameter */
+ *value = json_integer_value(tmp_obj);
+ RTE_LOG(DEBUG, APP, "get value = %d\n", *value);
+ return 0;
+}
+
+/*
+ * Get String data from config
+ */
+static int
+config_get_str_value(const json_t *obj, const char *path, char *value)
+{
+ /* 指定パラメータのJsonオブジェクト取得 */
+ json_t *tmp_obj = json_path_get(obj, path);
+ if (unlikely(tmp_obj == NULL)) {
+ RTE_LOG(DEBUG, APP, "No parameter. (path = %s)\n", path);
+ return -1;
+ }
+
+ /* String type check */
+ if (unlikely(!json_is_string(tmp_obj))) {
+ RTE_LOG(DEBUG, APP, "Not a string. (path = %s)\n", path);
+ return -1;
+ }
+
+ /* Set to OUT parameter */
+ strcpy(value, json_string_value(tmp_obj));
+ RTE_LOG(DEBUG, APP, "get value = %s\n", value);
+ return 0;
+}
+
+/*
+ * コンフィグ情報初期化
+ */
+static void
+config_init_data(struct spp_config_area *config)
+{
+ /* 0クリア */
+ memset(config, 0x00, sizeof(struct spp_config_area));
+ int core_cnt, port_cnt, table_cnt;
+
+ /* IF種別初期設定 */
+ 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;
+ config->proc.functions[core_cnt].tx_ports[port_cnt].if_type = UNDEF;
+ }
+ }
+ for (table_cnt = 0; table_cnt < SPP_CONFIG_MAC_TABLE_MAX; table_cnt++) {
+ config->classifier_table.mac_tables[table_cnt].port.if_type = UNDEF;
+ }
+
+ return;
+}
+
+/*
+ * IFの情報からIF種別とIF番号を取得する
+ * ("ring0" -> 種別:"ring"、番号:0)
+ */
+static int
+config_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;
+
+ /* IF type check */
+ if (strncmp(port, SPP_CONFIG_IFTYPE_NIC, strlen(SPP_CONFIG_IFTYPE_NIC)) == 0) {
+ /* NIC */
+ type = PHY;
+ no_str = &port[strlen(SPP_CONFIG_IFTYPE_NIC)];
+ } else if (strncmp(port, SPP_CONFIG_IFTYPE_VHOST, strlen(SPP_CONFIG_IFTYPE_VHOST)) == 0) {
+ /* VHOST */
+ type = VHOST;
+ no_str = &port[strlen(SPP_CONFIG_IFTYPE_VHOST)];
+ } else if (strncmp(port, SPP_CONFIG_IFTYPE_RING, strlen(SPP_CONFIG_IFTYPE_RING)) == 0) {
+ /* RING */
+ type = RING;
+ no_str = &port[strlen(SPP_CONFIG_IFTYPE_RING)];
+ } else {
+ /* OTHER */
+ RTE_LOG(ERR, APP, "Unknown interface type. (port = %s)\n", port);
+ return -1;
+ }
+
+ /* IF番号を文字列から数値変換 */
+ 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;
+ }
+
+ /* Set OUT parameter */
+ *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;
+}
+
+/*
+ * MAC addressを文字列から数値へ変換
+ */
+int64_t
+config_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_CONFIG_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 clolon(':') */
+ char *ret_tok = strtok_r(str, ":", &saveptr);
+ if (unlikely(ret_tok == NULL)) {
+ break;
+ }
+
+ /* Convert string to hex value */
+ int ret_tol = strtol(ret_tok, &endptr, 16);
+ if (unlikely(ret_tok == endptr) || unlikely(*endptr != '\0')) {
+ break;
+ }
+
+ /* 各数値をまとめる */
+ token_val = (int64_t)ret_tol;
+ ret_mac |= token_val << (token_cnt * 8);
+ token_cnt++;
+ str = NULL;
+ }
+
+ /* 区切り文字が5個以外 */
+ if (unlikely(token_cnt != ETHER_ADDR_LEN)) {
+ RTE_LOG(ERR, APP, "MAC address format error. (mac = %s)\n",
+ mac);
+ return -1;
+ }
+
+ RTE_LOG(DEBUG, APP, "MAC address change. (mac = %s => 0x%08lx)\n",
+ mac, ret_mac);
+ return ret_mac;
+}
+
+/*
+ * Classifier table読み込み
+ */
+static int
+config_load_classifier_table(const json_t *obj,
+ struct spp_config_classifier_table *classifier_table)
+{
+ /* classifier_table用オブジェクト取得 */
+ json_t *classifier_obj = json_path_get(obj, JSONPATH_CLASSIFIER_TABLE);
+ if (unlikely(classifier_obj == NULL)) {
+ RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
+ JSONPATH_CLASSIFIER_TABLE);
+ return -1;
+ }
+
+ /* name取得 */
+ int ret_name = config_get_str_value(classifier_obj, JSONPATH_NAME,
+ classifier_table->name);
+ if (unlikely(ret_name != 0)) {
+ RTE_LOG(ERR, APP, "Classifier table name get failed.\n");
+ return -1;
+ }
+
+ /* table用オブジェクト取得 */
+ json_t *array_obj = json_path_get(classifier_obj, JSONPATH_TABLE);
+ if (unlikely(!array_obj)) {
+ RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
+ JSONPATH_TABLE);
+ return -1;
+ }
+
+ /* table用オブジェクトが配列かチェック */
+ if (unlikely(!json_is_array(array_obj))) {
+ RTE_LOG(ERR, APP, "Not an array. (path = %s)\n",
+ JSONPATH_TABLE);
+ return -1;
+ }
+
+ /* table用オブジェクトの要素数取得 */
+ int array_num = json_array_size(array_obj);
+ if (unlikely(array_num <= 0) ||
+ unlikely(array_num >= SPP_CONFIG_MAC_TABLE_MAX)) {
+ RTE_LOG(ERR, APP, "Table size out of range. (path = %s, size = %d)\n",
+ JSONPATH_TABLE, array_num);
+ return -1;
+ }
+ classifier_table->num_table = array_num;
+
+ /* テーブルの各要素毎にデータ取得 */
+ struct spp_config_mac_table_element *tmp_table = NULL;
+ char if_str[SPP_CONFIG_STR_LEN];
+ int table_cnt = 0;
+ for (table_cnt = 0; table_cnt < array_num; table_cnt++) {
+ tmp_table = &classifier_table->mac_tables[table_cnt];
+
+ /* 要素取得 */
+ json_t *elements_obj = json_array_get(array_obj, table_cnt);
+ if (unlikely(elements_obj == NULL)) {
+ RTE_LOG(ERR, APP,
+ "Element get failed. (No = %d, path = %s)\n",
+ table_cnt, JSONPATH_TABLE);
+ return -1;
+ }
+
+ /* MACアドレス(文字列)取得 */
+ int ret_mac = config_get_str_value(elements_obj, JSONPATH_MAC,
+ tmp_table->mac_addr_str);
+ if (unlikely(ret_mac != 0)) {
+ RTE_LOG(ERR, APP,
+ "MAC address get failed. (No = %d, path = %s)\n",
+ table_cnt, JSONPATH_MAC);
+ return -1;
+ }
+
+ /* MACアドレス数値変換 */
+ int64_t ret_mac64 = config_change_mac_str_to_int64(
+ tmp_table->mac_addr_str);
+ if (unlikely(ret_mac64 == -1)) {
+ RTE_LOG(ERR, APP,
+ "MAC address change failed. (No = %d, mac = %s)\n",
+ table_cnt, tmp_table->mac_addr_str);
+ return -1;
+ }
+ tmp_table->mac_addr = ret_mac64;
+
+ /* IF情報取得 */
+ int ret_if_str = config_get_str_value(elements_obj,
+ JSONPATH_PORT, if_str);
+ if (unlikely(ret_if_str != 0)) {
+ RTE_LOG(ERR, APP,
+ "Interface get failed. (No = %d, path = %s)\n",
+ table_cnt, JSONPATH_PORT);
+ return -1;
+ }
+
+ /* IF種別とIF番号に分割 */
+ int ret_if = config_get_if_info(if_str, &tmp_table->port.if_type,
+ &tmp_table->port.if_no);
+ if (unlikely(ret_if != 0)) {
+ RTE_LOG(ERR, APP,
+ "Interface change failed. (No = %d, IF = %s)\n",
+ table_cnt, if_str);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * 処理種別を文字列から数値変換
+ */
+static enum spp_core_type
+config_change_core_type(const char *core_type)
+{
+ if(strncmp(core_type, CONFIG_CORE_TYPE_CLASSIFIER_MAC,
+ strlen(CONFIG_CORE_TYPE_CLASSIFIER_MAC)+1) == 0) {
+ /* Classifier */
+ return SPP_CONFIG_CLASSIFIER_MAC;
+ } else if (strncmp(core_type, CONFIG_CORE_TYPE_MERGE,
+ strlen(CONFIG_CORE_TYPE_MERGE)+1) == 0) {
+ /* Merge */
+ return SPP_CONFIG_MERGE;
+ } else if (strncmp(core_type, CONFIG_CORE_TYPE_FORWARD,
+ strlen(CONFIG_CORE_TYPE_FORWARD)+1) == 0) {
+ /* Forward */
+ return SPP_CONFIG_FORWARD;
+ }
+ return SPP_CONFIG_UNUSE;
+}
+
+/*
+ * 受信ポート取得
+ */
+static int
+config_set_rx_port(enum spp_core_type type, json_t *obj,
+ struct spp_config_functions *functions)
+{
+ struct spp_config_port_info *tmp_rx_port = NULL;
+ char if_str[SPP_CONFIG_STR_LEN];
+ if (type == SPP_CONFIG_MERGE) {
+ /* Merge */
+ /* 受信ポート用オブジェクト取得 */
+ json_t *array_obj = json_path_get(obj, JSONPATH_RX_PORT);
+ if (unlikely(!array_obj)) {
+ RTE_LOG(ERR, APP, "Json object get failed. (path = %s, route = merge)\n",
+ JSONPATH_RX_PORT);
+ return -1;
+ }
+
+ /* 受信ポート用オブジェクトが配列かチェック */
+ if (unlikely(!json_is_array(array_obj))) {
+ RTE_LOG(ERR, APP, "Not an array. (path = %s, route = merge)\n",
+ JSONPATH_TABLE);
+ return -1;
+ }
+
+ /* 受信ポート用オブジェクトの要素数取得 */
+ int port_num = json_array_size(array_obj);
+ if (unlikely(port_num <= 0) ||
+ unlikely(port_num >= RTE_MAX_ETHPORTS)) {
+ RTE_LOG(ERR, APP, "RX port out of range. (path = %s, port = %d, route = merge)\n",
+ JSONPATH_RX_PORT, port_num);
+ return -1;
+ }
+ functions->num_rx_port = port_num;
+
+ /* 要素毎にデータ取得 */
+ int array_cnt = 0;
+ for (array_cnt = 0; array_cnt < port_num; array_cnt++) {
+ tmp_rx_port = &functions->rx_ports[array_cnt];
+
+ /* 要素取得 */
+ json_t *elements_obj = json_array_get(array_obj, array_cnt);
+ if (unlikely(elements_obj == NULL)) {
+ RTE_LOG(ERR, APP,
+ "Element get failed. (No = %d, path = %s, route = merge)\n",
+ array_cnt, JSONPATH_RX_PORT);
+ return -1;
+ }
+
+ /* String type check */
+ if (unlikely(!json_is_string(elements_obj))) {
+ RTE_LOG(ERR, APP, "Not a string. (path = %s, No = %d, route = merge)\n",
+ JSONPATH_RX_PORT, array_cnt);
+ return -1;
+ }
+ strcpy(if_str, json_string_value(elements_obj));
+
+ /* IF種別とIF番号に分割 */
+ int ret_if = config_get_if_info(if_str, &tmp_rx_port->if_type,
+ &tmp_rx_port->if_no);
+ if (unlikely(ret_if != 0)) {
+ RTE_LOG(ERR, APP,
+ "Interface change failed. (No = %d, port = %s, route = merge)\n",
+ array_cnt, if_str);
+ return -1;
+ }
+ }
+ } else {
+ /* Classifier/Forward */
+ tmp_rx_port = &functions->rx_ports[0];
+ functions->num_rx_port = 1;
+
+ /* 受信ポート取得 */
+ int ret_rx_port = config_get_str_value(obj, JSONPATH_RX_PORT, if_str);
+ if (unlikely(ret_rx_port != 0)) {
+ RTE_LOG(ERR, APP, "RX port get failed.\n");
+ return -1;
+ }
+
+ /* IF種別とIF番号に分割 */
+ int ret_if = config_get_if_info(if_str, &tmp_rx_port->if_type,
+ &tmp_rx_port->if_no);
+ if (unlikely(ret_if != 0)) {
+ RTE_LOG(ERR, APP,
+ "Interface change failed. (port = %s)\n", if_str);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * 送信先ポート情報取得
+ */
+static int
+config_set_tx_port(enum spp_core_type type, json_t *obj,
+ struct spp_config_functions *functions,
+ struct spp_config_classifier_table *classifier_table)
+{
+ struct spp_config_port_info *tmp_tx_port = NULL;
+ char if_str[SPP_CONFIG_STR_LEN];
+ if ((type == SPP_CONFIG_MERGE) || (type == SPP_CONFIG_FORWARD)) {
+ /* Merge or Forward */
+ tmp_tx_port = &functions->tx_ports[0];
+ functions->num_tx_port = 1;
+
+ /* 送信ポート取得 */
+ int ret_tx_port = config_get_str_value(obj,
+ JSONPATH_TX_PORT, if_str);
+ if (unlikely(ret_tx_port != 0)) {
+ RTE_LOG(ERR, APP, "TX port get failed.\n");
+ return -1;
+ }
+
+ /* IF種別とIF番号に分割 */
+ int ret_if = config_get_if_info(if_str, &tmp_tx_port->if_type,
+ &tmp_tx_port->if_no);
+ if (unlikely(ret_if != 0)) {
+ RTE_LOG(ERR, APP,
+ "Interface change failed. (port = %s)\n",
+ if_str);
+ return -1;
+ }
+ } else {
+ /* Classifier */
+ int cnt = 0;
+ functions->num_tx_port = classifier_table->num_table;
+ struct spp_config_mac_table_element *tmp_mac_table = NULL;
+ for (cnt = 0; cnt < classifier_table->num_table; cnt++) {
+ tmp_tx_port = &functions->tx_ports[cnt];
+ tmp_mac_table = &classifier_table->mac_tables[cnt];
+
+ /* MAC振り分けテーブルより設定 */
+ tmp_tx_port->if_type = tmp_mac_table->port.if_type;
+ tmp_tx_port->if_no = tmp_mac_table->port.if_no;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * プロセス情報取得
+ */
+static int
+config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *config)
+{
+ struct spp_config_proc_info *proc = &config->proc;
+ struct spp_config_classifier_table *classifier_table = &config->classifier_table;
+
+ /* proc_table用オブジェクト取得 */
+ json_t *proc_table_obj = json_path_get(obj, JSONPATH_PROC_TABLE);
+ if (unlikely(proc_table_obj == NULL)) {
+ RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
+ JSONPATH_PROC_TABLE);
+ return -1;
+ }
+
+ /* table用オブジェクトが配列かチェック */
+ if (unlikely(!json_is_array(proc_table_obj))) {
+ RTE_LOG(ERR, APP, "Not an array. (path = %s)\n",
+ JSONPATH_TABLE);
+ return -1;
+ }
+
+ /* table用オブジェクトの要素数取得 */
+ int proc_table_num = json_array_size(proc_table_obj);
+ if (unlikely(proc_table_num < node_id)) {
+ RTE_LOG(ERR, APP, "No process data. (Size = %d, Node = %d)\n",
+ proc_table_num, node_id);
+ return -1;
+ }
+
+ /* 要素取得 */
+ json_t *proc_obj = json_array_get(proc_table_obj, node_id);
+ if (unlikely(proc_obj == NULL)) {
+ RTE_LOG(ERR, APP, "Process data get failed. (Node = %d)\n",
+ node_id);
+ return -1;
+ }
+
+ /* name取得 */
+ int ret_name = config_get_str_value(proc_obj, JSONPATH_NAME, proc->name);
+ if (unlikely(ret_name != 0)) {
+ RTE_LOG(ERR, APP, "Process name get failed.\n");
+ return -1;
+ }
+
+ /* VHOST数取得 */
+ int ret_vhost = config_get_int_value(proc_obj, JSONPATH_NUM_VHOST,
+ &proc->num_vhost);
+ if (unlikely(ret_vhost != 0)) {
+ RTE_LOG(ERR, APP, "VHOST number get failed.\n");
+ return -1;
+ }
+
+ /* RING数取得 */
+ int ret_ring = config_get_int_value(proc_obj, JSONPATH_NUM_RING,
+ &proc->num_ring);
+ if (unlikely(ret_ring != 0)) {
+ RTE_LOG(ERR, APP, "RING number get failed.\n");
+ return -1;
+ }
+
+ /* functions用オブジェクト取得 */
+ json_t *array_obj = json_path_get(proc_obj, JSONPATH_FUNCTIONS);
+ if (unlikely(!array_obj)) {
+ RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
+ JSONPATH_FUNCTIONS);
+ return -1;
+ }
+
+ /* functions用オブジェクトが配列かチェック */
+ if (unlikely(!json_is_array(array_obj))) {
+ RTE_LOG(ERR, APP, "Not an array. (path = %s)\n",
+ JSONPATH_FUNCTIONS);
+ return -1;
+ }
+
+ /* functions用オブジェクトの要素数取得 */
+ int array_num = json_array_size(array_obj);
+ if (unlikely(array_num <= 0) ||
+ unlikely(array_num >= SPP_CONFIG_CORE_MAX)) {
+ RTE_LOG(ERR, APP, "Functions size out of range. (path = %s, size = %d)\n",
+ JSONPATH_TABLE, array_num);
+ return -1;
+ }
+ proc->num_func = array_num;
+
+ /* 要素毎にデータ取得 */
+ struct spp_config_functions *tmp_functions = NULL;
+ char core_type_str[SPP_CONFIG_STR_LEN];
+ int array_cnt = 0;
+ for (array_cnt = 0; array_cnt < array_num; array_cnt++) {
+ tmp_functions = &proc->functions[array_cnt];
+
+ /* 要素取得 */
+ json_t *elements_obj = json_array_get(array_obj, array_cnt);
+ if (unlikely(elements_obj == NULL)) {
+ RTE_LOG(ERR, APP,
+ "Element get failed. (No = %d, path = %s)\n",
+ array_cnt, JSONPATH_FUNCTIONS);
+ return -1;
+ }
+
+ /* CORE番号取得 */
+ int ret_core = config_get_int_value(elements_obj, JSONPATH_CORE_NO,
+ &tmp_functions->core_no);
+ if (unlikely(ret_core != 0)) {
+ RTE_LOG(ERR, APP, "Core number get failed. (No = %d)\n",
+ array_cnt);
+ return -1;
+ }
+
+ /* 処理種別取得 */
+ int ret_core_type = config_get_str_value(elements_obj,
+ JSONPATH_CORE_TYPE, core_type_str);
+ if (unlikely(ret_core_type != 0)) {
+ RTE_LOG(ERR, APP, "Core type get failed. (No = %d)\n",
+ array_cnt);
+ return -1;
+ }
+
+ /* 処理種別を数値に変換 */
+ enum spp_core_type core_type = config_change_core_type(core_type_str);
+ if (unlikely(core_type == SPP_CONFIG_UNUSE)) {
+ RTE_LOG(ERR, APP,
+ "Unknown core type. (No = %d, type = %s)\n",
+ array_cnt, core_type_str);
+ return -1;
+ }
+ tmp_functions->type = core_type;
+
+ /* 受信ポート取得 */
+ int ret_rx_port = config_set_rx_port(core_type, elements_obj,
+ tmp_functions);
+ if (unlikely(ret_rx_port != 0)) {
+ RTE_LOG(ERR, APP, "RX port set failure. (No = %d)\n",
+ array_cnt);
+ return -1;
+ }
+
+ /* 送信ポート取得 */
+ int ret_tx_port = config_set_tx_port(core_type, elements_obj,
+ tmp_functions, classifier_table);
+ if (unlikely(ret_tx_port != 0)) {
+ RTE_LOG(ERR, APP, "TX port set failure. (No = %d)\n",
+ array_cnt);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Load config file
+ * OK : 0
+ * NG : -1
+ */
+int
+spp_config_load_file(int node_id, struct spp_config_area *config)
+{
+ /* Config initialize */
+ config_init_data(config);
+
+ /* Config load */
+ json_error_t json_error;
+ json_t *conf_obj = json_load_file(SPP_CONFIG_FILE_PATH, 0, &json_error);
+ if (unlikely(conf_obj == NULL)) {
+ /* Load error */
+ RTE_LOG(ERR, APP, "Config load failed. (path = %s, text = %s)\n",
+ SPP_CONFIG_FILE_PATH, json_error.text);
+ return -1;
+ }
+
+ /* classifier table */
+ int ret_classifier = config_load_classifier_table(conf_obj,
+ &config->classifier_table);
+ if (unlikely(ret_classifier != 0)) {
+ RTE_LOG(ERR, APP, "Classifier table load failed.\n");
+ json_decref(conf_obj);
+ return -1;
+ }
+
+ /* proc info */
+ int ret_proc = config_load_proc_info(conf_obj, node_id, config);
+ if (unlikely(ret_proc != 0)) {
+ RTE_LOG(ERR, APP, "Process table load failed.\n");
+ json_decref(conf_obj);
+ return -1;
+ }
+
+ /* Config object release */
+ json_decref(conf_obj);
+
+ return 0;
+}
diff --git a/src/vf/spp_config.h b/src/vf/spp_config.h
new file mode 100644
index 0000000..d2a6a4b
--- /dev/null
+++ b/src/vf/spp_config.h
@@ -0,0 +1,90 @@
+#ifndef __SPP_CONFIG_H__
+#define __SPP_CONFIG_H__
+
+#include "common.h"
+
+#define SPP_CONFIG_FILE_PATH "/usr/local/etc/spp/spp.json"
+
+#define SPP_CONFIG_IFTYPE_NIC "nic"
+#define SPP_CONFIG_IFTYPE_VHOST "vhost"
+#define SPP_CONFIG_IFTYPE_RING "ring"
+
+#define SPP_CONFIG_STR_LEN 32
+#define SPP_CONFIG_MAC_TABLE_MAX 16
+#define SPP_CONFIG_CORE_MAX 64
+
+/*
+ * Process type for each CORE
+ */
+enum spp_core_type {
+ SPP_CONFIG_UNUSE,
+ SPP_CONFIG_CLASSIFIER_MAC,
+ SPP_CONFIG_MERGE,
+ SPP_CONFIG_FORWARD,
+};
+
+/*
+ * Interface information structure
+ */
+struct spp_config_port_info {
+ enum port_type if_type;
+ int if_no;
+};
+
+/*
+ * MAC Table information structure
+ */
+struct spp_config_mac_table_element {
+ struct spp_config_port_info port;
+ char mac_addr_str[SPP_CONFIG_STR_LEN];
+ uint64_t mac_addr;
+};
+
+/*
+ * Classifier Table information structure
+ */
+struct spp_config_classifier_table {
+ char name[SPP_CONFIG_STR_LEN];
+ int num_table;
+ struct spp_config_mac_table_element mac_tables[SPP_CONFIG_MAC_TABLE_MAX];
+};
+
+/*
+ * Functions information structure
+ */
+struct spp_config_functions {
+ int core_no;
+ enum spp_core_type type;
+ 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];
+};
+
+/*
+ * Process information structure
+ */
+struct spp_config_proc_info {
+ char name[SPP_CONFIG_STR_LEN];
+ int num_vhost;
+ int num_ring;
+ int num_func;
+ struct spp_config_functions functions[SPP_CONFIG_CORE_MAX];
+};
+
+/*
+ * Config information structure
+ */
+struct spp_config_area {
+ struct spp_config_proc_info proc;
+ struct spp_config_classifier_table classifier_table;
+};
+
+/*
+ * Load config file
+ * OK : 0
+ * NG : -1
+ */
+int spp_config_load_file(int node_id, struct spp_config_area *config);
+
+#endif /* __SPP_CONFIG_H__ */
diff --git a/src/vf/spp_forward.c b/src/vf/spp_forward.c
new file mode 100644
index 0000000..4396929
--- /dev/null
+++ b/src/vf/spp_forward.c
@@ -0,0 +1,106 @@
+#include "spp_vf.h"
+#include "ringlatencystats.h"
+
+#define RTE_LOGTYPE_SPP_FORWARD RTE_LOGTYPE_USER1
+
+/*
+ * 送受信ポートの経路情報
+ */
+struct rxtx {
+ struct spp_core_port_info rx;
+ struct spp_core_port_info tx;
+};
+
+/*
+ * 使用するIF情報を移し替える
+ */
+void
+set_use_interface(struct spp_core_port_info *dst,
+ struct spp_core_port_info *src)
+{
+ dst->if_type = src->if_type;
+ dst->if_no = src->if_no;
+ dst->dpdk_port = src->dpdk_port;
+}
+
+/*
+ * Merge/Forward
+ */
+int
+spp_forward(void *arg)
+{
+ 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];
+
+ /* RX/TX Info setting */
+ 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]);
+ if (core_info->type == SPP_CONFIG_FORWARD) {
+ /* FORWARD */
+ set_use_interface(&patch[if_cnt].tx,
+ &core_info->tx_ports[if_cnt]);
+ } else {
+ /* MERGE */
+ set_use_interface(&patch[if_cnt].tx,
+ &core_info->tx_ports[0]);
+ }
+ }
+
+ /* Thread IDLE */
+ core_info->status = SPP_CORE_IDLE;
+ RTE_LOG(INFO, FORWARD, "Core[%d] Start. (type = %d)\n", lcore_id,
+ core_info->type);
+
+ 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;
+
+ /* Packet receive */
+ nb_rx = rte_eth_rx_burst(rx->dpdk_port, 0, bufs, MAX_PKT_BURST);
+ if (unlikely(nb_rx == 0)) {
+ continue;
+ }
+
+#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
+ if (rx->if_type == RING) {
+ /* Receive port is RING */
+ spp_ringlatencystats_calculate_latency(rx->if_no,
+ bufs, nb_rx);
+ }
+ if (tx->if_type == RING) {
+ /* Send port is RING */
+ spp_ringlatencystats_add_time_stamp(tx->if_no,
+ bufs, nb_rx);
+ }
+#endif /* SPP_RINGLATENCYSTATS_ENABLE */
+
+ /* Send packet */
+ nb_tx = rte_eth_tx_burst(tx->dpdk_port, 0, bufs, nb_rx);
+
+ /* Free any unsent packets. */
+ if (unlikely(nb_tx < nb_rx)) {
+ for (buf = nb_tx; buf < nb_rx; buf++) {
+ rte_pktmbuf_free(bufs[buf]);
+ }
+ }
+ }
+ }
+ }
+
+ /* Thread STOP */
+ 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
new file mode 100644
index 0000000..33208bf
--- /dev/null
+++ b/src/vf/spp_forward.h
@@ -0,0 +1,9 @@
+#ifndef __SPP_FORWARD_H__
+#define __SPP_FORWARD_H__
+
+/*
+ * Merge/Forward
+ */
+int spp_forward(void *arg);
+
+#endif /* __SPP_FORWARD_H__ */
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
new file mode 100644
index 0000000..ee5cf63
--- /dev/null
+++ b/src/vf/spp_vf.c
@@ -0,0 +1,794 @@
+#include <arpa/inet.h>
+#include <getopt.h>
+
+#include <rte_eth_ring.h>
+#include <rte_eth_vhost.h>
+#include <rte_memzone.h>
+
+#include "spp_vf.h"
+#include "ringlatencystats.h"
+#include "classifier_mac.h"
+#include "spp_forward.h"
+
+/* define */
+#define SPP_CORE_STATUS_CHECK_MAX 5
+#define SPP_RING_LATENCY_STATS_SAMPLING_INTERVAL 1000000
+
+/* struct */
+struct startup_param {
+ uint64_t cpu;
+};
+
+struct patch_info {
+ int use_flg;
+ int dpdk_port;
+ struct spp_config_mac_table_element *mac_info;
+ struct spp_core_port_info *rx_core;
+ struct spp_core_port_info *tx_core;
+};
+
+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];
+};
+
+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];
+
+/*
+ * print a usage message
+ */
+static void
+usage(const char *progname)
+{
+ RTE_LOG(INFO, APP, "Usage: %s [EAL args]\n\n", progname);
+}
+
+/*
+ * Set RING PMD
+ */
+static int
+add_ring_pmd(int ring_id)
+{
+ struct rte_ring *ring;
+ int ring_port_id;
+
+ /* look up ring, based on user's provided id*/
+ ring = rte_ring_lookup(get_rx_queue_name(ring_id));
+ if (unlikely(ring == NULL)) {
+ RTE_LOG(ERR, APP,
+ "Cannot get RX ring - is server process running?\n");
+ return -1;
+ }
+
+ /* create ring pmd*/
+ ring_port_id = rte_eth_from_ring(ring);
+ RTE_LOG(DEBUG, APP, "ring port id %d\n", ring_port_id);
+
+ return ring_port_id;
+}
+
+/*
+ * Set VHOST PMD
+ */
+static int
+add_vhost_pmd(int index)
+{
+ struct rte_eth_conf port_conf = {
+ .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN }
+ };
+ struct rte_mempool *mp;
+ uint8_t vhost_port_id;
+ int nr_queues = 1;
+ const char *name;
+ char devargs[64];
+ char *iface;
+ uint16_t q;
+ int ret;
+#define NR_DESCS 128
+
+ mp = rte_mempool_lookup(PKTMBUF_POOL_NAME);
+ if (unlikely(mp == NULL)) {
+ RTE_LOG(ERR, APP, "Cannot get mempool for mbufs. (name = %s)\n",
+ PKTMBUF_POOL_NAME);
+ return -1;
+ }
+
+ /* eth_vhost0 index 0 iface /tmp/sock0 on numa 0 */
+ name = get_vhost_backend_name(index);
+ iface = get_vhost_iface_name(index);
+
+ sprintf(devargs, "%s,iface=%s,queues=%d", name, iface, nr_queues);
+ ret = rte_eth_dev_attach(devargs, &vhost_port_id);
+ if (unlikely(ret < 0)) {
+ RTE_LOG(ERR, APP, "rte_eth_dev_attach error. (ret = %d)\n", ret);
+ return ret;
+ }
+
+ ret = rte_eth_dev_configure(vhost_port_id, nr_queues, nr_queues,
+ &port_conf);
+ if (unlikely(ret < 0)) {
+ RTE_LOG(ERR, APP, "rte_eth_dev_configure error. (ret = %d)\n",
+ ret);
+ return ret;
+ }
+
+ /* Allocate and set up 1 RX queue per Ethernet port. */
+ for (q = 0; q < nr_queues; q++) {
+ ret = rte_eth_rx_queue_setup(vhost_port_id, q, NR_DESCS,
+ rte_eth_dev_socket_id(vhost_port_id), NULL, mp);
+ if (unlikely(ret < 0)) {
+ RTE_LOG(ERR, APP,
+ "rte_eth_rx_queue_setup error. (ret = %d)\n",
+ ret);
+ return ret;
+ }
+ }
+
+ /* Allocate and set up 1 TX queue per Ethernet port. */
+ for (q = 0; q < nr_queues; q++) {
+ ret = rte_eth_tx_queue_setup(vhost_port_id, q, NR_DESCS,
+ rte_eth_dev_socket_id(vhost_port_id), NULL);
+ if (unlikely(ret < 0)) {
+ RTE_LOG(ERR, APP,
+ "rte_eth_tx_queue_setup error. (ret = %d)\n",
+ ret);
+ return ret;
+ }
+ }
+
+ /* Start the Ethernet port. */
+ ret = rte_eth_dev_start(vhost_port_id);
+ if (unlikely(ret < 0)) {
+ RTE_LOG(ERR, APP, "rte_eth_dev_start error. (ret = %d)\n", ret);
+ return ret;
+ }
+
+ RTE_LOG(DEBUG, APP, "vhost port id %d\n", vhost_port_id);
+
+ return vhost_port_id;
+}
+
+/*
+ * Check core status
+ */
+static int
+check_core_status(enum spp_core_status status)
+{
+ int cnt;
+ 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) {
+ /* Status mismatch */
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Wait for core status check
+ */
+static int
+check_core_status_wait(enum spp_core_status status)
+{
+ int cnt = 0;
+ for (cnt = 0; cnt < SPP_CORE_STATUS_CHECK_MAX; cnt++) {
+ sleep(1);
+ int ret = check_core_status(status);
+ if (ret == 0) {
+ return 0;
+ }
+ }
+
+ RTE_LOG(ERR, APP, "Status check time out. (status = %d)\n", status);
+ return -1;
+}
+
+/*
+ * Set core status
+ */
+static void
+set_core_status(enum spp_core_status status)
+{
+ int core_cnt = 0;
+ for(core_cnt = 0; core_cnt < SPP_CONFIG_CORE_MAX; core_cnt++) {
+ g_core_info[core_cnt].status = status;
+ }
+}
+
+/*
+ * Process stop
+ */
+void
+stop_process(int signal) {
+ if (unlikely(signal != SIGTERM) &&
+ unlikely(signal != SIGINT)) {
+ /* Other signals */
+ return;
+ }
+
+ set_core_status(SPP_CORE_STOP_REQUEST);
+}
+
+/*
+ * 起動パラメータのCPUのbitmapを数値へ変換
+ */
+static int
+parse_cpu_bit(uint64_t *cpu, const char *cpu_bit)
+{
+ char *endptr = NULL;
+ uint64_t temp;
+
+ temp = strtoull(cpu_bit, &endptr, 0);
+ if (unlikely(endptr == cpu_bit) || unlikely(*endptr != '\0')) {
+ return -1;
+ }
+
+ *cpu = temp;
+ RTE_LOG(DEBUG, APP, "cpu = %lu", *cpu);
+ return 0;
+}
+
+/*
+ * Parse the application arguments to the client app.
+ */
+static int
+parse_app_args(int argc, char *argv[])
+{
+ int option_index, opt;
+ char **argvopt = argv;
+ const char *progname = argv[0];
+ static struct option lgopts[] = { {0} };
+
+ /* Check DPDK parameter */
+ optind = 0;
+ opterr = 0;
+ while ((opt = getopt_long(argc, argvopt, "c:", lgopts,
+ &option_index)) != EOF) {
+ switch (opt) {
+ case 'c':
+ /* CPU */
+ if (parse_cpu_bit(&g_startup_param.cpu, optarg) != 0) {
+ usage(progname);
+ return -1;
+ }
+ break;
+ default:
+ /* CPU */
+ /* DPDKのパラメータは他にもあるので、エラーとはしない */
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * IF種別&IF番号のIF情報の領域取得
+ */
+static struct patch_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];
+ break;
+ case VHOST:
+ return &g_if_info.vhost_patchs[if_no];
+ break;
+ case RING:
+ return &g_if_info.ring_patchs[if_no];
+ break;
+ default:
+ /* エラー出力は呼び元でチェック */
+ return NULL;
+ break;
+ }
+}
+
+/*
+ * IF情報初期化
+ */
+static void
+init_if_info()
+{
+ memset(&g_if_info, 0x00, sizeof(g_if_info));
+}
+
+/*
+ * CORE情報初期化
+ */
+static void
+init_core_info()
+{
+ 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++) {
+ 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;
+ }
+ }
+}
+
+/*
+ * Configのプロセス情報から管理情報に設定
+ */
+static int
+set_form_proc_info(struct spp_config_area *config)
+{
+ /* Configのproc_infoから内部管理情報へ設定 */
+ int core_cnt, rx_start, rx_cnt, tx_start, tx_cnt;
+ enum port_type if_type;
+ int if_no;
+ int64_t cpu_bit = 0;
+ 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;
+ }
+
+ /* Forwardをまとめる事は可、他種別は不可 */
+ 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;
+ }
+
+ /* Set CORE type */
+ core_info->type = core_func->type;
+ cpu_bit |= 1 << core_func->core_no;
+
+ /* Set RX port */
+ 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;
+
+ /* IF種別とIF番号に対応するIF情報の領域取得 */
+ 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 (if_type = %d, if_no = %d)\n",
+ if_type, if_no);
+ return -1;
+ }
+
+ /* IF情報からCORE情報を変更する場合用に設定 */
+ 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;
+
+ /* IF種別とIF番号に対応するIF情報の領域取得 */
+ 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 (if_type = %d, if_no = %d)\n",
+ if_type, if_no);
+ return -1;
+ }
+
+ /* IF情報からCORE情報を変更する場合用に設定 */
+ patch_info->tx_core = &core_info->tx_ports[tx_start + tx_cnt];
+ }
+ }
+
+ if (unlikely((cpu_bit & g_startup_param.cpu) != cpu_bit)) {
+ /* CPU mismatch */
+ RTE_LOG(ERR, APP, "CPU mismatch (cpu param = %lx, config = %lx)\n",
+ g_startup_param.cpu, cpu_bit);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * ConfigのMACテーブル情報から管理情報に設定
+ */
+static int
+set_from_classifier_table(struct spp_config_area *config)
+{
+ /* MAC table */
+ 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;
+
+ /* IF種別とIF番号に対応するIF情報の領域取得 */
+ 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;
+ }
+
+ /* CORE情報側にもMACアドレスの情報設定 */
+ /* MACアドレスは送信側のみに影響する為、送信側のみ設定 */
+ patch_info->mac_info = mac_table;
+ 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;
+}
+
+/*
+ * NIC用の情報設定
+ */
+static int
+set_nic_interface(struct spp_config_area *config)
+{
+ /* 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];
+ /* Set DPDK port */
+ patch_info->dpdk_port = nic_cnt;
+
+ if (patch_info->use_flg == 0) {
+ /* Not Used */
+ continue;
+ }
+
+ /* CORE情報側にもDPDKポート番号の情報設定 */
+ 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の設定数カウント */
+ 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;
+ }
+
+ return 0;
+}
+
+/*
+ * VHOST用の情報設定
+ */
+static int
+set_vhost_interface(struct spp_config_area *config)
+{
+ /* VHOST Setting */
+ 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;
+ }
+
+ /* Set DPDK port */
+ int dpdk_port = add_vhost_pmd(vhost_cnt);
+ 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;
+
+ /* CORE情報側にもDPDKポート番号の情報設定 */
+ 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;
+}
+
+/*
+ * RING用の情報設定
+ */
+static int
+set_ring_interface(struct spp_config_area *config)
+{
+ /* RING Setting */
+ 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) {
+ /* Not Used */
+ continue;
+ }
+
+ /* Set DPDK port */
+ 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;
+
+ /* CORE情報側にもDPDKポート番号の情報設定 */
+ 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;
+}
+
+/*
+ * 管理データ初期設定
+ */
+static int
+init_manage_data(struct spp_config_area *config)
+{
+ /* Initialize */
+ init_if_info(config);
+ init_core_info(config);
+
+ /* Set config data */
+ int ret_proc = set_form_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;
+ }
+
+ /* Set interface data */
+ int ret_nic = set_nic_interface(config);
+ 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;
+}
+
+#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
+static void
+print_ring_latency_stats()
+{
+ /* Clear screen and move to top left */
+ const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' };
+ const char clr[] = { 27, '[', '2', 'J', '\0' };
+ printf("%s%s", clr, topLeft);
+
+ /* Print per RING */
+ int ring_cnt, stats_cnt;
+ struct spp_ringlatencystats_ring_latency_stats stats[RTE_MAX_ETHPORTS];
+ memset(&stats, 0x00, sizeof(stats));
+
+ 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) {
+ continue;
+ }
+ spp_ringlatencystats_get_stats(ring_cnt, &stats[ring_cnt]);
+ printf(", %-18d", ring_cnt);
+ }
+ printf("\n");
+
+ 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) {
+ continue;
+ }
+
+ printf(", 0x%-16lx", stats[ring_cnt].slot[stats_cnt]);
+ }
+ printf("\n");
+ }
+
+ return;
+}
+#endif /* SPP_RINGLATENCYSTATS_ENABLE */
+
+/*
+ * main
+ */
+int
+#ifndef USE_UT_SPP_VF
+main(int argc, char *argv[])
+#else /* ifndef USE_UT_SPP_VF */
+ut_main(int argc, char *argv[])
+#endif /* ifndef USE_UT_SPP_VF */
+{
+ int ret = -1;
+#ifdef SPP_DEMONIZE
+ /* Daemonize process */
+ int ret_daemon = daemon(0, 0);
+ if (unlikely(ret_daemon != 0)) {
+ RTE_LOG(ERR, APP, "daemonize is faild. (ret = %d)\n", ret_daemon);
+ return ret_daemon;
+ }
+#endif
+
+ /* Signal handler registration (SIGTERM/SIGINT) */
+ signal(SIGTERM, stop_process);
+ signal(SIGINT, stop_process);
+
+ unsigned int main_lcore_id = 0xffffffff;
+ while(1) {
+ /* Parse parameters */
+ int ret_parse = parse_app_args(argc, argv);
+ if (unlikely(ret_parse != 0)) {
+ break;
+ }
+
+ /* Load config */
+ int ret_config = spp_config_load_file(0, &g_config);
+ if (unlikely(ret_config != 0)) {
+ break;
+ }
+
+ /* DPDK initialize */
+ int ret_dpdk = rte_eal_init(argc, argv);
+ if (unlikely(ret_dpdk < 0)) {
+ break;
+ }
+ /* Get core id. */
+ main_lcore_id = rte_lcore_id();
+
+ /* 起動パラメータとコンフィグチェック */
+ /* 各IF情報設定 */
+ int ret_manage = init_manage_data(&g_config);
+ if (unlikely(ret_manage != 0)) {
+ break;
+ }
+
+ /* 他機能部初期化 */
+#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
+ int ret_ringlatency = spp_ringlatencystats_init(
+ SPP_RING_LATENCY_STATS_SAMPLING_INTERVAL, g_if_info.num_ring);
+ if (unlikely(ret_ringlatency != 0)) {
+ break;
+ }
+#endif /* SPP_RINGLATENCYSTATS_ENABLE */
+
+ /* Start thread */
+ 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);
+ }
+ }
+
+ /* スレッド状態確認 */
+ g_core_info[main_lcore_id].status = SPP_CORE_IDLE;
+ int ret_wait = check_core_status_wait(SPP_CORE_IDLE);
+ if (unlikely(ret_wait != 0)) {
+ break;
+ }
+
+ /* Start forward */
+ set_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");
+
+ /* loop */
+#ifndef USE_UT_SPP_VF
+ while(likely(g_core_info[main_lcore_id].status != SPP_CORE_STOP_REQUEST)) {
+#else
+ {
+#endif
+ sleep(1);
+
+#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
+ print_ring_latency_stats();
+#endif /* SPP_RINGLATENCYSTATS_ENABLE */
+ }
+
+ /* 正常終了 */
+ ret = 0;
+ break;
+ }
+
+ /* exit */
+ stop_process(SIGINT);
+ if (main_lcore_id == rte_lcore_id())
+ {
+ g_core_info[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");
+ }
+ }
+
+ /* 他機能部終了処理 */
+#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
+ spp_ringlatencystats_uninit();
+#endif /* SPP_RINGLATENCYSTATS_ENABLE */
+ RTE_LOG(INFO, APP, "spp_vf exit.\n");
+ return ret;
+}
diff --git a/src/vf/spp_vf.h b/src/vf/spp_vf.h
new file mode 100644
index 0000000..feb59b6
--- /dev/null
+++ b/src/vf/spp_vf.h
@@ -0,0 +1,40 @@
+#ifndef __SPP_VF_H__
+#define __SPP_VF_H__
+
+#include "common.h"
+#include "spp_config.h"
+
+/*
+ * State on core
+ */
+enum spp_core_status {
+ SPP_CORE_STOP,
+ SPP_CORE_IDLE,
+ SPP_CORE_FORWARD,
+ SPP_CORE_STOP_REQUEST
+};
+
+/*
+ * Port info on core
+ */
+struct spp_core_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];
+};
+
+/*
+ * Core info
+ */
+struct spp_core_info {
+ 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];
+};
+
+#endif /* __SPP_VF_H__ */
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* Re: [spp] [PATCH 01/57] spp_vf: add vf functions
2017-12-28 4:55 ` [spp] [PATCH 01/57] spp_vf: add vf functions x-fn-spp
@ 2017-12-28 8:49 ` Yasufumi Ogawa
0 siblings, 0 replies; 97+ messages in thread
From: Yasufumi Ogawa @ 2017-12-28 8:49 UTC (permalink / raw)
To: x-fn-spp, spp
Hi Hiroyuki,
Thank you for your contribution! I would like to review your patches for
merging.
Thanks,
Yasufumi
On 2017/12/28 13:55, x-fn-spp@sl.ntt-tx.co.jp wrote:
> From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
>
> Hi everyone,
>
> This the first patch of series for spp_vf. Some of them might not comply
> with coding style for whitespace or indenting and I would like to send
> patches to fix it later.
>
> I also would like to send another series of patches for documentation after
> you accept first series.
>
> Thanks,
>
> * Classifier by MAC address
> * Forwarder
> * Merger
>
> Signed-off-by: Tomoyuki Mizuguchi <mizuguchi.tomoyuki@po.ntt-tx.co.jp>
> Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
> ---
> src/Makefile | 1 +
> src/vf/Makefile | 56 ++++
> src/vf/classifier_mac.c | 233 ++++++++++++++
> src/vf/classifier_mac.h | 12 +
> src/vf/ringlatencystats.c | 147 +++++++++
> src/vf/ringlatencystats.h | 69 ++++
> src/vf/spp_config.c | 669 ++++++++++++++++++++++++++++++++++++++
> src/vf/spp_config.h | 90 ++++++
> src/vf/spp_forward.c | 106 +++++++
> src/vf/spp_forward.h | 9 +
> src/vf/spp_vf.c | 794 ++++++++++++++++++++++++++++++++++++++++++++++
> src/vf/spp_vf.h | 40 +++
> 12 files changed, 2226 insertions(+)
> create mode 100644 src/vf/Makefile
> create mode 100644 src/vf/classifier_mac.c
> create mode 100644 src/vf/classifier_mac.h
> create mode 100644 src/vf/ringlatencystats.c
> create mode 100644 src/vf/ringlatencystats.h
> create mode 100644 src/vf/spp_config.c
> create mode 100644 src/vf/spp_config.h
> create mode 100644 src/vf/spp_forward.c
> create mode 100644 src/vf/spp_forward.h
> create mode 100644 src/vf/spp_vf.c
> create mode 100644 src/vf/spp_vf.h
>
> diff --git a/src/Makefile b/src/Makefile
> index 6fd24b8..d2eb9b6 100644
> --- a/src/Makefile
> +++ b/src/Makefile
> @@ -41,5 +41,6 @@ include $(RTE_SDK)/mk/rte.vars.mk
> DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += nfv
> DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += primary
> DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += vm
> +DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += vf
>
> include $(RTE_SDK)/mk/rte.extsubdir.mk
> diff --git a/src/vf/Makefile b/src/vf/Makefile
> new file mode 100644
> index 0000000..4961d2e
> --- /dev/null
> +++ b/src/vf/Makefile
> @@ -0,0 +1,56 @@
> +# BSD LICENSE
> +#
> +# Copyright(c) 2015-2016 Intel Corporation. All rights reserved.
> +# All rights reserved.
> +#
> +# Redistribution and use in source and binary forms, with or without
> +# modification, are permitted provided that the following conditions
> +# are met:
> +#
> +# * Redistributions of source code must retain the above copyright
> +# notice, this list of conditions and the following disclaimer.
> +# * Redistributions in binary form must reproduce the above copyright
> +# notice, this list of conditions and the following disclaimer in
> +# the documentation and/or other materials provided with the
> +# distribution.
> +# * Neither the name of Intel Corporation nor the names of its
> +# contributors may be used to endorse or promote products derived
> +# from this software without specific prior written permission.
> +#
> +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +ifeq ($(RTE_SDK),)
> +$(error "Please define RTE_SDK environment variable")
> +endif
> +
> +# Default target, can be overriden by command line or environment
> +include $(RTE_SDK)/mk/rte.vars.mk
> +
> +# binary name
> +APP = spp_vf
> +
> +# all source are stored in SRCS-y
> +SRCS-y := spp_vf.c spp_config.c classifier_mac.c spp_forward.c ringlatencystats.c ../shared/common.c
> +
> +CFLAGS += $(WERROR_FLAGS) -O3
> +CFLAGS += -I$(SRCDIR)/../shared
> +#CFLAGS += -DSPP_DEMONIZE
> +#CFLAGS += -DSPP_RINGLATENCYSTATS_ENABLE
> +
> +LDLIBS += -ljansson
> +ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
> +LDLIBS += -lrte_pmd_ring
> +LDLIBS += -lrte_pmd_vhost
> +endif
> +
> +include $(RTE_SDK)/mk/rte.extapp.mk
> diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
> new file mode 100644
> index 0000000..da03905
> --- /dev/null
> +++ b/src/vf/classifier_mac.c
> @@ -0,0 +1,233 @@
> +#include <unistd.h>
> +#include <sys/types.h>
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <stddef.h>
> +#include <math.h>
> +
> +#include <rte_mbuf.h>
> +#include <rte_log.h>
> +#include <rte_cycles.h>
> +#include <rte_malloc.h>
> +#include <rte_memcpy.h>
> +#include <rte_random.h>
> +#include <rte_byteorder.h>
> +#include <rte_per_lcore.h>
> +#include <rte_eal.h>
> +#include <rte_launch.h>
> +#include <rte_hash.h>
> +
> +#include "spp_vf.h"
> +#include "ringlatencystats.h"
> +#include "classifier_mac.h"
> +
> +#define RTE_LOGTYPE_SPP_CLASSIFIER_MAC RTE_LOGTYPE_USER1
> +
> +#ifdef RTE_MACHINE_CPUFLAG_SSE4_2
> +#include <rte_hash_crc.h>
> +#define DEFAULT_HASH_FUNC rte_hash_crc
> +#else
> +#include <rte_jhash.h>
> +#define DEFAULT_HASH_FUNC rte_jhash
> +#endif
> +
> +/* number of classifier mac table entry */
> +#define NUM_CLASSIFIER_MAC_TABLE_ENTRY 128
> +
> +/* interval that transmit burst packet, if buffer is not filled.
> + nano second */
> +#define DRAIN_TX_PACKET_INTERVAL 100
> +
> +/* mac address string(xx:xx:xx:xx:xx:xx) buffer size */
> +static const size_t ETHER_ADDR_STR_BUF_SZ =
> + ETHER_ADDR_LEN * 2 + (ETHER_ADDR_LEN - 1) + 1;
> +
> +/* classified data (destination port, target packets, etc) */
> +struct classified_data {
> + int if_no;
> + uint8_t tx_port;
> + uint16_t num_pkt;
> + struct rte_mbuf *pkts[MAX_PKT_BURST];
> +};
> +
> +/* initialize classifier. */
> +static int
> +init_classifier(const struct spp_core_info *core_info,
> + struct rte_hash **classifier_mac_table, struct classified_data *classified_data)
> +{
> + int ret = -1;
> + int i;
> + struct ether_addr eth_addr;
> + char mac_addr_str[ETHER_ADDR_STR_BUF_SZ];
> +
> + /* set hash creating parameters */
> + struct rte_hash_parameters hash_params = {
> + .name = "classifier_mac_table",
> + .entries = NUM_CLASSIFIER_MAC_TABLE_ENTRY,
> + .key_len = sizeof(struct ether_addr),
> + .hash_func = DEFAULT_HASH_FUNC,
> + .hash_func_init_val = 0,
> + .socket_id = rte_socket_id(),
> + };
> +
> +#ifdef RTE_MACHINE_CPUFLAG_SSE4_2
> + RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, "Enabled SSE4.2. use crc hash.\n");
> +#else
> + RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, "Disabled SSE4.2. use jenkins hash.\n");
> +#endif
> +
> + /* create classifier mac table (hash table) */
> + *classifier_mac_table = rte_hash_create(&hash_params);
> + if (unlikely(*classifier_mac_table == NULL)) {
> + RTE_LOG(ERR, SPP_CLASSIFIER_MAC, "Cannot create classifier mac table\n");
> + return -1;
> + }
> +
> + /* populate the hash */
> + for (i = 0; i < core_info->num_tx_port; i++) {
> + rte_memcpy(ð_addr, &core_info->tx_ports[i].mac_addr, ETHER_ADDR_LEN);
> +
> + /* add entry to classifier mac table */
> + ret = rte_hash_add_key_data(*classifier_mac_table, (void*)ð_addr, (void*)(long)i);
> + if (unlikely(ret < 0)) {
> + ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð_addr);
> + RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
> + "Cannot add entry to classifier mac table. "
> + "ret=%d, mac_addr=%s\n", ret, mac_addr_str);
> + rte_hash_free(*classifier_mac_table);
> + *classifier_mac_table = NULL;
> + return -1;
> + }
> +
> + /* set value */
> + classified_data[i].if_no = i;
> + classified_data[i].tx_port = core_info->tx_ports[i].dpdk_port;
> + classified_data[i].num_pkt = 0;
> + }
> +
> + return 0;
> +}
> +
> +/* transimit packet to one destination. */
> +static inline void
> +transimit_packet(struct classified_data *classified_data)
> +{
> + int i;
> + uint16_t n_tx;
> +
> + /* set ringlatencystats */
> + spp_ringlatencystats_add_time_stamp(classified_data->if_no,
> + classified_data->pkts, classified_data->num_pkt);
> +
> + /* transimit packets */
> + n_tx = rte_eth_tx_burst(classified_data->tx_port, 0,
> + classified_data->pkts, classified_data->num_pkt);
> +
> + /* free cannnot transiit packets */
> + if (unlikely(n_tx != classified_data->num_pkt)) {
> + for (i = n_tx; i < classified_data->num_pkt; i++)
> + 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 = 0;
> +}
> +
> +/* classify packet by destination mac address,
> + and transimit packet (conditional). */
> +static inline void
> +classify_packet(struct rte_mbuf **rx_pkts, uint16_t n_rx,
> + struct rte_hash *classifier_mac_table, struct classified_data *classified_data)
> +{
> + int ret;
> + int i;
> + struct ether_hdr *eth;
> + struct classified_data *cd;
> + void *lookup_data;
> + char mac_addr_str[ETHER_ADDR_STR_BUF_SZ];
> +
> + for (i = 0; i < n_rx; i++) {
> + eth = rte_pktmbuf_mtod(rx_pkts[i], struct ether_hdr *);
> +
> + /* find in table (by destination mac address)*/
> + ret = rte_hash_lookup_data(classifier_mac_table,
> + (const void*)ð->d_addr, &lookup_data);
> + if (unlikely(ret < 0)) {
> + ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð->d_addr);
> + RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
> + "unknown mac address. ret=%d, mac_addr=%s\n", ret, mac_addr_str);
> + rte_pktmbuf_free(rx_pkts[i]);
> + continue;
> + }
> +
> + /* set mbuf pointer to tx buffer */
> + cd = classified_data + (long)lookup_data;
> + cd->pkts[cd->num_pkt++] = rx_pkts[i];
> +
> + /* transimit packet, if buffer is filled */
> + if (unlikely(cd->num_pkt == MAX_PKT_BURST))
> + transimit_packet(cd);
> + }
> +}
> +
> +/* classifier(mac address) thread function. */
> +int
> +spp_classifier_mac_do(void *arg)
> +{
> + int ret = -1;
> + int i;
> + int n_rx;
> + struct spp_core_info *core_info = (struct spp_core_info *)arg;
> + struct rte_mbuf *rx_pkts[MAX_PKT_BURST];
> +
> + struct rte_hash *classifier_mac_table = NULL;
> + const int n_classified_data = core_info->num_tx_port;
> + struct classified_data classified_data[n_classified_data];
> +
> + 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_mac_table, classified_data);
> + if (unlikely(ret != 0))
> + return ret;
> +
> + /* to idle */
> + core_info->status = SPP_CORE_IDLE;
> + while(likely(core_info->status == SPP_CORE_IDLE) ||
> + likely(core_info->status == SPP_CORE_FORWARD)) {
> +
> + while(likely(core_info->status == SPP_CORE_FORWARD)) {
> + /* 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))
> + transimit_packet(&classified_data[i]);
> + }
> + 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;
> +
> + /* classify and transimit (filled) */
> + classify_packet(rx_pkts, n_rx, classifier_mac_table, classified_data);
> + }
> + }
> +
> + /* uninitialize */
> + if (classifier_mac_table != NULL) {
> + rte_hash_free(classifier_mac_table);
> + classifier_mac_table = NULL;
> + }
> + core_info->status = SPP_CORE_STOP;
> +
> + return 0;
> +}
> diff --git a/src/vf/classifier_mac.h b/src/vf/classifier_mac.h
> new file mode 100644
> index 0000000..2661206
> --- /dev/null
> +++ b/src/vf/classifier_mac.h
> @@ -0,0 +1,12 @@
> +#ifndef _CLASSIFIER_MAC_H_
> +#define _CLASSIFIER_MAC_H_
> +
> +/**
> + * classifier(mac address) thread function.
> + *
> + * @param arg
> + * pointer to struct spp_core_info.
> + */
> +int spp_classifier_mac_do(void *arg);
> +
> +#endif /* _CLASSIFIER_MAC_H_ */
> diff --git a/src/vf/ringlatencystats.c b/src/vf/ringlatencystats.c
> new file mode 100644
> index 0000000..8f44020
> --- /dev/null
> +++ b/src/vf/ringlatencystats.c
> @@ -0,0 +1,147 @@
> +#include <unistd.h>
> +#include <sys/types.h>
> +#include <stdio.h>
> +#include <stddef.h>
> +#include <math.h>
> +
> +#include <rte_mbuf.h>
> +#include <rte_log.h>
> +#include <rte_cycles.h>
> +#include <rte_malloc.h>
> +#include <rte_memcpy.h>
> +
> +#include "ringlatencystats.h"
> +
> +#define NS_PER_SEC 1E9
> +
> +#define RTE_LOGTYPE_SPP_RING_LATENCY_STATS RTE_LOGTYPE_USER1
> +
> +#ifdef SPP_RINGLATENCYSTATS_ENABLE
> +
> +/** ring latency statistics information */
> +struct ring_latency_stats_info {
> + uint64_t timer_tsc; /**< sampling interval counter */
> + uint64_t prev_tsc; /**< previous time */
> + struct spp_ringlatencystats_ring_latency_stats stats; /**< ring latency statistics list */
> +};
> +
> +/** sampling interval */
> +static uint64_t g_samp_intvl = 0;
> +
> +/** ring latency statistics information instance */
> +static struct ring_latency_stats_info *g_stats_info = NULL;
> +
> +/** number of ring latency statisics */
> +static uint16_t g_stats_count = 0;
> +
> +/* clock cycles per nano second */
> +static inline uint64_t
> +cycles_per_ns(void)
> +{
> + return rte_get_timer_hz() / NS_PER_SEC;
> +}
> +
> +int
> +spp_ringlatencystats_init(uint64_t samp_intvl, uint16_t stats_count)
> +{
> + /* allocate memory for ring latency statisics infromation */
> + g_stats_info = rte_zmalloc(
> + "global ring_latency_stats_info",
> + sizeof(struct ring_latency_stats_info) * stats_count, 0);
> + if (unlikely(g_stats_info == NULL)) {
> + RTE_LOG(ERR, SPP_RING_LATENCY_STATS,
> + "Cannot allocate memory for ring latency stats info\n");
> + return -1;
> + }
> +
> + /* store global information for ring latency statistics */
> + g_samp_intvl = samp_intvl * cycles_per_ns();
> + g_stats_count = stats_count;
> +
> + RTE_LOG(DEBUG, SPP_RING_LATENCY_STATS,
> + "g_samp_intvl=%lu, g_stats_count=%hu, cpns=%lu\n",
> + g_samp_intvl, g_stats_count, cycles_per_ns());
> +
> + return 0;
> +}
> +
> +void
> +spp_ringlatencystats_uninit(void)
> +{
> + /* free memory for ring latency statisics infromation */
> + if (likely(g_stats_info != NULL)) {
> + rte_free(g_stats_info);
> + g_stats_count = 0;
> + }
> +}
> +
> +void
> +spp_ringlatencystats_add_time_stamp(int ring_id,
> + struct rte_mbuf **pkts, uint16_t nb_pkts)
> +{
> + unsigned int i;
> + uint64_t diff_tsc, now;
> + struct ring_latency_stats_info *stats_info = &g_stats_info[ring_id];
> +
> + for (i = 0; i < nb_pkts; i++) {
> +
> + /* get tsc now */
> + now = rte_rdtsc();
> +
> + /* calculate difference from the previous processing time */
> + diff_tsc = now - stats_info->prev_tsc;
> + stats_info->timer_tsc += diff_tsc;
> +
> + /* when it is over sampling interval */
> + /* set tsc to mbuf::timestamp */
> + if (unlikely(stats_info->timer_tsc >= g_samp_intvl)) {
> + pkts[i]->timestamp = now;
> + stats_info->timer_tsc = 0;
> + }
> +
> + /* update previus tsc */
> + stats_info->prev_tsc = now;
> + }
> +}
> +
> +void
> +spp_ringlatencystats_calculate_latency(int ring_id,
> + struct rte_mbuf **pkts, uint16_t nb_pkts)
> +{
> + unsigned int i;
> + uint64_t now;
> + int64_t latency;
> + struct ring_latency_stats_info *stats_info = &g_stats_info[ring_id];
> +
> + now = rte_rdtsc();
> + for (i = 0; i < nb_pkts; i++) {
> + if (likely(pkts[i]->timestamp == 0))
> + continue;
> +
> + /* when mbuf::timestamp is not zero */
> + /* calculate latency */
> + latency = (uint64_t)floor((now - pkts[i]->timestamp) / cycles_per_ns());
> + if (likely(latency < SPP_RINGLATENCYSTATS_STATS_SLOT_COUNT-1))
> + stats_info->stats.slot[latency]++;
> + else
> + stats_info->stats.slot[SPP_RINGLATENCYSTATS_STATS_SLOT_COUNT-1]++;
> + }
> +}
> +
> +int
> +spp_ringlatencystats_get_count(void)
> +{
> + return g_stats_count;
> +}
> +
> +void
> +spp_ringlatencystats_get_stats(int ring_id,
> + struct spp_ringlatencystats_ring_latency_stats *stats)
> +{
> + struct ring_latency_stats_info *stats_info = &g_stats_info[ring_id];
> +
> + rte_memcpy(stats, &stats_info->stats,
> + sizeof(struct spp_ringlatencystats_ring_latency_stats));
> +}
> +
> +#endif /* SPP_RINGLATENCYSTATS_ENABLE */
> diff --git a/src/vf/ringlatencystats.h b/src/vf/ringlatencystats.h
> new file mode 100644
> index 0000000..bc47699
> --- /dev/null
> +++ b/src/vf/ringlatencystats.h
> @@ -0,0 +1,69 @@
> +#ifndef _RINGLATENCYSTATS_H_
> +#define _RINGLATENCYSTATS_H_
> +
> +#include <rte_mbuf.h>
> +
> +/** number of slots to save latency. 0ns~99ns and 100ns over */
> +#define SPP_RINGLATENCYSTATS_STATS_SLOT_COUNT 101
> +
> +/** ring latency statistics */
> +struct spp_ringlatencystats_ring_latency_stats {
> + uint64_t slot[SPP_RINGLATENCYSTATS_STATS_SLOT_COUNT]; /**< slots to save latency */
> +};
> +
> +
> +#ifdef SPP_RINGLATENCYSTATS_ENABLE
> +/**
> + * initialize ring latency statisics.
> + *
> + * @retval 0: succeeded.
> + * @retval -1: failed.
> + */
> +int spp_ringlatencystats_init(uint64_t samp_intvl, uint16_t stats_count);
> +
> +/**
> + *uninitialize ring latency statisics.
> + */
> +void spp_ringlatencystats_uninit(void);
> +
> +/**
> + * add time-stamp to mbuf's member.
> + *
> + * call at enqueue.
> + */
> +void spp_ringlatencystats_add_time_stamp(int ring_id,
> + struct rte_mbuf **pkts, uint16_t nb_pkts);
> +
> +/**
> + * calculate latency.
> + *
> + * call at dequeue.
> + */
> +void spp_ringlatencystats_calculate_latency(int ring_id,
> + struct rte_mbuf **pkts, uint16_t nb_pkts);
> +
> +/**
> + * get number of ring latency statisics.
> + *
> + * @return spp_ringlatencystats_init's parameter "stats_count"
> + */
> +int spp_ringlatencystats_get_count(void);
> +
> +/**
> + *get specific ring latency statisics.
> + */
> +void spp_ringlatencystats_get_stats(int ring_id,
> + struct spp_ringlatencystats_ring_latency_stats *stats);
> +
> +#else
> +
> +#define spp_ringlatencystats_init(arg1, arg2) 0
> +#define spp_ringlatencystats_uninit()
> +#define spp_ringlatencystats_add_time_stamp(arg1, arg2, arg3)
> +#define spp_ringlatencystats_calculate_latency(arg1, arg2, arg3)
> +#define spp_ringlatencystats_get_count() 0
> +#define spp_ringlatencystats_get_stats(arg1, arg2)
> +
> +#endif /* SPP_RINGLATENCYSTATS_ENABLE */
> +
> +#endif /* _RINGLATENCYSTATS_H_ */
> diff --git a/src/vf/spp_config.c b/src/vf/spp_config.c
> new file mode 100644
> index 0000000..63b85f2
> --- /dev/null
> +++ b/src/vf/spp_config.c
> @@ -0,0 +1,669 @@
> +#include <sys/types.h>
> +#include <jansson.h>
> +
> +#include <rte_log.h>
> +
> +#include "spp_config.h"
> +
> +#define CONFIG_CORE_TYPE_CLASSIFIER_MAC "classifier_mac"
> +#define CONFIG_CORE_TYPE_MERGE "merge"
> +#define CONFIG_CORE_TYPE_FORWARD "forward"
> +
> +#define JSONPATH_CLASSIFIER_TABLE "$.classifier_table"
> +#define JSONPATH_PROC_TABLE "$.vfs"
> +#define JSONPATH_NAME "$.name"
> +#define JSONPATH_TABLE "$.table"
> +#define JSONPATH_MAC "$.mac"
> +#define JSONPATH_PORT "$.port"
> +#define JSONPATH_NUM_VHOST "$.num_vhost"
> +#define JSONPATH_NUM_RING "$.num_ring"
> +#define JSONPATH_FUNCTIONS "$.functions"
> +#define JSONPATH_CORE_NO "$.core"
> +#define JSONPATH_CORE_TYPE "$.type"
> +#define JSONPATH_RX_PORT "$.rx_port"
> +#define JSONPATH_TX_PORT "$.tx_port"
> +#define JSONPATH_TX_TABLE "$.tx_port_table"
> +
> +/*
> + * Get integer data from config
> + */
> +static int
> +config_get_int_value(const json_t *obj, const char *path, int *value)
> +{
> + /* 指定パラメータのJsonオブジェクト取得 */
> + json_t *tmp_obj = json_path_get(obj, path);
> + if (unlikely(tmp_obj == NULL)) {
> + /* 必須でないデータを取得する場合を考慮し、DEBUGログとする。 */
> + RTE_LOG(DEBUG, APP, "No parameter. (path = %s)\n", path);
> + return -1;
> + }
> +
> + /* Integer type check */
> + if (unlikely(!json_is_integer(tmp_obj))) {
> + /* 必須でないデータを取得する場合を考慮し、DEBUGログとする。 */
> + RTE_LOG(DEBUG, APP, "Not an integer. (path = %s)\n", path);
> + return -1;
> + }
> +
> + /* Set to OUT parameter */
> + *value = json_integer_value(tmp_obj);
> + RTE_LOG(DEBUG, APP, "get value = %d\n", *value);
> + return 0;
> +}
> +
> +/*
> + * Get String data from config
> + */
> +static int
> +config_get_str_value(const json_t *obj, const char *path, char *value)
> +{
> + /* 指定パラメータのJsonオブジェクト取得 */
> + json_t *tmp_obj = json_path_get(obj, path);
> + if (unlikely(tmp_obj == NULL)) {
> + RTE_LOG(DEBUG, APP, "No parameter. (path = %s)\n", path);
> + return -1;
> + }
> +
> + /* String type check */
> + if (unlikely(!json_is_string(tmp_obj))) {
> + RTE_LOG(DEBUG, APP, "Not a string. (path = %s)\n", path);
> + return -1;
> + }
> +
> + /* Set to OUT parameter */
> + strcpy(value, json_string_value(tmp_obj));
> + RTE_LOG(DEBUG, APP, "get value = %s\n", value);
> + return 0;
> +}
> +
> +/*
> + * コンフィグ情報初期化
> + */
> +static void
> +config_init_data(struct spp_config_area *config)
> +{
> + /* 0クリア */
> + memset(config, 0x00, sizeof(struct spp_config_area));
> + int core_cnt, port_cnt, table_cnt;
> +
> + /* IF種別初期設定 */
> + 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;
> + config->proc.functions[core_cnt].tx_ports[port_cnt].if_type = UNDEF;
> + }
> + }
> + for (table_cnt = 0; table_cnt < SPP_CONFIG_MAC_TABLE_MAX; table_cnt++) {
> + config->classifier_table.mac_tables[table_cnt].port.if_type = UNDEF;
> + }
> +
> + return;
> +}
> +
> +/*
> + * IFの情報からIF種別とIF番号を取得する
> + * ("ring0" -> 種別:"ring"、番号:0)
> + */
> +static int
> +config_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;
> +
> + /* IF type check */
> + if (strncmp(port, SPP_CONFIG_IFTYPE_NIC, strlen(SPP_CONFIG_IFTYPE_NIC)) == 0) {
> + /* NIC */
> + type = PHY;
> + no_str = &port[strlen(SPP_CONFIG_IFTYPE_NIC)];
> + } else if (strncmp(port, SPP_CONFIG_IFTYPE_VHOST, strlen(SPP_CONFIG_IFTYPE_VHOST)) == 0) {
> + /* VHOST */
> + type = VHOST;
> + no_str = &port[strlen(SPP_CONFIG_IFTYPE_VHOST)];
> + } else if (strncmp(port, SPP_CONFIG_IFTYPE_RING, strlen(SPP_CONFIG_IFTYPE_RING)) == 0) {
> + /* RING */
> + type = RING;
> + no_str = &port[strlen(SPP_CONFIG_IFTYPE_RING)];
> + } else {
> + /* OTHER */
> + RTE_LOG(ERR, APP, "Unknown interface type. (port = %s)\n", port);
> + return -1;
> + }
> +
> + /* IF番号を文字列から数値変換 */
> + 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;
> + }
> +
> + /* Set OUT parameter */
> + *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;
> +}
> +
> +/*
> + * MAC addressを文字列から数値へ変換
> + */
> +int64_t
> +config_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_CONFIG_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 clolon(':') */
> + char *ret_tok = strtok_r(str, ":", &saveptr);
> + if (unlikely(ret_tok == NULL)) {
> + break;
> + }
> +
> + /* Convert string to hex value */
> + int ret_tol = strtol(ret_tok, &endptr, 16);
> + if (unlikely(ret_tok == endptr) || unlikely(*endptr != '\0')) {
> + break;
> + }
> +
> + /* 各数値をまとめる */
> + token_val = (int64_t)ret_tol;
> + ret_mac |= token_val << (token_cnt * 8);
> + token_cnt++;
> + str = NULL;
> + }
> +
> + /* 区切り文字が5個以外 */
> + if (unlikely(token_cnt != ETHER_ADDR_LEN)) {
> + RTE_LOG(ERR, APP, "MAC address format error. (mac = %s)\n",
> + mac);
> + return -1;
> + }
> +
> + RTE_LOG(DEBUG, APP, "MAC address change. (mac = %s => 0x%08lx)\n",
> + mac, ret_mac);
> + return ret_mac;
> +}
> +
> +/*
> + * Classifier table読み込み
> + */
> +static int
> +config_load_classifier_table(const json_t *obj,
> + struct spp_config_classifier_table *classifier_table)
> +{
> + /* classifier_table用オブジェクト取得 */
> + json_t *classifier_obj = json_path_get(obj, JSONPATH_CLASSIFIER_TABLE);
> + if (unlikely(classifier_obj == NULL)) {
> + RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
> + JSONPATH_CLASSIFIER_TABLE);
> + return -1;
> + }
> +
> + /* name取得 */
> + int ret_name = config_get_str_value(classifier_obj, JSONPATH_NAME,
> + classifier_table->name);
> + if (unlikely(ret_name != 0)) {
> + RTE_LOG(ERR, APP, "Classifier table name get failed.\n");
> + return -1;
> + }
> +
> + /* table用オブジェクト取得 */
> + json_t *array_obj = json_path_get(classifier_obj, JSONPATH_TABLE);
> + if (unlikely(!array_obj)) {
> + RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
> + JSONPATH_TABLE);
> + return -1;
> + }
> +
> + /* table用オブジェクトが配列かチェック */
> + if (unlikely(!json_is_array(array_obj))) {
> + RTE_LOG(ERR, APP, "Not an array. (path = %s)\n",
> + JSONPATH_TABLE);
> + return -1;
> + }
> +
> + /* table用オブジェクトの要素数取得 */
> + int array_num = json_array_size(array_obj);
> + if (unlikely(array_num <= 0) ||
> + unlikely(array_num >= SPP_CONFIG_MAC_TABLE_MAX)) {
> + RTE_LOG(ERR, APP, "Table size out of range. (path = %s, size = %d)\n",
> + JSONPATH_TABLE, array_num);
> + return -1;
> + }
> + classifier_table->num_table = array_num;
> +
> + /* テーブルの各要素毎にデータ取得 */
> + struct spp_config_mac_table_element *tmp_table = NULL;
> + char if_str[SPP_CONFIG_STR_LEN];
> + int table_cnt = 0;
> + for (table_cnt = 0; table_cnt < array_num; table_cnt++) {
> + tmp_table = &classifier_table->mac_tables[table_cnt];
> +
> + /* 要素取得 */
> + json_t *elements_obj = json_array_get(array_obj, table_cnt);
> + if (unlikely(elements_obj == NULL)) {
> + RTE_LOG(ERR, APP,
> + "Element get failed. (No = %d, path = %s)\n",
> + table_cnt, JSONPATH_TABLE);
> + return -1;
> + }
> +
> + /* MACアドレス(文字列)取得 */
> + int ret_mac = config_get_str_value(elements_obj, JSONPATH_MAC,
> + tmp_table->mac_addr_str);
> + if (unlikely(ret_mac != 0)) {
> + RTE_LOG(ERR, APP,
> + "MAC address get failed. (No = %d, path = %s)\n",
> + table_cnt, JSONPATH_MAC);
> + return -1;
> + }
> +
> + /* MACアドレス数値変換 */
> + int64_t ret_mac64 = config_change_mac_str_to_int64(
> + tmp_table->mac_addr_str);
> + if (unlikely(ret_mac64 == -1)) {
> + RTE_LOG(ERR, APP,
> + "MAC address change failed. (No = %d, mac = %s)\n",
> + table_cnt, tmp_table->mac_addr_str);
> + return -1;
> + }
> + tmp_table->mac_addr = ret_mac64;
> +
> + /* IF情報取得 */
> + int ret_if_str = config_get_str_value(elements_obj,
> + JSONPATH_PORT, if_str);
> + if (unlikely(ret_if_str != 0)) {
> + RTE_LOG(ERR, APP,
> + "Interface get failed. (No = %d, path = %s)\n",
> + table_cnt, JSONPATH_PORT);
> + return -1;
> + }
> +
> + /* IF種別とIF番号に分割 */
> + int ret_if = config_get_if_info(if_str, &tmp_table->port.if_type,
> + &tmp_table->port.if_no);
> + if (unlikely(ret_if != 0)) {
> + RTE_LOG(ERR, APP,
> + "Interface change failed. (No = %d, IF = %s)\n",
> + table_cnt, if_str);
> + return -1;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * 処理種別を文字列から数値変換
> + */
> +static enum spp_core_type
> +config_change_core_type(const char *core_type)
> +{
> + if(strncmp(core_type, CONFIG_CORE_TYPE_CLASSIFIER_MAC,
> + strlen(CONFIG_CORE_TYPE_CLASSIFIER_MAC)+1) == 0) {
> + /* Classifier */
> + return SPP_CONFIG_CLASSIFIER_MAC;
> + } else if (strncmp(core_type, CONFIG_CORE_TYPE_MERGE,
> + strlen(CONFIG_CORE_TYPE_MERGE)+1) == 0) {
> + /* Merge */
> + return SPP_CONFIG_MERGE;
> + } else if (strncmp(core_type, CONFIG_CORE_TYPE_FORWARD,
> + strlen(CONFIG_CORE_TYPE_FORWARD)+1) == 0) {
> + /* Forward */
> + return SPP_CONFIG_FORWARD;
> + }
> + return SPP_CONFIG_UNUSE;
> +}
> +
> +/*
> + * 受信ポート取得
> + */
> +static int
> +config_set_rx_port(enum spp_core_type type, json_t *obj,
> + struct spp_config_functions *functions)
> +{
> + struct spp_config_port_info *tmp_rx_port = NULL;
> + char if_str[SPP_CONFIG_STR_LEN];
> + if (type == SPP_CONFIG_MERGE) {
> + /* Merge */
> + /* 受信ポート用オブジェクト取得 */
> + json_t *array_obj = json_path_get(obj, JSONPATH_RX_PORT);
> + if (unlikely(!array_obj)) {
> + RTE_LOG(ERR, APP, "Json object get failed. (path = %s, route = merge)\n",
> + JSONPATH_RX_PORT);
> + return -1;
> + }
> +
> + /* 受信ポート用オブジェクトが配列かチェック */
> + if (unlikely(!json_is_array(array_obj))) {
> + RTE_LOG(ERR, APP, "Not an array. (path = %s, route = merge)\n",
> + JSONPATH_TABLE);
> + return -1;
> + }
> +
> + /* 受信ポート用オブジェクトの要素数取得 */
> + int port_num = json_array_size(array_obj);
> + if (unlikely(port_num <= 0) ||
> + unlikely(port_num >= RTE_MAX_ETHPORTS)) {
> + RTE_LOG(ERR, APP, "RX port out of range. (path = %s, port = %d, route = merge)\n",
> + JSONPATH_RX_PORT, port_num);
> + return -1;
> + }
> + functions->num_rx_port = port_num;
> +
> + /* 要素毎にデータ取得 */
> + int array_cnt = 0;
> + for (array_cnt = 0; array_cnt < port_num; array_cnt++) {
> + tmp_rx_port = &functions->rx_ports[array_cnt];
> +
> + /* 要素取得 */
> + json_t *elements_obj = json_array_get(array_obj, array_cnt);
> + if (unlikely(elements_obj == NULL)) {
> + RTE_LOG(ERR, APP,
> + "Element get failed. (No = %d, path = %s, route = merge)\n",
> + array_cnt, JSONPATH_RX_PORT);
> + return -1;
> + }
> +
> + /* String type check */
> + if (unlikely(!json_is_string(elements_obj))) {
> + RTE_LOG(ERR, APP, "Not a string. (path = %s, No = %d, route = merge)\n",
> + JSONPATH_RX_PORT, array_cnt);
> + return -1;
> + }
> + strcpy(if_str, json_string_value(elements_obj));
> +
> + /* IF種別とIF番号に分割 */
> + int ret_if = config_get_if_info(if_str, &tmp_rx_port->if_type,
> + &tmp_rx_port->if_no);
> + if (unlikely(ret_if != 0)) {
> + RTE_LOG(ERR, APP,
> + "Interface change failed. (No = %d, port = %s, route = merge)\n",
> + array_cnt, if_str);
> + return -1;
> + }
> + }
> + } else {
> + /* Classifier/Forward */
> + tmp_rx_port = &functions->rx_ports[0];
> + functions->num_rx_port = 1;
> +
> + /* 受信ポート取得 */
> + int ret_rx_port = config_get_str_value(obj, JSONPATH_RX_PORT, if_str);
> + if (unlikely(ret_rx_port != 0)) {
> + RTE_LOG(ERR, APP, "RX port get failed.\n");
> + return -1;
> + }
> +
> + /* IF種別とIF番号に分割 */
> + int ret_if = config_get_if_info(if_str, &tmp_rx_port->if_type,
> + &tmp_rx_port->if_no);
> + if (unlikely(ret_if != 0)) {
> + RTE_LOG(ERR, APP,
> + "Interface change failed. (port = %s)\n", if_str);
> + return -1;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * 送信先ポート情報取得
> + */
> +static int
> +config_set_tx_port(enum spp_core_type type, json_t *obj,
> + struct spp_config_functions *functions,
> + struct spp_config_classifier_table *classifier_table)
> +{
> + struct spp_config_port_info *tmp_tx_port = NULL;
> + char if_str[SPP_CONFIG_STR_LEN];
> + if ((type == SPP_CONFIG_MERGE) || (type == SPP_CONFIG_FORWARD)) {
> + /* Merge or Forward */
> + tmp_tx_port = &functions->tx_ports[0];
> + functions->num_tx_port = 1;
> +
> + /* 送信ポート取得 */
> + int ret_tx_port = config_get_str_value(obj,
> + JSONPATH_TX_PORT, if_str);
> + if (unlikely(ret_tx_port != 0)) {
> + RTE_LOG(ERR, APP, "TX port get failed.\n");
> + return -1;
> + }
> +
> + /* IF種別とIF番号に分割 */
> + int ret_if = config_get_if_info(if_str, &tmp_tx_port->if_type,
> + &tmp_tx_port->if_no);
> + if (unlikely(ret_if != 0)) {
> + RTE_LOG(ERR, APP,
> + "Interface change failed. (port = %s)\n",
> + if_str);
> + return -1;
> + }
> + } else {
> + /* Classifier */
> + int cnt = 0;
> + functions->num_tx_port = classifier_table->num_table;
> + struct spp_config_mac_table_element *tmp_mac_table = NULL;
> + for (cnt = 0; cnt < classifier_table->num_table; cnt++) {
> + tmp_tx_port = &functions->tx_ports[cnt];
> + tmp_mac_table = &classifier_table->mac_tables[cnt];
> +
> + /* MAC振り分けテーブルより設定 */
> + tmp_tx_port->if_type = tmp_mac_table->port.if_type;
> + tmp_tx_port->if_no = tmp_mac_table->port.if_no;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * プロセス情報取得
> + */
> +static int
> +config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *config)
> +{
> + struct spp_config_proc_info *proc = &config->proc;
> + struct spp_config_classifier_table *classifier_table = &config->classifier_table;
> +
> + /* proc_table用オブジェクト取得 */
> + json_t *proc_table_obj = json_path_get(obj, JSONPATH_PROC_TABLE);
> + if (unlikely(proc_table_obj == NULL)) {
> + RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
> + JSONPATH_PROC_TABLE);
> + return -1;
> + }
> +
> + /* table用オブジェクトが配列かチェック */
> + if (unlikely(!json_is_array(proc_table_obj))) {
> + RTE_LOG(ERR, APP, "Not an array. (path = %s)\n",
> + JSONPATH_TABLE);
> + return -1;
> + }
> +
> + /* table用オブジェクトの要素数取得 */
> + int proc_table_num = json_array_size(proc_table_obj);
> + if (unlikely(proc_table_num < node_id)) {
> + RTE_LOG(ERR, APP, "No process data. (Size = %d, Node = %d)\n",
> + proc_table_num, node_id);
> + return -1;
> + }
> +
> + /* 要素取得 */
> + json_t *proc_obj = json_array_get(proc_table_obj, node_id);
> + if (unlikely(proc_obj == NULL)) {
> + RTE_LOG(ERR, APP, "Process data get failed. (Node = %d)\n",
> + node_id);
> + return -1;
> + }
> +
> + /* name取得 */
> + int ret_name = config_get_str_value(proc_obj, JSONPATH_NAME, proc->name);
> + if (unlikely(ret_name != 0)) {
> + RTE_LOG(ERR, APP, "Process name get failed.\n");
> + return -1;
> + }
> +
> + /* VHOST数取得 */
> + int ret_vhost = config_get_int_value(proc_obj, JSONPATH_NUM_VHOST,
> + &proc->num_vhost);
> + if (unlikely(ret_vhost != 0)) {
> + RTE_LOG(ERR, APP, "VHOST number get failed.\n");
> + return -1;
> + }
> +
> + /* RING数取得 */
> + int ret_ring = config_get_int_value(proc_obj, JSONPATH_NUM_RING,
> + &proc->num_ring);
> + if (unlikely(ret_ring != 0)) {
> + RTE_LOG(ERR, APP, "RING number get failed.\n");
> + return -1;
> + }
> +
> + /* functions用オブジェクト取得 */
> + json_t *array_obj = json_path_get(proc_obj, JSONPATH_FUNCTIONS);
> + if (unlikely(!array_obj)) {
> + RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
> + JSONPATH_FUNCTIONS);
> + return -1;
> + }
> +
> + /* functions用オブジェクトが配列かチェック */
> + if (unlikely(!json_is_array(array_obj))) {
> + RTE_LOG(ERR, APP, "Not an array. (path = %s)\n",
> + JSONPATH_FUNCTIONS);
> + return -1;
> + }
> +
> + /* functions用オブジェクトの要素数取得 */
> + int array_num = json_array_size(array_obj);
> + if (unlikely(array_num <= 0) ||
> + unlikely(array_num >= SPP_CONFIG_CORE_MAX)) {
> + RTE_LOG(ERR, APP, "Functions size out of range. (path = %s, size = %d)\n",
> + JSONPATH_TABLE, array_num);
> + return -1;
> + }
> + proc->num_func = array_num;
> +
> + /* 要素毎にデータ取得 */
> + struct spp_config_functions *tmp_functions = NULL;
> + char core_type_str[SPP_CONFIG_STR_LEN];
> + int array_cnt = 0;
> + for (array_cnt = 0; array_cnt < array_num; array_cnt++) {
> + tmp_functions = &proc->functions[array_cnt];
> +
> + /* 要素取得 */
> + json_t *elements_obj = json_array_get(array_obj, array_cnt);
> + if (unlikely(elements_obj == NULL)) {
> + RTE_LOG(ERR, APP,
> + "Element get failed. (No = %d, path = %s)\n",
> + array_cnt, JSONPATH_FUNCTIONS);
> + return -1;
> + }
> +
> + /* CORE番号取得 */
> + int ret_core = config_get_int_value(elements_obj, JSONPATH_CORE_NO,
> + &tmp_functions->core_no);
> + if (unlikely(ret_core != 0)) {
> + RTE_LOG(ERR, APP, "Core number get failed. (No = %d)\n",
> + array_cnt);
> + return -1;
> + }
> +
> + /* 処理種別取得 */
> + int ret_core_type = config_get_str_value(elements_obj,
> + JSONPATH_CORE_TYPE, core_type_str);
> + if (unlikely(ret_core_type != 0)) {
> + RTE_LOG(ERR, APP, "Core type get failed. (No = %d)\n",
> + array_cnt);
> + return -1;
> + }
> +
> + /* 処理種別を数値に変換 */
> + enum spp_core_type core_type = config_change_core_type(core_type_str);
> + if (unlikely(core_type == SPP_CONFIG_UNUSE)) {
> + RTE_LOG(ERR, APP,
> + "Unknown core type. (No = %d, type = %s)\n",
> + array_cnt, core_type_str);
> + return -1;
> + }
> + tmp_functions->type = core_type;
> +
> + /* 受信ポート取得 */
> + int ret_rx_port = config_set_rx_port(core_type, elements_obj,
> + tmp_functions);
> + if (unlikely(ret_rx_port != 0)) {
> + RTE_LOG(ERR, APP, "RX port set failure. (No = %d)\n",
> + array_cnt);
> + return -1;
> + }
> +
> + /* 送信ポート取得 */
> + int ret_tx_port = config_set_tx_port(core_type, elements_obj,
> + tmp_functions, classifier_table);
> + if (unlikely(ret_tx_port != 0)) {
> + RTE_LOG(ERR, APP, "TX port set failure. (No = %d)\n",
> + array_cnt);
> + return -1;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * Load config file
> + * OK : 0
> + * NG : -1
> + */
> +int
> +spp_config_load_file(int node_id, struct spp_config_area *config)
> +{
> + /* Config initialize */
> + config_init_data(config);
> +
> + /* Config load */
> + json_error_t json_error;
> + json_t *conf_obj = json_load_file(SPP_CONFIG_FILE_PATH, 0, &json_error);
> + if (unlikely(conf_obj == NULL)) {
> + /* Load error */
> + RTE_LOG(ERR, APP, "Config load failed. (path = %s, text = %s)\n",
> + SPP_CONFIG_FILE_PATH, json_error.text);
> + return -1;
> + }
> +
> + /* classifier table */
> + int ret_classifier = config_load_classifier_table(conf_obj,
> + &config->classifier_table);
> + if (unlikely(ret_classifier != 0)) {
> + RTE_LOG(ERR, APP, "Classifier table load failed.\n");
> + json_decref(conf_obj);
> + return -1;
> + }
> +
> + /* proc info */
> + int ret_proc = config_load_proc_info(conf_obj, node_id, config);
> + if (unlikely(ret_proc != 0)) {
> + RTE_LOG(ERR, APP, "Process table load failed.\n");
> + json_decref(conf_obj);
> + return -1;
> + }
> +
> + /* Config object release */
> + json_decref(conf_obj);
> +
> + return 0;
> +}
> diff --git a/src/vf/spp_config.h b/src/vf/spp_config.h
> new file mode 100644
> index 0000000..d2a6a4b
> --- /dev/null
> +++ b/src/vf/spp_config.h
> @@ -0,0 +1,90 @@
> +#ifndef __SPP_CONFIG_H__
> +#define __SPP_CONFIG_H__
> +
> +#include "common.h"
> +
> +#define SPP_CONFIG_FILE_PATH "/usr/local/etc/spp/spp.json"
> +
> +#define SPP_CONFIG_IFTYPE_NIC "nic"
> +#define SPP_CONFIG_IFTYPE_VHOST "vhost"
> +#define SPP_CONFIG_IFTYPE_RING "ring"
> +
> +#define SPP_CONFIG_STR_LEN 32
> +#define SPP_CONFIG_MAC_TABLE_MAX 16
> +#define SPP_CONFIG_CORE_MAX 64
> +
> +/*
> + * Process type for each CORE
> + */
> +enum spp_core_type {
> + SPP_CONFIG_UNUSE,
> + SPP_CONFIG_CLASSIFIER_MAC,
> + SPP_CONFIG_MERGE,
> + SPP_CONFIG_FORWARD,
> +};
> +
> +/*
> + * Interface information structure
> + */
> +struct spp_config_port_info {
> + enum port_type if_type;
> + int if_no;
> +};
> +
> +/*
> + * MAC Table information structure
> + */
> +struct spp_config_mac_table_element {
> + struct spp_config_port_info port;
> + char mac_addr_str[SPP_CONFIG_STR_LEN];
> + uint64_t mac_addr;
> +};
> +
> +/*
> + * Classifier Table information structure
> + */
> +struct spp_config_classifier_table {
> + char name[SPP_CONFIG_STR_LEN];
> + int num_table;
> + struct spp_config_mac_table_element mac_tables[SPP_CONFIG_MAC_TABLE_MAX];
> +};
> +
> +/*
> + * Functions information structure
> + */
> +struct spp_config_functions {
> + int core_no;
> + enum spp_core_type type;
> + 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];
> +};
> +
> +/*
> + * Process information structure
> + */
> +struct spp_config_proc_info {
> + char name[SPP_CONFIG_STR_LEN];
> + int num_vhost;
> + int num_ring;
> + int num_func;
> + struct spp_config_functions functions[SPP_CONFIG_CORE_MAX];
> +};
> +
> +/*
> + * Config information structure
> + */
> +struct spp_config_area {
> + struct spp_config_proc_info proc;
> + struct spp_config_classifier_table classifier_table;
> +};
> +
> +/*
> + * Load config file
> + * OK : 0
> + * NG : -1
> + */
> +int spp_config_load_file(int node_id, struct spp_config_area *config);
> +
> +#endif /* __SPP_CONFIG_H__ */
> diff --git a/src/vf/spp_forward.c b/src/vf/spp_forward.c
> new file mode 100644
> index 0000000..4396929
> --- /dev/null
> +++ b/src/vf/spp_forward.c
> @@ -0,0 +1,106 @@
> +#include "spp_vf.h"
> +#include "ringlatencystats.h"
> +
> +#define RTE_LOGTYPE_SPP_FORWARD RTE_LOGTYPE_USER1
> +
> +/*
> + * 送受信ポートの経路情報
> + */
> +struct rxtx {
> + struct spp_core_port_info rx;
> + struct spp_core_port_info tx;
> +};
> +
> +/*
> + * 使用するIF情報を移し替える
> + */
> +void
> +set_use_interface(struct spp_core_port_info *dst,
> + struct spp_core_port_info *src)
> +{
> + dst->if_type = src->if_type;
> + dst->if_no = src->if_no;
> + dst->dpdk_port = src->dpdk_port;
> +}
> +
> +/*
> + * Merge/Forward
> + */
> +int
> +spp_forward(void *arg)
> +{
> + 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];
> +
> + /* RX/TX Info setting */
> + 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]);
> + if (core_info->type == SPP_CONFIG_FORWARD) {
> + /* FORWARD */
> + set_use_interface(&patch[if_cnt].tx,
> + &core_info->tx_ports[if_cnt]);
> + } else {
> + /* MERGE */
> + set_use_interface(&patch[if_cnt].tx,
> + &core_info->tx_ports[0]);
> + }
> + }
> +
> + /* Thread IDLE */
> + core_info->status = SPP_CORE_IDLE;
> + RTE_LOG(INFO, FORWARD, "Core[%d] Start. (type = %d)\n", lcore_id,
> + core_info->type);
> +
> + 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;
> +
> + /* Packet receive */
> + nb_rx = rte_eth_rx_burst(rx->dpdk_port, 0, bufs, MAX_PKT_BURST);
> + if (unlikely(nb_rx == 0)) {
> + continue;
> + }
> +
> +#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
> + if (rx->if_type == RING) {
> + /* Receive port is RING */
> + spp_ringlatencystats_calculate_latency(rx->if_no,
> + bufs, nb_rx);
> + }
> + if (tx->if_type == RING) {
> + /* Send port is RING */
> + spp_ringlatencystats_add_time_stamp(tx->if_no,
> + bufs, nb_rx);
> + }
> +#endif /* SPP_RINGLATENCYSTATS_ENABLE */
> +
> + /* Send packet */
> + nb_tx = rte_eth_tx_burst(tx->dpdk_port, 0, bufs, nb_rx);
> +
> + /* Free any unsent packets. */
> + if (unlikely(nb_tx < nb_rx)) {
> + for (buf = nb_tx; buf < nb_rx; buf++) {
> + rte_pktmbuf_free(bufs[buf]);
> + }
> + }
> + }
> + }
> + }
> +
> + /* Thread STOP */
> + 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
> new file mode 100644
> index 0000000..33208bf
> --- /dev/null
> +++ b/src/vf/spp_forward.h
> @@ -0,0 +1,9 @@
> +#ifndef __SPP_FORWARD_H__
> +#define __SPP_FORWARD_H__
> +
> +/*
> + * Merge/Forward
> + */
> +int spp_forward(void *arg);
> +
> +#endif /* __SPP_FORWARD_H__ */
> diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
> new file mode 100644
> index 0000000..ee5cf63
> --- /dev/null
> +++ b/src/vf/spp_vf.c
> @@ -0,0 +1,794 @@
> +#include <arpa/inet.h>
> +#include <getopt.h>
> +
> +#include <rte_eth_ring.h>
> +#include <rte_eth_vhost.h>
> +#include <rte_memzone.h>
> +
> +#include "spp_vf.h"
> +#include "ringlatencystats.h"
> +#include "classifier_mac.h"
> +#include "spp_forward.h"
> +
> +/* define */
> +#define SPP_CORE_STATUS_CHECK_MAX 5
> +#define SPP_RING_LATENCY_STATS_SAMPLING_INTERVAL 1000000
> +
> +/* struct */
> +struct startup_param {
> + uint64_t cpu;
> +};
> +
> +struct patch_info {
> + int use_flg;
> + int dpdk_port;
> + struct spp_config_mac_table_element *mac_info;
> + struct spp_core_port_info *rx_core;
> + struct spp_core_port_info *tx_core;
> +};
> +
> +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];
> +};
> +
> +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];
> +
> +/*
> + * print a usage message
> + */
> +static void
> +usage(const char *progname)
> +{
> + RTE_LOG(INFO, APP, "Usage: %s [EAL args]\n\n", progname);
> +}
> +
> +/*
> + * Set RING PMD
> + */
> +static int
> +add_ring_pmd(int ring_id)
> +{
> + struct rte_ring *ring;
> + int ring_port_id;
> +
> + /* look up ring, based on user's provided id*/
> + ring = rte_ring_lookup(get_rx_queue_name(ring_id));
> + if (unlikely(ring == NULL)) {
> + RTE_LOG(ERR, APP,
> + "Cannot get RX ring - is server process running?\n");
> + return -1;
> + }
> +
> + /* create ring pmd*/
> + ring_port_id = rte_eth_from_ring(ring);
> + RTE_LOG(DEBUG, APP, "ring port id %d\n", ring_port_id);
> +
> + return ring_port_id;
> +}
> +
> +/*
> + * Set VHOST PMD
> + */
> +static int
> +add_vhost_pmd(int index)
> +{
> + struct rte_eth_conf port_conf = {
> + .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN }
> + };
> + struct rte_mempool *mp;
> + uint8_t vhost_port_id;
> + int nr_queues = 1;
> + const char *name;
> + char devargs[64];
> + char *iface;
> + uint16_t q;
> + int ret;
> +#define NR_DESCS 128
> +
> + mp = rte_mempool_lookup(PKTMBUF_POOL_NAME);
> + if (unlikely(mp == NULL)) {
> + RTE_LOG(ERR, APP, "Cannot get mempool for mbufs. (name = %s)\n",
> + PKTMBUF_POOL_NAME);
> + return -1;
> + }
> +
> + /* eth_vhost0 index 0 iface /tmp/sock0 on numa 0 */
> + name = get_vhost_backend_name(index);
> + iface = get_vhost_iface_name(index);
> +
> + sprintf(devargs, "%s,iface=%s,queues=%d", name, iface, nr_queues);
> + ret = rte_eth_dev_attach(devargs, &vhost_port_id);
> + if (unlikely(ret < 0)) {
> + RTE_LOG(ERR, APP, "rte_eth_dev_attach error. (ret = %d)\n", ret);
> + return ret;
> + }
> +
> + ret = rte_eth_dev_configure(vhost_port_id, nr_queues, nr_queues,
> + &port_conf);
> + if (unlikely(ret < 0)) {
> + RTE_LOG(ERR, APP, "rte_eth_dev_configure error. (ret = %d)\n",
> + ret);
> + return ret;
> + }
> +
> + /* Allocate and set up 1 RX queue per Ethernet port. */
> + for (q = 0; q < nr_queues; q++) {
> + ret = rte_eth_rx_queue_setup(vhost_port_id, q, NR_DESCS,
> + rte_eth_dev_socket_id(vhost_port_id), NULL, mp);
> + if (unlikely(ret < 0)) {
> + RTE_LOG(ERR, APP,
> + "rte_eth_rx_queue_setup error. (ret = %d)\n",
> + ret);
> + return ret;
> + }
> + }
> +
> + /* Allocate and set up 1 TX queue per Ethernet port. */
> + for (q = 0; q < nr_queues; q++) {
> + ret = rte_eth_tx_queue_setup(vhost_port_id, q, NR_DESCS,
> + rte_eth_dev_socket_id(vhost_port_id), NULL);
> + if (unlikely(ret < 0)) {
> + RTE_LOG(ERR, APP,
> + "rte_eth_tx_queue_setup error. (ret = %d)\n",
> + ret);
> + return ret;
> + }
> + }
> +
> + /* Start the Ethernet port. */
> + ret = rte_eth_dev_start(vhost_port_id);
> + if (unlikely(ret < 0)) {
> + RTE_LOG(ERR, APP, "rte_eth_dev_start error. (ret = %d)\n", ret);
> + return ret;
> + }
> +
> + RTE_LOG(DEBUG, APP, "vhost port id %d\n", vhost_port_id);
> +
> + return vhost_port_id;
> +}
> +
> +/*
> + * Check core status
> + */
> +static int
> +check_core_status(enum spp_core_status status)
> +{
> + int cnt;
> + 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) {
> + /* Status mismatch */
> + return -1;
> + }
> + }
> + return 0;
> +}
> +
> +/*
> + * Wait for core status check
> + */
> +static int
> +check_core_status_wait(enum spp_core_status status)
> +{
> + int cnt = 0;
> + for (cnt = 0; cnt < SPP_CORE_STATUS_CHECK_MAX; cnt++) {
> + sleep(1);
> + int ret = check_core_status(status);
> + if (ret == 0) {
> + return 0;
> + }
> + }
> +
> + RTE_LOG(ERR, APP, "Status check time out. (status = %d)\n", status);
> + return -1;
> +}
> +
> +/*
> + * Set core status
> + */
> +static void
> +set_core_status(enum spp_core_status status)
> +{
> + int core_cnt = 0;
> + for(core_cnt = 0; core_cnt < SPP_CONFIG_CORE_MAX; core_cnt++) {
> + g_core_info[core_cnt].status = status;
> + }
> +}
> +
> +/*
> + * Process stop
> + */
> +void
> +stop_process(int signal) {
> + if (unlikely(signal != SIGTERM) &&
> + unlikely(signal != SIGINT)) {
> + /* Other signals */
> + return;
> + }
> +
> + set_core_status(SPP_CORE_STOP_REQUEST);
> +}
> +
> +/*
> + * 起動パラメータのCPUのbitmapを数値へ変換
> + */
> +static int
> +parse_cpu_bit(uint64_t *cpu, const char *cpu_bit)
> +{
> + char *endptr = NULL;
> + uint64_t temp;
> +
> + temp = strtoull(cpu_bit, &endptr, 0);
> + if (unlikely(endptr == cpu_bit) || unlikely(*endptr != '\0')) {
> + return -1;
> + }
> +
> + *cpu = temp;
> + RTE_LOG(DEBUG, APP, "cpu = %lu", *cpu);
> + return 0;
> +}
> +
> +/*
> + * Parse the application arguments to the client app.
> + */
> +static int
> +parse_app_args(int argc, char *argv[])
> +{
> + int option_index, opt;
> + char **argvopt = argv;
> + const char *progname = argv[0];
> + static struct option lgopts[] = { {0} };
> +
> + /* Check DPDK parameter */
> + optind = 0;
> + opterr = 0;
> + while ((opt = getopt_long(argc, argvopt, "c:", lgopts,
> + &option_index)) != EOF) {
> + switch (opt) {
> + case 'c':
> + /* CPU */
> + if (parse_cpu_bit(&g_startup_param.cpu, optarg) != 0) {
> + usage(progname);
> + return -1;
> + }
> + break;
> + default:
> + /* CPU */
> + /* DPDKのパラメータは他にもあるので、エラーとはしない */
> + break;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * IF種別&IF番号のIF情報の領域取得
> + */
> +static struct patch_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];
> + break;
> + case VHOST:
> + return &g_if_info.vhost_patchs[if_no];
> + break;
> + case RING:
> + return &g_if_info.ring_patchs[if_no];
> + break;
> + default:
> + /* エラー出力は呼び元でチェック */
> + return NULL;
> + break;
> + }
> +}
> +
> +/*
> + * IF情報初期化
> + */
> +static void
> +init_if_info()
> +{
> + memset(&g_if_info, 0x00, sizeof(g_if_info));
> +}
> +
> +/*
> + * CORE情報初期化
> + */
> +static void
> +init_core_info()
> +{
> + 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++) {
> + 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;
> + }
> + }
> +}
> +
> +/*
> + * Configのプロセス情報から管理情報に設定
> + */
> +static int
> +set_form_proc_info(struct spp_config_area *config)
> +{
> + /* Configのproc_infoから内部管理情報へ設定 */
> + int core_cnt, rx_start, rx_cnt, tx_start, tx_cnt;
> + enum port_type if_type;
> + int if_no;
> + int64_t cpu_bit = 0;
> + 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;
> + }
> +
> + /* Forwardをまとめる事は可、他種別は不可 */
> + 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;
> + }
> +
> + /* Set CORE type */
> + core_info->type = core_func->type;
> + cpu_bit |= 1 << core_func->core_no;
> +
> + /* Set RX port */
> + 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;
> +
> + /* IF種別とIF番号に対応するIF情報の領域取得 */
> + 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 (if_type = %d, if_no = %d)\n",
> + if_type, if_no);
> + return -1;
> + }
> +
> + /* IF情報からCORE情報を変更する場合用に設定 */
> + 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;
> +
> + /* IF種別とIF番号に対応するIF情報の領域取得 */
> + 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 (if_type = %d, if_no = %d)\n",
> + if_type, if_no);
> + return -1;
> + }
> +
> + /* IF情報からCORE情報を変更する場合用に設定 */
> + patch_info->tx_core = &core_info->tx_ports[tx_start + tx_cnt];
> + }
> + }
> +
> + if (unlikely((cpu_bit & g_startup_param.cpu) != cpu_bit)) {
> + /* CPU mismatch */
> + RTE_LOG(ERR, APP, "CPU mismatch (cpu param = %lx, config = %lx)\n",
> + g_startup_param.cpu, cpu_bit);
> + return -1;
> + }
> + return 0;
> +}
> +
> +/*
> + * ConfigのMACテーブル情報から管理情報に設定
> + */
> +static int
> +set_from_classifier_table(struct spp_config_area *config)
> +{
> + /* MAC table */
> + 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;
> +
> + /* IF種別とIF番号に対応するIF情報の領域取得 */
> + 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;
> + }
> +
> + /* CORE情報側にもMACアドレスの情報設定 */
> + /* MACアドレスは送信側のみに影響する為、送信側のみ設定 */
> + patch_info->mac_info = mac_table;
> + 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;
> +}
> +
> +/*
> + * NIC用の情報設定
> + */
> +static int
> +set_nic_interface(struct spp_config_area *config)
> +{
> + /* 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];
> + /* Set DPDK port */
> + patch_info->dpdk_port = nic_cnt;
> +
> + if (patch_info->use_flg == 0) {
> + /* Not Used */
> + continue;
> + }
> +
> + /* CORE情報側にもDPDKポート番号の情報設定 */
> + 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の設定数カウント */
> + 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;
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * VHOST用の情報設定
> + */
> +static int
> +set_vhost_interface(struct spp_config_area *config)
> +{
> + /* VHOST Setting */
> + 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;
> + }
> +
> + /* Set DPDK port */
> + int dpdk_port = add_vhost_pmd(vhost_cnt);
> + 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;
> +
> + /* CORE情報側にもDPDKポート番号の情報設定 */
> + 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;
> +}
> +
> +/*
> + * RING用の情報設定
> + */
> +static int
> +set_ring_interface(struct spp_config_area *config)
> +{
> + /* RING Setting */
> + 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) {
> + /* Not Used */
> + continue;
> + }
> +
> + /* Set DPDK port */
> + 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;
> +
> + /* CORE情報側にもDPDKポート番号の情報設定 */
> + 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;
> +}
> +
> +/*
> + * 管理データ初期設定
> + */
> +static int
> +init_manage_data(struct spp_config_area *config)
> +{
> + /* Initialize */
> + init_if_info(config);
> + init_core_info(config);
> +
> + /* Set config data */
> + int ret_proc = set_form_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;
> + }
> +
> + /* Set interface data */
> + int ret_nic = set_nic_interface(config);
> + 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;
> +}
> +
> +#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
> +static void
> +print_ring_latency_stats()
> +{
> + /* Clear screen and move to top left */
> + const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' };
> + const char clr[] = { 27, '[', '2', 'J', '\0' };
> + printf("%s%s", clr, topLeft);
> +
> + /* Print per RING */
> + int ring_cnt, stats_cnt;
> + struct spp_ringlatencystats_ring_latency_stats stats[RTE_MAX_ETHPORTS];
> + memset(&stats, 0x00, sizeof(stats));
> +
> + 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) {
> + continue;
> + }
> + spp_ringlatencystats_get_stats(ring_cnt, &stats[ring_cnt]);
> + printf(", %-18d", ring_cnt);
> + }
> + printf("\n");
> +
> + 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) {
> + continue;
> + }
> +
> + printf(", 0x%-16lx", stats[ring_cnt].slot[stats_cnt]);
> + }
> + printf("\n");
> + }
> +
> + return;
> +}
> +#endif /* SPP_RINGLATENCYSTATS_ENABLE */
> +
> +/*
> + * main
> + */
> +int
> +#ifndef USE_UT_SPP_VF
> +main(int argc, char *argv[])
> +#else /* ifndef USE_UT_SPP_VF */
> +ut_main(int argc, char *argv[])
> +#endif /* ifndef USE_UT_SPP_VF */
> +{
> + int ret = -1;
> +#ifdef SPP_DEMONIZE
> + /* Daemonize process */
> + int ret_daemon = daemon(0, 0);
> + if (unlikely(ret_daemon != 0)) {
> + RTE_LOG(ERR, APP, "daemonize is faild. (ret = %d)\n", ret_daemon);
> + return ret_daemon;
> + }
> +#endif
> +
> + /* Signal handler registration (SIGTERM/SIGINT) */
> + signal(SIGTERM, stop_process);
> + signal(SIGINT, stop_process);
> +
> + unsigned int main_lcore_id = 0xffffffff;
> + while(1) {
> + /* Parse parameters */
> + int ret_parse = parse_app_args(argc, argv);
> + if (unlikely(ret_parse != 0)) {
> + break;
> + }
> +
> + /* Load config */
> + int ret_config = spp_config_load_file(0, &g_config);
> + if (unlikely(ret_config != 0)) {
> + break;
> + }
> +
> + /* DPDK initialize */
> + int ret_dpdk = rte_eal_init(argc, argv);
> + if (unlikely(ret_dpdk < 0)) {
> + break;
> + }
> + /* Get core id. */
> + main_lcore_id = rte_lcore_id();
> +
> + /* 起動パラメータとコンフィグチェック */
> + /* 各IF情報設定 */
> + int ret_manage = init_manage_data(&g_config);
> + if (unlikely(ret_manage != 0)) {
> + break;
> + }
> +
> + /* 他機能部初期化 */
> +#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
> + int ret_ringlatency = spp_ringlatencystats_init(
> + SPP_RING_LATENCY_STATS_SAMPLING_INTERVAL, g_if_info.num_ring);
> + if (unlikely(ret_ringlatency != 0)) {
> + break;
> + }
> +#endif /* SPP_RINGLATENCYSTATS_ENABLE */
> +
> + /* Start thread */
> + 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);
> + }
> + }
> +
> + /* スレッド状態確認 */
> + g_core_info[main_lcore_id].status = SPP_CORE_IDLE;
> + int ret_wait = check_core_status_wait(SPP_CORE_IDLE);
> + if (unlikely(ret_wait != 0)) {
> + break;
> + }
> +
> + /* Start forward */
> + set_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");
> +
> + /* loop */
> +#ifndef USE_UT_SPP_VF
> + while(likely(g_core_info[main_lcore_id].status != SPP_CORE_STOP_REQUEST)) {
> +#else
> + {
> +#endif
> + sleep(1);
> +
> +#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
> + print_ring_latency_stats();
> +#endif /* SPP_RINGLATENCYSTATS_ENABLE */
> + }
> +
> + /* 正常終了 */
> + ret = 0;
> + break;
> + }
> +
> + /* exit */
> + stop_process(SIGINT);
> + if (main_lcore_id == rte_lcore_id())
> + {
> + g_core_info[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");
> + }
> + }
> +
> + /* 他機能部終了処理 */
> +#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
> + spp_ringlatencystats_uninit();
> +#endif /* SPP_RINGLATENCYSTATS_ENABLE */
> + RTE_LOG(INFO, APP, "spp_vf exit.\n");
> + return ret;
> +}
> diff --git a/src/vf/spp_vf.h b/src/vf/spp_vf.h
> new file mode 100644
> index 0000000..feb59b6
> --- /dev/null
> +++ b/src/vf/spp_vf.h
> @@ -0,0 +1,40 @@
> +#ifndef __SPP_VF_H__
> +#define __SPP_VF_H__
> +
> +#include "common.h"
> +#include "spp_config.h"
> +
> +/*
> + * State on core
> + */
> +enum spp_core_status {
> + SPP_CORE_STOP,
> + SPP_CORE_IDLE,
> + SPP_CORE_FORWARD,
> + SPP_CORE_STOP_REQUEST
> +};
> +
> +/*
> + * Port info on core
> + */
> +struct spp_core_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];
> +};
> +
> +/*
> + * Core info
> + */
> +struct spp_core_info {
> + 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];
> +};
> +
> +#endif /* __SPP_VF_H__ */
>
--
Yasufumi Ogawa
NTT Network Service Systems Labs
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 02/57] spp_vf: support multi process
2017-12-26 1:54 ` Yasufumi Ogawa
2017-12-28 4:55 ` [spp] [PATCH 01/57] spp_vf: add vf functions x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2018-02-07 16:50 ` Ferruh Yigit
2017-12-28 4:55 ` [spp] [PATCH 03/57] spp_vf: comment out check of using cores x-fn-spp
` (54 subsequent siblings)
56 siblings, 1 reply; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
spp_vf was only a single process so far, but spp_vf supported
multi process. Following modification has been made.
* Change naming machanism to allow hashtable on shared memory
to be operated by multiple processes.
* Get config file path from command line argument.
And following modification has been made.
* Modify comment.
* Add and modify log message.
* Add function to remove vhost socket file.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/classifier_mac.c | 79 ++++++++++++++++++------
src/vf/ringlatencystats.c | 6 +-
src/vf/spp_config.c | 14 ++---
src/vf/spp_config.h | 2 +-
src/vf/spp_forward.c | 5 +-
src/vf/spp_vf.c | 154 ++++++++++++++++++++++++++++++++++++++--------
src/vf/spp_vf.h | 4 +-
7 files changed, 206 insertions(+), 58 deletions(-)
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
index da03905..374f164 100644
--- a/src/vf/classifier_mac.c
+++ b/src/vf/classifier_mac.c
@@ -5,6 +5,7 @@
#include <stddef.h>
#include <math.h>
+#include <rte_common.h>
#include <rte_mbuf.h>
#include <rte_log.h>
#include <rte_cycles.h>
@@ -38,18 +39,36 @@
nano second */
#define DRAIN_TX_PACKET_INTERVAL 100
+/* hash table name buffer size
+ [reson for value]
+ in dpdk's lib/librte_hash/rte_cuckoo_hash.c
+ snprintf(ring_name, sizeof(ring_name), "HT_%s", params->name);
+ snprintf(hash_name, sizeof(hash_name), "HT_%s", params->name);
+ ring_name buffer size is RTE_RING_NAMESIZE
+ hash_name buffer size is RTE_HASH_NAMESIZE */
+static const size_t HASH_TABLE_NAME_BUF_SZ =
+ ((RTE_HASH_NAMESIZE < RTE_RING_NAMESIZE) ?
+ RTE_HASH_NAMESIZE: RTE_RING_NAMESIZE) - 3;
+
/* mac address string(xx:xx:xx:xx:xx:xx) buffer size */
static const size_t ETHER_ADDR_STR_BUF_SZ =
ETHER_ADDR_LEN * 2 + (ETHER_ADDR_LEN - 1) + 1;
/* classified data (destination port, target packets, etc) */
struct classified_data {
- int if_no;
- uint8_t tx_port;
- uint16_t num_pkt;
+ enum port_type if_type;
+ int if_no;
+ uint8_t tx_port;
+ uint16_t num_pkt;
struct rte_mbuf *pkts[MAX_PKT_BURST];
};
+/* hash table count. use to make hash table name.
+ [reason for value]
+ it is incremented at the time of use,
+ but since we want to start at 0. */
+static rte_atomic16_t g_hash_table_count = RTE_ATOMIC16_INIT(0xff);
+
/* initialize classifier. */
static int
init_classifier(const struct spp_core_info *core_info,
@@ -58,11 +77,19 @@ init_classifier(const struct spp_core_info *core_info,
int ret = -1;
int i;
struct ether_addr eth_addr;
+ char hash_table_name[HASH_TABLE_NAME_BUF_SZ];
char mac_addr_str[ETHER_ADDR_STR_BUF_SZ];
+ /* make hash table name(require uniqueness between processes) */
+ sprintf(hash_table_name, "cmtab_%08x%02hx",
+ getpid(), rte_atomic16_add_return(&g_hash_table_count, 1));
+
+ RTE_LOG(INFO, SPP_CLASSIFIER_MAC, "Create table. name=%s, bufsz=%lu\n",
+ hash_table_name, HASH_TABLE_NAME_BUF_SZ);
+
/* set hash creating parameters */
struct rte_hash_parameters hash_params = {
- .name = "classifier_mac_table",
+ .name = hash_table_name,
.entries = NUM_CLASSIFIER_MAC_TABLE_ENTRY,
.key_len = sizeof(struct ether_addr),
.hash_func = DEFAULT_HASH_FUNC,
@@ -100,6 +127,7 @@ init_classifier(const struct spp_core_info *core_info,
}
/* set value */
+ classified_data[i].if_type = core_info->tx_ports[i].if_type;
classified_data[i].if_no = i;
classified_data[i].tx_port = core_info->tx_ports[i].dpdk_port;
classified_data[i].num_pkt = 0;
@@ -108,22 +136,25 @@ init_classifier(const struct spp_core_info *core_info,
return 0;
}
-/* transimit packet to one destination. */
+/* transmit packet to one destination. */
static inline void
-transimit_packet(struct classified_data *classified_data)
+transmit_packet(struct classified_data *classified_data)
{
int i;
uint16_t n_tx;
- /* set ringlatencystats */
- spp_ringlatencystats_add_time_stamp(classified_data->if_no,
- classified_data->pkts, classified_data->num_pkt);
+#ifdef SPP_RINGLATENCYSTATS_ENABLE
+ if (classified_data->if_type == RING)
+ /* if tx-if is ring, set ringlatencystats */
+ spp_ringlatencystats_add_time_stamp(classified_data->if_no,
+ classified_data->pkts, classified_data->num_pkt);
+#endif
- /* transimit packets */
+ /* transmit packets */
n_tx = rte_eth_tx_burst(classified_data->tx_port, 0,
classified_data->pkts, classified_data->num_pkt);
- /* free cannnot transiit packets */
+ /* free cannnot transmit packets */
if (unlikely(n_tx != classified_data->num_pkt)) {
for (i = n_tx; i < classified_data->num_pkt; i++)
rte_pktmbuf_free(classified_data->pkts[i]);
@@ -136,7 +167,7 @@ transimit_packet(struct classified_data *classified_data)
}
/* classify packet by destination mac address,
- and transimit packet (conditional). */
+ and transmit packet (conditional). */
static inline void
classify_packet(struct rte_mbuf **rx_pkts, uint16_t n_rx,
struct rte_hash *classifier_mac_table, struct classified_data *classified_data)
@@ -166,9 +197,12 @@ classify_packet(struct rte_mbuf **rx_pkts, uint16_t n_rx,
cd = classified_data + (long)lookup_data;
cd->pkts[cd->num_pkt++] = rx_pkts[i];
- /* transimit packet, if buffer is filled */
- if (unlikely(cd->num_pkt == MAX_PKT_BURST))
- transimit_packet(cd);
+ /* transmit packet, if buffer is filled */
+ if (unlikely(cd->num_pkt == MAX_PKT_BURST)) {
+ RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC,
+ "transimit packets (buffer is filled). index=%ld, num_pkt=%hu\n", (long)lookup_data, cd->num_pkt);
+ transmit_packet(cd);
+ }
}
}
@@ -205,8 +239,11 @@ spp_classifier_mac_do(void *arg)
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))
- transimit_packet(&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]);
+ }
}
prev_tsc = cur_tsc;
}
@@ -217,7 +254,13 @@ spp_classifier_mac_do(void *arg)
if (unlikely(n_rx == 0))
continue;
- /* classify and transimit (filled) */
+#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);
+#endif
+
+ /* classify and transmit (filled) */
classify_packet(rx_pkts, n_rx, classifier_mac_table, classified_data);
}
}
diff --git a/src/vf/ringlatencystats.c b/src/vf/ringlatencystats.c
index 8f44020..32ff55c 100644
--- a/src/vf/ringlatencystats.c
+++ b/src/vf/ringlatencystats.c
@@ -59,8 +59,8 @@ spp_ringlatencystats_init(uint64_t samp_intvl, uint16_t stats_count)
g_stats_count = stats_count;
RTE_LOG(DEBUG, SPP_RING_LATENCY_STATS,
- "g_samp_intvl=%lu, g_stats_count=%hu, cpns=%lu\n",
- g_samp_intvl, g_stats_count, cycles_per_ns());
+ "g_samp_intvl=%lu, g_stats_count=%hu, cpns=%lu, NS_PER_SEC=%f\n",
+ g_samp_intvl, g_stats_count, cycles_per_ns(), NS_PER_SEC);
return 0;
}
@@ -95,6 +95,8 @@ spp_ringlatencystats_add_time_stamp(int ring_id,
/* when it is over sampling interval */
/* set tsc to mbuf::timestamp */
if (unlikely(stats_info->timer_tsc >= g_samp_intvl)) {
+ RTE_LOG(DEBUG, SPP_RING_LATENCY_STATS,
+ "Set timestamp. ring_id=%d, pkts_index=%u, timestamp=%lu\n", ring_id, i, now);
pkts[i]->timestamp = now;
stats_info->timer_tsc = 0;
}
diff --git a/src/vf/spp_config.c b/src/vf/spp_config.c
index 63b85f2..a4d8a67 100644
--- a/src/vf/spp_config.c
+++ b/src/vf/spp_config.c
@@ -150,7 +150,7 @@ config_get_if_info(const char *port, enum port_type *if_type, int *if_no)
/*
* MAC addressを文字列から数値へ変換
*/
-int64_t
+static int64_t
config_change_mac_str_to_int64(const char *mac)
{
int64_t ret_mac = 0;
@@ -237,7 +237,7 @@ config_load_classifier_table(const json_t *obj,
/* table用オブジェクトの要素数取得 */
int array_num = json_array_size(array_obj);
if (unlikely(array_num <= 0) ||
- unlikely(array_num >= SPP_CONFIG_MAC_TABLE_MAX)) {
+ unlikely(array_num > SPP_CONFIG_MAC_TABLE_MAX)) {
RTE_LOG(ERR, APP, "Table size out of range. (path = %s, size = %d)\n",
JSONPATH_TABLE, array_num);
return -1;
@@ -356,7 +356,7 @@ config_set_rx_port(enum spp_core_type type, json_t *obj,
/* 受信ポート用オブジェクトの要素数取得 */
int port_num = json_array_size(array_obj);
if (unlikely(port_num <= 0) ||
- unlikely(port_num >= RTE_MAX_ETHPORTS)) {
+ unlikely(port_num > RTE_MAX_ETHPORTS)) {
RTE_LOG(ERR, APP, "RX port out of range. (path = %s, port = %d, route = merge)\n",
JSONPATH_RX_PORT, port_num);
return -1;
@@ -551,7 +551,7 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
/* functions用オブジェクトの要素数取得 */
int array_num = json_array_size(array_obj);
if (unlikely(array_num <= 0) ||
- unlikely(array_num >= SPP_CONFIG_CORE_MAX)) {
+ unlikely(array_num > SPP_CONFIG_CORE_MAX)) {
RTE_LOG(ERR, APP, "Functions size out of range. (path = %s, size = %d)\n",
JSONPATH_TABLE, array_num);
return -1;
@@ -630,18 +630,18 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
* NG : -1
*/
int
-spp_config_load_file(int node_id, struct spp_config_area *config)
+spp_config_load_file(const char* config_file_path, int node_id, struct spp_config_area *config)
{
/* Config initialize */
config_init_data(config);
/* Config load */
json_error_t json_error;
- json_t *conf_obj = json_load_file(SPP_CONFIG_FILE_PATH, 0, &json_error);
+ json_t *conf_obj = json_load_file(config_file_path, 0, &json_error);
if (unlikely(conf_obj == NULL)) {
/* Load error */
RTE_LOG(ERR, APP, "Config load failed. (path = %s, text = %s)\n",
- SPP_CONFIG_FILE_PATH, json_error.text);
+ config_file_path, json_error.text);
return -1;
}
diff --git a/src/vf/spp_config.h b/src/vf/spp_config.h
index d2a6a4b..24ddd32 100644
--- a/src/vf/spp_config.h
+++ b/src/vf/spp_config.h
@@ -85,6 +85,6 @@ struct spp_config_area {
* OK : 0
* NG : -1
*/
-int spp_config_load_file(int node_id, struct spp_config_area *config);
+int spp_config_load_file(const char* config_file_path, int node_id, struct spp_config_area *config);
#endif /* __SPP_CONFIG_H__ */
diff --git a/src/vf/spp_forward.c b/src/vf/spp_forward.c
index 4396929..e153e85 100644
--- a/src/vf/spp_forward.c
+++ b/src/vf/spp_forward.c
@@ -1,7 +1,8 @@
#include "spp_vf.h"
#include "ringlatencystats.h"
+#include "spp_forward.h"
-#define RTE_LOGTYPE_SPP_FORWARD RTE_LOGTYPE_USER1
+#define RTE_LOGTYPE_FORWARD RTE_LOGTYPE_USER1
/*
* 送受信ポートの経路情報
@@ -14,7 +15,7 @@ struct rxtx {
/*
* 使用するIF情報を移し替える
*/
-void
+static void
set_use_interface(struct spp_core_port_info *dst,
struct spp_core_port_info *src)
{
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index ee5cf63..f035d07 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -14,6 +14,15 @@
#define SPP_CORE_STATUS_CHECK_MAX 5
#define SPP_RING_LATENCY_STATS_SAMPLING_INTERVAL 1000000
+/* getopt_long return value for long option */
+enum SPP_LONGOPT_RETVAL {
+ SPP_LONGOPT_RETVAL__ = 127,
+
+ /* add below */
+
+ SPP_LONGOPT_RETVAL_CONFIG,
+};
+
/* struct */
struct startup_param {
uint64_t cpu;
@@ -41,13 +50,18 @@ 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 char config_file_path[PATH_MAX];
+
/*
* print a usage message
*/
static void
usage(const char *progname)
{
- RTE_LOG(INFO, APP, "Usage: %s [EAL args]\n\n", progname);
+ RTE_LOG(INFO, APP, "Usage: %s [EAL args] -- [--config CONFIG_FILE_PATH]\n"
+ " --config CONFIG_FILE_PATH: specific config file path\n"
+ "\n"
+ , progname);
}
/*
@@ -208,7 +222,7 @@ set_core_status(enum spp_core_status status)
/*
* Process stop
*/
-void
+static void
stop_process(int signal) {
if (unlikely(signal != SIGTERM) &&
unlikely(signal != SIGINT)) {
@@ -239,16 +253,23 @@ parse_cpu_bit(uint64_t *cpu, const char *cpu_bit)
}
/*
- * Parse the application arguments to the client app.
+ * Parse the dpdk arguments for use in client app.
*/
static int
-parse_app_args(int argc, char *argv[])
+parse_dpdk_args(int argc, char *argv[])
{
+ int cnt;
int option_index, opt;
- char **argvopt = argv;
+ const int argcopt = argc;
+ char *argvopt[argcopt];
const char *progname = argv[0];
static struct option lgopts[] = { {0} };
+ /* getoptを使用するとargvが並び変わるみたいなので、コピーを実施 */
+ for (cnt = 0; cnt < argcopt; cnt++) {
+ argvopt[cnt] = argv[cnt];
+ }
+
/* Check DPDK parameter */
optind = 0;
opterr = 0;
@@ -273,6 +294,48 @@ parse_app_args(int argc, char *argv[])
}
/*
+ * Parse the application arguments to the client app.
+ */
+static int
+parse_app_args(int argc, char *argv[])
+{
+ int cnt;
+ int option_index, opt;
+ const int argcopt = argc;
+ char *argvopt[argcopt];
+ const char *progname = argv[0];
+ static struct option lgopts[] = {
+ { "config", required_argument, NULL, SPP_LONGOPT_RETVAL_CONFIG },
+ { 0 },
+ };
+
+ /* getoptを使用するとargvが並び変わるみたいなので、コピーを実施 */
+ for (cnt = 0; cnt < argcopt; cnt++) {
+ argvopt[cnt] = argv[cnt];
+ }
+
+ /* Check application parameter */
+ optind = 0;
+ opterr = 0;
+ while ((opt = getopt_long(argc, argvopt, "", 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;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*
* IF種別&IF番号のIF情報の領域取得
*/
static struct patch_info *
@@ -299,7 +362,7 @@ get_if_area(enum port_type if_type, int if_no)
* IF情報初期化
*/
static void
-init_if_info()
+init_if_info(void)
{
memset(&g_if_info, 0x00, sizeof(g_if_info));
}
@@ -308,7 +371,7 @@ init_if_info()
* CORE情報初期化
*/
static void
-init_core_info()
+init_core_info(void)
{
memset(&g_core_info, 0x00, sizeof(g_core_info));
int core_cnt, port_cnt;
@@ -330,7 +393,7 @@ set_form_proc_info(struct spp_config_area *config)
int core_cnt, rx_start, rx_cnt, tx_start, tx_cnt;
enum port_type if_type;
int if_no;
- int64_t cpu_bit = 0;
+ uint64_t cpu_bit = 0;
struct spp_config_functions *core_func = NULL;
struct spp_core_info *core_info = NULL;
struct patch_info *patch_info = NULL;
@@ -344,7 +407,7 @@ set_form_proc_info(struct spp_config_area *config)
/* Forwardをまとめる事は可、他種別は不可 */
if ((core_info->type != SPP_CONFIG_UNUSE) &&
- ((core_info->type != SPP_CONFIG_FORWARD) &&
+ ((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,
@@ -371,8 +434,8 @@ set_form_proc_info(struct spp_config_area *config)
patch_info->use_flg = 1;
if (unlikely(patch_info->rx_core != NULL)) {
- RTE_LOG(ERR, APP, "Used RX port (if_type = %d, if_no = %d)\n",
- if_type, if_no);
+ 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;
}
@@ -395,8 +458,8 @@ set_form_proc_info(struct spp_config_area *config)
patch_info->use_flg = 1;
if (unlikely(patch_info->tx_core != NULL)) {
- RTE_LOG(ERR, APP, "Used TX port (if_type = %d, if_no = %d)\n",
- if_type, if_no);
+ 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;
}
@@ -456,7 +519,7 @@ set_from_classifier_table(struct spp_config_area *config)
* NIC用の情報設定
*/
static int
-set_nic_interface(struct spp_config_area *config)
+set_nic_interface(struct spp_config_area *config __attribute__ ((unused)))
{
/* NIC Setting */
g_if_info.num_nic = rte_eth_dev_count();
@@ -590,8 +653,8 @@ static int
init_manage_data(struct spp_config_area *config)
{
/* Initialize */
- init_if_info(config);
- init_core_info(config);
+ init_if_info();
+ init_core_info();
/* Set config data */
int ret_proc = set_form_proc_info(config);
@@ -629,7 +692,7 @@ init_manage_data(struct spp_config_area *config)
#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
static void
-print_ring_latency_stats()
+print_ring_latency_stats(void)
{
/* Clear screen and move to top left */
const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' };
@@ -669,6 +732,24 @@ print_ring_latency_stats()
#endif /* SPP_RINGLATENCYSTATS_ENABLE */
/*
+ * VHOST用ソケットファイル削除
+ */
+static void
+del_vhost_sockfile(struct patch_info *vhost_patchs)
+{
+ int cnt;
+ for (cnt = 0; cnt < RTE_MAX_ETHPORTS; cnt++) {
+ if (likely(vhost_patchs[cnt].use_flg == 0)) {
+ /* VHOST未使用はスキップ */
+ continue;
+ }
+
+ /* 使用していたVHOSTについて削除を行う */
+ remove(get_vhost_iface_name(cnt));
+ }
+}
+
+/*
* main
*/
int
@@ -692,25 +773,44 @@ ut_main(int argc, char *argv[])
signal(SIGTERM, stop_process);
signal(SIGINT, stop_process);
+ /* set default config file path */
+ strcpy(config_file_path, SPP_CONFIG_FILE_PATH);
+
unsigned int main_lcore_id = 0xffffffff;
while(1) {
- /* Parse parameters */
- int ret_parse = parse_app_args(argc, argv);
+ /* Parse dpdk parameters */
+ int ret_parse = parse_dpdk_args(argc, argv);
if (unlikely(ret_parse != 0)) {
break;
}
- /* Load config */
- int ret_config = spp_config_load_file(0, &g_config);
- if (unlikely(ret_config != 0)) {
- break;
- }
-
/* DPDK initialize */
int ret_dpdk = rte_eal_init(argc, argv);
if (unlikely(ret_dpdk < 0)) {
break;
}
+
+ /* Skip dpdk parameters */
+ argc -= ret_dpdk;
+ argv += ret_dpdk;
+
+ /* Set log level */
+ rte_log_set_global_level(RTE_LOG_LEVEL);
+
+ /* Parse application parameters */
+ ret_parse = parse_app_args(argc, argv);
+ if (unlikely(ret_parse != 0)) {
+ break;
+ }
+
+ RTE_LOG(INFO, APP, "Load config file(%s)\n", config_file_path);
+
+ /* Load config */
+ int ret_config = spp_config_load_file(config_file_path, 0, &g_config);
+ if (unlikely(ret_config != 0)) {
+ break;
+ }
+
/* Get core id. */
main_lcore_id = rte_lcore_id();
@@ -775,7 +875,6 @@ ut_main(int argc, char *argv[])
}
/* exit */
- stop_process(SIGINT);
if (main_lcore_id == rte_lcore_id())
{
g_core_info[main_lcore_id].status = SPP_CORE_STOP;
@@ -783,6 +882,9 @@ ut_main(int argc, char *argv[])
if (unlikely(ret_core_end != 0)) {
RTE_LOG(ERR, APP, "Core did not stop.\n");
}
+
+ /* 使用していたVHOSTのソケットファイルを削除 */
+ del_vhost_sockfile(g_if_info.vhost_patchs);
}
/* 他機能部終了処理 */
diff --git a/src/vf/spp_vf.h b/src/vf/spp_vf.h
index feb59b6..c0faa57 100644
--- a/src/vf/spp_vf.h
+++ b/src/vf/spp_vf.h
@@ -29,8 +29,8 @@ struct spp_core_port_info {
* Core info
*/
struct spp_core_info {
- enum spp_core_status status;
- enum spp_core_type type;
+ 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];
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* Re: [spp] [PATCH 02/57] spp_vf: support multi process
2017-12-28 4:55 ` [spp] [PATCH 02/57] spp_vf: support multi process x-fn-spp
@ 2018-02-07 16:50 ` Ferruh Yigit
2018-02-08 1:21 ` Yasufumi Ogawa
2018-02-08 6:44 ` [spp] [spp 02168] " Nakamura Hioryuki
0 siblings, 2 replies; 97+ messages in thread
From: Ferruh Yigit @ 2018-02-07 16:50 UTC (permalink / raw)
To: x-fn-spp, spp
On 12/28/2017 4:55 AM, x-fn-spp@sl.ntt-tx.co.jp wrote:
> From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
>
> spp_vf was only a single process so far, but spp_vf supported
> multi process. Following modification has been made.
>
> * Change naming machanism to allow hashtable on shared memory
> to be operated by multiple processes.
> * Get config file path from command line argument.
>
> And following modification has been made.
> * Modify comment.
> * Add and modify log message.
> * Add function to remove vhost socket file.
>
> Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
> Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
<...>
> @@ -669,6 +732,24 @@ print_ring_latency_stats()
> #endif /* SPP_RINGLATENCYSTATS_ENABLE */
>
> /*
> + * VHOST用ソケットファイル削除
> + */
> +static void
> +del_vhost_sockfile(struct patch_info *vhost_patchs)
> +{
> + int cnt;
> + for (cnt = 0; cnt < RTE_MAX_ETHPORTS; cnt++) {
> + if (likely(vhost_patchs[cnt].use_flg == 0)) {
> + /* VHOST未使用はスキップ */
> + continue;
> + }
> +
> + /* 使用していたVHOSTについて削除を行う */
Would you mind translating comments to English. It helps if code understood by
more people.
<...>
> }
> +
> + /* Skip dpdk parameters */
> + argc -= ret_dpdk;
> + argv += ret_dpdk;
> +
> + /* Set log level */
> + rte_log_set_global_level(RTE_LOG_LEVEL);
Hi Daiki, Yasufum,
This breaks the build with dpdk master because RTE_LOG_LEVEL removed in this
release.
Can you please check this?
^ permalink raw reply [flat|nested] 97+ messages in thread
* Re: [spp] [PATCH 02/57] spp_vf: support multi process
2018-02-07 16:50 ` Ferruh Yigit
@ 2018-02-08 1:21 ` Yasufumi Ogawa
2018-02-08 6:44 ` [spp] [spp 02168] " Nakamura Hioryuki
1 sibling, 0 replies; 97+ messages in thread
From: Yasufumi Ogawa @ 2018-02-08 1:21 UTC (permalink / raw)
To: Ferruh Yigit, x-fn-spp, spp
On 2018/02/08 1:50, Ferruh Yigit wrote:
> On 12/28/2017 4:55 AM, x-fn-spp@sl.ntt-tx.co.jp wrote:
>> From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
>>
>> spp_vf was only a single process so far, but spp_vf supported
>> multi process. Following modification has been made.
>>
>> * Change naming machanism to allow hashtable on shared memory
>> to be operated by multiple processes.
>> * Get config file path from command line argument.
>>
>> And following modification has been made.
>> * Modify comment.
>> * Add and modify log message.
>> * Add function to remove vhost socket file.
>>
>> Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
>> Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
>
> <...>
>
>> @@ -669,6 +732,24 @@ print_ring_latency_stats()
>> #endif /* SPP_RINGLATENCYSTATS_ENABLE */
>>
>> /*
>> + * VHOST用ソケットファイル削除
>> + */
>> +static void
>> +del_vhost_sockfile(struct patch_info *vhost_patchs)
>> +{
>> + int cnt;
>> + for (cnt = 0; cnt < RTE_MAX_ETHPORTS; cnt++) {
>> + if (likely(vhost_patchs[cnt].use_flg == 0)) {
>> + /* VHOST未使用はスキップ */
>> + continue;
>> + }
>> +
>> + /* 使用していたVHOSTについて削除を行う */
>
> Would you mind translating comments to English. It helps if code understood by
> more people.
>
> <...>
>
>> }
>> +
>> + /* Skip dpdk parameters */
>> + argc -= ret_dpdk;
>> + argv += ret_dpdk;
>> +
>> + /* Set log level */
>> + rte_log_set_global_level(RTE_LOG_LEVEL);
>
> Hi Daiki, Yasufum,
>
> This breaks the build with dpdk master because RTE_LOG_LEVEL removed in this
> release.
>
> Can you please check this?
Hi Ferruh,
We have talked how to fix this issue and are preparing a patch for. As
you mention before, this is because difference of versions of DPDK, 1711
and 1802. I think we should also update version of SPP, so I send
another patch for updating.
To clear which of DPDK version for compiling SPP, I will check for it is
safely compiled with latest DPDK and update the version immediately in
future.
Thanks,
>
>
--
Yasufumi Ogawa
NTT Network Service Systems Labs
^ permalink raw reply [flat|nested] 97+ messages in thread
* Re: [spp] [spp 02168] Re: [PATCH 02/57] spp_vf: support multi process
2018-02-07 16:50 ` Ferruh Yigit
2018-02-08 1:21 ` Yasufumi Ogawa
@ 2018-02-08 6:44 ` Nakamura Hioryuki
1 sibling, 0 replies; 97+ messages in thread
From: Nakamura Hioryuki @ 2018-02-08 6:44 UTC (permalink / raw)
To: Ferruh Yigit; +Cc: spp
> On 12/28/2017 4:55 AM, x-fn-spp@sl.ntt-tx.co.jp wrote:
> > From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
> >
> > spp_vf was only a single process so far, but spp_vf supported
> > multi process. Following modification has been made.
> >
> > * Change naming machanism to allow hashtable on shared memory
> > to be operated by multiple processes.
> > * Get config file path from command line argument.
> >
> > And following modification has been made.
> > * Modify comment.
> > * Add and modify log message.
> > * Add function to remove vhost socket file.
> >
> > Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
> > Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
>
<snip>
>
> Would you mind translating comments to English. It helps if code understood by
> more people.
All the comment of latest code on http://dpdk.org/git/apps/spp has
already been translated to English.
> > +
> > + /* Set log level */
> > + rte_log_set_global_level(RTE_LOG_LEVEL);
>
> Hi Daiki, Yasufum,
>
> This breaks the build with dpdk master because RTE_LOG_LEVEL removed in this
> release.
>
> Can you please check this?
We've sent a patch,
[PATCH 9/9] spp_vf: change log level setting
This will enable spp_vf to build on dpdk master.
Thanks,
--
Nakamura Hioryuki <nakamua.hiroyuki@po.ntt-tx.co.jp>
--
Nakamura Hioryuki <nakamua.hiroyuki@po.ntt-tx.co.jp>
NTTテクノクロス フューチャーネットワーク事業部 第一事業ユニット
〒167-0043 杉並区上荻1-2-1 インテグラルタワー 14階
TEL:03-5347-8024 FAX:03-3392-2907
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 03/57] spp_vf: comment out check of using cores
2017-12-26 1:54 ` Yasufumi Ogawa
2017-12-28 4:55 ` [spp] [PATCH 01/57] spp_vf: add vf functions x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 02/57] spp_vf: support multi process x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 04/57] spp_vf: modify classifier for upd command x-fn-spp
` (53 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Bug workaround.
Current implementation prevent use of over 32 cores due to
int type restriction.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_vf.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index f035d07..830aaaa 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -468,12 +468,14 @@ set_form_proc_info(struct spp_config_area *config)
}
}
+#if 0 /* bugfix#385 */
if (unlikely((cpu_bit & g_startup_param.cpu) != cpu_bit)) {
/* CPU mismatch */
RTE_LOG(ERR, APP, "CPU mismatch (cpu param = %lx, config = %lx)\n",
g_startup_param.cpu, cpu_bit);
return -1;
}
+#endif
return 0;
}
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 04/57] spp_vf: modify classifier for upd command
2017-12-26 1:54 ` Yasufumi Ogawa
` (2 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 03/57] spp_vf: comment out check of using cores x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 05/57] spp_vf: add procedure that mac address is null x-fn-spp
` (52 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
spp_vf supports command for modifying classifier table.
* Classifier changes to have two tables (for reference and update).
* Classifier use reference-table when packet handling.
* When updating, update update-table. After the update,
switch the roles of two table.(update->reference, reference->update)
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/classifier_mac.c | 223 +++++++++++++++++++++++++++++++++++++++++-------
src/vf/classifier_mac.h | 10 +++
2 files changed, 200 insertions(+), 33 deletions(-)
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
index 374f164..6d8b222 100644
--- a/src/vf/classifier_mac.c
+++ b/src/vf/classifier_mac.c
@@ -35,6 +35,13 @@
/* number of classifier mac table entry */
#define NUM_CLASSIFIER_MAC_TABLE_ENTRY 128
+/* number of classifier information (reference/update) */
+#define NUM_CLASSIFIER_MAC_INFO 2
+
+/* interval that wait untill change update index
+ micro second */
+#define CHANGE_UPDATE_INDEX_WAIT_INTERVAL 10
+
/* interval that transmit burst packet, if buffer is not filled.
nano second */
#define DRAIN_TX_PACKET_INTERVAL 100
@@ -54,6 +61,18 @@ static const size_t HASH_TABLE_NAME_BUF_SZ =
static const size_t ETHER_ADDR_STR_BUF_SZ =
ETHER_ADDR_LEN * 2 + (ETHER_ADDR_LEN - 1) + 1;
+/* classifier information */
+struct classifier_mac_info {
+ struct rte_hash *classifier_table;
+};
+
+/* classifier management information */
+struct classifier_mac_mng_info {
+ struct classifier_mac_info info[NUM_CLASSIFIER_MAC_INFO];
+ volatile int ref_index;
+ volatile int upd_index;
+};
+
/* classified data (destination port, target packets, etc) */
struct classified_data {
enum port_type if_type;
@@ -63,16 +82,59 @@ struct classified_data {
struct rte_mbuf *pkts[MAX_PKT_BURST];
};
+/* classifier information per lcore */
+static struct classifier_mac_mng_info g_classifier_mng_info[RTE_MAX_LCORE];
+
/* hash table count. use to make hash table name.
[reason for value]
it is incremented at the time of use,
but since we want to start at 0. */
static rte_atomic16_t g_hash_table_count = RTE_ATOMIC16_INIT(0xff);
+/* initialize classifier table. */
+static int
+init_classifier_table(struct rte_hash **classifier_table,
+ struct spp_core_info *core_info)
+{
+ int ret = -1;
+ int i;
+ struct ether_addr eth_addr;
+ char mac_addr_str[ETHER_ADDR_STR_BUF_SZ];
+
+ rte_hash_reset(*classifier_table);
+
+ for (i = 0; i < core_info->num_tx_port; i++) {
+ rte_memcpy(ð_addr, &core_info->tx_ports[i].mac_addr, ETHER_ADDR_LEN);
+
+ /* add entry to classifier mac table */
+ ret = rte_hash_add_key_data(*classifier_table,
+ (void*)ð_addr, (void*)(long)i);
+ if (unlikely(ret < 0)) {
+ ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð_addr);
+ RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
+ "Cannot add entry to classifier mac table. "
+ "ret=%d, mac_addr=%s\n", ret, mac_addr_str);
+ rte_hash_free(*classifier_table);
+ *classifier_table = NULL;
+ return -1;
+ }
+
+ RTE_LOG(DEBUG, 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);
+ }
+
+ return 0;
+}
+
/* initialize classifier. */
static int
init_classifier(const struct spp_core_info *core_info,
- struct rte_hash **classifier_mac_table, struct classified_data *classified_data)
+ struct classifier_mac_mng_info *classifier_mng_info,
+ struct classified_data *classified_data)
{
int ret = -1;
int i;
@@ -80,22 +142,11 @@ init_classifier(const struct spp_core_info *core_info,
char hash_table_name[HASH_TABLE_NAME_BUF_SZ];
char mac_addr_str[ETHER_ADDR_STR_BUF_SZ];
- /* make hash table name(require uniqueness between processes) */
- sprintf(hash_table_name, "cmtab_%08x%02hx",
- getpid(), rte_atomic16_add_return(&g_hash_table_count, 1));
+ struct rte_hash **classifier_mac_table = NULL;
- RTE_LOG(INFO, SPP_CLASSIFIER_MAC, "Create table. name=%s, bufsz=%lu\n",
- hash_table_name, HASH_TABLE_NAME_BUF_SZ);
-
- /* set hash creating parameters */
- struct rte_hash_parameters hash_params = {
- .name = hash_table_name,
- .entries = NUM_CLASSIFIER_MAC_TABLE_ENTRY,
- .key_len = sizeof(struct ether_addr),
- .hash_func = DEFAULT_HASH_FUNC,
- .hash_func_init_val = 0,
- .socket_id = rte_socket_id(),
- };
+ memset(classifier_mng_info, 0, sizeof(struct classifier_mac_mng_info));
+ classifier_mng_info->ref_index = 0;
+ classifier_mng_info->upd_index = classifier_mng_info->ref_index + 1;
#ifdef RTE_MACHINE_CPUFLAG_SSE4_2
RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, "Enabled SSE4.2. use crc hash.\n");
@@ -103,19 +154,48 @@ init_classifier(const struct spp_core_info *core_info,
RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, "Disabled SSE4.2. use jenkins hash.\n");
#endif
- /* create classifier mac table (hash table) */
- *classifier_mac_table = rte_hash_create(&hash_params);
- if (unlikely(*classifier_mac_table == NULL)) {
- RTE_LOG(ERR, SPP_CLASSIFIER_MAC, "Cannot create classifier mac table\n");
- return -1;
+ for (i = 0; i < NUM_CLASSIFIER_MAC_INFO; ++i) {
+
+ classifier_mac_table = &classifier_mng_info->info[i].classifier_table;
+
+ /* make hash table name(require uniqueness between processes) */
+ sprintf(hash_table_name, "cmtab_%07x%02hx%x",
+ getpid(), rte_atomic16_add_return(&g_hash_table_count, 1), i);
+
+ RTE_LOG(INFO, SPP_CLASSIFIER_MAC, "Create table. name=%s, bufsz=%lu\n",
+ hash_table_name, HASH_TABLE_NAME_BUF_SZ);
+
+ /* set hash creating parameters */
+ struct rte_hash_parameters hash_params = {
+ .name = hash_table_name,
+ .entries = NUM_CLASSIFIER_MAC_TABLE_ENTRY,
+ .key_len = sizeof(struct ether_addr),
+ .hash_func = DEFAULT_HASH_FUNC,
+ .hash_func_init_val = 0,
+ .socket_id = rte_socket_id(),
+ };
+
+ /* create classifier mac table (hash table) */
+ *classifier_mac_table = rte_hash_create(&hash_params);
+ if (unlikely(*classifier_mac_table == NULL)) {
+ RTE_LOG(ERR, SPP_CLASSIFIER_MAC, "Cannot create classifier mac table. "
+ "name=%s\n", hash_table_name);
+ return -1;
+ }
}
- /* populate the hash */
+ /* populate the hash at reference table */
+ classifier_mac_table = &classifier_mng_info->info[classifier_mng_info->ref_index].
+ classifier_table;
+
for (i = 0; i < core_info->num_tx_port; i++) {
rte_memcpy(ð_addr, &core_info->tx_ports[i].mac_addr, ETHER_ADDR_LEN);
+ /* TODO:when modify this code, consider to use init_classifier_table function */
+
/* add entry to classifier mac table */
- ret = rte_hash_add_key_data(*classifier_mac_table, (void*)ð_addr, (void*)(long)i);
+ ret = rte_hash_add_key_data(*classifier_mac_table,
+ (void*)ð_addr, (void*)(long)i);
if (unlikely(ret < 0)) {
ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð_addr);
RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
@@ -136,6 +216,20 @@ init_classifier(const struct spp_core_info *core_info,
return 0;
}
+/* uninitialize classifier. */
+static void
+uninit_classifier(struct classifier_mac_mng_info *classifier_mng_info)
+{
+ int i;
+
+ for (i = 0; i < NUM_CLASSIFIER_MAC_INFO; ++i) {
+ if (classifier_mng_info->info[i].classifier_table != NULL){
+ rte_hash_free(classifier_mng_info->info[i].classifier_table);
+ classifier_mng_info->info[i].classifier_table = NULL;
+ }
+ }
+}
+
/* transmit packet to one destination. */
static inline void
transmit_packet(struct classified_data *classified_data)
@@ -170,7 +264,8 @@ transmit_packet(struct classified_data *classified_data)
and transmit packet (conditional). */
static inline void
classify_packet(struct rte_mbuf **rx_pkts, uint16_t n_rx,
- struct rte_hash *classifier_mac_table, struct classified_data *classified_data)
+ struct classifier_mac_info *classifier_info,
+ struct classified_data *classified_data)
{
int ret;
int i;
@@ -183,7 +278,7 @@ classify_packet(struct rte_mbuf **rx_pkts, uint16_t n_rx,
eth = rte_pktmbuf_mtod(rx_pkts[i], struct ether_hdr *);
/* find in table (by destination mac address)*/
- ret = rte_hash_lookup_data(classifier_mac_table,
+ ret = rte_hash_lookup_data(classifier_info->classifier_table,
(const void*)ð->d_addr, &lookup_data);
if (unlikely(ret < 0)) {
ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð->d_addr);
@@ -206,6 +301,43 @@ classify_packet(struct rte_mbuf **rx_pkts, uint16_t n_rx,
}
}
+/* classifier(mac address) update component info. */
+int
+spp_classifier_mac_update(struct spp_core_info *core_info)
+{
+ int ret = -1;
+ unsigned int lcore_id = core_info->lcore_id;
+
+ struct classifier_mac_mng_info *classifier_mng_info =
+ g_classifier_mng_info + lcore_id;
+
+ struct classifier_mac_info *classifier_info =
+ classifier_mng_info->info + classifier_mng_info->upd_index;
+
+ RTE_LOG(INFO, SPP_CLASSIFIER_MAC,
+ "Core[%u] Start update component.", lcore_id);
+
+ /* initialize update side classifier table */
+ ret = init_classifier_table(&classifier_info->classifier_table, core_info);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
+ "Cannot update classifer mac. ret=%d\n", ret);
+ return ret;
+ }
+
+ /* change index of reference side */
+ classifier_mng_info->ref_index = classifier_mng_info->upd_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.", lcore_id);
+
+ return 0;
+}
+
/* classifier(mac address) thread function. */
int
spp_classifier_mac_do(void *arg)
@@ -213,10 +345,14 @@ spp_classifier_mac_do(void *arg)
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();
+
+ struct classifier_mac_info *classifier_info = NULL;
struct rte_mbuf *rx_pkts[MAX_PKT_BURST];
- struct rte_hash *classifier_mac_table = NULL;
const int n_classified_data = core_info->num_tx_port;
struct classified_data classified_data[n_classified_data];
@@ -225,23 +361,46 @@ spp_classifier_mac_do(void *arg)
US_PER_S * DRAIN_TX_PACKET_INTERVAL;
/* initialize */
- ret = init_classifier(core_info, &classifier_mac_table, classified_data);
+ ret = init_classifier(core_info, classifier_mng_info, classified_data);
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 */
+ if (unlikely(classifier_mng_info->ref_index ==
+ classifier_mng_info->upd_index)) {
+ RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC,
+ "Core[%u] Change update index.", lcore_id);
+ classifier_mng_info->upd_index =
+ (classifier_mng_info->upd_index + 1) %
+ NUM_CLASSIFIER_MAC_INFO;
+ }
+
+ /* 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);
+ "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]);
}
}
@@ -261,15 +420,13 @@ spp_classifier_mac_do(void *arg)
#endif
/* classify and transmit (filled) */
- classify_packet(rx_pkts, n_rx, classifier_mac_table, classified_data);
+ classify_packet(rx_pkts, n_rx, classifier_info, classified_data);
}
}
/* uninitialize */
- if (classifier_mac_table != NULL) {
- rte_hash_free(classifier_mac_table);
- classifier_mac_table = NULL;
- }
+ uninit_classifier(classifier_mng_info);
+
core_info->status = SPP_CORE_STOP;
return 0;
diff --git a/src/vf/classifier_mac.h b/src/vf/classifier_mac.h
index 2661206..6bbdb15 100644
--- a/src/vf/classifier_mac.h
+++ b/src/vf/classifier_mac.h
@@ -1,6 +1,16 @@
#ifndef _CLASSIFIER_MAC_H_
#define _CLASSIFIER_MAC_H_
+struct spp_core_info;
+
+/**
+ * classifier(mac address) update component info.
+ *
+ * @param core_info
+ * point to struct spp_core_info.
+ */
+int spp_classifier_mac_update(struct spp_core_info *core_info);
+
/**
* classifier(mac address) thread function.
*
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 05/57] spp_vf: add procedure that mac address is null
2017-12-26 1:54 ` Yasufumi Ogawa
` (3 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 04/57] spp_vf: modify classifier for upd command x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 06/57] spp_vf: change config format for upd command x-fn-spp
` (51 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
spp_vf supports command for modifying classifier table.
* Add procedure that MAC address is null.
* Refactor classifier table initialization.
* Refactor classifier table switching.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/classifier_mac.c | 55 ++++++++++++++++++++++++++-----------------------
src/vf/classifier_mac.h | 4 ++++
2 files changed, 33 insertions(+), 26 deletions(-)
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
index 6d8b222..6808062 100644
--- a/src/vf/classifier_mac.c
+++ b/src/vf/classifier_mac.c
@@ -104,6 +104,10 @@ init_classifier_table(struct rte_hash **classifier_table,
rte_hash_reset(*classifier_table);
for (i = 0; i < core_info->num_tx_port; i++) {
+ if (core_info->tx_ports[i].mac_addr == 0) {
+ continue;
+ }
+
rte_memcpy(ð_addr, &core_info->tx_ports[i].mac_addr, ETHER_ADDR_LEN);
/* add entry to classifier mac table */
@@ -188,25 +192,15 @@ init_classifier(const struct spp_core_info *core_info,
classifier_mac_table = &classifier_mng_info->info[classifier_mng_info->ref_index].
classifier_table;
- for (i = 0; i < core_info->num_tx_port; i++) {
- rte_memcpy(ð_addr, &core_info->tx_ports[i].mac_addr, ETHER_ADDR_LEN);
-
- /* TODO:when modify this code, consider to use init_classifier_table function */
-
- /* add entry to classifier mac table */
- ret = rte_hash_add_key_data(*classifier_mac_table,
- (void*)ð_addr, (void*)(long)i);
- if (unlikely(ret < 0)) {
- ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð_addr);
- RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
- "Cannot add entry to classifier mac table. "
- "ret=%d, mac_addr=%s\n", ret, mac_addr_str);
- rte_hash_free(*classifier_mac_table);
- *classifier_mac_table = NULL;
- return -1;
- }
+ ret = init_classifier_table(classifier_mac_table, core_info);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
+ "Cannot initialize classifer mac table. ret=%d\n", ret);
+ return -1;
+ }
- /* set value */
+ /* 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].tx_port = core_info->tx_ports[i].dpdk_port;
@@ -301,6 +295,19 @@ classify_packet(struct rte_mbuf **rx_pkts, uint16_t n_rx,
}
}
+static inline void
+change_update_index(struct classifier_mac_mng_info *classifier_mng_info, unsigned int lcore_id)
+{
+ if (unlikely(classifier_mng_info->ref_index ==
+ classifier_mng_info->upd_index)) {
+ RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC,
+ "Core[%u] Change update index.", lcore_id);
+ classifier_mng_info->upd_index =
+ (classifier_mng_info->upd_index + 1) %
+ NUM_CLASSIFIER_MAC_INFO;
+ }
+}
+
/* classifier(mac address) update component info. */
int
spp_classifier_mac_update(struct spp_core_info *core_info)
@@ -375,14 +382,7 @@ spp_classifier_mac_do(void *arg)
while(likely(core_info->status == SPP_CORE_FORWARD)) {
/* change index of update side */
- if (unlikely(classifier_mng_info->ref_index ==
- classifier_mng_info->upd_index)) {
- RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC,
- "Core[%u] Change update index.", lcore_id);
- classifier_mng_info->upd_index =
- (classifier_mng_info->upd_index + 1) %
- NUM_CLASSIFIER_MAC_INFO;
- }
+ change_update_index(classifier_mng_info, lcore_id);
/* decide classifier infomation of the current cycle */
classifier_info = classifier_mng_info->info +
@@ -424,6 +424,9 @@ spp_classifier_mac_do(void *arg)
}
}
+ /* just in case */
+ change_update_index(classifier_mng_info, lcore_id);
+
/* uninitialize */
uninit_classifier(classifier_mng_info);
diff --git a/src/vf/classifier_mac.h b/src/vf/classifier_mac.h
index 6bbdb15..98f47a5 100644
--- a/src/vf/classifier_mac.h
+++ b/src/vf/classifier_mac.h
@@ -1,6 +1,7 @@
#ifndef _CLASSIFIER_MAC_H_
#define _CLASSIFIER_MAC_H_
+/* forward declaration */
struct spp_core_info;
/**
@@ -8,6 +9,9 @@ struct spp_core_info;
*
* @param core_info
* point to struct spp_core_info.
+ *
+ * @ret_val 0 succeeded.
+ * @ret_val -1 failed.
*/
int spp_classifier_mac_update(struct spp_core_info *core_info);
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 06/57] spp_vf: change config format for upd command
2017-12-26 1:54 ` Yasufumi Ogawa
` (4 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 05/57] spp_vf: add procedure that mac address is null x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 07/57] spp_vf: fix compiler warning in classifier_mac.c x-fn-spp
` (50 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
spp_vf supports command for modifying classifier table.
* Change the config file format.
* Modify code to support the file format change.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_config.c | 91 +++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 78 insertions(+), 13 deletions(-)
diff --git a/src/vf/spp_config.c b/src/vf/spp_config.c
index a4d8a67..1794e84 100644
--- a/src/vf/spp_config.c
+++ b/src/vf/spp_config.c
@@ -206,9 +206,8 @@ config_load_classifier_table(const json_t *obj,
/* classifier_table用オブジェクト取得 */
json_t *classifier_obj = json_path_get(obj, JSONPATH_CLASSIFIER_TABLE);
if (unlikely(classifier_obj == NULL)) {
- RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
- JSONPATH_CLASSIFIER_TABLE);
- return -1;
+ RTE_LOG(INFO, APP, "No classifier table.\n");
+ return 0;
}
/* name取得 */
@@ -428,6 +427,7 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
struct spp_config_functions *functions,
struct spp_config_classifier_table *classifier_table)
{
+ int cnt = 0;
struct spp_config_port_info *tmp_tx_port = NULL;
char if_str[SPP_CONFIG_STR_LEN];
if ((type == SPP_CONFIG_MERGE) || (type == SPP_CONFIG_FORWARD)) {
@@ -454,16 +454,81 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
}
} else {
/* Classifier */
- int cnt = 0;
- functions->num_tx_port = classifier_table->num_table;
- struct spp_config_mac_table_element *tmp_mac_table = NULL;
- for (cnt = 0; cnt < classifier_table->num_table; cnt++) {
- tmp_tx_port = &functions->tx_ports[cnt];
- tmp_mac_table = &classifier_table->mac_tables[cnt];
-
- /* MAC振り分けテーブルより設定 */
- tmp_tx_port->if_type = tmp_mac_table->port.if_type;
- tmp_tx_port->if_no = tmp_mac_table->port.if_no;
+ json_t *table_obj = json_path_get(obj, JSONPATH_TX_TABLE);
+ if (unlikely(table_obj != NULL)) {
+ /* Classifier Tableから取得 */
+ functions->num_tx_port = classifier_table->num_table;
+ struct spp_config_mac_table_element *tmp_mac_table = NULL;
+ for (cnt = 0; cnt < classifier_table->num_table; cnt++) {
+ tmp_tx_port = &functions->tx_ports[cnt];
+ tmp_mac_table = &classifier_table->mac_tables[cnt];
+
+ /* MAC振り分けテーブルより設定 */
+ tmp_tx_port->if_type = tmp_mac_table->port.if_type;
+ tmp_tx_port->if_no = tmp_mac_table->port.if_no;
+ }
+
+ }
+ else
+ {
+ /* tx_portパラメータより取得 */
+ /* 送信ポート用オブジェクト取得 */
+ json_t *array_obj = json_path_get(obj, JSONPATH_TX_PORT);
+ if (unlikely(array_obj == NULL)) {
+ RTE_LOG(ERR, APP, "Json object get failed. (path = %s, route = classifier)\n",
+ JSONPATH_TX_PORT);
+ return -1;
+ }
+
+ /* 送信ポート用オブジェクトが配列かチェック */
+ if (unlikely(!json_is_array(array_obj))) {
+ RTE_LOG(ERR, APP, "Not an array. (path = %s, route = classifier)\n",
+ JSONPATH_TX_PORT);
+ return -1;
+ }
+
+ /* 受信ポート用オブジェクトの要素数取得 */
+ int port_num = json_array_size(array_obj);
+ if (unlikely(port_num <= 0) ||
+ unlikely(port_num > RTE_MAX_ETHPORTS)) {
+ RTE_LOG(ERR, APP, "TX port out of range. (path = %s, port = %d, route = classifier)\n",
+ JSONPATH_TX_PORT, port_num);
+ return -1;
+ }
+ functions->num_tx_port = port_num;
+
+ /* 要素毎にデータ取得 */
+ int array_cnt = 0;
+ for (array_cnt = 0; array_cnt < port_num; array_cnt++) {
+ tmp_tx_port = &functions->tx_ports[array_cnt];
+
+ /* 要素取得 */
+ json_t *elements_obj = json_array_get(array_obj, array_cnt);
+ if (unlikely(elements_obj == NULL)) {
+ RTE_LOG(ERR, APP,
+ "Element get failed. (No = %d, path = %s, route = classifier)\n",
+ array_cnt, JSONPATH_TX_PORT);
+ return -1;
+ }
+
+ /* String type check */
+ 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);
+ return -1;
+ }
+ strcpy(if_str, json_string_value(elements_obj));
+
+ /* IF種別とIF番号に分割 */
+ int ret_if = config_get_if_info(if_str, &tmp_tx_port->if_type,
+ &tmp_tx_port->if_no);
+ if (unlikely(ret_if != 0)) {
+ RTE_LOG(ERR, APP,
+ "Interface change failed. (No = %d, port = %s, route = classifier)\n",
+ array_cnt, if_str);
+ return -1;
+ }
+ }
}
}
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 07/57] spp_vf: fix compiler warning in classifier_mac.c
2017-12-26 1:54 ` Yasufumi Ogawa
` (5 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 06/57] spp_vf: change config format for upd command x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 08/57] spp_vf: modify data struct for upd command x-fn-spp
` (49 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Add const keyword to parameter.
* Remove unused variables.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/classifier_mac.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
index 6808062..0852938 100644
--- a/src/vf/classifier_mac.c
+++ b/src/vf/classifier_mac.c
@@ -94,7 +94,7 @@ static rte_atomic16_t g_hash_table_count = RTE_ATOMIC16_INIT(0xff);
/* initialize classifier table. */
static int
init_classifier_table(struct rte_hash **classifier_table,
- struct spp_core_info *core_info)
+ const struct spp_core_info *core_info)
{
int ret = -1;
int i;
@@ -142,9 +142,7 @@ init_classifier(const struct spp_core_info *core_info,
{
int ret = -1;
int i;
- struct ether_addr eth_addr;
char hash_table_name[HASH_TABLE_NAME_BUF_SZ];
- char mac_addr_str[ETHER_ADDR_STR_BUF_SZ];
struct rte_hash **classifier_mac_table = NULL;
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 08/57] spp_vf: modify data struct for upd command
2017-12-26 1:54 ` Yasufumi Ogawa
` (6 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 07/57] spp_vf: fix compiler warning in classifier_mac.c x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 09/57] spp_vf: add functions of command acceptance x-fn-spp
` (48 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
spp_vf supports command for modifying classifier table.
* Modify internal data structure to support this command.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_vf.c | 274 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
src/vf/spp_vf.h | 47 +++++++++-
2 files changed, 307 insertions(+), 14 deletions(-)
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 830aaaa..4fb25a4 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -1,3 +1,4 @@
+#include <netinet/in.h>
#include <arpa/inet.h>
#include <getopt.h>
@@ -21,19 +22,26 @@ enum SPP_LONGOPT_RETVAL {
/* add below */
SPP_LONGOPT_RETVAL_CONFIG,
+ SPP_LONGOPT_RETVAL_PROCESS_ID
};
/* struct */
struct startup_param {
uint64_t cpu;
+ int process_id;
+ char server_ip[INET_ADDRSTRLEN];
+ int server_port;
};
struct patch_info {
- int use_flg;
- int dpdk_port;
- struct spp_config_mac_table_element *mac_info;
- struct spp_core_port_info *rx_core;
- struct spp_core_port_info *tx_core;
+ int use_flg;
+ int dpdk_port;
+ 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;
};
struct if_info {
@@ -49,6 +57,7 @@ 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];
static char config_file_path[PATH_MAX];
@@ -58,9 +67,10 @@ static char config_file_path[PATH_MAX];
static void
usage(const char *progname)
{
- RTE_LOG(INFO, APP, "Usage: %s [EAL args] -- [--config CONFIG_FILE_PATH]\n"
- " --config CONFIG_FILE_PATH: specific config file path\n"
- "\n"
+ RTE_LOG(INFO, APP, "Usage: %s [EAL args] -- --process-id PROC_ID [--config CONFIG_FILE_PATH] -s SERVER_IP:SERVER_PORT\n"
+ " --process-id PROCESS_ID : My process ID\n"
+ " --config CONFIG_FILE_PATH : specific config file path\n"
+ " -s SERVER_IP:SERVER_PORT : Access information to the server\n"
, progname);
}
@@ -294,6 +304,47 @@ parse_dpdk_args(int argc, char *argv[])
}
/*
+ * Parses the process ID of the application argument.
+ */
+static int
+parse_app_process_id(const char *process_id_str, int *process_id)
+{
+ int id = 0;
+ char *endptr = NULL;
+
+ id = strtol(process_id_str, &endptr, 0);
+ if (unlikely(process_id_str == endptr) || unlikely(*endptr != '\0'))
+ return -1;
+
+ *process_id = id;
+ RTE_LOG(DEBUG, APP, "Set process id = %d\n", *process_id);
+ return 0;
+}
+
+/*
+ * Parses server information of application arguments.
+ */
+static int
+parse_app_server(const char *server_str, char *server_ip, int *server_port)
+{
+ const char delim[2] = ":";
+ int pos = 0;
+ int port = 0;
+ char *endptr = NULL;
+
+ pos = strcspn(server_str, delim);
+ port = strtol(&server_str[pos+1], &endptr, 0);
+ if (unlikely(&server_str[pos+1] == endptr) || unlikely(*endptr != '\0'))
+ return -1;
+
+ memcpy(server_ip, server_str, pos);
+ *server_port = port;
+ RTE_LOG(DEBUG, APP, "Set server ip = %s\n", server_ip);
+ RTE_LOG(DEBUG, APP, "Set server port = %d\n", *server_port);
+ return 0;
+}
+
+/*
* Parse the application arguments to the client app.
*/
static int
@@ -306,8 +357,9 @@ parse_app_args(int argc, char *argv[])
const char *progname = argv[0];
static struct option lgopts[] = {
{ "config", required_argument, NULL, SPP_LONGOPT_RETVAL_CONFIG },
+ { "process-id", required_argument, NULL, SPP_LONGOPT_RETVAL_PROCESS_ID },
{ 0 },
- };
+ };
/* getoptを使用するとargvが並び変わるみたいなので、コピーを実施 */
for (cnt = 0; cnt < argcopt; cnt++) {
@@ -317,7 +369,7 @@ parse_app_args(int argc, char *argv[])
/* Check application parameter */
optind = 0;
opterr = 0;
- while ((opt = getopt_long(argc, argvopt, "", lgopts,
+ while ((opt = getopt_long(argc, argvopt, "s:", lgopts,
&option_index)) != EOF) {
switch (opt) {
case SPP_LONGOPT_RETVAL_CONFIG:
@@ -327,11 +379,31 @@ parse_app_args(int argc, char *argv[])
}
strcpy(config_file_path, optarg);
break;
+ case SPP_LONGOPT_RETVAL_PROCESS_ID:
+ if (parse_app_process_id(optarg, &g_startup_param.process_id) != 0) {
+ usage(progname);
+ return -1;
+ }
+ break;
+ case 's':
+ if (parse_app_server(optarg, g_startup_param.server_ip,
+ &g_startup_param.server_port) != 0) {
+ usage(progname);
+ return -1;
+ }
+ break;
default:
+ usage(progname);
+ return -1;
break;
}
}
+ RTE_LOG(INFO, APP, "application arguments value. (process id = %d, config = %s, server = %s:%d)\n",
+ g_startup_param.process_id,
+ config_file_path,
+ g_startup_param.server_ip,
+ g_startup_param.server_port);
return 0;
}
@@ -364,7 +436,16 @@ get_if_area(enum port_type if_type, int if_no)
static void
init_if_info(void)
{
+ int port_cnt;
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;
+ }
}
/*
@@ -376,11 +457,13 @@ init_core_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;
}
}
+ memset(g_change_core, 0x00, sizeof(g_change_core));
}
/*
@@ -440,7 +523,8 @@ set_form_proc_info(struct spp_config_area *config)
}
/* IF情報からCORE情報を変更する場合用に設定 */
- patch_info->rx_core = &core_info->rx_ports[rx_start + rx_cnt];
+ patch_info->rx_core_no = core_cnt;
+ patch_info->rx_core = &core_info->rx_ports[rx_start + rx_cnt];
}
/* Set TX port */
@@ -464,7 +548,8 @@ set_form_proc_info(struct spp_config_area *config)
}
/* IF情報からCORE情報を変更する場合用に設定 */
- patch_info->tx_core = &core_info->tx_ports[tx_start + tx_cnt];
+ patch_info->tx_core_no = core_cnt;
+ patch_info->tx_core = &core_info->tx_ports[tx_start + tx_cnt];
}
}
@@ -508,7 +593,8 @@ set_from_classifier_table(struct spp_config_area *config)
/* CORE情報側にもMACアドレスの情報設定 */
/* MACアドレスは送信側のみに影響する為、送信側のみ設定 */
- patch_info->mac_info = mac_table;
+ 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);
@@ -864,6 +950,8 @@ ut_main(int argc, char *argv[])
#else
{
#endif
+ /* コマンド受付追加予定箇所 */
+ /* 戻り値等があれば、判定文も追加予定 */
sleep(1);
#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
@@ -896,3 +984,163 @@ ut_main(int argc, char *argv[])
RTE_LOG(INFO, APP, "spp_vf exit.\n");
return ret;
}
+
+/*
+ * Get process ID
+ */
+int
+spp_get_process_id(void)
+{
+ return g_startup_param.process_id;
+}
+
+/*
+ * Check the MAC address used on the interface
+ */
+static int
+check_mac_used_interface(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;
+ }
+ if (unlikely(g_if_info.ring_patchs[cnt].mac_addr == mac_addr)) {
+ *if_type = RING;
+ *if_no = cnt;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+/*
+ * Update Classifier_table
+ */
+int
+spp_update_classifier_table(
+ enum spp_classifier_type type,
+ const char *data,
+ struct spp_config_port_info *port)
+{
+ enum port_type if_type = UNDEF;
+ int if_no = 0;
+ struct patch_info *patch_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);
+ 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;
+ }
+
+ 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);
+ 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);
+ }
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+
+ 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);
+ return SPP_RET_NG;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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);
+ }
+ }
+ }
+
+ /* 更新コマンドで設定した場合、コア毎に変更有無を保持 */
+ g_change_core[patch_info->tx_core_no] = 1;
+ return SPP_RET_OK;
+}
+
+/*
+ * Flush SPP component
+ */
+int
+spp_flush(void)
+{
+ int core_cnt = 0;
+ int ret_classifier = 0;
+ struct spp_core_info *core_info = NULL;
+
+ for(core_cnt = 0; core_cnt < SPP_CONFIG_CORE_MAX; core_cnt++) {
+ if (g_change_core[core_cnt] == 0)
+ continue;
+
+ 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;
+ }
+ }
+ }
+
+ /* 更新完了により変更したコアをクリア */
+ memset(g_change_core, 0x00, sizeof(g_change_core));
+ return SPP_RET_OK;
+}
diff --git a/src/vf/spp_vf.h b/src/vf/spp_vf.h
index c0faa57..f9707d7 100644
--- a/src/vf/spp_vf.h
+++ b/src/vf/spp_vf.h
@@ -4,6 +4,8 @@
#include "common.h"
#include "spp_config.h"
+#define SPP_PROCESS_MAX 128
+
/*
* State on core
*/
@@ -15,10 +17,29 @@ enum spp_core_status {
};
/*
+ * Classifier Type
+ */
+enum spp_classifier_type {
+ SPP_CLASSIFIER_TYPE_NONE,
+ SPP_CLASSIFIER_TYPE_MAC
+};
+
+/*
+ * API Return value
+ */
+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 info on core
*/
struct spp_core_port_info {
- enum port_type if_type;
+ enum port_type if_type;
int if_no;
int dpdk_port;
uint64_t mac_addr;
@@ -29,6 +50,7 @@ struct spp_core_port_info {
* 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;
@@ -37,4 +59,27 @@ struct spp_core_info {
struct spp_core_port_info tx_ports[RTE_MAX_ETHPORTS];
};
+/*
+ * Get process ID
+ * RETURN : PROCESS ID(0~127)
+ */
+int spp_get_process_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, struct spp_config_port_info *port);
+
+/*
+ * Flush SPP component
+ * OK : SPP_RET_OK(0)
+ * NG : SPP_RET_NG(-1)
+ */
+int spp_flush(void);
+
#endif /* __SPP_VF_H__ */
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 09/57] spp_vf: add functions of command acceptance
2017-12-26 1:54 ` Yasufumi Ogawa
` (7 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 08/57] spp_vf: modify data struct for upd command x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 10/57] spp_vf: add command acceptance calling x-fn-spp
` (47 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
spp_vf supports command for modifying classifier table.
* Add functions of command acceptance.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/Makefile | 2 +-
src/vf/command_proc.c | 669 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/vf/command_proc.h | 25 ++
src/vf/spp_config.c | 20 +-
src/vf/spp_config.h | 15 ++
5 files changed, 720 insertions(+), 11 deletions(-)
create mode 100644 src/vf/command_proc.c
create mode 100644 src/vf/command_proc.h
diff --git a/src/vf/Makefile b/src/vf/Makefile
index 4961d2e..19617f6 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 ringlatencystats.c ../shared/common.c
+SRCS-y := spp_vf.c spp_config.c classifier_mac.c spp_forward.c command_proc.c ringlatencystats.c ../shared/common.c
CFLAGS += $(WERROR_FLAGS) -O3
CFLAGS += -I$(SRCDIR)/../shared
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
new file mode 100644
index 0000000..f8d368f
--- /dev/null
+++ b/src/vf/command_proc.c
@@ -0,0 +1,669 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_branch_prediction.h>
+
+#include <jansson.h>
+
+#include "spp_vf.h"
+#include "spp_config.h"
+
+
+#define RTE_LOGTYPE_SPP_COMMAND_PROC RTE_LOGTYPE_USER1
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+#define MESSAGE_BUFFER_BLOCK_SIZE 512
+
+static char g_controller_ip[128] = "";
+static int g_controller_port = 0;
+
+/* */
+inline char*
+msgbuf_allocate(size_t capacity)
+{
+ char* buf = (char *)malloc(capacity + sizeof(size_t));
+ if (unlikely(buf == NULL))
+ return NULL;
+
+ *((size_t *)buf) = capacity;
+
+ return buf + sizeof(size_t);
+}
+
+/* */
+inline void
+msgbuf_free(char* msgbuf)
+{
+ if (likely(msgbuf != NULL))
+ free(msgbuf - sizeof(size_t));
+}
+
+/* */
+inline size_t
+msgbuf_get_capacity(const char *msgbuf)
+{
+ return *((const size_t *)(msgbuf - sizeof(size_t)));
+}
+
+/* */
+inline char*
+msgbuf_reallocate(char *msgbuf, size_t required_len)
+{
+ size_t new_cap = msgbuf_get_capacity(msgbuf) * 2;
+ char *new_msgbuf = NULL;
+
+ while (unlikely(new_cap <= required_len))
+ new_cap *= 2;
+
+ new_msgbuf = msgbuf_allocate(new_cap);
+ if (unlikely(new_msgbuf == NULL))
+ return NULL;
+
+ strcpy(new_msgbuf, msgbuf);
+ msgbuf_free(msgbuf);
+
+ return new_msgbuf;
+}
+
+/* */
+inline char*
+msgbuf_append(char *msgbuf, const char *append, size_t append_len)
+{
+ size_t cap = msgbuf_get_capacity(msgbuf);
+ size_t len = strlen(msgbuf);
+ char *new_msgbuf = msgbuf;
+
+ if (unlikely(len + append_len >= cap)) {
+ new_msgbuf = msgbuf_reallocate(msgbuf, len + append_len);
+ if (unlikely(new_msgbuf == NULL))
+ return NULL;
+ }
+
+ memcpy(new_msgbuf + len, append, append_len);
+ *(new_msgbuf + len + append_len) = '\0';
+
+ return new_msgbuf;
+}
+
+/* */
+inline char*
+msgbuf_remove_front(char *msgbuf, size_t remove_len)
+{
+ size_t len = strlen(msgbuf);
+ size_t new_len = len - remove_len;
+
+ if (likely(new_len == 0)) {
+ *msgbuf = '\0';
+ return msgbuf;
+ }
+
+ return memmove(msgbuf, msgbuf + remove_len, new_len + 1);
+}
+
+/* */
+static int
+connect_to_controller(int *sock)
+{
+ static struct sockaddr_in controller_addr;
+ int ret = -1;
+ int sock_flg = 0;
+
+ if (likely(*sock >=0))
+ return 0;
+
+ if (*sock < 0) {
+ *sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (*sock < 0) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC,
+ "Cannot create tcp socket. errno=%d\n", errno);
+ return -1;
+ }
+
+ memset(&controller_addr, 0, sizeof(controller_addr));
+ controller_addr.sin_family = AF_INET;
+ controller_addr.sin_addr.s_addr = inet_addr(g_controller_ip);
+ controller_addr.sin_port = htons(g_controller_port);
+ }
+
+ ret = connect(*sock, (struct sockaddr *)&controller_addr,
+ sizeof(controller_addr));
+ if (ret < 0) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC,
+ "Cannot connect to controller. errno=%d\n", errno);
+ return -1;
+ }
+
+ sock_flg = fcntl(*sock, F_GETFL, 0);
+ fcntl(*sock, F_SETFL, sock_flg | O_NONBLOCK);
+
+ return 0;
+}
+
+/* */
+static int
+receive_request(int *sock, char **msgbuf)
+{
+ int ret = -1;
+ int n_rx = 0;
+ char *new_msgbuf = NULL;
+
+ char rx_buf[MESSAGE_BUFFER_BLOCK_SIZE];
+ size_t rx_buf_sz = MESSAGE_BUFFER_BLOCK_SIZE;
+
+ ret = recv(*sock, rx_buf, rx_buf_sz, 0);
+ if (ret <= 0) {
+ if (ret == 0) {
+
+ } else {
+ if (errno != EAGAIN && errno != EWOULDBLOCK) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC,
+ "Cannot receive from socket. errno=%d\n", errno);
+ }
+ return 0;
+ }
+ }
+
+ n_rx = ret;
+
+ new_msgbuf = msgbuf_append(*msgbuf, rx_buf, n_rx);
+ if (unlikely(new_msgbuf == NULL)) {
+ return -1;
+ }
+
+ *msgbuf = new_msgbuf;
+
+ return n_rx;
+}
+
+/* */
+static int
+send_response(void)
+{
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+#define CMD_MAX_COMMANDS 32
+
+#define CMD_NAME_BUFSZ 32
+
+#define CMD_CLASSIFIER_TABLE_VALUE_BUFSZ 62
+
+#define component_type spp_core_type
+
+/* command type */
+enum command_type {
+ CMDTYPE_ADD,
+ CMDTYPE_COMPONENT,
+ CMDTYPE_CLASSIFIER_TABLE,
+ CMDTYPE_FLUSH,
+ CMDTYPE_FORWARD,
+ CMDTYPE_STOP,
+
+ CMDTYPE_PROCESS,
+};
+
+/* command type string list */
+static const char *COMMAND_TYPE_STRINGS[] = {
+ "add",
+ "component",
+ "classifier_table",
+ "flush",
+ "forward",
+ "stop",
+
+ /* termination */ "",
+};
+
+/* classifier type */
+enum classifier_type {
+ CLASSIFIERTYPE_MAC,
+};
+
+/* classifier type string list */
+static const char *CLASSIFILER_TYPE_STRINGS[] = {
+ "mac",
+
+ /* termination */ "",
+};
+
+/* "add" command parameters */
+struct add_command {
+ struct spp_config_port_info ports[RTE_MAX_ETHPORTS];
+};
+
+/* "component" command specific parameters */
+struct component_command {
+ enum component_type type;
+ unsigned int core_id;
+ struct spp_config_port_info rx_ports[RTE_MAX_ETHPORTS];
+ struct spp_config_port_info tx_ports[RTE_MAX_ETHPORTS];
+};
+
+/* "classifier_table" command specific parameters */
+struct classifier_table_command {
+ enum classifier_type type;
+ char value[CMD_CLASSIFIER_TABLE_VALUE_BUFSZ];
+ struct spp_config_port_info port;
+};
+
+#if 0
+/* "flush" command specific parameters */
+struct flush_command {
+ /* nothing specific */
+};
+#endif
+
+/* command parameters */
+struct command {
+ enum command_type type;
+
+ union {
+ struct add_command add;
+ struct component_command component;
+ struct classifier_table_command classifier_table;
+ } spec;
+};
+
+/* request parameters */
+struct request {
+ int num_command;
+ struct command commands[CMD_MAX_COMMANDS];
+};
+
+/* forward declaration */
+struct json_value_decode_rule;
+
+/* definition of decode procedure function */
+typedef int (*json_value_decode_proc)(void *, const json_t *, const struct json_value_decode_rule *);
+
+/* rule definition that decode json object to c-struct */
+struct json_value_decode_rule {
+ char name[CMD_NAME_BUFSZ];
+ json_type json_type;
+ size_t offset;
+ json_value_decode_proc decode_proc;
+#if 0
+ union {
+ size_t buf_sz;
+ } spec;
+
+ json_type sub_json_type;
+ const struct json_value_decode_rule *sub_rules;
+#endif
+ size_t sub_offset;
+ size_t sub_offset_num;
+};
+
+/* get output address for decoded json value */
+#define DR_GET_OUTPUT(output_base, rule__) ((char *)output_base + rule__->offset)
+
+/* helper */
+#define END_OF_DECODE_RULE {.name = ""},
+#define IS_END_OF_DECODE_RULE(rule) ((rule)->name[0] == '\0')
+
+/* definition helper that enum value decode procedure */
+#define DECODE_ENUM_VALUE(proc_name, enum_type, string_table) \
+int \
+decode_##proc_name##_value(void *output, const json_t *value_obj, \
+ const struct json_value_decode_rule *rule) \
+{ \
+ int i; \
+ enum_type type; \
+ const char *str_val = json_string_value(value_obj); \
+ \
+ for (i = 0; string_table[i][0] != '\0'; ++i) { \
+ if (unlikely(strcmp(str_val, string_table[i]) == 0)) { \
+ type = i; \
+ memcpy(output, &type, sizeof(enum_type)); \
+ return 0; \
+ } \
+ } \
+ \
+ return -1; \
+} \
+
+/* enum value decode procedure for "command_type" */
+DECODE_ENUM_VALUE(command_type, enum command_type, COMMAND_TYPE_STRINGS)
+
+/* enum value decode procedure for "classifier_type" */
+DECODE_ENUM_VALUE(classifier_type, enum classifier_type, CLASSIFILER_TYPE_STRINGS)
+
+/* decode procedure for integer */
+static int
+decode_int_value(void *output, const json_t *value_obj,
+ const struct json_value_decode_rule *rule)
+{
+ int val = json_integer_value(value_obj);
+ memcpy(output, &val, sizeof(int));
+
+ return 0;
+}
+
+/* decode procedure for string */
+static int
+decode_string_value(void *output, const json_t *value_obj,
+ const struct json_value_decode_rule *rule)
+{
+ const char* str_val = json_string_value(value_obj);
+#if 0
+ size_t len = strlen(str_val);
+ if (unlikely(len >= rule->spec.buf_sz)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Invalid json value. "
+ "name=%s\n", rule->name);
+ return -1;
+ }
+#endif
+ strcpy(output, str_val);
+
+ return 0;
+}
+
+/* decode procedure for spp_config_port_info */
+static int
+decode_port_value(void *output, const json_t *value_obj,
+ const struct json_value_decode_rule *rule)
+{
+ int ret = -1;
+ struct spp_config_port_info *port = (struct spp_config_port_info *)output;
+
+ const char* str_val = json_string_value(value_obj);
+
+ ret = spp_config_get_if_info(str_val, &port->if_type, &port->if_no);
+ if (unlikely(ret != 0))
+ return -1;
+
+ return 0;
+}
+
+/* decode json object */
+static int
+decode_json_object(void *output, const json_t *parent_obj,
+ const struct json_value_decode_rule *rules)
+{
+ int ret = -1;
+ int i, n;
+ json_t *obj;
+ json_t *value_obj;
+ const struct json_value_decode_rule *rule;
+
+ void *sub_output;
+
+ for (i = 0; unlikely(! IS_END_OF_DECODE_RULE(&rules[i])); ++ i) {
+ rule = rules + 1;
+
+ value_obj = json_object_get(parent_obj, rule->name);
+ if (unlikely(value_obj == NULL) ||
+ unlikely(json_typeof(value_obj) != rule->json_type)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Invalid json value. "
+ "name=%s\n", rule->name);
+ return -1;
+ }
+
+ switch (rule->json_type) {
+ case JSON_ARRAY:
+ json_array_foreach(value_obj, n, obj) {
+ sub_output = DR_GET_OUTPUT(output, rule) + (rule->sub_offset * i);
+ ret = (*rule->decode_proc)(sub_output, obj, rule);
+ }
+ *(int *)((char *)output + rule->sub_offset_num) = n;
+ break;
+ default:
+ sub_output = DR_GET_OUTPUT(output, rule);
+ ret = (*rule->decode_proc)(sub_output, value_obj, rule);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* */
+const struct json_value_decode_rule DECODERULE_COMMAND_BASE[] = {
+ {
+ .name = "command",
+ .json_type = JSON_STRING,
+ .offset = offsetof(struct command, type),
+ .decode_proc = decode_command_type_value,
+ },
+ END_OF_DECODE_RULE
+};
+
+/* */
+const struct json_value_decode_rule DECODERULE_ADD_COMMAND[] = {
+ {
+ .name = "ports",
+ .json_type = JSON_ARRAY,
+ .offset = offsetof(struct add_command, ports),
+ .decode_proc = decode_port_value,
+// .sub_json_type = JSON_STRING,
+ .sub_offset = sizeof(struct spp_config_port_info),
+ },
+ END_OF_DECODE_RULE
+};
+
+/* */
+const struct json_value_decode_rule DECODERULE_CLASSIFIER_TABLE_COMMAND[] = {
+ {
+ .name = "type",
+ .json_type = JSON_STRING,
+ .offset = offsetof(struct classifier_table_command, type),
+ .decode_proc = decode_classifier_type_value,
+ },{
+ .name = "value",
+ .json_type = JSON_STRING,
+ .offset = offsetof(struct classifier_table_command, value),
+ .decode_proc = decode_string_value,
+ },{
+ .name = "port",
+ .json_type = JSON_STRING,
+ .offset = offsetof(struct classifier_table_command, port),
+ .decode_proc = decode_port_value,
+ },
+ END_OF_DECODE_RULE
+};
+
+/* */
+static int
+decode_command_object(void* output, const json_t *parent_obj,
+ const struct json_value_decode_rule *rule)
+{
+ int ret = -1;
+ struct command *command = (struct command *)output;
+ const struct json_value_decode_rule *spec_rules = NULL;
+
+ /* decode command base */
+ ret = decode_json_object(command, parent_obj, DECODERULE_COMMAND_BASE);
+ if (unlikely(ret != 0)) {
+ // TODO:コマンドがデコード失敗
+ return -1;
+ }
+
+ /* decode command specific */
+ switch (command->type) {
+ case CMDTYPE_CLASSIFIER_TABLE:
+ spec_rules = DECODERULE_CLASSIFIER_TABLE_COMMAND;
+ break;
+
+ case CMDTYPE_FLUSH:
+ break;
+
+ default:
+ break;
+ }
+
+ if (likely(spec_rules != NULL)) {
+ ret = decode_json_object(&command->spec, parent_obj, spec_rules);
+ if (unlikely(ret != 0)) {
+ // TODO:コマンドがデコード失敗
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* */
+const struct json_value_decode_rule DECODERULE_REQUEST[] = {
+ {
+ .name = "commands",
+ .json_type = JSON_ARRAY,
+ .offset = offsetof(struct request, commands),
+ .decode_proc = decode_command_object,
+// .sub_json_type = JSON_OBJECT,
+ .sub_offset = sizeof(struct command),
+ .sub_offset_num = offsetof(struct request, num_command),
+ },
+ END_OF_DECODE_RULE
+};
+
+/* */
+static int
+decode_request(struct request *request, json_t **top_obj, const char *request_str, size_t request_str_len)
+{
+ int ret = -1;
+ int i;
+ json_error_t json_error;
+
+ /* parse json string */
+ *top_obj = json_loadb(request_str, request_str_len, 0, &json_error);
+ if (unlikely(*top_obj == NULL)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot parse command request. "
+ "error=%s\n",
+ json_error.text);
+ return -1;
+ }
+
+ /* decode request object */
+ ret = decode_json_object(request, *top_obj, DECODERULE_REQUEST);
+ if (unlikely(ret != 0)) {
+ // TODO:エラー
+ return -1;
+ }
+
+ return 0;
+}
+
+/* */
+static int
+execute_command(const struct command *command)
+{
+ int ret = -1;
+
+ switch (command->type) {
+ case CMDTYPE_CLASSIFIER_TABLE:
+ ret = spp_update_classifier_table(
+ SPP_CLASSIFIER_TYPE_MAC,
+// command->spec.classifier_table.type,
+ command->spec.classifier_table.value,
+ &command->spec.classifier_table.port);
+ break;
+
+ case CMDTYPE_FLUSH:
+ ret = spp_flush();
+ break;
+
+ case CMDTYPE_PROCESS:
+ break;
+
+ default:
+ ret = 0;
+ break;
+ }
+
+ return 0;
+}
+
+/* */
+static int
+process_request(const char *request_str, size_t request_str_len)
+{
+ int ret = -1;
+ int i;
+
+ struct request request;
+ json_t *top_obj;
+
+ memset(&request, 0, sizeof(struct request));
+
+ ret = decode_request(&request, &top_obj, request_str, request_str_len);
+ if (unlikely(ret != 0))
+ return -1;
+
+ for (i = 0; i < request.num_command ; ++i) {
+ ret = execute_command(request.commands + i);
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+/* */
+int
+spp_command_proc_init(const char *controller_ip, int controller_port)
+{
+ strcpy(g_controller_ip, controller_ip);
+ g_controller_port = controller_port;
+
+ return 0;
+}
+
+/* */
+void
+spp_command_proc_do(void)
+{
+ int ret = -1;
+ int i;
+
+ static int sock = -1;
+ static char *msgbuf = NULL;
+ static size_t msg_len = 0;
+
+ static size_t rb_cnt = 0;
+ static size_t lb_cnt = 0;
+
+ if (unlikely(msgbuf == NULL))
+ msgbuf = msgbuf_allocate(MESSAGE_BUFFER_BLOCK_SIZE);
+
+ ret = connect_to_controller(&sock);
+ if (unlikely(ret != 0))
+ return;
+
+ ret = receive_request(&sock, &msgbuf);
+ if (likely(ret == 0)) {
+ return;
+ }
+
+ for (i = 0; i < ret; ++i) {
+ switch (*(msgbuf + msg_len + i)) {
+ case '{':
+ ++lb_cnt;
+ break;
+ case '}':
+ ++rb_cnt;
+ break;
+ }
+
+ if (likely(lb_cnt != 0) && unlikely(rb_cnt == lb_cnt)) {
+ msg_len += (i + 1);
+ ret = process_request(msgbuf, msg_len);
+
+ msgbuf_remove_front(msgbuf, msg_len);
+ msg_len = 0;
+ rb_cnt = 0;
+ lb_cnt = 0;
+ }
+ }
+}
diff --git a/src/vf/command_proc.h b/src/vf/command_proc.h
new file mode 100644
index 0000000..8774070
--- /dev/null
+++ b/src/vf/command_proc.h
@@ -0,0 +1,25 @@
+#ifndef _COMMAND_PROC_H_
+#define _COMMAND_PROC_H_
+
+/**
+ * intialize command processor.
+ *
+ * @param controller_ip
+ * controller listen ip address.
+ *
+ * @param controller_port
+ * controller listen port number.
+ *
+ * @ret_val 0 succeeded.
+ * @ret_val -1 failed.
+ */
+int
+spp_command_proc_init(const char *controller_ip, int controller_port);
+
+/**
+ * process command from controller.
+ */
+void
+spp_command_proc_do(void);
+
+#endif /* _COMMAND_PROC_H_ */
diff --git a/src/vf/spp_config.c b/src/vf/spp_config.c
index 1794e84..4ad4f87 100644
--- a/src/vf/spp_config.c
+++ b/src/vf/spp_config.c
@@ -104,8 +104,8 @@ config_init_data(struct spp_config_area *config)
* IFの情報からIF種別とIF番号を取得する
* ("ring0" -> 種別:"ring"、番号:0)
*/
-static int
-config_get_if_info(const char *port, enum port_type *if_type, int *if_no)
+int
+spp_config_get_if_info(const char *port, enum port_type *if_type, int *if_no)
{
enum port_type type = UNDEF;
const char *no_str = NULL;
@@ -150,8 +150,8 @@ config_get_if_info(const char *port, enum port_type *if_type, int *if_no)
/*
* MAC addressを文字列から数値へ変換
*/
-static int64_t
-config_change_mac_str_to_int64(const char *mac)
+int64_t
+spp_config_change_mac_str_to_int64(const char *mac)
{
int64_t ret_mac = 0;
int64_t token_val = 0;
@@ -270,7 +270,7 @@ config_load_classifier_table(const json_t *obj,
}
/* MACアドレス数値変換 */
- int64_t ret_mac64 = config_change_mac_str_to_int64(
+ int64_t ret_mac64 = spp_config_change_mac_str_to_int64(
tmp_table->mac_addr_str);
if (unlikely(ret_mac64 == -1)) {
RTE_LOG(ERR, APP,
@@ -291,7 +291,7 @@ config_load_classifier_table(const json_t *obj,
}
/* IF種別とIF番号に分割 */
- int ret_if = config_get_if_info(if_str, &tmp_table->port.if_type,
+ 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)) {
RTE_LOG(ERR, APP,
@@ -385,7 +385,7 @@ config_set_rx_port(enum spp_core_type type, json_t *obj,
strcpy(if_str, json_string_value(elements_obj));
/* IF種別とIF番号に分割 */
- int ret_if = config_get_if_info(if_str, &tmp_rx_port->if_type,
+ int ret_if = spp_config_get_if_info(if_str, &tmp_rx_port->if_type,
&tmp_rx_port->if_no);
if (unlikely(ret_if != 0)) {
RTE_LOG(ERR, APP,
@@ -407,7 +407,7 @@ config_set_rx_port(enum spp_core_type type, json_t *obj,
}
/* IF種別とIF番号に分割 */
- int ret_if = config_get_if_info(if_str, &tmp_rx_port->if_type,
+ int ret_if = spp_config_get_if_info(if_str, &tmp_rx_port->if_type,
&tmp_rx_port->if_no);
if (unlikely(ret_if != 0)) {
RTE_LOG(ERR, APP,
@@ -444,7 +444,7 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
}
/* IF種別とIF番号に分割 */
- int ret_if = config_get_if_info(if_str, &tmp_tx_port->if_type,
+ 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)) {
RTE_LOG(ERR, APP,
@@ -520,7 +520,7 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
strcpy(if_str, json_string_value(elements_obj));
/* IF種別とIF番号に分割 */
- int ret_if = config_get_if_info(if_str, &tmp_tx_port->if_type,
+ 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)) {
RTE_LOG(ERR, APP,
diff --git a/src/vf/spp_config.h b/src/vf/spp_config.h
index 24ddd32..37414cf 100644
--- a/src/vf/spp_config.h
+++ b/src/vf/spp_config.h
@@ -81,6 +81,21 @@ struct spp_config_area {
};
/*
+ * Change mac address string to int64
+ * OK : int64 that store mac address
+ * NG : -1
+ */
+int64_t spp_config_change_mac_str_to_int64(const char *mac);
+
+/*
+ * Extract if-type/if-number from port string
+ *
+ * OK : 0
+ * NG : -1
+ */
+int spp_config_get_if_info(const char *port, enum port_type *if_type, int *if_no);
+
+/*
* Load config file
* OK : 0
* NG : -1
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 10/57] spp_vf: add command acceptance calling
2017-12-26 1:54 ` Yasufumi Ogawa
` (8 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 09/57] spp_vf: add functions of command acceptance x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 11/57] spp_vf: fix compiler warning in command_proc.c x-fn-spp
` (46 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
spp_vf supports command for modifying classifier table.
* Add functions for command acceptance.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_vf.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 4fb25a4..805c582 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -10,6 +10,7 @@
#include "ringlatencystats.h"
#include "classifier_mac.h"
#include "spp_forward.h"
+#include "command_proc.h"
/* define */
#define SPP_CORE_STATUS_CHECK_MAX 5
@@ -910,6 +911,14 @@ ut_main(int argc, char *argv[])
}
/* 他機能部初期化 */
+ /* コマンド機能部初期化 */
+ int ret_command_init = spp_command_proc_init(
+ g_startup_param.server_ip,
+ g_startup_param.server_port);
+ if (unlikely(ret_command_init != 0)) {
+ break;
+ }
+
#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
int ret_ringlatency = spp_ringlatencystats_init(
SPP_RING_LATENCY_STATS_SAMPLING_INTERVAL, g_if_info.num_ring);
@@ -950,8 +959,10 @@ ut_main(int argc, char *argv[])
#else
{
#endif
- /* コマンド受付追加予定箇所 */
- /* 戻り値等があれば、判定文も追加予定 */
+ /* コマンド受付 */
+ spp_command_proc_do();
+
+ /* CPUを占有しない様に1秒スリープ */
sleep(1);
#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
@@ -1132,7 +1143,7 @@ spp_flush(void)
core_info = &g_core_info[core_cnt];
if (core_info->type == SPP_CONFIG_CLASSIFIER_MAC) {
-// ret_classifier = spp_classifier_mac_update(core_info);
+ 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;
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 11/57] spp_vf: fix compiler warning in command_proc.c
2017-12-26 1:54 ` Yasufumi Ogawa
` (9 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 10/57] spp_vf: add command acceptance calling x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 12/57] " x-fn-spp
` (45 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Add include header.
* Add variable declaration.
* Mark unused parameter.
* Add comment and log.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_proc.c | 42 ++++++++++++++++++++++--------------------
1 file changed, 22 insertions(+), 20 deletions(-)
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index f8d368f..7a5ed56 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -14,6 +14,7 @@
#include "spp_vf.h"
#include "spp_config.h"
+#include "command_proc.h"
#define RTE_LOGTYPE_SPP_COMMAND_PROC RTE_LOGTYPE_USER1
@@ -279,6 +280,7 @@ struct command {
/* request parameters */
struct request {
int num_command;
+ int num_valid_command;
struct command commands[CMD_MAX_COMMANDS];
};
@@ -315,9 +317,9 @@ struct json_value_decode_rule {
/* definition helper that enum value decode procedure */
#define DECODE_ENUM_VALUE(proc_name, enum_type, string_table) \
-int \
+static int \
decode_##proc_name##_value(void *output, const json_t *value_obj, \
- const struct json_value_decode_rule *rule) \
+ __rte_unused const struct json_value_decode_rule *rule) \
{ \
int i; \
enum_type type; \
@@ -343,7 +345,7 @@ DECODE_ENUM_VALUE(classifier_type, enum classifier_type, CLASSIFILER_TYPE_STRING
/* decode procedure for integer */
static int
decode_int_value(void *output, const json_t *value_obj,
- const struct json_value_decode_rule *rule)
+ __rte_unused const struct json_value_decode_rule *rule)
{
int val = json_integer_value(value_obj);
memcpy(output, &val, sizeof(int));
@@ -354,7 +356,7 @@ decode_int_value(void *output, const json_t *value_obj,
/* decode procedure for string */
static int
decode_string_value(void *output, const json_t *value_obj,
- const struct json_value_decode_rule *rule)
+ __rte_unused const struct json_value_decode_rule *rule)
{
const char* str_val = json_string_value(value_obj);
#if 0
@@ -373,7 +375,7 @@ decode_string_value(void *output, const json_t *value_obj,
/* decode procedure for spp_config_port_info */
static int
decode_port_value(void *output, const json_t *value_obj,
- const struct json_value_decode_rule *rule)
+ __rte_unused const struct json_value_decode_rule *rule)
{
int ret = -1;
struct spp_config_port_info *port = (struct spp_config_port_info *)output;
@@ -477,7 +479,7 @@ const struct json_value_decode_rule DECODERULE_CLASSIFIER_TABLE_COMMAND[] = {
/* */
static int
decode_command_object(void* output, const json_t *parent_obj,
- const struct json_value_decode_rule *rule)
+ __rte_unused const struct json_value_decode_rule *rule)
{
int ret = -1;
struct command *command = (struct command *)output;
@@ -530,23 +532,23 @@ const struct json_value_decode_rule DECODERULE_REQUEST[] = {
/* */
static int
-decode_request(struct request *request, json_t **top_obj, const char *request_str, size_t request_str_len)
+decode_request(struct request *request, const char *request_str, size_t request_str_len)
{
int ret = -1;
- int i;
+ json_t *top_obj;
json_error_t json_error;
/* parse json string */
- *top_obj = json_loadb(request_str, request_str_len, 0, &json_error);
+ top_obj = json_loadb(request_str, request_str_len, 0, &json_error);
if (unlikely(*top_obj == NULL)) {
RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot parse command request. "
- "error=%s\n",
- json_error.text);
+ "error=%s, request_str=%.*s\n",
+ json_error.text, request_str_len, request_str);
return -1;
}
/* decode request object */
- ret = decode_json_object(request, *top_obj, DECODERULE_REQUEST);
+ ret = decode_json_object(request, top_obj, DECODERULE_REQUEST);
if (unlikely(ret != 0)) {
// TODO:エラー
return -1;
@@ -593,24 +595,24 @@ process_request(const char *request_str, size_t request_str_len)
int i;
struct request request;
- json_t *top_obj;
+
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Receive command request. "
+ "request_str=%.*s\n", request_str_len, request_str);
memset(&request, 0, sizeof(struct request));
- ret = decode_request(&request, &top_obj, request_str, request_str_len);
+ ret = decode_request(&request, request_str, request_str_len);
if (unlikely(ret != 0))
return -1;
for (i = 0; i < request.num_command ; ++i) {
ret = execute_command(request.commands + i);
}
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
+ return 0;
+}
-/* */
+/* initialize command processor. */
int
spp_command_proc_init(const char *controller_ip, int controller_port)
{
@@ -620,7 +622,7 @@ spp_command_proc_init(const char *controller_ip, int controller_port)
return 0;
}
-/* */
+/* process command from controller. */
void
spp_command_proc_do(void)
{
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 12/57] spp_vf: fix compiler warning in command_proc.c
2017-12-26 1:54 ` Yasufumi Ogawa
` (10 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 11/57] spp_vf: fix compiler warning in command_proc.c x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 13/57] spp_vf: refactor command acceptance/decode x-fn-spp
` (44 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Fix type unmatch.
* Refactor log.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_proc.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index 7a5ed56..d203857 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -540,17 +540,19 @@ decode_request(struct request *request, const char *request_str, size_t request_
/* parse json string */
top_obj = json_loadb(request_str, request_str_len, 0, &json_error);
- if (unlikely(*top_obj == NULL)) {
+ if (unlikely(top_obj == NULL)) {
RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot parse command request. "
"error=%s, request_str=%.*s\n",
- json_error.text, request_str_len, request_str);
+ json_error.text, (int)request_str_len, request_str);
return -1;
}
/* decode request object */
ret = decode_json_object(request, top_obj, DECODERULE_REQUEST);
if (unlikely(ret != 0)) {
- // TODO:エラー
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot decode command request. "
+ "ret=%d, request_str=%.*s\n",
+ ret, (int)request_str_len, request_str);
return -1;
}
@@ -597,7 +599,7 @@ process_request(const char *request_str, size_t request_str_len)
struct request request;
RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Receive command request. "
- "request_str=%.*s\n", request_str_len, request_str);
+ "request_str=%.*s\n", (int)request_str_len, request_str);
memset(&request, 0, sizeof(struct request));
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 13/57] spp_vf: refactor command acceptance/decode
2017-12-26 1:54 ` Yasufumi Ogawa
` (11 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 12/57] " x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 14/57] spp_vf: fix return value overwrite problem x-fn-spp
` (43 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Add/Refactor comment and log.
* Add error handling.
* Add strict check(MAC address, iface string).
* Refactor json->internal-structure converting.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_proc.c | 300 +++++++++++++++++++++++++++++++++++---------------
1 file changed, 210 insertions(+), 90 deletions(-)
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index d203857..d8e7fd1 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -16,19 +16,25 @@
#include "spp_config.h"
#include "command_proc.h"
-
#define RTE_LOGTYPE_SPP_COMMAND_PROC RTE_LOGTYPE_USER1
-////////////////////////////////////////////////////////////////////////////////
-
+/*******************************************************************************
+ *
+ * operate connection with controller
+ *
+ ******************************************************************************/
+/* receive message buffer size */
#define MESSAGE_BUFFER_BLOCK_SIZE 512
+/* controller's ip address */
static char g_controller_ip[128] = "";
+
+/* controller's port number */
static int g_controller_port = 0;
-/* */
+/* allocate message buffer */
inline char*
msgbuf_allocate(size_t capacity)
{
@@ -41,7 +47,7 @@ msgbuf_allocate(size_t capacity)
return buf + sizeof(size_t);
}
-/* */
+/* free message buffer */
inline void
msgbuf_free(char* msgbuf)
{
@@ -49,14 +55,14 @@ msgbuf_free(char* msgbuf)
free(msgbuf - sizeof(size_t));
}
-/* */
+/* get message buffer capacity */
inline size_t
msgbuf_get_capacity(const char *msgbuf)
{
return *((const size_t *)(msgbuf - sizeof(size_t)));
}
-/* */
+/* re-allocate message buffer */
inline char*
msgbuf_reallocate(char *msgbuf, size_t required_len)
{
@@ -76,7 +82,7 @@ msgbuf_reallocate(char *msgbuf, size_t required_len)
return new_msgbuf;
}
-/* */
+/* append message to buffer */
inline char*
msgbuf_append(char *msgbuf, const char *append, size_t append_len)
{
@@ -96,7 +102,7 @@ msgbuf_append(char *msgbuf, const char *append, size_t append_len)
return new_msgbuf;
}
-/* */
+/* remove message from front */
inline char*
msgbuf_remove_front(char *msgbuf, size_t remove_len)
{
@@ -111,7 +117,7 @@ msgbuf_remove_front(char *msgbuf, size_t remove_len)
return memmove(msgbuf, msgbuf + remove_len, new_len + 1);
}
-/* */
+/* connect to controller */
static int
connect_to_controller(int *sock)
{
@@ -122,7 +128,9 @@ connect_to_controller(int *sock)
if (likely(*sock >=0))
return 0;
+ /* create socket */
if (*sock < 0) {
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Creating socket...\n");
*sock = socket(AF_INET, SOCK_STREAM, 0);
if (*sock < 0) {
RTE_LOG(ERR, SPP_COMMAND_PROC,
@@ -136,6 +144,8 @@ connect_to_controller(int *sock)
controller_addr.sin_port = htons(g_controller_port);
}
+ /* connect to */
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Trying to connect ... socket=%d\n", *sock);
ret = connect(*sock, (struct sockaddr *)&controller_addr,
sizeof(controller_addr));
if (ret < 0) {
@@ -144,15 +154,18 @@ connect_to_controller(int *sock)
return -1;
}
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Connected\n");
+
+ /* set non-blocking */
sock_flg = fcntl(*sock, F_GETFL, 0);
fcntl(*sock, F_SETFL, sock_flg | O_NONBLOCK);
return 0;
}
-/* */
+/* receive message */
static int
-receive_request(int *sock, char **msgbuf)
+receive_message(int *sock, char **msgbuf)
{
int ret = -1;
int n_rx = 0;
@@ -162,16 +175,23 @@ receive_request(int *sock, char **msgbuf)
size_t rx_buf_sz = MESSAGE_BUFFER_BLOCK_SIZE;
ret = recv(*sock, rx_buf, rx_buf_sz, 0);
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Receive message. count=%d\n", ret);
if (ret <= 0) {
if (ret == 0) {
-
- } else {
- if (errno != EAGAIN && errno != EWOULDBLOCK) {
- RTE_LOG(ERR, SPP_COMMAND_PROC,
- "Cannot receive from socket. errno=%d\n", errno);
- }
+ RTE_LOG(INFO, SPP_COMMAND_PROC,
+ "Controller has performed an shutdown.");
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ /* no receive message */
return 0;
+ } else {
+ RTE_LOG(ERR, SPP_COMMAND_PROC,
+ "Receive failure. errno=%d\n", errno);
}
+
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Assume Server closed connection\n");
+ close(*sock);
+ *sock = -1;
+ return -1;
}
n_rx = ret;
@@ -186,14 +206,27 @@ receive_request(int *sock, char **msgbuf)
return n_rx;
}
-/* */
+/* send message */
static int
-send_response(void)
+send_message(int *sock, const char* message, size_t message_len)
{
+ int ret = -1;
+
+ ret = send(*sock, message, message_len, 0);
+ if (unlikely(ret == -1)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Send failure. ret=%d\n", ret);
+ return -1;
+ }
+
return 0;
}
-////////////////////////////////////////////////////////////////////////////////
+
+/*******************************************************************************
+ *
+ * process command request(json string)
+ *
+ ******************************************************************************/
#define CMD_MAX_COMMANDS 32
@@ -201,9 +234,21 @@ send_response(void)
#define CMD_CLASSIFIER_TABLE_VALUE_BUFSZ 62
+#define CMD_UNUSE "unuse"
+
#define component_type spp_core_type
-/* command type */
+/* decode error code */
+enum decode_error_code {
+ DERR_BAD_FORMAT = 1,
+ DERR_UNKNOWN_COMMAND,
+ DERR_NO_PARAM,
+ DERR_BAD_TYPE,
+ DERR_BAD_VALUE,
+};
+
+/* command type
+ do it same as the order of COMMAND_TYPE_STRINGS */
enum command_type {
CMDTYPE_ADD,
CMDTYPE_COMPONENT,
@@ -215,7 +260,8 @@ enum command_type {
CMDTYPE_PROCESS,
};
-/* command type string list */
+/* command type string list
+ do it same as the order of enum command_type */
static const char *COMMAND_TYPE_STRINGS[] = {
"add",
"component",
@@ -227,20 +273,19 @@ static const char *COMMAND_TYPE_STRINGS[] = {
/* termination */ "",
};
-/* classifier type */
-enum classifier_type {
- CLASSIFIERTYPE_MAC,
-};
-
-/* classifier type string list */
+/* classifier type string list
+ do it same as the order of enum spp_classifier_type (spp_vf.h) */
static const char *CLASSIFILER_TYPE_STRINGS[] = {
+ "none",
"mac",
/* termination */ "",
};
+#if 0 /* not supported */
/* "add" command parameters */
struct add_command {
+ int num_port;
struct spp_config_port_info ports[RTE_MAX_ETHPORTS];
};
@@ -248,32 +293,36 @@ struct add_command {
struct component_command {
enum 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 classifier_table_command {
- enum classifier_type type;
+ enum spp_classifier_type type;
char value[CMD_CLASSIFIER_TABLE_VALUE_BUFSZ];
struct spp_config_port_info port;
};
-#if 0
/* "flush" command specific parameters */
struct flush_command {
/* nothing specific */
};
-#endif
/* command parameters */
struct command {
enum command_type type;
union {
+#if 0 /* not supported */
struct add_command add;
struct component_command component;
+#endif
struct classifier_table_command classifier_table;
+ struct flush_command flush;
} spec;
};
@@ -296,16 +345,13 @@ struct json_value_decode_rule {
json_type json_type;
size_t offset;
json_value_decode_proc decode_proc;
-#if 0
- union {
- size_t buf_sz;
- } spec;
- json_type sub_json_type;
- const struct json_value_decode_rule *sub_rules;
-#endif
- size_t sub_offset;
- size_t sub_offset_num;
+ struct {
+ json_type json_type;
+ size_t element_sz;
+ size_t offset_num;
+ size_t offset_num_valid;
+ } array;
};
/* get output address for decoded json value */
@@ -340,8 +386,9 @@ decode_##proc_name##_value(void *output, const json_t *value_obj, \
DECODE_ENUM_VALUE(command_type, enum command_type, COMMAND_TYPE_STRINGS)
/* enum value decode procedure for "classifier_type" */
-DECODE_ENUM_VALUE(classifier_type, enum classifier_type, CLASSIFILER_TYPE_STRINGS)
+DECODE_ENUM_VALUE(classifier_type, enum spp_classifier_type, CLASSIFILER_TYPE_STRINGS)
+#if 0 /* not supported */
/* decode procedure for integer */
static int
decode_int_value(void *output, const json_t *value_obj,
@@ -359,14 +406,27 @@ decode_string_value(void *output, const json_t *value_obj,
__rte_unused const struct json_value_decode_rule *rule)
{
const char* str_val = json_string_value(value_obj);
-#if 0
- size_t len = strlen(str_val);
- if (unlikely(len >= rule->spec.buf_sz)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Invalid json value. "
- "name=%s\n", rule->name);
- return -1;
- }
+ strcpy(output, str_val);
+
+ return 0;
+}
#endif
+
+/* decode procedure for mac address string */
+static int
+decode_mac_addr_str_value(void *output, const json_t *value_obj,
+ __rte_unused const struct json_value_decode_rule *rule)
+{
+ int ret = -1;
+ const char* str_val = json_string_value(value_obj);
+
+ ret = spp_config_change_mac_str_to_int64(str_val);
+ if (unlikely(ret == -1)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad mac address string. val=%s\n",
+ str_val);
+ return DERR_BAD_VALUE;
+ }
+
strcpy(output, str_val);
return 0;
@@ -378,13 +438,20 @@ decode_port_value(void *output, const json_t *value_obj,
__rte_unused const struct json_value_decode_rule *rule)
{
int ret = -1;
+ const char* str_val = json_string_value(value_obj);
struct spp_config_port_info *port = (struct spp_config_port_info *)output;
- const char* str_val = json_string_value(value_obj);
+ if (strcmp(str_val, CMD_UNUSE) == 0) {
+ port->if_type = UNDEF;
+ port->if_no = 0;
+ return 0;
+ }
ret = spp_config_get_if_info(str_val, &port->if_type, &port->if_no);
- if (unlikely(ret != 0))
- return -1;
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad port. val=%s\n", str_val);
+ return DERR_BAD_VALUE;
+ }
return 0;
}
@@ -405,25 +472,56 @@ decode_json_object(void *output, const json_t *parent_obj,
for (i = 0; unlikely(! IS_END_OF_DECODE_RULE(&rules[i])); ++ i) {
rule = rules + 1;
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "get one object. name=%s\n",
+ rule->name);
+
value_obj = json_object_get(parent_obj, rule->name);
- if (unlikely(value_obj == NULL) ||
- unlikely(json_typeof(value_obj) != rule->json_type)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Invalid json value. "
+ if (unlikely(value_obj == NULL)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "No parameter. "
"name=%s\n", rule->name);
- return -1;
+ return DERR_NO_PARAM;
+ } else if (unlikely(json_typeof(value_obj) != rule->json_type)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value type. "
+ "name=%s\n", rule->name);
+ return DERR_BAD_TYPE;
}
switch (rule->json_type) {
case JSON_ARRAY:
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decode array. num=%lu\n",
+ json_array_size(value_obj));
+
+ *(int *)((char *)output + rule->array.offset_num) =
+ (int)json_array_size(value_obj);
+
json_array_foreach(value_obj, n, obj) {
- sub_output = DR_GET_OUTPUT(output, rule) + (rule->sub_offset * i);
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decode array element. "
+ "index=%d\n", i);
+
+ if (unlikely(json_typeof(obj) != rule->array.json_type)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value type. "
+ "name=%s, index=%d\n", rule->name, i);
+ return DERR_BAD_TYPE;
+ }
+
+ sub_output = DR_GET_OUTPUT(output, rule) +
+ (rule->array.element_sz * i);
ret = (*rule->decode_proc)(sub_output, obj, rule);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value. "
+ "name=%s, index=%d\n", rule->name, i);
+ return ret;
+ }
}
- *(int *)((char *)output + rule->sub_offset_num) = n;
break;
default:
sub_output = DR_GET_OUTPUT(output, rule);
ret = (*rule->decode_proc)(sub_output, value_obj, rule);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value. "
+ "name=%s\n", rule->name);
+ return ret;
+ }
break;
}
}
@@ -431,7 +529,7 @@ decode_json_object(void *output, const json_t *parent_obj,
return 0;
}
-/* */
+/* decode rule for command-base */
const struct json_value_decode_rule DECODERULE_COMMAND_BASE[] = {
{
.name = "command",
@@ -442,20 +540,24 @@ const struct json_value_decode_rule DECODERULE_COMMAND_BASE[] = {
END_OF_DECODE_RULE
};
-/* */
+#if 0 /* not supported */
+/* decode rule for add-command-spec */
const struct json_value_decode_rule DECODERULE_ADD_COMMAND[] = {
{
.name = "ports",
.json_type = JSON_ARRAY,
.offset = offsetof(struct add_command, ports),
.decode_proc = decode_port_value,
-// .sub_json_type = JSON_STRING,
- .sub_offset = sizeof(struct spp_config_port_info),
+
+ .array.element_sz = sizeof(struct spp_config_port_info),
+ .array.json_type = JSON_STRING,
+ .array.offset_num = offsetof(struct add_command, num_port),
},
END_OF_DECODE_RULE
};
+#endif
-/* */
+/* decode rule for classifier-table-command-spec */
const struct json_value_decode_rule DECODERULE_CLASSIFIER_TABLE_COMMAND[] = {
{
.name = "type",
@@ -466,7 +568,7 @@ const struct json_value_decode_rule DECODERULE_CLASSIFIER_TABLE_COMMAND[] = {
.name = "value",
.json_type = JSON_STRING,
.offset = offsetof(struct classifier_table_command, value),
- .decode_proc = decode_string_value,
+ .decode_proc = decode_mac_addr_str_value,
},{
.name = "port",
.json_type = JSON_STRING,
@@ -476,7 +578,7 @@ const struct json_value_decode_rule DECODERULE_CLASSIFIER_TABLE_COMMAND[] = {
END_OF_DECODE_RULE
};
-/* */
+/* decode procedure for command */
static int
decode_command_object(void* output, const json_t *parent_obj,
__rte_unused const struct json_value_decode_rule *rule)
@@ -485,52 +587,58 @@ decode_command_object(void* output, const json_t *parent_obj,
struct command *command = (struct command *)output;
const struct json_value_decode_rule *spec_rules = NULL;
- /* decode command base */
+ /* decode command-base */
ret = decode_json_object(command, parent_obj, DECODERULE_COMMAND_BASE);
if (unlikely(ret != 0)) {
- // TODO:コマンドがデコード失敗
- return -1;
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad command. ret=%d\n", ret);
+ return ret;
}
- /* decode command specific */
+ /* decode command-specific */
switch (command->type) {
case CMDTYPE_CLASSIFIER_TABLE:
spec_rules = DECODERULE_CLASSIFIER_TABLE_COMMAND;
break;
case CMDTYPE_FLUSH:
+ /* nothing specific */
break;
default:
- break;
+ /* unknown command */
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown command. type=%d\n",
+ command->type);
+ return DERR_UNKNOWN_COMMAND;
}
if (likely(spec_rules != NULL)) {
ret = decode_json_object(&command->spec, parent_obj, spec_rules);
if (unlikely(ret != 0)) {
- // TODO:コマンドがデコード失敗
- return -1;
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad command. ret=%d\n", ret);
+ return ret;
}
}
return 0;
}
-/* */
+/* decode rule for command request */
const struct json_value_decode_rule DECODERULE_REQUEST[] = {
{
.name = "commands",
.json_type = JSON_ARRAY,
.offset = offsetof(struct request, commands),
.decode_proc = decode_command_object,
-// .sub_json_type = JSON_OBJECT,
- .sub_offset = sizeof(struct command),
- .sub_offset_num = offsetof(struct request, num_command),
+
+ .array.element_sz = sizeof(struct command),
+ .array.json_type = JSON_OBJECT,
+ .array.offset_num = offsetof(struct request, num_command),
+ .array.offset_num_valid = offsetof(struct request, num_valid_command),
},
END_OF_DECODE_RULE
};
-/* */
+/* decode request from no-null-terminated string */
static int
decode_request(struct request *request, const char *request_str, size_t request_str_len)
{
@@ -544,7 +652,7 @@ decode_request(struct request *request, const char *request_str, size_t request_
RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot parse command request. "
"error=%s, request_str=%.*s\n",
json_error.text, (int)request_str_len, request_str);
- return -1;
+ return DERR_BAD_FORMAT;
}
/* decode request object */
@@ -553,13 +661,13 @@ decode_request(struct request *request, const char *request_str, size_t request_
RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot decode command request. "
"ret=%d, request_str=%.*s\n",
ret, (int)request_str_len, request_str);
- return -1;
+ return ret;
}
return 0;
}
-/* */
+/* execute one command */
static int
execute_command(const struct command *command)
{
@@ -567,29 +675,33 @@ execute_command(const struct command *command)
switch (command->type) {
case CMDTYPE_CLASSIFIER_TABLE:
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Execute classifier_table command.");
ret = spp_update_classifier_table(
- SPP_CLASSIFIER_TYPE_MAC,
-// command->spec.classifier_table.type,
+ command->spec.classifier_table.type,
command->spec.classifier_table.value,
&command->spec.classifier_table.port);
break;
case CMDTYPE_FLUSH:
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Execute flush command.");
ret = spp_flush();
break;
case CMDTYPE_PROCESS:
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Execute process command.");
+ ret = spp_get_process_id();
break;
default:
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown command. type=%d\n", command->type);
ret = 0;
break;
}
- return 0;
+ return ret;
}
-/* */
+/* process command request from no-null-terminated string */
static int
process_request(const char *request_str, size_t request_str_len)
{
@@ -597,20 +709,28 @@ process_request(const char *request_str, size_t request_str_len)
int i;
struct request request;
+ memset(&request, 0, sizeof(struct request));
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Receive command request. "
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Start command request processing. "
"request_str=%.*s\n", (int)request_str_len, request_str);
- memset(&request, 0, sizeof(struct request));
-
ret = decode_request(&request, request_str, request_str_len);
- if (unlikely(ret != 0))
- return -1;
+ if (unlikely(ret != 0)) {
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Failed to process command request. "
+ "ret=%d\n", ret);
+ return ret;
+ }
+
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decoded command request. "
+ "num_command=%d, num_valid_command=%d\n",
+ request.num_command, request.num_valid_command);
for (i = 0; i < request.num_command ; ++i) {
ret = execute_command(request.commands + i);
}
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Succeeded to process command request.\n");
+
return 0;
}
@@ -645,7 +765,7 @@ spp_command_proc_do(void)
if (unlikely(ret != 0))
return;
- ret = receive_request(&sock, &msgbuf);
+ ret = receive_message(&sock, &msgbuf);
if (likely(ret == 0)) {
return;
}
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 14/57] spp_vf: fix return value overwrite problem
2017-12-26 1:54 ` Yasufumi Ogawa
` (12 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 13/57] spp_vf: refactor command acceptance/decode x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 15/57] spp_vf: initialize message buffer x-fn-spp
` (42 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Add new variable for saving the return value of receive_message()
to avoid overwrite problem.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_proc.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index d8e7fd1..3ec4f5b 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -749,6 +749,7 @@ void
spp_command_proc_do(void)
{
int ret = -1;
+ int msg_ret = -1;
int i;
static int sock = -1;
@@ -765,12 +766,12 @@ spp_command_proc_do(void)
if (unlikely(ret != 0))
return;
- ret = receive_message(&sock, &msgbuf);
- if (likely(ret == 0)) {
+ msg_ret = receive_message(&sock, &msgbuf);
+ if (likely(msg_ret == 0)) {
return;
}
- for (i = 0; i < ret; ++i) {
+ for (i = 0; i < msg_ret; ++i) {
switch (*(msgbuf + msg_len + i)) {
case '{':
++lb_cnt;
@@ -785,9 +786,12 @@ spp_command_proc_do(void)
ret = process_request(msgbuf, msg_len);
msgbuf_remove_front(msgbuf, msg_len);
+ msg_ret = 0;
msg_len = 0;
rb_cnt = 0;
lb_cnt = 0;
}
}
+
+ msg_len = msg_len + msg_ret;
}
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 15/57] spp_vf: initialize message buffer
2017-12-26 1:54 ` Yasufumi Ogawa
` (13 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 14/57] spp_vf: fix return value overwrite problem x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 16/57] spp_vf: add const keyword to parameter x-fn-spp
` (41 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Clear the message buffer by character '\0'.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_proc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index 3ec4f5b..6ff817f 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -42,6 +42,7 @@ msgbuf_allocate(size_t capacity)
if (unlikely(buf == NULL))
return NULL;
+ memset(buf, 0x00, capacity + sizeof(size_t));
*((size_t *)buf) = capacity;
return buf + sizeof(size_t);
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 16/57] spp_vf: add const keyword to parameter
2017-12-26 1:54 ` Yasufumi Ogawa
` (14 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 15/57] spp_vf: initialize message buffer x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 17/57] spp_vf: fix wrong comparison operator x-fn-spp
` (40 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
spp_vf supports command for modifying classifier table.
* Misc. modifications.
* Add const keyword to parameter.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_vf.c | 2 +-
src/vf/spp_vf.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 805c582..45ab6c6 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -1039,7 +1039,7 @@ int
spp_update_classifier_table(
enum spp_classifier_type type,
const char *data,
- struct spp_config_port_info *port)
+ const struct spp_config_port_info *port)
{
enum port_type if_type = UNDEF;
int if_no = 0;
diff --git a/src/vf/spp_vf.h b/src/vf/spp_vf.h
index f9707d7..4ca4568 100644
--- a/src/vf/spp_vf.h
+++ b/src/vf/spp_vf.h
@@ -73,7 +73,7 @@ int spp_get_process_id(void);
* : SPP_RET_NOT_ADD_PORT(-3)
* : SPP_RET_USED_PORT(-4)
*/
-int spp_update_classifier_table(enum spp_classifier_type type, const char *data, struct spp_config_port_info *port);
+int spp_update_classifier_table(enum spp_classifier_type type, const char *data, const struct spp_config_port_info *port);
/*
* Flush SPP component
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 17/57] spp_vf: fix wrong comparison operator
2017-12-26 1:54 ` Yasufumi Ogawa
` (15 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 16/57] spp_vf: add const keyword to parameter x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 18/57] spp_vf: fix wrong variable to be assigned x-fn-spp
` (39 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_proc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index 6ff817f..1de43f8 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -768,7 +768,7 @@ spp_command_proc_do(void)
return;
msg_ret = receive_message(&sock, &msgbuf);
- if (likely(msg_ret == 0)) {
+ if (likely(msg_ret <= 0)) {
return;
}
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 18/57] spp_vf: fix wrong variable to be assigned
2017-12-26 1:54 ` Yasufumi Ogawa
` (16 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 17/57] spp_vf: fix wrong comparison operator x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 19/57] spp_vf: refactor parsing server ip address x-fn-spp
` (38 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_vf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 45ab6c6..208dd30 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -524,7 +524,7 @@ set_form_proc_info(struct spp_config_area *config)
}
/* IF情報からCORE情報を変更する場合用に設定 */
- patch_info->rx_core_no = core_cnt;
+ patch_info->rx_core_no = core_func->core_no;
patch_info->rx_core = &core_info->rx_ports[rx_start + rx_cnt];
}
@@ -549,7 +549,7 @@ set_form_proc_info(struct spp_config_area *config)
}
/* IF情報からCORE情報を変更する場合用に設定 */
- patch_info->tx_core_no = core_cnt;
+ patch_info->tx_core_no = core_func->core_no;
patch_info->tx_core = &core_info->tx_ports[tx_start + tx_cnt];
}
}
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 19/57] spp_vf: refactor parsing server ip address
2017-12-26 1:54 ` Yasufumi Ogawa
` (17 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 18/57] spp_vf: fix wrong variable to be assigned x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 20/57] spp_vf: fix error in command decode x-fn-spp
` (37 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
The following two changes are made in parse_app_server()
in order to get server IP address.
* Check the number of characters in IP address string.
* Add terminator '\0' to IP address string.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_vf.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 7bb1ac0..e5dc1c9 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -329,16 +329,20 @@ static int
parse_app_server(const char *server_str, char *server_ip, int *server_port)
{
const char delim[2] = ":";
- int pos = 0;
+ unsigned int pos = 0;
int port = 0;
char *endptr = NULL;
pos = strcspn(server_str, delim);
+ if (pos >= strlen(server_str))
+ return -1;
+
port = strtol(&server_str[pos+1], &endptr, 0);
if (unlikely(&server_str[pos+1] == endptr) || unlikely(*endptr != '\0'))
return -1;
memcpy(server_ip, server_str, pos);
+ server_ip[pos] = '\0';
*server_port = port;
RTE_LOG(DEBUG, APP, "Set server ip = %s\n", server_ip);
RTE_LOG(DEBUG, APP, "Set server port = %d\n", *server_port);
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 20/57] spp_vf: fix error in command decode
2017-12-26 1:54 ` Yasufumi Ogawa
` (18 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 19/57] spp_vf: refactor parsing server ip address x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 21/57] spp_vf: fix comparison operator in spp_vf.c x-fn-spp
` (36 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Fix wrong counter variable to be used.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_proc.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index 1de43f8..bec762e 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -471,7 +471,7 @@ decode_json_object(void *output, const json_t *parent_obj,
void *sub_output;
for (i = 0; unlikely(! IS_END_OF_DECODE_RULE(&rules[i])); ++ i) {
- rule = rules + 1;
+ rule = rules + i;
RTE_LOG(DEBUG, SPP_COMMAND_PROC, "get one object. name=%s\n",
rule->name);
@@ -497,20 +497,20 @@ decode_json_object(void *output, const json_t *parent_obj,
json_array_foreach(value_obj, n, obj) {
RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decode array element. "
- "index=%d\n", i);
+ "index=%d\n", n);
if (unlikely(json_typeof(obj) != rule->array.json_type)) {
RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value type. "
- "name=%s, index=%d\n", rule->name, i);
+ "name=%s, index=%d\n", rule->name, n);
return DERR_BAD_TYPE;
}
sub_output = DR_GET_OUTPUT(output, rule) +
- (rule->array.element_sz * i);
+ (rule->array.element_sz * n);
ret = (*rule->decode_proc)(sub_output, obj, rule);
if (unlikely(ret != 0)) {
RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value. "
- "name=%s, index=%d\n", rule->name, i);
+ "name=%s, index=%d\n", rule->name, n);
return ret;
}
}
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 21/57] spp_vf: fix comparison operator in spp_vf.c
2017-12-26 1:54 ` Yasufumi Ogawa
` (19 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 20/57] spp_vf: fix error in command decode x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 22/57] spp_vf: check upper limit to the number of process x-fn-spp
` (35 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_vf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 208dd30..7bb1ac0 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -1103,7 +1103,7 @@ spp_update_classifier_table(
return SPP_RET_NG;
}
- if (unlikely(patch_info->use_flg != 0)) {
+ 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;
}
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 22/57] spp_vf: check upper limit to the number of process
2017-12-26 1:54 ` Yasufumi Ogawa
` (20 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 21/57] spp_vf: fix comparison operator in spp_vf.c x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 23/57] spp_vf: display usage message x-fn-spp
` (34 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Add upper limit check of the number of process.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_vf.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index e5dc1c9..6c6b832 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -317,6 +317,9 @@ parse_app_process_id(const char *process_id_str, int *process_id)
if (unlikely(process_id_str == endptr) || unlikely(*endptr != '\0'))
return -1;
+ if (id >= SPP_PROCESS_MAX)
+ return -1;
+
*process_id = id;
RTE_LOG(DEBUG, APP, "Set process id = %d\n", *process_id);
return 0;
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 23/57] spp_vf: display usage message
2017-12-26 1:54 ` Yasufumi Ogawa
` (21 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 22/57] spp_vf: check upper limit to the number of process x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 24/57] spp_vf: split command processing source file x-fn-spp
` (33 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* When there is no required startup parameter,
usage message will displayed.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_vf.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 6c6b832..1eaaac9 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -359,6 +359,8 @@ static int
parse_app_args(int argc, char *argv[])
{
int cnt;
+ int proc_flg = 0;
+ int server_flg = 0;
int option_index, opt;
const int argcopt = argc;
char *argvopt[argcopt];
@@ -392,6 +394,7 @@ parse_app_args(int argc, char *argv[])
usage(progname);
return -1;
}
+ proc_flg = 1;
break;
case 's':
if (parse_app_server(optarg, g_startup_param.server_ip,
@@ -399,6 +402,7 @@ parse_app_args(int argc, char *argv[])
usage(progname);
return -1;
}
+ server_flg = 1;
break;
default:
usage(progname);
@@ -407,6 +411,11 @@ parse_app_args(int argc, char *argv[])
}
}
+ /* Check mandatory parameters */
+ if ((proc_flg == 0) || (server_flg == 0)) {
+ usage(progname);
+ return -1;
+ }
RTE_LOG(INFO, APP, "application arguments value. (process id = %d, config = %s, server = %s:%d)\n",
g_startup_param.process_id,
config_file_path,
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 24/57] spp_vf: split command processing source file
2017-12-26 1:54 ` Yasufumi Ogawa
` (22 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 23/57] spp_vf: display usage message x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 25/57] spp_vf: add new log and line break x-fn-spp
` (32 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* For better maintainability,
split 1 source file into 3 files(acceptance, decode, and utility).
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/Makefile | 2 +-
src/vf/command_conn.c | 136 ++++++++
src/vf/command_conn.h | 63 ++++
src/vf/command_dec.c | 433 +++++++++++++++++++++++++
src/vf/command_dec.h | 110 +++++++
src/vf/command_proc.c | 866 ++++++++++++++-----------------------------------
src/vf/string_buffer.c | 90 +++++
src/vf/string_buffer.h | 16 +
8 files changed, 1097 insertions(+), 619 deletions(-)
create mode 100644 src/vf/command_conn.c
create mode 100644 src/vf/command_conn.h
create mode 100644 src/vf/command_dec.c
create mode 100644 src/vf/command_dec.h
create mode 100644 src/vf/string_buffer.c
create mode 100644 src/vf/string_buffer.h
diff --git a/src/vf/Makefile b/src/vf/Makefile
index 19617f6..1284733 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 command_proc.c ringlatencystats.c ../shared/common.c
+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
CFLAGS += $(WERROR_FLAGS) -O3
CFLAGS += -I$(SRCDIR)/../shared
diff --git a/src/vf/command_conn.c b/src/vf/command_conn.c
new file mode 100644
index 0000000..edd4d4c
--- /dev/null
+++ b/src/vf/command_conn.c
@@ -0,0 +1,136 @@
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+#include <rte_log.h>
+#include <rte_branch_prediction.h>
+
+#include "string_buffer.h"
+#include "command_conn.h"
+
+#define RTE_LOGTYPE_SPP_COMMAND_PROC RTE_LOGTYPE_USER1
+
+/* one receive message size */
+#define MESSAGE_BUFFER_BLOCK_SIZE 2048
+
+/* controller's ip address */
+static char g_controller_ip[128] = "";
+
+/* controller's port number */
+static int g_controller_port = 0;
+
+/* initialize command connection */
+int
+spp_command_conn_init(const char *controller_ip, int controller_port)
+{
+ strcpy(g_controller_ip, controller_ip);
+ g_controller_port = controller_port;
+
+ return 0;
+}
+
+/* connect to controller */
+int
+spp_connect_to_controller(int *sock)
+{
+ static struct sockaddr_in controller_addr;
+ int ret = -1;
+ int sock_flg = 0;
+
+ if (likely(*sock >=0))
+ return 0;
+
+ /* create socket */
+ if (*sock < 0) {
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Creating socket...\n");
+ *sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (*sock < 0) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC,
+ "Cannot create tcp socket. errno=%d\n", errno);
+ return -1;
+ }
+
+ memset(&controller_addr, 0, sizeof(controller_addr));
+ controller_addr.sin_family = AF_INET;
+ controller_addr.sin_addr.s_addr = inet_addr(g_controller_ip);
+ controller_addr.sin_port = htons(g_controller_port);
+ }
+
+ /* connect to */
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Trying to connect ... socket=%d\n", *sock);
+ ret = connect(*sock, (struct sockaddr *)&controller_addr,
+ sizeof(controller_addr));
+ if (ret < 0) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC,
+ "Cannot connect to controller. errno=%d\n", errno);
+ return -1;
+ }
+
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Connected\n");
+
+ /* set non-blocking */
+ sock_flg = fcntl(*sock, F_GETFL, 0);
+ fcntl(*sock, F_SETFL, sock_flg | O_NONBLOCK);
+
+ return 0;
+}
+
+/* receive message */
+int
+spp_receive_message(int *sock, char **strbuf)
+{
+ int ret = -1;
+ int n_rx = 0;
+ char *new_strbuf = NULL;
+
+ char rx_buf[MESSAGE_BUFFER_BLOCK_SIZE];
+ size_t rx_buf_sz = MESSAGE_BUFFER_BLOCK_SIZE;
+
+ ret = recv(*sock, rx_buf, rx_buf_sz, 0);
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Receive message. count=%d\n", ret);
+ if (ret <= 0) {
+ if (ret == 0) {
+ RTE_LOG(INFO, SPP_COMMAND_PROC,
+ "Controller has performed an shutdown.");
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ /* no receive message */
+ return 0;
+ } else {
+ RTE_LOG(ERR, SPP_COMMAND_PROC,
+ "Receive failure. errno=%d\n", errno);
+ }
+
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Assume Server closed connection\n");
+ close(*sock);
+ *sock = -1;
+ return -1;
+ }
+
+ n_rx = ret;
+
+ new_strbuf = spp_strbuf_append(*strbuf, rx_buf, n_rx);
+ if (unlikely(new_strbuf == NULL)) {
+ return -1;
+ }
+
+ *strbuf = new_strbuf;
+
+ return n_rx;
+}
+
+/* send message */
+int
+spp_send_message(int *sock, const char* message, size_t message_len)
+{
+ int ret = -1;
+
+ ret = send(*sock, message, message_len, 0);
+ if (unlikely(ret == -1)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Send failure. ret=%d\n", ret);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/vf/command_conn.h b/src/vf/command_conn.h
new file mode 100644
index 0000000..0136d75
--- /dev/null
+++ b/src/vf/command_conn.h
@@ -0,0 +1,63 @@
+#ifndef _COMMAND_CONN_H_
+#define _COMMAND_CONN_H_
+
+/**
+ * intialize command connection.
+ *
+ * @param controller_ip
+ * controller listen ip address.
+ *
+ * @param controller_port
+ * controller listen port number.
+ *
+ * @ret_val 0 succeeded.
+ * @ret_val -1 failed.
+ */
+int spp_command_conn_init(const char *controller_ip, int controller_port);
+
+/**
+ * connect to controller.
+ *
+ * @note bocking.
+ *
+ * @param sock
+ * socket that connect to controller.
+ *
+ * @ret_val 0 succeeded.
+ * @ret_val -1 failed.
+ */
+int spp_connect_to_controller(int *sock);
+
+/**
+ * receive message.
+ *
+ * @note non-blocking.
+ *
+ * @param sock
+ * socket that read data.
+ *
+ * @ret_val 0 succeeded.
+ * @ret_val -1 failed.
+ */
+int spp_receive_message(int *sock, char **msgbuf);
+
+/**
+ * send message.
+ *
+ * @note non-blocking.
+ *
+ * @param sock
+ * socket that write data.
+ *
+ * @param message
+ * send data.
+ *
+ * @param message_len
+ * send data length.
+ *
+ * @ret_val 0 succeeded.
+ * @ret_val -1 failed.
+ */
+int spp_send_message(int *sock, const char* message, size_t message_len);
+
+#endif /* _COMMAND_CONN_H_ */
diff --git a/src/vf/command_dec.c b/src/vf/command_dec.c
new file mode 100644
index 0000000..85f935b
--- /dev/null
+++ b/src/vf/command_dec.c
@@ -0,0 +1,433 @@
+#include <unistd.h>
+#include <string.h>
+
+#include <rte_log.h>
+#include <rte_branch_prediction.h>
+
+#include <jansson.h>
+
+#include "spp_vf.h"
+#include "spp_config.h"
+#include "command_dec.h"
+
+#define RTE_LOGTYPE_SPP_COMMAND_PROC RTE_LOGTYPE_USER1
+
+/* command type string list
+ do it same as the order of enum command_type */
+static const char *COMMAND_TYPE_STRINGS[] = {
+#if 0 /* not supported yet */
+ "add",
+ "component",
+#endif
+ "classifier_table",
+ "flush",
+#if 0 /* not supported yet */
+ "forward",
+ "stop",
+#endif
+ "process",
+
+ /* termination */ "",
+};
+
+/* classifier type string list
+ do it same as the order of enum spp_classifier_type (spp_vf.h) */
+static const char *CLASSIFILER_TYPE_STRINGS[] = {
+ "none",
+ "mac",
+
+ /* termination */ "",
+};
+
+/* forward declaration */
+struct json_value_decode_rule;
+
+/* definition of decode procedure function */
+typedef int (*json_value_decode_proc)(
+ void *,
+ const json_t *,
+ const struct json_value_decode_rule *,
+ struct spp_command_decode_error *);
+
+/* rule definition that decode json object to c-struct */
+struct json_value_decode_rule {
+ char name[SPP_CMD_NAME_BUFSZ];
+ json_type json_type;
+ size_t offset;
+ json_value_decode_proc decode_proc;
+
+ struct {
+ json_type json_type;
+ size_t element_sz;
+ size_t offset_num;
+ size_t offset_num_valid;
+ } array;
+};
+
+/* get output address for decoded json value */
+#define DR_GET_OUTPUT(output_base, rule__) ((char *)output_base + rule__->offset)
+
+/* set decode error */
+inline int
+set_decode_error(struct spp_command_decode_error *error,
+ int error_code,
+ const struct json_value_decode_rule *error_rule)
+{
+ error->code = error_code;
+
+ if (likely(error_rule != NULL))
+ strcpy(error->value_name, error_rule->name);
+
+ return error->code;
+}
+
+/* set decode error */
+inline int
+set_string_value_decode_error(struct spp_command_decode_error *error,
+ const char* value,
+ const struct json_value_decode_rule *error_rule)
+{
+ strcpy(error->value, value);
+ return set_decode_error(error, SPP_CMD_DERR_BAD_VALUE, error_rule);
+}
+
+/* helper */
+#define END_OF_DECODE_RULE {.name = ""},
+#define IS_END_OF_DECODE_RULE(rule) ((rule)->name[0] == '\0')
+
+/* definition helper that enum value decode procedure */
+#define DECODE_ENUM_VALUE(proc_name, enum_type, string_table) \
+static int \
+decode_##proc_name##_value(void *output, const json_t *value_obj, \
+ const struct json_value_decode_rule *rule, \
+ struct spp_command_decode_error *error) \
+{ \
+ int i; \
+ enum_type type; \
+ const char *str_val = json_string_value(value_obj); \
+ \
+ for (i = 0; string_table[i][0] != '\0'; ++i) { \
+ if (unlikely(strcmp(str_val, string_table[i]) == 0)) { \
+ type = i; \
+ memcpy(output, &type, sizeof(enum_type)); \
+ return 0; \
+ } \
+ } \
+ \
+ return set_string_value_decode_error(error, str_val, rule); \
+} \
+
+/* enum value decode procedure for "command_type" */
+DECODE_ENUM_VALUE(command_type, enum spp_command_type, COMMAND_TYPE_STRINGS)
+
+/* enum value decode procedure for "classifier_type" */
+DECODE_ENUM_VALUE(classifier_type, enum spp_classifier_type, CLASSIFILER_TYPE_STRINGS)
+
+#if 0 /* not supported yet */
+/* decode procedure for integer */
+static int
+decode_int_value(void *output, const json_t *value_obj,
+ __rte_unused const struct json_value_decode_rule *rule,
+ __rte_unused struct spp_command_decode_error *error)
+{
+ int val = json_integer_value(value_obj);
+ memcpy(output, &val, sizeof(int));
+
+ return 0;
+}
+
+/* decode procedure for string */
+static int
+decode_string_value(void *output, const json_t *value_obj,
+ __rte_unused const struct json_value_decode_rule *rule,
+ __rte_unused struct spp_command_decode_error *error)
+{
+ const char* str_val = json_string_value(value_obj);
+ strcpy(output, str_val);
+
+ return 0;
+}
+#endif
+
+/* decode procedure for mac address string */
+static int
+decode_mac_addr_str_value(void *output, const json_t *value_obj,
+ const struct json_value_decode_rule *rule,
+ struct spp_command_decode_error *error)
+{
+ int ret = -1;
+ const char* str_val = json_string_value(value_obj);
+
+ ret = spp_config_change_mac_str_to_int64(str_val);
+ if (unlikely(ret == -1)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad mac address string. val=%s\n",
+ str_val);
+ return set_string_value_decode_error(error, str_val, rule);
+ }
+
+ strcpy(output, str_val);
+
+ return 0;
+}
+
+/* decode procedure for spp_config_port_info */
+static int
+decode_port_value(void *output, const json_t *value_obj,
+ const struct json_value_decode_rule *rule,
+ struct spp_command_decode_error *error)
+{
+ int ret = -1;
+ const char* str_val = json_string_value(value_obj);
+ struct spp_config_port_info *port = (struct spp_config_port_info *)output;
+
+ if (strcmp(str_val, SPP_CMD_UNUSE) == 0) {
+ port->if_type = UNDEF;
+ port->if_no = 0;
+ return 0;
+ }
+
+ ret = spp_config_get_if_info(str_val, &port->if_type, &port->if_no);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad port. val=%s\n", str_val);
+ return set_string_value_decode_error(error, str_val, rule);
+ }
+
+ return 0;
+}
+
+/* decode json object */
+static int
+decode_json_object(void *output, const json_t *parent_obj,
+ const struct json_value_decode_rule *rules,
+ struct spp_command_decode_error *error)
+{
+ int ret = -1;
+ int i, n;
+ json_t *obj;
+ json_t *value_obj;
+ const struct json_value_decode_rule *rule;
+
+ void *sub_output;
+
+ for (i = 0; unlikely(! IS_END_OF_DECODE_RULE(&rules[i])); ++ i) {
+ rule = rules + i;
+
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Get one object. name=%s\n",
+ rule->name);
+
+ value_obj = json_object_get(parent_obj, rule->name);
+ if (unlikely(value_obj == NULL)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "No parameter. "
+ "name=%s\n", rule->name);
+ return set_decode_error(error, SPP_CMD_DERR_NO_PARAM, rule);
+ } else if (unlikely(json_typeof(value_obj) != rule->json_type)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value type. "
+ "name=%s\n", rule->name);
+ return set_decode_error(error, SPP_CMD_DERR_BAD_TYPE, rule);
+ }
+
+ switch (rule->json_type) {
+ case JSON_ARRAY:
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decode array. num=%lu\n",
+ json_array_size(value_obj));
+
+ *(int *)((char *)output + rule->array.offset_num) =
+ (int)json_array_size(value_obj);
+
+ json_array_foreach(value_obj, n, obj) {
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decode array element. "
+ "index=%d\n", n);
+
+ if (unlikely(json_typeof(obj) != rule->array.json_type)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value type. "
+ "name=%s, index=%d\n", rule->name, n);
+ return set_decode_error(error, SPP_CMD_DERR_BAD_TYPE, rule);
+ }
+
+ sub_output = DR_GET_OUTPUT(output, rule) +
+ (rule->array.element_sz * n);
+ ret = (*rule->decode_proc)(sub_output, obj, rule, error);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value. "
+ "name=%s, index=%d\n", rule->name, n);
+ /* decode error is set in decode function */
+ return ret;
+ }
+
+ *(int *)((char *)output +
+ rule->array.offset_num_valid) = n + 1;
+ }
+ break;
+ default:
+ sub_output = DR_GET_OUTPUT(output, rule);
+ ret = (*rule->decode_proc)(sub_output, value_obj, rule, error);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value. "
+ "name=%s\n", rule->name);
+ /* decode error is set in decode function */
+ return ret;
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* decode rule for command-base */
+const struct json_value_decode_rule DECODERULE_COMMAND_BASE[] = {
+ {
+ .name = "command",
+ .json_type = JSON_STRING,
+ .offset = offsetof(struct spp_command, type),
+ .decode_proc = decode_command_type_value,
+ },
+ END_OF_DECODE_RULE
+};
+
+#if 0 /* not supported yet */
+/* decode rule for add-command-spec */
+const struct json_value_decode_rule DECODERULE_ADD_COMMAND[] = {
+ {
+ .name = "ports",
+ .json_type = JSON_ARRAY,
+ .offset = offsetof(struct spp_command_add, ports),
+ .decode_proc = decode_port_value,
+
+ .array.element_sz = sizeof(struct spp_config_port_info),
+ .array.json_type = JSON_STRING,
+ .array.offset_num = offsetof(struct spp_command_add, num_port),
+ },
+ END_OF_DECODE_RULE
+};
+#endif
+
+/* decode rule for classifier-table-command-spec */
+const struct json_value_decode_rule DECODERULE_CLASSIFIER_TABLE_COMMAND[] = {
+ {
+ .name = "type",
+ .json_type = JSON_STRING,
+ .offset = offsetof(struct spp_command_classifier_table, type),
+ .decode_proc = decode_classifier_type_value,
+ },{
+ .name = "value",
+ .json_type = JSON_STRING,
+ .offset = offsetof(struct spp_command_classifier_table, value),
+ .decode_proc = decode_mac_addr_str_value,
+ },{
+ .name = "port",
+ .json_type = JSON_STRING,
+ .offset = offsetof(struct spp_command_classifier_table, port),
+ .decode_proc = decode_port_value,
+ },
+ END_OF_DECODE_RULE
+};
+
+/* decode procedure for command */
+static int
+decode_command_object(void* output, const json_t *parent_obj,
+ __rte_unused const struct json_value_decode_rule *rule,
+ struct spp_command_decode_error *error)
+{
+ int ret = -1;
+ struct spp_command *command = (struct spp_command *)output;
+ const struct json_value_decode_rule *spec_rules = NULL;
+
+ /* decode command-base */
+ ret = decode_json_object(command, parent_obj, DECODERULE_COMMAND_BASE, error);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad command. ret=%d\n", ret);
+ /* decode error is set in decode_json_object function */
+ return ret;
+ }
+
+ /* decode command-specific */
+ switch (command->type) {
+ case SPP_CMDTYPE_CLASSIFIER_TABLE:
+ spec_rules = DECODERULE_CLASSIFIER_TABLE_COMMAND;
+ break;
+
+ case SPP_CMDTYPE_FLUSH:
+ /* nothing specific */
+ break;
+
+ default:
+ /* unknown command */
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown command. type=%d\n",
+ command->type);
+ return set_decode_error(error, SPP_CMD_DERR_UNKNOWN_COMMAND, rule);
+ }
+
+ if (likely(spec_rules != NULL)) {
+ ret = decode_json_object(&command->spec, parent_obj, spec_rules, error);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad command. ret=%d\n", ret);
+ /* decode error is set in decode_json_object function */
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/* decode rule for command request */
+const struct json_value_decode_rule DECODERULE_REQUEST[] = {
+ {
+ .name = "commands",
+ .json_type = JSON_ARRAY,
+ .offset = offsetof(struct spp_command_request, commands),
+ .decode_proc = decode_command_object,
+
+ .array.element_sz = sizeof(struct spp_command),
+ .array.json_type = JSON_OBJECT,
+ .array.offset_num = offsetof(struct spp_command_request, num_command),
+ .array.offset_num_valid = offsetof(struct spp_command_request, num_valid_command),
+ },
+ END_OF_DECODE_RULE
+};
+
+/* decode request from no-null-terminated string */
+int
+spp_command_decode_request(struct spp_command_request *request, const char *request_str,
+ size_t request_str_len, struct spp_command_decode_error *error)
+{
+ int ret = -1;
+ int i;
+ json_t *top_obj;
+ json_error_t json_error;
+
+ /* parse json string */
+ top_obj = json_loadb(request_str, request_str_len, 0, &json_error);
+ if (unlikely(top_obj == NULL)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot parse command request. "
+ "error=%s, request_str=%.*s\n",
+ json_error.text, (int)request_str_len, request_str);
+ return set_decode_error(error, SPP_CMD_DERR_BAD_FORMAT, NULL);
+ }
+
+ /* decode request object */
+ ret = decode_json_object(request, top_obj, DECODERULE_REQUEST, error);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot decode command request. "
+ "ret=%d, request_str=%.*s\n",
+ ret, (int)request_str_len, request_str);
+ /* decode error is set in decode_json_object function */
+ }
+
+ /* free json object */
+ json_decref(top_obj);
+
+ /* check getter command */
+ for (i = 0; i < request->num_valid_command; ++i) {
+ switch (request->commands[i].type) {
+ case SPP_CMDTYPE_PROCESS:
+ request->is_requested_process = 1;
+ break;
+ default:
+ /* nothing to do */
+ break;
+ }
+ }
+
+ return ret;
+}
diff --git a/src/vf/command_dec.h b/src/vf/command_dec.h
new file mode 100644
index 0000000..25e1ea0
--- /dev/null
+++ b/src/vf/command_dec.h
@@ -0,0 +1,110 @@
+#ifndef _COMMAND_DEC_H_
+#define _COMMAND_DEC_H_
+
+/* max number of command per request */
+#define SPP_CMD_MAX_COMMANDS 32
+
+/* command name string buffer size (include null char) */
+#define SPP_CMD_NAME_BUFSZ 32
+
+/* command value string buffer size (include null char) */
+#define SPP_CMD_VALUE_BUFSZ 128
+
+/* 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 */
+ SPP_CMD_DERR_BAD_FORMAT = 1,
+ SPP_CMD_DERR_UNKNOWN_COMMAND,
+ SPP_CMD_DERR_NO_PARAM,
+ SPP_CMD_DERR_BAD_TYPE,
+ SPP_CMD_DERR_BAD_VALUE,
+};
+
+/* command type
+ do it same as the order of COMMAND_TYPE_STRINGS */
+enum spp_command_type {
+#if 0 /* not supported yet yet */
+ SPP_CMDTYPE_ADD,
+ SPP_CMDTYPE_COMPONENT,
+#endif
+ SPP_CMDTYPE_CLASSIFIER_TABLE,
+ SPP_CMDTYPE_FLUSH,
+#if 0 /* not supported yet */
+ SPP_CMDTYPE_FORWARD,
+ SPP_CMDTYPE_STOP,
+#endif
+ SPP_CMDTYPE_PROCESS,
+};
+
+#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_classifier_type type;
+ char value[SPP_CMD_VALUE_BUFSZ];
+ struct spp_config_port_info port;
+};
+
+/* "flush" command specific parameters */
+struct spp_command_flush {
+ /* nothing specific */
+};
+
+/* 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;
+ } spec;
+};
+
+/* request parameters */
+struct spp_command_request {
+ int num_command;
+ int num_valid_command;
+ struct spp_command commands[SPP_CMD_MAX_COMMANDS];
+
+ int is_requested_process;
+};
+
+/* decode error information */
+struct spp_command_decode_error {
+ int code;
+ char value_name[SPP_CMD_NAME_BUFSZ];
+ char value[SPP_CMD_VALUE_BUFSZ];
+};
+
+/* decode request from no-null-terminated string */
+int spp_command_decode_request(struct spp_command_request *request,
+ const char *request_str, size_t request_str_len,
+ struct spp_command_decode_error *error);
+
+#endif /* _COMMAND_DEC_H_ */
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index bec762e..097483c 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -1,12 +1,6 @@
#include <unistd.h>
-#include <sys/types.h>
-#include <stdio.h>
#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <arpa/inet.h>
-#include <rte_common.h>
#include <rte_log.h>
#include <rte_branch_prediction.h>
@@ -14,723 +8,362 @@
#include "spp_vf.h"
#include "spp_config.h"
+#include "string_buffer.h"
+#include "command_conn.h"
+#include "command_dec.h"
#include "command_proc.h"
#define RTE_LOGTYPE_SPP_COMMAND_PROC RTE_LOGTYPE_USER1
+/* request message initial size */
+#define MESSAGE_BUFFER_BLOCK_SIZE 2048
-/*******************************************************************************
- *
- * operate connection with controller
- *
- ******************************************************************************/
-
-/* receive message buffer size */
-#define MESSAGE_BUFFER_BLOCK_SIZE 512
-
-/* controller's ip address */
-static char g_controller_ip[128] = "";
+/* command execution result code */
+enum command_result_code {
+ CRES_SUCCESS = 0,
+ CRES_FAILURE,
+ CRES_INVALID,
+};
-/* controller's port number */
-static int g_controller_port = 0;
+/* command execution result information */
+struct command_result {
+ int code;
+};
-/* allocate message buffer */
-inline char*
-msgbuf_allocate(size_t capacity)
+/* execute one command */
+static int
+execute_command(const struct spp_command *command)
{
- char* buf = (char *)malloc(capacity + sizeof(size_t));
- if (unlikely(buf == NULL))
- return NULL;
+ int ret = 0;
- memset(buf, 0x00, capacity + sizeof(size_t));
- *((size_t *)buf) = capacity;
+ switch (command->type) {
+ case SPP_CMDTYPE_CLASSIFIER_TABLE:
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Execute classifier_table command.");
+ ret = spp_update_classifier_table(
+ command->spec.classifier_table.type,
+ command->spec.classifier_table.value,
+ &command->spec.classifier_table.port);
+ break;
- return buf + sizeof(size_t);
-}
+ case SPP_CMDTYPE_FLUSH:
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Execute flush command.");
+ ret = spp_flush();
+ break;
-/* free message buffer */
-inline void
-msgbuf_free(char* msgbuf)
-{
- if (likely(msgbuf != NULL))
- free(msgbuf - sizeof(size_t));
-}
+ case SPP_CMDTYPE_PROCESS:
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Process command is requested.");
+ /* nothing to do here */
+ break;
-/* get message buffer capacity */
-inline size_t
-msgbuf_get_capacity(const char *msgbuf)
-{
- return *((const size_t *)(msgbuf - sizeof(size_t)));
+ default:
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown command. type=%d\n", command->type);
+ /* nothing to do here */
+ break;
+ }
+
+ return ret;
}
-/* re-allocate message buffer */
-inline char*
-msgbuf_reallocate(char *msgbuf, size_t required_len)
+/* make decode error message for response */
+static const char *
+make_decode_error_message(const struct spp_command_decode_error *decode_error, char *message)
{
- size_t new_cap = msgbuf_get_capacity(msgbuf) * 2;
- char *new_msgbuf = NULL;
+ switch (decode_error->code) {
+ case SPP_CMD_DERR_BAD_FORMAT:
+ sprintf(message, "bad message format");
+ break;
- while (unlikely(new_cap <= required_len))
- new_cap *= 2;
+ case SPP_CMD_DERR_UNKNOWN_COMMAND:
+ sprintf(message, "unknown command(%s)", decode_error->value);
+ break;
- new_msgbuf = msgbuf_allocate(new_cap);
- if (unlikely(new_msgbuf == NULL))
- return NULL;
+ case SPP_CMD_DERR_NO_PARAM:
+ sprintf(message, "not enough parameter(%s)", decode_error->value_name);
+ break;
- strcpy(new_msgbuf, msgbuf);
- msgbuf_free(msgbuf);
+ case SPP_CMD_DERR_BAD_TYPE:
+ sprintf(message, "bad value type(%s)", decode_error->value_name);
+ break;
- return new_msgbuf;
-}
+ case SPP_CMD_DERR_BAD_VALUE:
+ sprintf(message, "bad value(%s)", decode_error->value_name);
+ break;
-/* append message to buffer */
-inline char*
-msgbuf_append(char *msgbuf, const char *append, size_t append_len)
-{
- size_t cap = msgbuf_get_capacity(msgbuf);
- size_t len = strlen(msgbuf);
- char *new_msgbuf = msgbuf;
-
- if (unlikely(len + append_len >= cap)) {
- new_msgbuf = msgbuf_reallocate(msgbuf, len + append_len);
- if (unlikely(new_msgbuf == NULL))
- return NULL;
+ default:
+ sprintf(message, "error occur");
+ break;
}
- memcpy(new_msgbuf + len, append, append_len);
- *(new_msgbuf + len + append_len) = '\0';
-
- return new_msgbuf;
+ return message;
}
-/* remove message from front */
-inline char*
-msgbuf_remove_front(char *msgbuf, size_t remove_len)
+/* create error result object form decode error information */
+inline json_t *
+create_result_object(const char* res_str)
{
- size_t len = strlen(msgbuf);
- size_t new_len = len - remove_len;
-
- if (likely(new_len == 0)) {
- *msgbuf = '\0';
- return msgbuf;
- }
+ return json_pack("{ss}", "result", res_str);
+}
- return memmove(msgbuf, msgbuf + remove_len, new_len + 1);
+/* create error result object form decode error information */
+inline json_t *
+create_error_result_object(const char* err_msg)
+{
+ return json_pack("{sss{ss}}", "result", "error", "error_details",
+ "message", err_msg);
}
-/* connect to controller */
+/* */
static int
-connect_to_controller(int *sock)
+append_response_decode_results_object(json_t *parent_obj,
+ const struct spp_command_request *request,
+ const struct spp_command_decode_error *decode_error)
{
- static struct sockaddr_in controller_addr;
int ret = -1;
- int sock_flg = 0;
-
- if (likely(*sock >=0))
- return 0;
-
- /* create socket */
- if (*sock < 0) {
- RTE_LOG(INFO, SPP_COMMAND_PROC, "Creating socket...\n");
- *sock = socket(AF_INET, SOCK_STREAM, 0);
- if (*sock < 0) {
- RTE_LOG(ERR, SPP_COMMAND_PROC,
- "Cannot create tcp socket. errno=%d\n", errno);
+ int i;
+ json_t *results_obj;
+ char err_msg[128];
+
+ results_obj = json_array();
+ if (unlikely(results_obj == NULL))
+ return -1;
+
+ if (unlikely(decode_error->code == SPP_CMD_DERR_BAD_FORMAT)) {
+ /* create & append bad message format result */
+ ret = json_array_append_new(results_obj,
+ create_error_result_object(
+ make_decode_error_message(decode_error, err_msg)));
+ if (unlikely(ret != 0)) {
+ json_decref(results_obj);
return -1;
}
+ } else {
+ /* create & append results */
+ for (i = 0; i < request->num_command; ++i) {
+ ret = json_array_append_new(results_obj, create_result_object("invalid"));
+ if (unlikely(ret != 0)) {
+ json_decref(results_obj);
+ return -1;
+ }
+ }
- memset(&controller_addr, 0, sizeof(controller_addr));
- controller_addr.sin_family = AF_INET;
- controller_addr.sin_addr.s_addr = inet_addr(g_controller_ip);
- controller_addr.sin_port = htons(g_controller_port);
+ /* create & rewrite error result */
+ if (unlikely(request->num_command != request->num_valid_command)) {
+ ret = json_array_set_new(results_obj,
+ request->num_valid_command,
+ create_error_result_object(
+ make_decode_error_message(decode_error, err_msg)));
+ if (unlikely(ret != 0)) {
+ json_decref(results_obj);
+ return -1;
+ }
+ }
}
- /* connect to */
- RTE_LOG(INFO, SPP_COMMAND_PROC, "Trying to connect ... socket=%d\n", *sock);
- ret = connect(*sock, (struct sockaddr *)&controller_addr,
- sizeof(controller_addr));
- if (ret < 0) {
- RTE_LOG(ERR, SPP_COMMAND_PROC,
- "Cannot connect to controller. errno=%d\n", errno);
+ /* set results object in parent object */
+ ret = json_object_set_new(parent_obj, "results", results_obj);
+ if (unlikely(ret != 0))
return -1;
- }
-
- RTE_LOG(INFO, SPP_COMMAND_PROC, "Connected\n");
-
- /* set non-blocking */
- sock_flg = fcntl(*sock, F_GETFL, 0);
- fcntl(*sock, F_SETFL, sock_flg | O_NONBLOCK);
return 0;
}
-/* receive message */
+/* */
static int
-receive_message(int *sock, char **msgbuf)
+append_response_command_results_object(json_t *parent_obj,
+ const struct spp_command_request *request,
+ const struct command_result *results)
{
int ret = -1;
- int n_rx = 0;
- char *new_msgbuf = NULL;
-
- char rx_buf[MESSAGE_BUFFER_BLOCK_SIZE];
- size_t rx_buf_sz = MESSAGE_BUFFER_BLOCK_SIZE;
-
- ret = recv(*sock, rx_buf, rx_buf_sz, 0);
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Receive message. count=%d\n", ret);
- if (ret <= 0) {
- if (ret == 0) {
- RTE_LOG(INFO, SPP_COMMAND_PROC,
- "Controller has performed an shutdown.");
- } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
- /* no receive message */
- return 0;
- } else {
- RTE_LOG(ERR, SPP_COMMAND_PROC,
- "Receive failure. errno=%d\n", errno);
- }
+ int i;
+ json_t *results_obj, *res_obj;
- RTE_LOG(INFO, SPP_COMMAND_PROC, "Assume Server closed connection\n");
- close(*sock);
- *sock = -1;
+ results_obj = json_array();
+ if (unlikely(results_obj == NULL))
return -1;
- }
- n_rx = ret;
+ /* create & append results */
+ for (i = 0; i < request->num_command; ++i) {
+ switch (results[i].code) {
+ case CRES_SUCCESS:
+ res_obj = create_result_object("success");
+ break;
+ case CRES_FAILURE:
+ res_obj = create_error_result_object("error occur");
+ break;
+ case CRES_INVALID: /* FALLTHROUGH */
+ default:
+ res_obj = create_result_object("invalid");
+ break;
+ }
- new_msgbuf = msgbuf_append(*msgbuf, rx_buf, n_rx);
- if (unlikely(new_msgbuf == NULL)) {
- return -1;
+ ret = json_array_append_new(results_obj, res_obj);
+ if (unlikely(ret != 0)) {
+ json_decref(results_obj);
+ return -1;
+ }
}
- *msgbuf = new_msgbuf;
-
- return n_rx;
-}
-
-/* send message */
-static int
-send_message(int *sock, const char* message, size_t message_len)
-{
- int ret = -1;
-
- ret = send(*sock, message, message_len, 0);
- if (unlikely(ret == -1)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Send failure. ret=%d\n", ret);
+ /* set results object in parent object */
+ ret = json_object_set_new(parent_obj, "results", results_obj);
+ if (unlikely(ret != 0))
return -1;
- }
return 0;
}
-
-/*******************************************************************************
- *
- * process command request(json string)
- *
- ******************************************************************************/
-
-#define CMD_MAX_COMMANDS 32
-
-#define CMD_NAME_BUFSZ 32
-
-#define CMD_CLASSIFIER_TABLE_VALUE_BUFSZ 62
-
-#define CMD_UNUSE "unuse"
-
-#define component_type spp_core_type
-
-/* decode error code */
-enum decode_error_code {
- DERR_BAD_FORMAT = 1,
- DERR_UNKNOWN_COMMAND,
- DERR_NO_PARAM,
- DERR_BAD_TYPE,
- DERR_BAD_VALUE,
-};
-
-/* command type
- do it same as the order of COMMAND_TYPE_STRINGS */
-enum command_type {
- CMDTYPE_ADD,
- CMDTYPE_COMPONENT,
- CMDTYPE_CLASSIFIER_TABLE,
- CMDTYPE_FLUSH,
- CMDTYPE_FORWARD,
- CMDTYPE_STOP,
-
- CMDTYPE_PROCESS,
-};
-
-/* command type string list
- do it same as the order of enum command_type */
-static const char *COMMAND_TYPE_STRINGS[] = {
- "add",
- "component",
- "classifier_table",
- "flush",
- "forward",
- "stop",
-
- /* termination */ "",
-};
-
-/* classifier type string list
- do it same as the order of enum spp_classifier_type (spp_vf.h) */
-static const char *CLASSIFILER_TYPE_STRINGS[] = {
- "none",
- "mac",
-
- /* termination */ "",
-};
-
-#if 0 /* not supported */
-/* "add" command parameters */
-struct add_command {
- int num_port;
- struct spp_config_port_info ports[RTE_MAX_ETHPORTS];
-};
-
-/* "component" command specific parameters */
-struct component_command {
- enum 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 classifier_table_command {
- enum spp_classifier_type type;
- char value[CMD_CLASSIFIER_TABLE_VALUE_BUFSZ];
- struct spp_config_port_info port;
-};
-
-/* "flush" command specific parameters */
-struct flush_command {
- /* nothing specific */
-};
-
-/* command parameters */
-struct command {
- enum command_type type;
-
- union {
-#if 0 /* not supported */
- struct add_command add;
- struct component_command component;
-#endif
- struct classifier_table_command classifier_table;
- struct flush_command flush;
- } spec;
-};
-
-/* request parameters */
-struct request {
- int num_command;
- int num_valid_command;
- struct command commands[CMD_MAX_COMMANDS];
-};
-
-/* forward declaration */
-struct json_value_decode_rule;
-
-/* definition of decode procedure function */
-typedef int (*json_value_decode_proc)(void *, const json_t *, const struct json_value_decode_rule *);
-
-/* rule definition that decode json object to c-struct */
-struct json_value_decode_rule {
- char name[CMD_NAME_BUFSZ];
- json_type json_type;
- size_t offset;
- json_value_decode_proc decode_proc;
-
- struct {
- json_type json_type;
- size_t element_sz;
- size_t offset_num;
- size_t offset_num_valid;
- } array;
-};
-
-/* get output address for decoded json value */
-#define DR_GET_OUTPUT(output_base, rule__) ((char *)output_base + rule__->offset)
-
-/* helper */
-#define END_OF_DECODE_RULE {.name = ""},
-#define IS_END_OF_DECODE_RULE(rule) ((rule)->name[0] == '\0')
-
-/* definition helper that enum value decode procedure */
-#define DECODE_ENUM_VALUE(proc_name, enum_type, string_table) \
-static int \
-decode_##proc_name##_value(void *output, const json_t *value_obj, \
- __rte_unused const struct json_value_decode_rule *rule) \
-{ \
- int i; \
- enum_type type; \
- const char *str_val = json_string_value(value_obj); \
- \
- for (i = 0; string_table[i][0] != '\0'; ++i) { \
- if (unlikely(strcmp(str_val, string_table[i]) == 0)) { \
- type = i; \
- memcpy(output, &type, sizeof(enum_type)); \
- return 0; \
- } \
- } \
- \
- return -1; \
-} \
-
-/* enum value decode procedure for "command_type" */
-DECODE_ENUM_VALUE(command_type, enum command_type, COMMAND_TYPE_STRINGS)
-
-/* enum value decode procedure for "classifier_type" */
-DECODE_ENUM_VALUE(classifier_type, enum spp_classifier_type, CLASSIFILER_TYPE_STRINGS)
-
-#if 0 /* not supported */
-/* decode procedure for integer */
+/* append process value to specified json object */
static int
-decode_int_value(void *output, const json_t *value_obj,
- __rte_unused const struct json_value_decode_rule *rule)
-{
- int val = json_integer_value(value_obj);
- memcpy(output, &val, sizeof(int));
-
- return 0;
-}
-
-/* decode procedure for string */
-static int
-decode_string_value(void *output, const json_t *value_obj,
- __rte_unused const struct json_value_decode_rule *rule)
-{
- const char* str_val = json_string_value(value_obj);
- strcpy(output, str_val);
-
- return 0;
-}
-#endif
-
-/* decode procedure for mac address string */
-static int
-decode_mac_addr_str_value(void *output, const json_t *value_obj,
- __rte_unused const struct json_value_decode_rule *rule)
+append_response_process_value(json_t *parent_obj)
{
int ret = -1;
- const char* str_val = json_string_value(value_obj);
+ json_t *proc_obj;
- ret = spp_config_change_mac_str_to_int64(str_val);
- if (unlikely(ret == -1)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad mac address string. val=%s\n",
- str_val);
- return DERR_BAD_VALUE;
- }
+ proc_obj = json_integer(spp_get_process_id());
+ if (unlikely(proc_obj == NULL))
+ return -1;
- strcpy(output, str_val);
+ ret = json_object_set_new(parent_obj, "process", proc_obj);
+ if (unlikely(ret != 0))
+ return -1;
return 0;
}
-/* decode procedure for spp_config_port_info */
-static int
-decode_port_value(void *output, const json_t *value_obj,
- __rte_unused const struct json_value_decode_rule *rule)
+/* send response for decode error */
+static void
+send_decode_error_response(int *sock, const struct spp_command_request *request,
+ const struct spp_command_decode_error *decode_error)
{
int ret = -1;
- const char* str_val = json_string_value(value_obj);
- struct spp_config_port_info *port = (struct spp_config_port_info *)output;
+ char *msg;
+ json_t *top_obj;
- if (strcmp(str_val, CMD_UNUSE) == 0) {
- port->if_type = UNDEF;
- port->if_no = 0;
- return 0;
+ top_obj = json_object();
+ if (unlikely(top_obj == NULL)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to make decode error response.");
+ return;
}
- ret = spp_config_get_if_info(str_val, &port->if_type, &port->if_no);
+ /* create & append result array */
+ ret = append_response_decode_results_object(top_obj, request, decode_error);
if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad port. val=%s\n", str_val);
- return DERR_BAD_VALUE;
- }
-
- return 0;
-}
-
-/* decode json object */
-static int
-decode_json_object(void *output, const json_t *parent_obj,
- const struct json_value_decode_rule *rules)
-{
- int ret = -1;
- int i, n;
- json_t *obj;
- json_t *value_obj;
- const struct json_value_decode_rule *rule;
-
- void *sub_output;
-
- for (i = 0; unlikely(! IS_END_OF_DECODE_RULE(&rules[i])); ++ i) {
- rule = rules + i;
-
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "get one object. name=%s\n",
- rule->name);
-
- value_obj = json_object_get(parent_obj, rule->name);
- if (unlikely(value_obj == NULL)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "No parameter. "
- "name=%s\n", rule->name);
- return DERR_NO_PARAM;
- } else if (unlikely(json_typeof(value_obj) != rule->json_type)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value type. "
- "name=%s\n", rule->name);
- return DERR_BAD_TYPE;
- }
-
- switch (rule->json_type) {
- case JSON_ARRAY:
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decode array. num=%lu\n",
- json_array_size(value_obj));
-
- *(int *)((char *)output + rule->array.offset_num) =
- (int)json_array_size(value_obj);
-
- json_array_foreach(value_obj, n, obj) {
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decode array element. "
- "index=%d\n", n);
-
- if (unlikely(json_typeof(obj) != rule->array.json_type)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value type. "
- "name=%s, index=%d\n", rule->name, n);
- return DERR_BAD_TYPE;
- }
-
- sub_output = DR_GET_OUTPUT(output, rule) +
- (rule->array.element_sz * n);
- ret = (*rule->decode_proc)(sub_output, obj, rule);
- if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value. "
- "name=%s, index=%d\n", rule->name, n);
- return ret;
- }
- }
- break;
- default:
- sub_output = DR_GET_OUTPUT(output, rule);
- ret = (*rule->decode_proc)(sub_output, value_obj, rule);
- if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value. "
- "name=%s\n", rule->name);
- return ret;
- }
- break;
- }
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to make decode error response.");
+ json_decref(top_obj);
+ return;
}
- return 0;
-}
-
-/* decode rule for command-base */
-const struct json_value_decode_rule DECODERULE_COMMAND_BASE[] = {
- {
- .name = "command",
- .json_type = JSON_STRING,
- .offset = offsetof(struct command, type),
- .decode_proc = decode_command_type_value,
- },
- END_OF_DECODE_RULE
-};
+ /* serialize */
+ msg = json_dumps(top_obj, JSON_INDENT(2));
+ json_decref(top_obj);
-#if 0 /* not supported */
-/* decode rule for add-command-spec */
-const struct json_value_decode_rule DECODERULE_ADD_COMMAND[] = {
- {
- .name = "ports",
- .json_type = JSON_ARRAY,
- .offset = offsetof(struct add_command, ports),
- .decode_proc = decode_port_value,
-
- .array.element_sz = sizeof(struct spp_config_port_info),
- .array.json_type = JSON_STRING,
- .array.offset_num = offsetof(struct add_command, num_port),
- },
- END_OF_DECODE_RULE
-};
-#endif
-
-/* decode rule for classifier-table-command-spec */
-const struct json_value_decode_rule DECODERULE_CLASSIFIER_TABLE_COMMAND[] = {
- {
- .name = "type",
- .json_type = JSON_STRING,
- .offset = offsetof(struct classifier_table_command, type),
- .decode_proc = decode_classifier_type_value,
- },{
- .name = "value",
- .json_type = JSON_STRING,
- .offset = offsetof(struct classifier_table_command, value),
- .decode_proc = decode_mac_addr_str_value,
- },{
- .name = "port",
- .json_type = JSON_STRING,
- .offset = offsetof(struct classifier_table_command, port),
- .decode_proc = decode_port_value,
- },
- END_OF_DECODE_RULE
-};
-
-/* decode procedure for command */
-static int
-decode_command_object(void* output, const json_t *parent_obj,
- __rte_unused const struct json_value_decode_rule *rule)
-{
- int ret = -1;
- struct command *command = (struct command *)output;
- const struct json_value_decode_rule *spec_rules = NULL;
-
- /* decode command-base */
- ret = decode_json_object(command, parent_obj, DECODERULE_COMMAND_BASE);
+ /* send response to requester */
+ ret = spp_send_message(sock, msg, strlen(msg));
if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad command. ret=%d\n", ret);
- return ret;
- }
-
- /* decode command-specific */
- switch (command->type) {
- case CMDTYPE_CLASSIFIER_TABLE:
- spec_rules = DECODERULE_CLASSIFIER_TABLE_COMMAND;
- break;
-
- case CMDTYPE_FLUSH:
- /* nothing specific */
- break;
-
- default:
- /* unknown command */
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown command. type=%d\n",
- command->type);
- return DERR_UNKNOWN_COMMAND;
- }
-
- if (likely(spec_rules != NULL)) {
- ret = decode_json_object(&command->spec, parent_obj, spec_rules);
- if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad command. ret=%d\n", ret);
- return ret;
- }
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to send decode error response.");
+ /* not return */
}
- return 0;
+ free(msg);
}
-/* decode rule for command request */
-const struct json_value_decode_rule DECODERULE_REQUEST[] = {
- {
- .name = "commands",
- .json_type = JSON_ARRAY,
- .offset = offsetof(struct request, commands),
- .decode_proc = decode_command_object,
-
- .array.element_sz = sizeof(struct command),
- .array.json_type = JSON_OBJECT,
- .array.offset_num = offsetof(struct request, num_command),
- .array.offset_num_valid = offsetof(struct request, num_valid_command),
- },
- END_OF_DECODE_RULE
-};
-
-/* decode request from no-null-terminated string */
-static int
-decode_request(struct request *request, const char *request_str, size_t request_str_len)
+/* send response for command execution result */
+static void
+send_command_result_response(int *sock, const struct spp_command_request *request,
+ const struct command_result *command_results)
{
int ret = -1;
+ char *msg;
json_t *top_obj;
- json_error_t json_error;
- /* parse json string */
- top_obj = json_loadb(request_str, request_str_len, 0, &json_error);
+ top_obj = json_object();
if (unlikely(top_obj == NULL)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot parse command request. "
- "error=%s, request_str=%.*s\n",
- json_error.text, (int)request_str_len, request_str);
- return DERR_BAD_FORMAT;
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to make command result response.");
+ return;
}
- /* decode request object */
- ret = decode_json_object(request, top_obj, DECODERULE_REQUEST);
+ /* create & append result array */
+ ret = append_response_command_results_object(top_obj, request, command_results);
if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot decode command request. "
- "ret=%d, request_str=%.*s\n",
- ret, (int)request_str_len, request_str);
- return ret;
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to make command result response.");
+ json_decref(top_obj);
+ return;
}
- return 0;
-}
-
-/* execute one command */
-static int
-execute_command(const struct command *command)
-{
- int ret = -1;
-
- switch (command->type) {
- case CMDTYPE_CLASSIFIER_TABLE:
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Execute classifier_table command.");
- ret = spp_update_classifier_table(
- command->spec.classifier_table.type,
- command->spec.classifier_table.value,
- &command->spec.classifier_table.port);
- break;
-
- case CMDTYPE_FLUSH:
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Execute flush command.");
- ret = spp_flush();
- break;
+ /* append process information value */
+ if (request->is_requested_process) {
+ ret = append_response_process_value(top_obj);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to make command result response.");
+ json_decref(top_obj);
+ return;
+ }
+ }
- case CMDTYPE_PROCESS:
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Execute process command.");
- ret = spp_get_process_id();
- break;
+ /* serialize */
+ msg = json_dumps(top_obj, JSON_INDENT(2));
+ json_decref(top_obj);
- default:
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown command. type=%d\n", command->type);
- ret = 0;
- break;
+ /* send response to requester */
+ ret = spp_send_message(sock, msg, strlen(msg));
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to send decode error response.");
+ /* not return */
}
- return ret;
+ free(msg);
}
/* process command request from no-null-terminated string */
static int
-process_request(const char *request_str, size_t request_str_len)
+process_request(int *sock, const char *request_str, size_t request_str_len)
{
int ret = -1;
int i;
- struct request request;
- memset(&request, 0, sizeof(struct request));
+ struct spp_command_request request;
+ struct spp_command_decode_error decode_error;
+ struct command_result command_results[SPP_CMD_MAX_COMMANDS];
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Start command request processing. "
+ memset(&request, 0, sizeof(struct spp_command_request));
+ memset(&decode_error, 0, sizeof(struct spp_command_decode_error));
+ memset(command_results, 0, sizeof(command_results));
+
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Start command request processing. "
"request_str=%.*s\n", (int)request_str_len, request_str);
- ret = decode_request(&request, request_str, request_str_len);
+ /* decode request message */
+ ret = spp_command_decode_request(
+ &request, request_str, request_str_len, &decode_error);
if (unlikely(ret != 0)) {
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Failed to process command request. "
- "ret=%d\n", ret);
+ /* send error response */
+ send_decode_error_response(sock, &request, &decode_error);
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "End command request processing.\n");
return ret;
}
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decoded command request. "
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Command request is valid. "
"num_command=%d, num_valid_command=%d\n",
request.num_command, request.num_valid_command);
+ /* execute commands */
for (i = 0; i < request.num_command ; ++i) {
ret = execute_command(request.commands + i);
+ if (unlikely(ret != 0)) {
+ command_results[i].code = CRES_FAILURE;
+
+ /* not execute remaining commands */
+ for (++i; i < request.num_command ; ++i)
+ command_results[i].code = CRES_INVALID;
+ break;
+ }
+
+ command_results[i].code = CRES_SUCCESS;
}
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Succeeded to process command request.\n");
+ /* send response */
+ send_command_result_response(sock, &request, command_results);
+
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "End command request processing.\n");
return 0;
}
@@ -739,10 +372,7 @@ process_request(const char *request_str, size_t request_str_len)
int
spp_command_proc_init(const char *controller_ip, int controller_port)
{
- strcpy(g_controller_ip, controller_ip);
- g_controller_port = controller_port;
-
- return 0;
+ return spp_command_conn_init(controller_ip, controller_port);
}
/* process command from controller. */
@@ -761,13 +391,13 @@ spp_command_proc_do(void)
static size_t lb_cnt = 0;
if (unlikely(msgbuf == NULL))
- msgbuf = msgbuf_allocate(MESSAGE_BUFFER_BLOCK_SIZE);
+ msgbuf = spp_strbuf_allocate(MESSAGE_BUFFER_BLOCK_SIZE);
- ret = connect_to_controller(&sock);
+ ret = spp_connect_to_controller(&sock);
if (unlikely(ret != 0))
return;
- msg_ret = receive_message(&sock, &msgbuf);
+ msg_ret = spp_receive_message(&sock, &msgbuf);
if (likely(msg_ret <= 0)) {
return;
}
@@ -784,9 +414,9 @@ spp_command_proc_do(void)
if (likely(lb_cnt != 0) && unlikely(rb_cnt == lb_cnt)) {
msg_len += (i + 1);
- ret = process_request(msgbuf, msg_len);
+ ret = process_request(&sock, msgbuf, msg_len);
- msgbuf_remove_front(msgbuf, msg_len);
+ spp_strbuf_remove_front(msgbuf, msg_len);
msg_ret = 0;
msg_len = 0;
rb_cnt = 0;
diff --git a/src/vf/string_buffer.c b/src/vf/string_buffer.c
new file mode 100644
index 0000000..535d050
--- /dev/null
+++ b/src/vf/string_buffer.c
@@ -0,0 +1,90 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_branch_prediction.h>
+
+#include "string_buffer.h"
+
+/* get message buffer capacity */
+inline size_t
+strbuf_get_capacity(const char *strbuf)
+{
+ return *((const size_t *)(strbuf - sizeof(size_t)));
+}
+
+/* re-allocate message buffer */
+inline char*
+strbuf_reallocate(char *strbuf, size_t required_len)
+{
+ size_t new_cap = strbuf_get_capacity(strbuf) * 2;
+ char *new_strbuf = NULL;
+
+ while (unlikely(new_cap <= required_len))
+ new_cap *= 2;
+
+ new_strbuf = spp_strbuf_allocate(new_cap);
+ if (unlikely(new_strbuf == NULL))
+ return NULL;
+
+ strcpy(new_strbuf, strbuf);
+ spp_strbuf_free(strbuf);
+
+ return new_strbuf;
+}
+
+/* allocate message buffer */
+char*
+spp_strbuf_allocate(size_t capacity)
+{
+ char* buf = (char *)malloc(capacity + sizeof(size_t));
+ if (unlikely(buf == NULL))
+ return NULL;
+
+ memset(buf, 0x00, capacity + sizeof(size_t));
+ *((size_t *)buf) = capacity;
+
+ return buf + sizeof(size_t);
+}
+
+/* free message buffer */
+void
+spp_strbuf_free(char* strbuf)
+{
+ if (likely(strbuf != NULL))
+ free(strbuf - sizeof(size_t));
+}
+
+/* append message to buffer */
+char*
+spp_strbuf_append(char *strbuf, const char *append, size_t append_len)
+{
+ size_t cap = strbuf_get_capacity(strbuf);
+ size_t len = strlen(strbuf);
+ char *new_strbuf = strbuf;
+
+ if (unlikely(len + append_len >= cap)) {
+ new_strbuf = strbuf_reallocate(strbuf, len + append_len);
+ if (unlikely(new_strbuf == NULL))
+ return NULL;
+ }
+
+ memcpy(new_strbuf + len, append, append_len);
+ *(new_strbuf + len + append_len) = '\0';
+
+ return new_strbuf;
+}
+
+/* remove message from front */
+char*
+spp_strbuf_remove_front(char *strbuf, size_t remove_len)
+{
+ size_t len = strlen(strbuf);
+ size_t new_len = len - remove_len;
+
+ if (likely(new_len == 0)) {
+ *strbuf = '\0';
+ return strbuf;
+ }
+
+ return memmove(strbuf, strbuf + remove_len, new_len + 1);
+}
diff --git a/src/vf/string_buffer.h b/src/vf/string_buffer.h
new file mode 100644
index 0000000..adc52ef
--- /dev/null
+++ b/src/vf/string_buffer.h
@@ -0,0 +1,16 @@
+#ifndef _STRING_BUFFER_H_
+#define _STRING_BUFFER_H_
+
+/* allocate message buffer */
+char* spp_strbuf_allocate(size_t capacity);
+
+/* free message buffer */
+void spp_strbuf_free(char* strbuf);
+
+/* append message to buffer */
+char* spp_strbuf_append(char *strbuf, const char *append, size_t append_len);
+
+/* remove message from front */
+char* spp_strbuf_remove_front(char *strbuf, size_t remove_len);
+
+#endif /* _STRING_BUFFER_H_ */
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 25/57] spp_vf: add new log and line break
2017-12-26 1:54 ` Yasufumi Ogawa
` (23 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 24/57] spp_vf: split command processing source file x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 26/57] spp_vf: support get-process-id command x-fn-spp
` (31 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Add new log of command response for better understanding.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_conn.c | 2 +-
src/vf/command_proc.c | 10 ++++++++--
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/vf/command_conn.c b/src/vf/command_conn.c
index edd4d4c..7da4eec 100644
--- a/src/vf/command_conn.c
+++ b/src/vf/command_conn.c
@@ -89,7 +89,6 @@ spp_receive_message(int *sock, char **strbuf)
size_t rx_buf_sz = MESSAGE_BUFFER_BLOCK_SIZE;
ret = recv(*sock, rx_buf, rx_buf_sz, 0);
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Receive message. count=%d\n", ret);
if (ret <= 0) {
if (ret == 0) {
RTE_LOG(INFO, SPP_COMMAND_PROC,
@@ -108,6 +107,7 @@ spp_receive_message(int *sock, char **strbuf)
return -1;
}
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Receive message. count=%d\n", ret);
n_rx = ret;
new_strbuf = spp_strbuf_append(*strbuf, rx_buf, n_rx);
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index 097483c..cda72be 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -256,6 +256,9 @@ send_decode_error_response(int *sock, const struct spp_command_request *request,
msg = json_dumps(top_obj, JSON_INDENT(2));
json_decref(top_obj);
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Make command response (decode error). "
+ "response_str=\n%s\n", msg);
+
/* send response to requester */
ret = spp_send_message(sock, msg, strlen(msg));
if (unlikely(ret != 0)) {
@@ -303,10 +306,13 @@ send_command_result_response(int *sock, const struct spp_command_request *reques
msg = json_dumps(top_obj, JSON_INDENT(2));
json_decref(top_obj);
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Make command response (command result). "
+ "response_str=\n%s\n", msg);
+
/* send response to requester */
ret = spp_send_message(sock, msg, strlen(msg));
if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to send decode error response.");
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to send command result response.");
/* not return */
}
@@ -329,7 +335,7 @@ process_request(int *sock, const char *request_str, size_t request_str_len)
memset(command_results, 0, sizeof(command_results));
RTE_LOG(INFO, SPP_COMMAND_PROC, "Start command request processing. "
- "request_str=%.*s\n", (int)request_str_len, request_str);
+ "request_str=\n%.*s\n", (int)request_str_len, request_str);
/* decode request message */
ret = spp_command_decode_request(
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 26/57] spp_vf: support get-process-id command
2017-12-26 1:54 ` Yasufumi Ogawa
` (24 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 25/57] spp_vf: add new log and line break x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 27/57] spp_vf: update socket creation procedure x-fn-spp
` (30 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
The get-process-id command was missed in the command type check,
and it was processed as an unrecognized command.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_dec.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/src/vf/command_dec.c b/src/vf/command_dec.c
index 85f935b..d3ff27a 100644
--- a/src/vf/command_dec.c
+++ b/src/vf/command_dec.c
@@ -347,15 +347,10 @@ decode_command_object(void* output, const json_t *parent_obj,
spec_rules = DECODERULE_CLASSIFIER_TABLE_COMMAND;
break;
- case SPP_CMDTYPE_FLUSH:
+ default:
/* nothing specific */
+ /* (unknown command is already checked) */
break;
-
- default:
- /* unknown command */
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown command. type=%d\n",
- command->type);
- return set_decode_error(error, SPP_CMD_DERR_UNKNOWN_COMMAND, rule);
}
if (likely(spec_rules != NULL)) {
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 27/57] spp_vf: update socket creation procedure
2017-12-26 1:54 ` Yasufumi Ogawa
` (25 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 26/57] spp_vf: support get-process-id command x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 28/57] spp_vf: change log level and add line break x-fn-spp
` (29 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Update socket socket creation procedure as follows:
* Stop recreating socket spontaneously on failure so the caller can
decide corresponding action.
* Add socket closing procedure when error occurred.
* Add comments.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_conn.c | 26 ++++++++++++++------------
src/vf/command_proc.c | 8 ++++----
src/vf/string_buffer.h | 48 ++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 62 insertions(+), 20 deletions(-)
diff --git a/src/vf/command_conn.c b/src/vf/command_conn.c
index edd4d4c..4ac61a2 100644
--- a/src/vf/command_conn.c
+++ b/src/vf/command_conn.c
@@ -43,21 +43,19 @@ spp_connect_to_controller(int *sock)
return 0;
/* create socket */
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Creating socket...\n");
+ *sock = socket(AF_INET, SOCK_STREAM, 0);
if (*sock < 0) {
- RTE_LOG(INFO, SPP_COMMAND_PROC, "Creating socket...\n");
- *sock = socket(AF_INET, SOCK_STREAM, 0);
- if (*sock < 0) {
- RTE_LOG(ERR, SPP_COMMAND_PROC,
- "Cannot create tcp socket. errno=%d\n", errno);
- return -1;
- }
-
- memset(&controller_addr, 0, sizeof(controller_addr));
- controller_addr.sin_family = AF_INET;
- controller_addr.sin_addr.s_addr = inet_addr(g_controller_ip);
- controller_addr.sin_port = htons(g_controller_port);
+ RTE_LOG(ERR, SPP_COMMAND_PROC,
+ "Cannot create tcp socket. errno=%d\n", errno);
+ return -1;
}
+ memset(&controller_addr, 0, sizeof(controller_addr));
+ controller_addr.sin_family = AF_INET;
+ controller_addr.sin_addr.s_addr = inet_addr(g_controller_ip);
+ controller_addr.sin_port = htons(g_controller_port);
+
/* connect to */
RTE_LOG(INFO, SPP_COMMAND_PROC, "Trying to connect ... socket=%d\n", *sock);
ret = connect(*sock, (struct sockaddr *)&controller_addr,
@@ -65,6 +63,8 @@ spp_connect_to_controller(int *sock)
if (ret < 0) {
RTE_LOG(ERR, SPP_COMMAND_PROC,
"Cannot connect to controller. errno=%d\n", errno);
+ close(*sock);
+ *sock = -1;
return -1;
}
@@ -129,6 +129,8 @@ spp_send_message(int *sock, const char* message, size_t message_len)
ret = send(*sock, message, message_len, 0);
if (unlikely(ret == -1)) {
RTE_LOG(ERR, SPP_COMMAND_PROC, "Send failure. ret=%d\n", ret);
+ close(*sock);
+ *sock = -1;
return -1;
}
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index 097483c..10e209c 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -16,7 +16,7 @@
#define RTE_LOGTYPE_SPP_COMMAND_PROC RTE_LOGTYPE_USER1
/* request message initial size */
-#define MESSAGE_BUFFER_BLOCK_SIZE 2048
+#define CMD_REQ_BUF_INIT_SIZE 2048
/* command execution result code */
enum command_result_code {
@@ -112,7 +112,7 @@ create_error_result_object(const char* err_msg)
"message", err_msg);
}
-/* */
+/* append decode result array object to specified object */
static int
append_response_decode_results_object(json_t *parent_obj,
const struct spp_command_request *request,
@@ -167,7 +167,7 @@ append_response_decode_results_object(json_t *parent_obj,
return 0;
}
-/* */
+/* append command execution result array object to specified object */
static int
append_response_command_results_object(json_t *parent_obj,
const struct spp_command_request *request,
@@ -391,7 +391,7 @@ spp_command_proc_do(void)
static size_t lb_cnt = 0;
if (unlikely(msgbuf == NULL))
- msgbuf = spp_strbuf_allocate(MESSAGE_BUFFER_BLOCK_SIZE);
+ msgbuf = spp_strbuf_allocate(CMD_REQ_BUF_INIT_SIZE);
ret = spp_connect_to_controller(&sock);
if (unlikely(ret != 0))
diff --git a/src/vf/string_buffer.h b/src/vf/string_buffer.h
index adc52ef..9879b9d 100644
--- a/src/vf/string_buffer.h
+++ b/src/vf/string_buffer.h
@@ -1,16 +1,56 @@
#ifndef _STRING_BUFFER_H_
#define _STRING_BUFFER_H_
-/* allocate message buffer */
+/**
+ * allocate string buffer from heap memory.
+ *
+ * @attention allocated memory must free by spp_strbuf_free function.
+ *
+ * @param capacity
+ * initial buffer size (include null char).
+ *
+ * @retval not-NULL pointer to the allocated memory.
+ * @retval NULL error.
+ */
char* spp_strbuf_allocate(size_t capacity);
-/* free message buffer */
+/**
+ * free string buffer.
+ *
+ * @param strbuf
+ * spp_strbuf_allocate/spp_strbuf_append return value.
+ */
void spp_strbuf_free(char* strbuf);
-/* append message to buffer */
+/**
+ * append string to buffer.
+ *
+ * @param strbuf
+ * destination string buffer.
+ * spp_strbuf_allocate/spp_strbuf_append return value.
+ *
+ * @param append
+ * string to append. normal c-string.
+ *
+ * @param append_len
+ * length of append string.
+ *
+ * @return if the capacity is enough, the 1st parameter "strbuf",
+ * if it is insufficient, a new pointer to the allocated memory.
+ * in that case, old strbuf is freed in the function.
+ */
char* spp_strbuf_append(char *strbuf, const char *append, size_t append_len);
-/* remove message from front */
+/**
+ * remove string from front.
+ *
+ * @param strbuf
+ * target string buffer.
+ * spp_strbuf_allocate/spp_strbuf_append return value.
+ *
+ * @param remove_len
+ * length of remove.
+ */
char* spp_strbuf_remove_front(char *strbuf, size_t remove_len);
#endif /* _STRING_BUFFER_H_ */
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 28/57] spp_vf: change log level and add line break
2017-12-26 1:54 ` Yasufumi Ogawa
` (26 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 27/57] spp_vf: update socket creation procedure x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 29/57] spp_vf: replace unsupported jansson api x-fn-spp
` (28 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Change log level and add line break.
* Refactoring
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/classifier_mac.c | 10 +++++-----
src/vf/command_proc.c | 6 +++---
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
index 0852938..cc4af2b 100644
--- a/src/vf/classifier_mac.c
+++ b/src/vf/classifier_mac.c
@@ -109,12 +109,12 @@ init_classifier_table(struct rte_hash **classifier_table,
}
rte_memcpy(ð_addr, &core_info->tx_ports[i].mac_addr, ETHER_ADDR_LEN);
+ ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð_addr);
/* add entry to classifier mac table */
ret = rte_hash_add_key_data(*classifier_table,
(void*)ð_addr, (void*)(long)i);
if (unlikely(ret < 0)) {
- ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð_addr);
RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
"Cannot add entry to classifier mac table. "
"ret=%d, mac_addr=%s\n", ret, mac_addr_str);
@@ -123,7 +123,7 @@ init_classifier_table(struct rte_hash **classifier_table,
return -1;
}
- RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, "Add entry to classifier mac table. "
+ 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,
@@ -299,7 +299,7 @@ change_update_index(struct classifier_mac_mng_info *classifier_mng_info, unsigne
if (unlikely(classifier_mng_info->ref_index ==
classifier_mng_info->upd_index)) {
RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC,
- "Core[%u] Change update index.", lcore_id);
+ "Core[%u] Change update index.\n", lcore_id);
classifier_mng_info->upd_index =
(classifier_mng_info->upd_index + 1) %
NUM_CLASSIFIER_MAC_INFO;
@@ -320,7 +320,7 @@ spp_classifier_mac_update(struct spp_core_info *core_info)
classifier_mng_info->info + classifier_mng_info->upd_index;
RTE_LOG(INFO, SPP_CLASSIFIER_MAC,
- "Core[%u] Start update component.", lcore_id);
+ "Core[%u] Start update component.\n", lcore_id);
/* initialize update side classifier table */
ret = init_classifier_table(&classifier_info->classifier_table, core_info);
@@ -338,7 +338,7 @@ spp_classifier_mac_update(struct spp_core_info *core_info)
rte_delay_us_block(CHANGE_UPDATE_INDEX_WAIT_INTERVAL);
RTE_LOG(INFO, SPP_CLASSIFIER_MAC,
- "Core[%u] Complete update component.", lcore_id);
+ "Core[%u] Complete update component.\n", lcore_id);
return 0;
}
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index cda72be..81bb625 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -38,7 +38,7 @@ execute_command(const struct spp_command *command)
switch (command->type) {
case SPP_CMDTYPE_CLASSIFIER_TABLE:
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Execute classifier_table command.");
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Execute classifier_table command.\n");
ret = spp_update_classifier_table(
command->spec.classifier_table.type,
command->spec.classifier_table.value,
@@ -46,12 +46,12 @@ execute_command(const struct spp_command *command)
break;
case SPP_CMDTYPE_FLUSH:
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Execute flush command.");
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Execute flush command.\n");
ret = spp_flush();
break;
case SPP_CMDTYPE_PROCESS:
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Process command is requested.");
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Execute process command.\n");
/* nothing to do here */
break;
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 29/57] spp_vf: replace unsupported jansson api
2017-12-26 1:54 ` Yasufumi Ogawa
` (27 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 28/57] spp_vf: change log level and add line break x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 30/57] spp_vf: change order of command result in json object x-fn-spp
` (27 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Stop using the json_path_get function and replace it with our own
spp_config_get_path_obj function.
* The json_path_get function is only available at branch of
Jansson project, and it can not be provided in most of
the pkgs(deb,rpm). This change made
for build convenience.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_config.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++-------
src/vf/spp_config.h | 9 +++++++
2 files changed, 68 insertions(+), 9 deletions(-)
diff --git a/src/vf/spp_config.c b/src/vf/spp_config.c
index 4ad4f87..6d8e380 100644
--- a/src/vf/spp_config.c
+++ b/src/vf/spp_config.c
@@ -25,13 +25,63 @@
#define JSONPATH_TX_TABLE "$.tx_port_table"
/*
+ * Instead of json_path_get
+ */
+json_t *
+spp_config_get_path_obj(const json_t *json, const char *path)
+{
+ const json_t *obj, *array_obj;
+ json_t *new_obj = NULL;
+ char buf[SPP_CONFIG_PATH_LEN];
+ char *str, *token, *bracket, *endptr;
+ int index = 0;
+
+ if (unlikely(path[0] != '$') || unlikely(path[1] != '.') ||
+ unlikely(strlen(path) >= SPP_CONFIG_PATH_LEN))
+ return NULL;
+
+ strcpy(buf, path);
+ obj = json;
+ str = buf+1;
+ while(str != NULL) {
+ token = str+1;
+ str = strpbrk(token, ".");
+ if (str != NULL)
+ *str = '\0';
+
+ bracket = strpbrk(token, "[");
+ if (bracket != NULL)
+ *bracket = '\0';
+
+ new_obj = json_object_get(obj, token);
+ if (new_obj == NULL)
+ return NULL;
+
+ if (bracket != NULL) {
+ index = strtol(bracket+1, &endptr, 0);
+ if (unlikely(str == endptr) || unlikely(*endptr != ']'))
+ return NULL;
+
+ array_obj = new_obj;
+ new_obj = json_array_get(array_obj, index);
+ if (new_obj == NULL)
+ return NULL;
+ }
+
+ obj = new_obj;
+ }
+
+ return new_obj;
+}
+
+/*
* Get integer data from config
*/
static int
config_get_int_value(const json_t *obj, const char *path, int *value)
{
/* 指定パラメータのJsonオブジェクト取得 */
- json_t *tmp_obj = json_path_get(obj, path);
+ json_t *tmp_obj = spp_config_get_path_obj(obj, path);
if (unlikely(tmp_obj == NULL)) {
/* 必須でないデータを取得する場合を考慮し、DEBUGログとする。 */
RTE_LOG(DEBUG, APP, "No parameter. (path = %s)\n", path);
@@ -58,7 +108,7 @@ static int
config_get_str_value(const json_t *obj, const char *path, char *value)
{
/* 指定パラメータのJsonオブジェクト取得 */
- json_t *tmp_obj = json_path_get(obj, path);
+ json_t *tmp_obj = spp_config_get_path_obj(obj, path);
if (unlikely(tmp_obj == NULL)) {
RTE_LOG(DEBUG, APP, "No parameter. (path = %s)\n", path);
return -1;
@@ -204,7 +254,7 @@ config_load_classifier_table(const json_t *obj,
struct spp_config_classifier_table *classifier_table)
{
/* classifier_table用オブジェクト取得 */
- json_t *classifier_obj = json_path_get(obj, JSONPATH_CLASSIFIER_TABLE);
+ json_t *classifier_obj = spp_config_get_path_obj(obj, JSONPATH_CLASSIFIER_TABLE);
if (unlikely(classifier_obj == NULL)) {
RTE_LOG(INFO, APP, "No classifier table.\n");
return 0;
@@ -219,7 +269,7 @@ config_load_classifier_table(const json_t *obj,
}
/* table用オブジェクト取得 */
- json_t *array_obj = json_path_get(classifier_obj, JSONPATH_TABLE);
+ json_t *array_obj = spp_config_get_path_obj(classifier_obj, JSONPATH_TABLE);
if (unlikely(!array_obj)) {
RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
JSONPATH_TABLE);
@@ -338,7 +388,7 @@ config_set_rx_port(enum spp_core_type type, json_t *obj,
if (type == SPP_CONFIG_MERGE) {
/* Merge */
/* 受信ポート用オブジェクト取得 */
- json_t *array_obj = json_path_get(obj, JSONPATH_RX_PORT);
+ json_t *array_obj = spp_config_get_path_obj(obj, JSONPATH_RX_PORT);
if (unlikely(!array_obj)) {
RTE_LOG(ERR, APP, "Json object get failed. (path = %s, route = merge)\n",
JSONPATH_RX_PORT);
@@ -454,7 +504,7 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
}
} else {
/* Classifier */
- json_t *table_obj = json_path_get(obj, JSONPATH_TX_TABLE);
+ json_t *table_obj = spp_config_get_path_obj(obj, JSONPATH_TX_TABLE);
if (unlikely(table_obj != NULL)) {
/* Classifier Tableから取得 */
functions->num_tx_port = classifier_table->num_table;
@@ -473,7 +523,7 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
{
/* tx_portパラメータより取得 */
/* 送信ポート用オブジェクト取得 */
- json_t *array_obj = json_path_get(obj, JSONPATH_TX_PORT);
+ json_t *array_obj = spp_config_get_path_obj(obj, JSONPATH_TX_PORT);
if (unlikely(array_obj == NULL)) {
RTE_LOG(ERR, APP, "Json object get failed. (path = %s, route = classifier)\n",
JSONPATH_TX_PORT);
@@ -545,7 +595,7 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
struct spp_config_classifier_table *classifier_table = &config->classifier_table;
/* proc_table用オブジェクト取得 */
- json_t *proc_table_obj = json_path_get(obj, JSONPATH_PROC_TABLE);
+ json_t *proc_table_obj = spp_config_get_path_obj(obj, JSONPATH_PROC_TABLE);
if (unlikely(proc_table_obj == NULL)) {
RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
JSONPATH_PROC_TABLE);
@@ -599,7 +649,7 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
}
/* functions用オブジェクト取得 */
- json_t *array_obj = json_path_get(proc_obj, JSONPATH_FUNCTIONS);
+ json_t *array_obj = spp_config_get_path_obj(proc_obj, JSONPATH_FUNCTIONS);
if (unlikely(!array_obj)) {
RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
JSONPATH_FUNCTIONS);
diff --git a/src/vf/spp_config.h b/src/vf/spp_config.h
index 37414cf..7945807 100644
--- a/src/vf/spp_config.h
+++ b/src/vf/spp_config.h
@@ -1,6 +1,7 @@
#ifndef __SPP_CONFIG_H__
#define __SPP_CONFIG_H__
+#include <jansson.h>
#include "common.h"
#define SPP_CONFIG_FILE_PATH "/usr/local/etc/spp/spp.json"
@@ -12,6 +13,7 @@
#define SPP_CONFIG_STR_LEN 32
#define SPP_CONFIG_MAC_TABLE_MAX 16
#define SPP_CONFIG_CORE_MAX 64
+#define SPP_CONFIG_PATH_LEN 1024
/*
* Process type for each CORE
@@ -81,6 +83,13 @@ struct spp_config_area {
};
/*
+ * Instead of json_path_get
+ * OK : Json object address
+ * NG : NULL
+ */
+json_t *spp_config_get_path_obj(const json_t *json, const char *path);
+
+/*
* Change mac address string to int64
* OK : int64 that store mac address
* NG : -1
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 30/57] spp_vf: change order of command result in json object
2017-12-26 1:54 ` Yasufumi Ogawa
` (28 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 29/57] spp_vf: replace unsupported jansson api x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 31/57] spp_vf: use prediction keywords x-fn-spp
` (26 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Change order of command result in json object (bug fix).
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_proc.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index 81bb625..291e3da 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -244,6 +244,10 @@ send_decode_error_response(int *sock, const struct spp_command_request *request,
return;
}
+ /* **
+ * output order of object in string is inverse to addition order
+ * **/
+
/* create & append result array */
ret = append_response_decode_results_object(top_obj, request, decode_error);
if (unlikely(ret != 0)) {
@@ -284,13 +288,9 @@ send_command_result_response(int *sock, const struct spp_command_request *reques
return;
}
- /* create & append result array */
- ret = append_response_command_results_object(top_obj, request, command_results);
- if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to make command result response.");
- json_decref(top_obj);
- return;
- }
+ /* **
+ * output order of object in string is inverse to addition order
+ * **/
/* append process information value */
if (request->is_requested_process) {
@@ -302,6 +302,14 @@ send_command_result_response(int *sock, const struct spp_command_request *reques
}
}
+ /* create & append result array */
+ ret = append_response_command_results_object(top_obj, request, command_results);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to make command result response.");
+ json_decref(top_obj);
+ return;
+ }
+
/* serialize */
msg = json_dumps(top_obj, JSON_INDENT(2));
json_decref(top_obj);
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 31/57] spp_vf: use prediction keywords
2017-12-26 1:54 ` Yasufumi Ogawa
` (29 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 30/57] spp_vf: change order of command result in json object x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 32/57] spp_vf: fix wrong comparison x-fn-spp
` (25 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Add branch prediction keyword(likely/unlikely) according to DPDK
coding style.
* Add and modify logging procedures.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_conn.c | 17 ++++++++++-------
src/vf/command_proc.c | 8 +++++++-
2 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/src/vf/command_conn.c b/src/vf/command_conn.c
index 98a7e27..ae60c4b 100644
--- a/src/vf/command_conn.c
+++ b/src/vf/command_conn.c
@@ -4,6 +4,7 @@
#include <errno.h>
#include <arpa/inet.h>
+#include <rte_common.h>
#include <rte_log.h>
#include <rte_branch_prediction.h>
@@ -45,7 +46,7 @@ spp_connect_to_controller(int *sock)
/* create socket */
RTE_LOG(INFO, SPP_COMMAND_PROC, "Creating socket...\n");
*sock = socket(AF_INET, SOCK_STREAM, 0);
- if (*sock < 0) {
+ if (unlikely(*sock < 0)) {
RTE_LOG(ERR, SPP_COMMAND_PROC,
"Cannot create tcp socket. errno=%d\n", errno);
return -1;
@@ -60,7 +61,7 @@ spp_connect_to_controller(int *sock)
RTE_LOG(INFO, SPP_COMMAND_PROC, "Trying to connect ... socket=%d\n", *sock);
ret = connect(*sock, (struct sockaddr *)&controller_addr,
sizeof(controller_addr));
- if (ret < 0) {
+ if (unlikely(ret < 0)) {
RTE_LOG(ERR, SPP_COMMAND_PROC,
"Cannot connect to controller. errno=%d\n", errno);
close(*sock);
@@ -89,11 +90,11 @@ spp_receive_message(int *sock, char **strbuf)
size_t rx_buf_sz = MESSAGE_BUFFER_BLOCK_SIZE;
ret = recv(*sock, rx_buf, rx_buf_sz, 0);
- if (ret <= 0) {
- if (ret == 0) {
+ if (unlikely(ret <= 0)) {
+ if (likely(ret == 0)) {
RTE_LOG(INFO, SPP_COMMAND_PROC,
"Controller has performed an shutdown.");
- } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ } else if (likely(errno == EAGAIN || errno == EWOULDBLOCK)) {
/* no receive message */
return 0;
} else {
@@ -101,7 +102,7 @@ spp_receive_message(int *sock, char **strbuf)
"Receive failure. errno=%d\n", errno);
}
- RTE_LOG(INFO, SPP_COMMAND_PROC, "Assume Server closed connection\n");
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Assume Server closed connection.\n");
close(*sock);
*sock = -1;
return -1;
@@ -112,7 +113,9 @@ spp_receive_message(int *sock, char **strbuf)
new_strbuf = spp_strbuf_append(*strbuf, rx_buf, n_rx);
if (unlikely(new_strbuf == NULL)) {
- return -1;
+ RTE_LOG(ERR, SPP_COMMAND_PROC,
+ "Cannot allocate memory for receive data.\n");
+ rte_exit(-1, "Cannot allocate memory for receive data.\n");
}
*strbuf = new_strbuf;
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index f0a1e79..fafb007 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -404,8 +404,14 @@ spp_command_proc_do(void)
static size_t rb_cnt = 0;
static size_t lb_cnt = 0;
- if (unlikely(msgbuf == NULL))
+ if (unlikely(msgbuf == NULL)) {
msgbuf = spp_strbuf_allocate(CMD_REQ_BUF_INIT_SIZE);
+ if (unlikely(msgbuf == NULL)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC,
+ "Cannot allocate memory for receive data(init).\n");
+ rte_exit(-1, "Cannot allocate memory for receive data(init).\n");
+ }
+ }
ret = spp_connect_to_controller(&sock);
if (unlikely(ret != 0))
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 32/57] spp_vf: fix wrong comparison
2017-12-26 1:54 ` Yasufumi Ogawa
` (30 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 31/57] spp_vf: use prediction keywords x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 33/57] spp_vf: update sending error status x-fn-spp
` (24 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Fix variable to be compared.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_config.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vf/spp_config.c b/src/vf/spp_config.c
index 6d8e380..8c82c13 100644
--- a/src/vf/spp_config.c
+++ b/src/vf/spp_config.c
@@ -59,7 +59,7 @@ spp_config_get_path_obj(const json_t *json, const char *path)
if (bracket != NULL) {
index = strtol(bracket+1, &endptr, 0);
- if (unlikely(str == endptr) || unlikely(*endptr != ']'))
+ if (unlikely(bracket+1 == endptr) || unlikely(*endptr != ']'))
return NULL;
array_obj = new_obj;
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 33/57] spp_vf: update sending error status
2017-12-26 1:54 ` Yasufumi Ogawa
` (31 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 32/57] spp_vf: fix wrong comparison x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 34/57] spp_vf: modify conditional statement x-fn-spp
` (23 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Update status code to tell if sending error is temporary or fatal.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_conn.c | 10 +++++-----
src/vf/command_conn.h | 23 +++++++++++++++--------
src/vf/command_proc.c | 14 +++++++++-----
src/vf/command_proc.h | 9 ++++++---
src/vf/spp_vf.c | 11 ++++++++++-
5 files changed, 45 insertions(+), 22 deletions(-)
diff --git a/src/vf/command_conn.c b/src/vf/command_conn.c
index ae60c4b..f3aa76f 100644
--- a/src/vf/command_conn.c
+++ b/src/vf/command_conn.c
@@ -49,7 +49,7 @@ spp_connect_to_controller(int *sock)
if (unlikely(*sock < 0)) {
RTE_LOG(ERR, SPP_COMMAND_PROC,
"Cannot create tcp socket. errno=%d\n", errno);
- return -1;
+ return SPP_CONNERR_TEMPORARY;
}
memset(&controller_addr, 0, sizeof(controller_addr));
@@ -66,7 +66,7 @@ spp_connect_to_controller(int *sock)
"Cannot connect to controller. errno=%d\n", errno);
close(*sock);
*sock = -1;
- return -1;
+ return SPP_CONNERR_TEMPORARY;
}
RTE_LOG(INFO, SPP_COMMAND_PROC, "Connected\n");
@@ -105,7 +105,7 @@ spp_receive_message(int *sock, char **strbuf)
RTE_LOG(INFO, SPP_COMMAND_PROC, "Assume Server closed connection.\n");
close(*sock);
*sock = -1;
- return -1;
+ return SPP_CONNERR_TEMPORARY;
}
RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Receive message. count=%d\n", ret);
@@ -115,7 +115,7 @@ spp_receive_message(int *sock, char **strbuf)
if (unlikely(new_strbuf == NULL)) {
RTE_LOG(ERR, SPP_COMMAND_PROC,
"Cannot allocate memory for receive data.\n");
- rte_exit(-1, "Cannot allocate memory for receive data.\n");
+ return SPP_CONNERR_FATAL;
}
*strbuf = new_strbuf;
@@ -134,7 +134,7 @@ spp_send_message(int *sock, const char* message, size_t message_len)
RTE_LOG(ERR, SPP_COMMAND_PROC, "Send failure. ret=%d\n", ret);
close(*sock);
*sock = -1;
- return -1;
+ return SPP_CONNERR_TEMPORARY;
}
return 0;
diff --git a/src/vf/command_conn.h b/src/vf/command_conn.h
index 0136d75..932c647 100644
--- a/src/vf/command_conn.h
+++ b/src/vf/command_conn.h
@@ -1,6 +1,11 @@
#ifndef _COMMAND_CONN_H_
#define _COMMAND_CONN_H_
+/** result code - temporary error. please retry */
+#define SPP_CONNERR_TEMPORARY -1
+/** result code - fatal error occurred. should teminate process. */
+#define SPP_CONNERR_FATAL -2
+
/**
* intialize command connection.
*
@@ -10,8 +15,8 @@
* @param controller_port
* controller listen port number.
*
- * @ret_val 0 succeeded.
- * @ret_val -1 failed.
+ * @retval 0 succeeded.
+ * @retval SPP_CONNERR_TEMPORARY temporary error. please retry.
*/
int spp_command_conn_init(const char *controller_ip, int controller_port);
@@ -23,8 +28,8 @@ int spp_command_conn_init(const char *controller_ip, int controller_port);
* @param sock
* socket that connect to controller.
*
- * @ret_val 0 succeeded.
- * @ret_val -1 failed.
+ * @retval 0 succeeded.
+ * @retval -1 failed.
*/
int spp_connect_to_controller(int *sock);
@@ -36,8 +41,10 @@ int spp_connect_to_controller(int *sock);
* @param sock
* socket that read data.
*
- * @ret_val 0 succeeded.
- * @ret_val -1 failed.
+ * @retval 0 < succeeded. number of bytes received.
+ * @retval 0 no receive message.
+ * @retval SPP_CONNERR_TEMPORARY temporary error. please reconnect.
+ * @retval SPP_CONNERR_FATAL fatal error occurred. should teminate process.
*/
int spp_receive_message(int *sock, char **msgbuf);
@@ -55,8 +62,8 @@ int spp_receive_message(int *sock, char **msgbuf);
* @param message_len
* send data length.
*
- * @ret_val 0 succeeded.
- * @ret_val -1 failed.
+ * @retval 0 succeeded.
+ * @retval SPP_CONNERR_TEMPORARY temporary error. please reconnect.
*/
int spp_send_message(int *sock, const char* message, size_t message_len);
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index fafb007..c921b51 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -390,7 +390,7 @@ spp_command_proc_init(const char *controller_ip, int controller_port)
}
/* process command from controller. */
-void
+int
spp_command_proc_do(void)
{
int ret = -1;
@@ -409,17 +409,19 @@ spp_command_proc_do(void)
if (unlikely(msgbuf == NULL)) {
RTE_LOG(ERR, SPP_COMMAND_PROC,
"Cannot allocate memory for receive data(init).\n");
- rte_exit(-1, "Cannot allocate memory for receive data(init).\n");
+ return -1;
}
}
ret = spp_connect_to_controller(&sock);
if (unlikely(ret != 0))
- return;
+ return 0;
msg_ret = spp_receive_message(&sock, &msgbuf);
- if (likely(msg_ret <= 0)) {
- return;
+ if (unlikely(msg_ret == 0 || msg_ret == SPP_CONNERR_TEMPORARY)) {
+ return 0;
+ } else if (unlikely(msg_ret < 0)) {
+ return -1;
}
for (i = 0; i < msg_ret; ++i) {
@@ -445,4 +447,6 @@ spp_command_proc_do(void)
}
msg_len = msg_len + msg_ret;
+
+ return 0;
}
diff --git a/src/vf/command_proc.h b/src/vf/command_proc.h
index 8774070..37e55ad 100644
--- a/src/vf/command_proc.h
+++ b/src/vf/command_proc.h
@@ -10,16 +10,19 @@
* @param controller_port
* controller listen port number.
*
- * @ret_val 0 succeeded.
- * @ret_val -1 failed.
+ * @retval 0 succeeded.
+ * @retval -1 failed.
*/
int
spp_command_proc_init(const char *controller_ip, int controller_port);
/**
* process command from controller.
+ *
+ * @retval 0 succeeded.
+ * @retval -1 failed.
*/
-void
+int
spp_command_proc_do(void);
#endif /* _COMMAND_PROC_H_ */
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 7bb1ac0..bd97818 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -954,13 +954,17 @@ ut_main(int argc, char *argv[])
RTE_LOG(INFO, APP, "[Press Ctrl-C to quit ...]\n");
/* loop */
+ int ret_do = 0;
#ifndef USE_UT_SPP_VF
while(likely(g_core_info[main_lcore_id].status != SPP_CORE_STOP_REQUEST)) {
#else
{
#endif
/* コマンド受付 */
- spp_command_proc_do();
+ ret_do = spp_command_proc_do();
+ if (unlikely(ret_do != 0)) {
+ break;
+ }
/* CPUを占有しない様に1秒スリープ */
sleep(1);
@@ -970,6 +974,11 @@ ut_main(int argc, char *argv[])
#endif /* SPP_RINGLATENCYSTATS_ENABLE */
}
+ /* エラー終了 */
+ if (unlikely(ret_do != 0)) {
+ break;
+ }
+
/* 正常終了 */
ret = 0;
break;
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 34/57] spp_vf: modify conditional statement
2017-12-26 1:54 ` Yasufumi Ogawa
` (32 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 33/57] spp_vf: update sending error status x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 35/57] spp_vf: add proc on receiving l2 multicast x-fn-spp
` (22 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Modify followings:
* Comments on function's return value.
* Conditional statement for the actions corresponding to return values
of spp_receive_message.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_conn.h | 8 ++++----
src/vf/command_proc.c | 11 +++++++----
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/src/vf/command_conn.h b/src/vf/command_conn.h
index 932c647..d414ec6 100644
--- a/src/vf/command_conn.h
+++ b/src/vf/command_conn.h
@@ -15,8 +15,8 @@
* @param controller_port
* controller listen port number.
*
- * @retval 0 succeeded.
- * @retval SPP_CONNERR_TEMPORARY temporary error. please retry.
+ * @retval 0 succeeded.
+ * @retval -1 failed.
*/
int spp_command_conn_init(const char *controller_ip, int controller_port);
@@ -28,8 +28,8 @@ int spp_command_conn_init(const char *controller_ip, int controller_port);
* @param sock
* socket that connect to controller.
*
- * @retval 0 succeeded.
- * @retval -1 failed.
+ * @retval 0 succeeded.
+ * @retval SPP_CONNERR_TEMPORARY temporary error. please retry.
*/
int spp_connect_to_controller(int *sock);
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index c921b51..50418cc 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -418,10 +418,13 @@ spp_command_proc_do(void)
return 0;
msg_ret = spp_receive_message(&sock, &msgbuf);
- if (unlikely(msg_ret == 0 || msg_ret == SPP_CONNERR_TEMPORARY)) {
- return 0;
- } else if (unlikely(msg_ret < 0)) {
- return -1;
+ if (unlikely(msg_ret <= 0)) {
+ if (likely(msg_ret == 0))
+ return 0;
+ else if (unlikely(msg_ret == SPP_CONNERR_TEMPORARY))
+ return 0;
+ else
+ return -1;
}
for (i = 0; i < msg_ret; ++i) {
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 35/57] spp_vf: add proc on receiving l2 multicast
2017-12-26 1:54 ` Yasufumi Ogawa
` (33 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 34/57] spp_vf: modify conditional statement x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 36/57] spp_vf: extend limit on number of usable cores x-fn-spp
` (21 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Add two functions for L2 multicast packets
* Transmit them to multiple ports.
* Transmit them to default port when there is no classification.
Add followings to transmit packets to multiple ports:
* Make a list of ports corresponding to MAC addresses.
* Transmit packets of multicast address(I/G bit is 1) to all the ports
listed.
Add followings to transmit packets to default port:
* Set default port via command.
* Use default port when there is no classification.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/classifier_mac.c | 119 ++++++++++++++++++++++++++++++++++++++----------
src/vf/command_dec.c | 4 ++
src/vf/spp_config.c | 6 +++
src/vf/spp_config.h | 4 ++
4 files changed, 108 insertions(+), 25 deletions(-)
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
index cc4af2b..e69347f 100644
--- a/src/vf/classifier_mac.c
+++ b/src/vf/classifier_mac.c
@@ -64,6 +64,9 @@ static const size_t ETHER_ADDR_STR_BUF_SZ =
/* classifier information */
struct classifier_mac_info {
struct rte_hash *classifier_table;
+ int num_active_classified;
+ int active_classifieds[RTE_MAX_ETHPORTS];
+ int default_classified;
};
/* classifier management information */
@@ -91,27 +94,46 @@ static struct classifier_mac_mng_info g_classifier_mng_info[RTE_MAX_LCORE];
but since we want to start at 0. */
static rte_atomic16_t g_hash_table_count = RTE_ATOMIC16_INIT(0xff);
-/* initialize classifier table. */
+/* initialize classifier information. */
static int
-init_classifier_table(struct rte_hash **classifier_table,
+init_classifier_info(struct classifier_mac_info *classifier_info,
const struct spp_core_info *core_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];
rte_hash_reset(*classifier_table);
+ classifier_info->num_active_classified = 0;
+ classifier_info->default_classified = -1;
for (i = 0; i < core_info->num_tx_port; i++) {
if (core_info->tx_ports[i].mac_addr == 0) {
continue;
}
+ /* store active tx_port that associate with mac address */
+ classifier_info->active_classifieds[classifier_info->
+ num_active_classified++] = i;
+
+ /* store default classified */
+ if (unlikely(core_info->tx_ports[i].mac_addr ==
+ SPP_CONFIG_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);
+ continue;
+ }
+
+ /* add entry to classifier mac table */
rte_memcpy(ð_addr, &core_info->tx_ports[i].mac_addr, ETHER_ADDR_LEN);
ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð_addr);
- /* add entry to classifier mac table */
ret = rte_hash_add_key_data(*classifier_table,
(void*)ð_addr, (void*)(long)i);
if (unlikely(ret < 0)) {
@@ -186,11 +208,9 @@ init_classifier(const struct spp_core_info *core_info,
}
}
- /* populate the hash at reference table */
- classifier_mac_table = &classifier_mng_info->info[classifier_mng_info->ref_index].
- classifier_table;
-
- ret = init_classifier_table(classifier_mac_table, core_info);
+ /* populate the classifier information at reference */
+ ret = init_classifier_info(&classifier_mng_info->
+ info[classifier_mng_info->ref_index], core_info);
if (unlikely(ret != 0)) {
RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
"Cannot initialize classifer mac table. ret=%d\n", ret);
@@ -252,6 +272,42 @@ transmit_packet(struct classified_data *classified_data)
classified_data->num_pkt = 0;
}
+/* set mbuf pointer to tx buffer
+ and transmit packet, if buffer is filled */
+static inline void
+push_packet(struct rte_mbuf *pkt, struct classified_data *classified_data)
+{
+ classified_data->pkts[classified_data->num_pkt++] = pkt;
+
+ /* transmit packet, if buffer is filled */
+ if (unlikely(classified_data->num_pkt == MAX_PKT_BURST)) {
+ RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC,
+ "transimit packets (buffer is filled). "
+ "if_type=%d, if_no=%d, tx_port=%hhd, num_pkt=%hu\n",
+ classified_data->if_type,
+ classified_data->if_no,
+ classified_data->tx_port,
+ classified_data->num_pkt);
+ transmit_packet(classified_data);
+ }
+}
+
+/* handle L2 multicast(include broadcast) packet */
+static inline void
+handle_l2multicast_packet(struct rte_mbuf *pkt,
+ struct classifier_mac_info *classifier_info,
+ struct classified_data *classified_data)
+{
+ int i;
+
+ rte_mbuf_refcnt_update(pkt, classifier_info->num_active_classified);
+
+ for (i= 0; i < classifier_info->num_active_classified; i++) {
+ push_packet(pkt, classified_data +
+ (long)classifier_info->active_classifieds[i]);
+ }
+}
+
/* classify packet by destination mac address,
and transmit packet (conditional). */
static inline void
@@ -262,7 +318,6 @@ classify_packet(struct rte_mbuf **rx_pkts, uint16_t n_rx,
int ret;
int i;
struct ether_hdr *eth;
- struct classified_data *cd;
void *lookup_data;
char mac_addr_str[ETHER_ADDR_STR_BUF_SZ];
@@ -272,27 +327,41 @@ classify_packet(struct rte_mbuf **rx_pkts, uint16_t n_rx,
/* find in table (by destination mac address)*/
ret = rte_hash_lookup_data(classifier_info->classifier_table,
(const void*)ð->d_addr, &lookup_data);
- if (unlikely(ret < 0)) {
- ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð->d_addr);
- RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
- "unknown mac address. ret=%d, mac_addr=%s\n", ret, mac_addr_str);
- rte_pktmbuf_free(rx_pkts[i]);
- continue;
- }
+ if (ret < 0) {
+ /* L2 multicast(include broadcast) ? */
+ if (unlikely(is_multicast_ether_addr(ð->d_addr))) {
+ RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC,
+ "multicast mac address.\n");
+ handle_l2multicast_packet(rx_pkts[i],
+ classifier_info, classified_data);
+ continue;
+ }
- /* set mbuf pointer to tx buffer */
- cd = classified_data + (long)lookup_data;
- cd->pkts[cd->num_pkt++] = rx_pkts[i];
+ /* if no default, drop packet */
+ if (unlikely(classifier_info->default_classified == -1)) {
+ ether_format_addr(mac_addr_str,
+ sizeof(mac_addr_str), ð->d_addr);
+ RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
+ "unknown mac address. "
+ "ret=%d, mac_addr=%s\n",
+ ret, mac_addr_str);
+ rte_pktmbuf_free(rx_pkts[i]);
+ continue;
+ }
- /* transmit packet, if buffer is filled */
- if (unlikely(cd->num_pkt == MAX_PKT_BURST)) {
+ /* to default classifed */
RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC,
- "transimit packets (buffer is filled). index=%ld, num_pkt=%hu\n", (long)lookup_data, cd->num_pkt);
- transmit_packet(cd);
+ "to default classified.\n");
+ lookup_data = (void *)(long)classifier_info->default_classified;
}
+
+ /* set mbuf pointer to tx buffer
+ and transmit packet, if buffer is filled */
+ push_packet(rx_pkts[i], classified_data + (long)lookup_data);
}
}
+/* 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)
{
@@ -322,8 +391,8 @@ spp_classifier_mac_update(struct spp_core_info *core_info)
RTE_LOG(INFO, SPP_CLASSIFIER_MAC,
"Core[%u] Start update component.\n", lcore_id);
- /* initialize update side classifier table */
- ret = init_classifier_table(&classifier_info->classifier_table, core_info);
+ /* initialize update side classifier information */
+ ret = init_classifier_info(classifier_info, core_info);
if (unlikely(ret != 0)) {
RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
"Cannot update classifer mac. ret=%d\n", ret);
diff --git a/src/vf/command_dec.c b/src/vf/command_dec.c
index d3ff27a..3295618 100644
--- a/src/vf/command_dec.c
+++ b/src/vf/command_dec.c
@@ -158,6 +158,10 @@ decode_mac_addr_str_value(void *output, const json_t *value_obj,
int ret = -1;
const char* str_val = json_string_value(value_obj);
+ /* 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;
+
ret = spp_config_change_mac_str_to_int64(str_val);
if (unlikely(ret == -1)) {
RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad mac address string. val=%s\n",
diff --git a/src/vf/spp_config.c b/src/vf/spp_config.c
index 8c82c13..663a609 100644
--- a/src/vf/spp_config.c
+++ b/src/vf/spp_config.c
@@ -319,6 +319,12 @@ config_load_classifier_table(const json_t *obj,
return -1;
}
+ /* デフォルト転送先指定であれば内部流通用ダミーアドレスに変換 */
+ if (unlikely(strcmp(tmp_table->mac_addr_str,
+ SPP_CONFIG_DEFAULT_CLASSIFIED_SPEC_STR) == 0))
+ strcpy(tmp_table->mac_addr_str,
+ SPP_CONFIG_DEFAULT_CLASSIFIED_DMY_ADDR_STR);
+
/* MACアドレス数値変換 */
int64_t ret_mac64 = spp_config_change_mac_str_to_int64(
tmp_table->mac_addr_str);
diff --git a/src/vf/spp_config.h b/src/vf/spp_config.h
index 7945807..ac2bc55 100644
--- a/src/vf/spp_config.h
+++ b/src/vf/spp_config.h
@@ -15,6 +15,10 @@
#define SPP_CONFIG_CORE_MAX 64
#define SPP_CONFIG_PATH_LEN 1024
+#define SPP_CONFIG_DEFAULT_CLASSIFIED_SPEC_STR "default"
+#define SPP_CONFIG_DEFAULT_CLASSIFIED_DMY_ADDR_STR "00:00:00:00:00:01"
+#define SPP_CONFIG_DEFAULT_CLASSIFIED_DMY_ADDR 0x010000000000
+
/*
* Process type for each CORE
*/
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 36/57] spp_vf: extend limit on number of usable cores
2017-12-26 1:54 ` Yasufumi Ogawa
` (34 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 35/57] spp_vf: add proc on receiving l2 multicast x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 37/57] spp_vf: add restart procedure for vhost client x-fn-spp
` (20 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Extend the limit on the number of usable cores to 128.
Remove unnecessary check procedure.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_config.h | 2 +-
src/vf/spp_vf.c | 84 +++++------------------------------------------------
2 files changed, 8 insertions(+), 78 deletions(-)
diff --git a/src/vf/spp_config.h b/src/vf/spp_config.h
index ac2bc55..69f6a3f 100644
--- a/src/vf/spp_config.h
+++ b/src/vf/spp_config.h
@@ -12,7 +12,7 @@
#define SPP_CONFIG_STR_LEN 32
#define SPP_CONFIG_MAC_TABLE_MAX 16
-#define SPP_CONFIG_CORE_MAX 64
+#define SPP_CONFIG_CORE_MAX 128
#define SPP_CONFIG_PATH_LEN 1024
#define SPP_CONFIG_DEFAULT_CLASSIFIED_SPEC_STR "default"
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 418520f..6947bf0 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -245,66 +245,6 @@ stop_process(int signal) {
}
/*
- * 起動パラメータのCPUのbitmapを数値へ変換
- */
-static int
-parse_cpu_bit(uint64_t *cpu, const char *cpu_bit)
-{
- char *endptr = NULL;
- uint64_t temp;
-
- temp = strtoull(cpu_bit, &endptr, 0);
- if (unlikely(endptr == cpu_bit) || unlikely(*endptr != '\0')) {
- return -1;
- }
-
- *cpu = temp;
- RTE_LOG(DEBUG, APP, "cpu = %lu", *cpu);
- return 0;
-}
-
-/*
- * Parse the dpdk arguments for use in client app.
- */
-static int
-parse_dpdk_args(int argc, char *argv[])
-{
- int cnt;
- int option_index, opt;
- const int argcopt = argc;
- char *argvopt[argcopt];
- const char *progname = argv[0];
- static struct option lgopts[] = { {0} };
-
- /* getoptを使用するとargvが並び変わるみたいなので、コピーを実施 */
- for (cnt = 0; cnt < argcopt; cnt++) {
- argvopt[cnt] = argv[cnt];
- }
-
- /* Check DPDK parameter */
- optind = 0;
- opterr = 0;
- while ((opt = getopt_long(argc, argvopt, "c:", lgopts,
- &option_index)) != EOF) {
- switch (opt) {
- case 'c':
- /* CPU */
- if (parse_cpu_bit(&g_startup_param.cpu, optarg) != 0) {
- usage(progname);
- return -1;
- }
- break;
- default:
- /* CPU */
- /* DPDKのパラメータは他にもあるので、エラーとはしない */
- break;
- }
- }
-
- return 0;
-}
-
-/*
* Parses the process ID of the application argument.
*/
static int
@@ -493,7 +433,6 @@ set_form_proc_info(struct spp_config_area *config)
int core_cnt, rx_start, rx_cnt, tx_start, tx_cnt;
enum port_type if_type;
int if_no;
- uint64_t cpu_bit = 0;
struct spp_config_functions *core_func = NULL;
struct spp_core_info *core_info = NULL;
struct patch_info *patch_info = NULL;
@@ -517,7 +456,12 @@ set_form_proc_info(struct spp_config_area *config)
/* Set CORE type */
core_info->type = core_func->type;
- cpu_bit |= 1 << core_func->core_no;
+ 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;
+ }
/* Set RX port */
rx_start = core_info->num_rx_port;
@@ -570,14 +514,6 @@ set_form_proc_info(struct spp_config_area *config)
}
}
-#if 0 /* bugfix#385 */
- if (unlikely((cpu_bit & g_startup_param.cpu) != cpu_bit)) {
- /* CPU mismatch */
- RTE_LOG(ERR, APP, "CPU mismatch (cpu param = %lx, config = %lx)\n",
- g_startup_param.cpu, cpu_bit);
- return -1;
- }
-#endif
return 0;
}
@@ -883,12 +819,6 @@ ut_main(int argc, char *argv[])
unsigned int main_lcore_id = 0xffffffff;
while(1) {
- /* Parse dpdk parameters */
- int ret_parse = parse_dpdk_args(argc, argv);
- if (unlikely(ret_parse != 0)) {
- break;
- }
-
/* DPDK initialize */
int ret_dpdk = rte_eal_init(argc, argv);
if (unlikely(ret_dpdk < 0)) {
@@ -903,7 +833,7 @@ ut_main(int argc, char *argv[])
rte_log_set_global_level(RTE_LOG_LEVEL);
/* Parse application parameters */
- ret_parse = parse_app_args(argc, argv);
+ int ret_parse = parse_app_args(argc, argv);
if (unlikely(ret_parse != 0)) {
break;
}
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 37/57] spp_vf: add restart procedure for vhost client
2017-12-26 1:54 ` Yasufumi Ogawa
` (35 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 36/57] spp_vf: extend limit on number of usable cores x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 38/57] spp_vf: fix classifier mbuf handling x-fn-spp
` (19 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Add procedure for restarting vhost-user client
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_vf.c | 36 ++++++++++++++++++++++++++++--------
1 file changed, 28 insertions(+), 8 deletions(-)
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 6947bf0..23c1bd9 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -23,15 +23,16 @@ enum SPP_LONGOPT_RETVAL {
/* add below */
SPP_LONGOPT_RETVAL_CONFIG,
- SPP_LONGOPT_RETVAL_PROCESS_ID
+ SPP_LONGOPT_RETVAL_PROCESS_ID,
+ SPP_LONGOPT_RETVAL_VHOST_CLIENT
};
/* struct */
struct startup_param {
- uint64_t cpu;
int process_id;
char server_ip[INET_ADDRSTRLEN];
int server_port;
+ int vhost_client;
};
struct patch_info {
@@ -68,10 +69,15 @@ static char config_file_path[PATH_MAX];
static void
usage(const char *progname)
{
- RTE_LOG(INFO, APP, "Usage: %s [EAL args] -- --process-id PROC_ID [--config CONFIG_FILE_PATH] -s SERVER_IP:SERVER_PORT\n"
+ RTE_LOG(INFO, APP, "Usage: %s [EAL args] --"
+ " --process-id PROC_ID"
+ " [--config CONFIG_FILE_PATH]"
+ " -s SERVER_IP:SERVER_PORT"
+ " [--vhost-client]\n"
" --process-id PROCESS_ID : My process 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);
}
@@ -103,7 +109,7 @@ add_ring_pmd(int ring_id)
* Set VHOST PMD
*/
static int
-add_vhost_pmd(int index)
+add_vhost_pmd(int index, int client)
{
struct rte_eth_conf port_conf = {
.rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN }
@@ -129,7 +135,8 @@ add_vhost_pmd(int index)
name = get_vhost_backend_name(index);
iface = get_vhost_iface_name(index);
- sprintf(devargs, "%s,iface=%s,queues=%d", name, iface, nr_queues);
+ sprintf(devargs, "%s,iface=%s,queues=%d,client=%d",
+ name, iface, nr_queues, client);
ret = rte_eth_dev_attach(devargs, &vhost_port_id);
if (unlikely(ret < 0)) {
RTE_LOG(ERR, APP, "rte_eth_dev_attach error. (ret = %d)\n", ret);
@@ -308,6 +315,7 @@ parse_app_args(int argc, char *argv[])
static struct option lgopts[] = {
{ "config", required_argument, NULL, SPP_LONGOPT_RETVAL_CONFIG },
{ "process-id", required_argument, NULL, SPP_LONGOPT_RETVAL_PROCESS_ID },
+ { "vhost-client", no_argument, NULL, SPP_LONGOPT_RETVAL_VHOST_CLIENT },
{ 0 },
};
@@ -316,6 +324,9 @@ parse_app_args(int argc, char *argv[])
argvopt[cnt] = argv[cnt];
}
+ /* Clear startup parameters */
+ memset(&g_startup_param, 0x00, sizeof(g_startup_param));
+
/* Check application parameter */
optind = 0;
opterr = 0;
@@ -336,6 +347,9 @@ parse_app_args(int argc, char *argv[])
}
proc_flg = 1;
break;
+ case SPP_LONGOPT_RETVAL_VHOST_CLIENT:
+ g_startup_param.vhost_client = 1;
+ break;
case 's':
if (parse_app_server(optarg, g_startup_param.server_ip,
&g_startup_param.server_port) != 0) {
@@ -356,11 +370,12 @@ parse_app_args(int argc, char *argv[])
usage(progname);
return -1;
}
- RTE_LOG(INFO, APP, "application arguments value. (process id = %d, config = %s, server = %s:%d)\n",
+ RTE_LOG(INFO, APP, "application arguments value. (process id = %d, config = %s, server = %s:%d, vhost client = %d)\n",
g_startup_param.process_id,
config_file_path,
g_startup_param.server_ip,
- g_startup_param.server_port);
+ g_startup_param.server_port,
+ g_startup_param.vhost_client);
return 0;
}
@@ -619,7 +634,7 @@ set_vhost_interface(struct spp_config_area *config)
}
/* Set DPDK port */
- int dpdk_port = add_vhost_pmd(vhost_cnt);
+ 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);
@@ -779,6 +794,11 @@ static void
del_vhost_sockfile(struct patch_info *vhost_patchs)
{
int cnt;
+
+ /* Do not delete for vhost client. */
+ if (g_startup_param.vhost_client != 0)
+ return;
+
for (cnt = 0; cnt < RTE_MAX_ETHPORTS; cnt++) {
if (likely(vhost_patchs[cnt].use_flg == 0)) {
/* VHOST未使用はスキップ */
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 38/57] spp_vf: fix classifier mbuf handling
2017-12-26 1:54 ` Yasufumi Ogawa
` (36 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 37/57] spp_vf: add restart procedure for vhost client x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 39/57] spp_vf: add status command x-fn-spp
` (18 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Fix mbuf handling on receiving L2 multicast packet
when no destination port is set.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/classifier_mac.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
index e69347f..64e9883 100644
--- a/src/vf/classifier_mac.c
+++ b/src/vf/classifier_mac.c
@@ -300,6 +300,12 @@ handle_l2multicast_packet(struct rte_mbuf *pkt,
{
int i;
+ if (unlikely(classifier_info->num_active_classified == 0)) {
+ RTE_LOG(ERR, SPP_CLASSIFIER_MAC, "No mac address.\n");
+ rte_pktmbuf_free(pkt);
+ return;
+ }
+
rte_mbuf_refcnt_update(pkt, classifier_info->num_active_classified);
for (i= 0; i < classifier_info->num_active_classified; i++) {
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 39/57] spp_vf: add status command
2017-12-26 1:54 ` Yasufumi Ogawa
` (37 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 38/57] spp_vf: fix classifier mbuf handling x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 40/57] spp_vf: add output source information in error log x-fn-spp
` (17 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* classifier_mac.c: Add new data and associated operations.
* classifier_mac.c: Add new API to get classifier status information.
* command_dec.c: Add command type for new decoding rule.
* command_proc.c: Add status for preparing command response.
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/classifier_mac.c | 100 ++++++++++++++++++++++++++++++++++------
src/vf/classifier_mac.h | 12 +++++
src/vf/command_dec.c | 4 ++
src/vf/command_dec.h | 2 +
src/vf/command_proc.c | 118 +++++++++++++++++++++++++++++++++++++-----------
src/vf/spp_config.c | 26 +++++++++++
src/vf/spp_config.h | 8 ++++
src/vf/spp_vf.c | 22 +++++++++
src/vf/spp_vf.h | 18 ++++++++
9 files changed, 268 insertions(+), 42 deletions(-)
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
index e69347f..81a20ac 100644
--- a/src/vf/classifier_mac.c
+++ b/src/vf/classifier_mac.c
@@ -61,6 +61,16 @@ static const size_t HASH_TABLE_NAME_BUF_SZ =
static const size_t ETHER_ADDR_STR_BUF_SZ =
ETHER_ADDR_LEN * 2 + (ETHER_ADDR_LEN - 1) + 1;
+/* 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];
+};
+
/* classifier information */
struct classifier_mac_info {
struct rte_hash *classifier_table;
@@ -74,15 +84,7 @@ struct classifier_mac_mng_info {
struct classifier_mac_info info[NUM_CLASSIFIER_MAC_INFO];
volatile int ref_index;
volatile int upd_index;
-};
-
-/* classified data (destination port, target packets, etc) */
-struct classified_data {
- enum port_type if_type;
- int if_no;
- uint8_t tx_port;
- uint16_t num_pkt;
- struct rte_mbuf *pkts[MAX_PKT_BURST];
+ struct classified_data classified_data[RTE_MAX_ETHPORTS];
};
/* classifier information per lcore */
@@ -94,6 +96,12 @@ static struct classifier_mac_mng_info g_classifier_mng_info[RTE_MAX_LCORE];
but since we want to start at 0. */
static rte_atomic16_t g_hash_table_count = RTE_ATOMIC16_INIT(0xff);
+static inline int
+is_used_mng_info(const struct classifier_mac_mng_info *mng_info)
+{
+ return (mng_info != NULL && mng_info->info[0].classifier_table != NULL);
+}
+
/* initialize classifier information. */
static int
init_classifier_info(struct classifier_mac_info *classifier_info,
@@ -219,10 +227,11 @@ init_classifier(const struct spp_core_info *core_info,
/* 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].tx_port = core_info->tx_ports[i].dpdk_port;
- classified_data[i].num_pkt = 0;
+ 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;
}
return 0;
@@ -283,8 +292,9 @@ push_packet(struct rte_mbuf *pkt, struct classified_data *classified_data)
if (unlikely(classified_data->num_pkt == MAX_PKT_BURST)) {
RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC,
"transimit packets (buffer is filled). "
- "if_type=%d, if_no=%d, tx_port=%hhd, num_pkt=%hu\n",
+ "if_type=%d, if_no={%d,%d}, tx_port=%hhd, num_pkt=%hu\n",
classified_data->if_type,
+ classified_data->if_no_global,
classified_data->if_no,
classified_data->tx_port,
classified_data->num_pkt);
@@ -375,6 +385,15 @@ change_update_index(struct classifier_mac_mng_info *classifier_mng_info, unsigne
}
}
+/* classifier(mac address) initialize globals. */
+int
+spp_classifier_mac_init(void)
+{
+ memset(g_classifier_mng_info, 0, sizeof(g_classifier_mng_info));
+
+ return 0;
+}
+
/* classifier(mac address) update component info. */
int
spp_classifier_mac_update(struct spp_core_info *core_info)
@@ -428,7 +447,7 @@ spp_classifier_mac_do(void *arg)
struct rte_mbuf *rx_pkts[MAX_PKT_BURST];
const int n_classified_data = core_info->num_tx_port;
- struct classified_data classified_data[n_classified_data];
+ struct classified_data *classified_data = classifier_mng_info->classified_data;
uint64_t cur_tsc, prev_tsc = 0;
const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
@@ -501,3 +520,54 @@ spp_classifier_mac_do(void *arg)
return 0;
}
+
+/* classifier(mac address) iterate classifier table. */
+int spp_classifier_mac_iterate_table(
+ struct spp_iterate_classifier_table_params *params)
+{
+ int ret, i;
+ const void *key;
+ void *data;
+ uint32_t next = 0;
+ 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;
+ char mac_addr_str[ETHER_ADDR_STR_BUF_SZ];
+
+ for (i = 0; i < RTE_MAX_LCORE; i++) {
+ classifier_mng_info = g_classifier_mng_info + i;
+ if (! is_used_mng_info(classifier_mng_info))
+ continue;
+
+ classifier_info = classifier_mng_info->info +
+ classifier_mng_info->ref_index;
+
+ classified_data = classifier_mng_info->classified_data;
+
+ RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC,
+ "Core[%u] Start iterate classifier table.\n", i);
+
+ while(1) {
+ ret = rte_hash_iterate(classifier_info->classifier_table,
+ &key, &data, &next);
+
+ if (unlikely(ret < 0))
+ break;
+
+ ether_format_addr(mac_addr_str, sizeof(mac_addr_str),
+ (const struct ether_addr *)key);
+
+ port.if_type = (classified_data + (long)data)->if_type;
+ port.if_no = (classified_data + (long)data)->if_no_global;
+
+ (*params->element_proc)(
+ params->opaque,
+ SPP_CLASSIFIER_TYPE_MAC,
+ mac_addr_str,
+ &port);
+ }
+ }
+
+ return 0;
+}
diff --git a/src/vf/classifier_mac.h b/src/vf/classifier_mac.h
index 98f47a5..b1d0198 100644
--- a/src/vf/classifier_mac.h
+++ b/src/vf/classifier_mac.h
@@ -3,6 +3,12 @@
/* forward declaration */
struct spp_core_info;
+struct spp_iterate_classifier_table_params;
+
+/**
+ * classifier(mac address) initialize globals.
+ */
+int spp_classifier_mac_init(void);
/**
* classifier(mac address) update component info.
@@ -23,4 +29,10 @@ int spp_classifier_mac_update(struct spp_core_info *core_info);
*/
int spp_classifier_mac_do(void *arg);
+/**
+ * classifier(mac address) iterate classifier table.
+ */
+int spp_classifier_mac_iterate_table(
+ struct spp_iterate_classifier_table_params *params);
+
#endif /* _CLASSIFIER_MAC_H_ */
diff --git a/src/vf/command_dec.c b/src/vf/command_dec.c
index 3295618..bc8829f 100644
--- a/src/vf/command_dec.c
+++ b/src/vf/command_dec.c
@@ -26,6 +26,7 @@ static const char *COMMAND_TYPE_STRINGS[] = {
"stop",
#endif
"process",
+ "status",
/* termination */ "",
};
@@ -422,6 +423,9 @@ spp_command_decode_request(struct spp_command_request *request, const char *requ
case SPP_CMDTYPE_PROCESS:
request->is_requested_process = 1;
break;
+ case SPP_CMDTYPE_STATUS:
+ request->is_requested_status = 1;
+ break;
default:
/* nothing to do */
break;
diff --git a/src/vf/command_dec.h b/src/vf/command_dec.h
index 25e1ea0..42a0168 100644
--- a/src/vf/command_dec.h
+++ b/src/vf/command_dec.h
@@ -40,6 +40,7 @@ enum spp_command_type {
SPP_CMDTYPE_STOP,
#endif
SPP_CMDTYPE_PROCESS,
+ SPP_CMDTYPE_STATUS,
};
#if 0 /* not supported yet */
@@ -93,6 +94,7 @@ struct spp_command_request {
struct spp_command commands[SPP_CMD_MAX_COMMANDS];
int is_requested_process;
+ int is_requested_status;
};
/* decode error information */
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index 50418cc..a627277 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -50,13 +50,8 @@ execute_command(const struct spp_command *command)
ret = spp_flush();
break;
- case SPP_CMDTYPE_PROCESS:
- RTE_LOG(INFO, SPP_COMMAND_PROC, "Execute process command.\n");
- /* nothing to do here */
- break;
-
default:
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown command. type=%d\n", command->type);
+ RTE_LOG(INFO, SPP_COMMAND_PROC, "Execute other command. type=%d\n", command->type);
/* nothing to do here */
break;
}
@@ -229,6 +224,73 @@ append_response_process_value(json_t *parent_obj)
return 0;
}
+/* append classifier element value */
+static
+int append_classifier_element_value(
+ void *opaque,
+ __rte_unused enum spp_classifier_type type,
+ const char *data,
+ const struct spp_config_port_info *port)
+{
+ json_t *parent_obj = (json_t *)opaque;
+
+ char port_str[64];
+ spp_config_format_if_info(port_str, port->if_type, port->if_no);
+
+ json_array_append_new(parent_obj, json_pack(
+ "{ssssss}",
+ "type", "mac",
+ "value", data,
+ "port", port_str));
+
+ return 0;
+}
+
+/* append info value(status response) to specified json object */
+static int
+append_response_info_value(json_t *parent_obj)
+{
+ int ret = -1;
+ json_t *info_obj, *tab_obj;
+ struct spp_iterate_classifier_table_params itr_params;
+
+ /* create classifier_table array */
+ tab_obj = json_array();
+ if (unlikely(tab_obj == NULL))
+ return -1;
+
+ itr_params.opaque = tab_obj;
+ itr_params.element_proc = append_classifier_element_value;
+
+ ret = spp_iterate_classifier_table(&itr_params);
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
+
+ /* set classifier_table object in info object */
+ info_obj = json_object();
+ if (unlikely(info_obj == NULL)) {
+ json_decref(tab_obj);
+ return -1;
+ }
+
+ ret = json_object_set_new(info_obj, "classifier_table", tab_obj);
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
+
+ /* set info object in parent object */
+ ret = json_object_set_new(parent_obj, "info", info_obj);
+ if (unlikely(ret != 0)) {
+ json_decref(info_obj);
+ return -1;
+ }
+
+ return 0;
+}
+
/* send response for decode error */
static void
send_decode_error_response(int *sock, const struct spp_command_request *request,
@@ -244,10 +306,6 @@ send_decode_error_response(int *sock, const struct spp_command_request *request,
return;
}
- /* **
- * output order of object in string is inverse to addition order
- * **/
-
/* create & append result array */
ret = append_response_decode_results_object(top_obj, request, decode_error);
if (unlikely(ret != 0)) {
@@ -257,10 +315,10 @@ send_decode_error_response(int *sock, const struct spp_command_request *request,
}
/* serialize */
- msg = json_dumps(top_obj, JSON_INDENT(2));
+ msg = json_dumps(top_obj, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
json_decref(top_obj);
- RTE_LOG(INFO, SPP_COMMAND_PROC, "Make command response (decode error). "
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Make command response (decode error). "
"response_str=\n%s\n", msg);
/* send response to requester */
@@ -288,9 +346,13 @@ send_command_result_response(int *sock, const struct spp_command_request *reques
return;
}
- /* **
- * output order of object in string is inverse to addition order
- * **/
+ /* create & append result array */
+ ret = append_response_command_results_object(top_obj, request, command_results);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to make command result response.");
+ json_decref(top_obj);
+ return;
+ }
/* append process information value */
if (request->is_requested_process) {
@@ -302,19 +364,21 @@ send_command_result_response(int *sock, const struct spp_command_request *reques
}
}
- /* create & append result array */
- ret = append_response_command_results_object(top_obj, request, command_results);
- if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to make command result response.");
- json_decref(top_obj);
- return;
+ /* append info value */
+ if (request->is_requested_status) {
+ ret = append_response_info_value(top_obj);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to make command result response.");
+ json_decref(top_obj);
+ return;
+ }
}
/* serialize */
- msg = json_dumps(top_obj, JSON_INDENT(2));
+ msg = json_dumps(top_obj, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
json_decref(top_obj);
- RTE_LOG(INFO, SPP_COMMAND_PROC, "Make command response (command result). "
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Make command response (command result). "
"response_str=\n%s\n", msg);
/* send response to requester */
@@ -342,7 +406,7 @@ process_request(int *sock, const char *request_str, size_t request_str_len)
memset(&decode_error, 0, sizeof(struct spp_command_decode_error));
memset(command_results, 0, sizeof(command_results));
- RTE_LOG(INFO, SPP_COMMAND_PROC, "Start command request processing. "
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Start command request processing. "
"request_str=\n%.*s\n", (int)request_str_len, request_str);
/* decode request message */
@@ -351,11 +415,11 @@ process_request(int *sock, const char *request_str, size_t request_str_len)
if (unlikely(ret != 0)) {
/* send error response */
send_decode_error_response(sock, &request, &decode_error);
- RTE_LOG(INFO, SPP_COMMAND_PROC, "End command request processing.\n");
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "End command request processing.\n");
return ret;
}
- RTE_LOG(INFO, SPP_COMMAND_PROC, "Command request is valid. "
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Command request is valid. "
"num_command=%d, num_valid_command=%d\n",
request.num_command, request.num_valid_command);
@@ -377,7 +441,7 @@ process_request(int *sock, const char *request_str, size_t request_str_len)
/* send response */
send_command_result_response(sock, &request, command_results);
- RTE_LOG(INFO, SPP_COMMAND_PROC, "End command request processing.\n");
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "End command request processing.\n");
return 0;
}
diff --git a/src/vf/spp_config.c b/src/vf/spp_config.c
index 663a609..01f279a 100644
--- a/src/vf/spp_config.c
+++ b/src/vf/spp_config.c
@@ -198,6 +198,32 @@ spp_config_get_if_info(const char *port, enum port_type *if_type, int *if_no)
}
/*
+ * IF種別とIF番号からIF情報文字列を作成する
+ */
+int spp_config_format_if_info(char *port, enum port_type if_type, int if_no)
+{
+ const char* if_type_str;
+
+ switch (if_type) {
+ case PHY:
+ if_type_str = SPP_CONFIG_IFTYPE_NIC;
+ break;
+ case RING:
+ if_type_str = SPP_CONFIG_IFTYPE_RING;
+ break;
+ case VHOST:
+ if_type_str = SPP_CONFIG_IFTYPE_VHOST;
+ break;
+ default:
+ return -1;
+ }
+
+ sprintf(port, "%s%d", if_type_str, if_no);
+
+ return 0;
+}
+
+/*
* MAC addressを文字列から数値へ変換
*/
int64_t
diff --git a/src/vf/spp_config.h b/src/vf/spp_config.h
index 69f6a3f..a9bcb85 100644
--- a/src/vf/spp_config.h
+++ b/src/vf/spp_config.h
@@ -109,6 +109,14 @@ int64_t spp_config_change_mac_str_to_int64(const char *mac);
int spp_config_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_config_format_if_info(char *port, enum port_type if_type, int if_no);
+
+/*
* Load config file
* OK : 0
* NG : -1
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 23c1bd9..18533d1 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -877,6 +877,12 @@ ut_main(int argc, char *argv[])
}
/* 他機能部初期化 */
+ /* MAC振分初期化 */
+ int ret_classifier_mac_init = spp_classifier_mac_init();
+ if (unlikely(ret_classifier_mac_init != 0)) {
+ break;
+ }
+
/* コマンド機能部初期化 */
int ret_command_init = spp_command_proc_init(
g_startup_param.server_ip,
@@ -1130,3 +1136,19 @@ spp_flush(void)
memset(g_change_core, 0x00, sizeof(g_change_core));
return SPP_RET_OK;
}
+
+/*
+ * Iterate Classifier_table
+ */
+int spp_iterate_classifier_table(struct spp_iterate_classifier_table_params *params)
+{
+ int ret;
+
+ ret = spp_classifier_mac_iterate_table(params);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, APP, "Cannot iterate classfier_mac_table.\n");
+ return SPP_RET_NG;
+ }
+
+ return SPP_RET_OK;
+}
diff --git a/src/vf/spp_vf.h b/src/vf/spp_vf.h
index 4ca4568..bbdb904 100644
--- a/src/vf/spp_vf.h
+++ b/src/vf/spp_vf.h
@@ -82,4 +82,22 @@ int spp_update_classifier_table(enum spp_classifier_type type, const char *data,
*/
int spp_flush(void);
+/* definition of iterated classifier element procedure function */
+typedef int (*spp_iterate_classifier_element_proc)(
+ void *opaque,
+ enum spp_classifier_type type,
+ const char *data,
+ const struct spp_config_port_info *port);
+
+/* iterate classifier table parameters */
+struct spp_iterate_classifier_table_params {
+ void *opaque;
+ spp_iterate_classifier_element_proc element_proc;
+};
+
+/*
+ * Iterate Classifier_table
+ */
+int spp_iterate_classifier_table(struct spp_iterate_classifier_table_params *params);
+
#endif /* __SPP_VF_H__ */
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 40/57] spp_vf: add output source information in error log
2017-12-26 1:54 ` Yasufumi Ogawa
` (38 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 39/57] spp_vf: add status command x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 41/57] spp_vf: change function names x-fn-spp
` (16 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Add output source information in error log so that it becomes unique.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/classifier_mac.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
index 64e9883..157ee02 100644
--- a/src/vf/classifier_mac.c
+++ b/src/vf/classifier_mac.c
@@ -301,7 +301,7 @@ handle_l2multicast_packet(struct rte_mbuf *pkt,
int i;
if (unlikely(classifier_info->num_active_classified == 0)) {
- RTE_LOG(ERR, SPP_CLASSIFIER_MAC, "No mac address.\n");
+ RTE_LOG(ERR, SPP_CLASSIFIER_MAC, "No mac address.(l2multicast packet)\n");
rte_pktmbuf_free(pkt);
return;
}
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 41/57] spp_vf: change function names
2017-12-26 1:54 ` Yasufumi Ogawa
` (39 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 40/57] spp_vf: add output source information in error log x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 42/57] spp_vf: change how to request commands x-fn-spp
` (15 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Change function name in program files according to the change of
the function name from "spp_config_format_if_info" to
"spp_config_format_port_string"
Signed-off-by: Daiki Yamashita <yamashita.daiki.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_proc.c | 2 +-
src/vf/spp_config.c | 2 +-
src/vf/spp_config.h | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index a627277..fe18e22 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -235,7 +235,7 @@ int append_classifier_element_value(
json_t *parent_obj = (json_t *)opaque;
char port_str[64];
- spp_config_format_if_info(port_str, port->if_type, port->if_no);
+ spp_config_format_port_string(port_str, port->if_type, port->if_no);
json_array_append_new(parent_obj, json_pack(
"{ssssss}",
diff --git a/src/vf/spp_config.c b/src/vf/spp_config.c
index 01f279a..27bce8f 100644
--- a/src/vf/spp_config.c
+++ b/src/vf/spp_config.c
@@ -200,7 +200,7 @@ spp_config_get_if_info(const char *port, enum port_type *if_type, int *if_no)
/*
* IF種別とIF番号からIF情報文字列を作成する
*/
-int spp_config_format_if_info(char *port, enum port_type if_type, int if_no)
+int spp_config_format_port_string(char *port, enum port_type if_type, int if_no)
{
const char* if_type_str;
diff --git a/src/vf/spp_config.h b/src/vf/spp_config.h
index a9bcb85..7a8bdf6 100644
--- a/src/vf/spp_config.h
+++ b/src/vf/spp_config.h
@@ -114,7 +114,7 @@ int spp_config_get_if_info(const char *port, enum port_type *if_type, int *if_no
* OK : 0
* NG : -1
*/
-int spp_config_format_if_info(char *port, enum port_type if_type, int if_no);
+int spp_config_format_port_string(char *port, enum port_type if_type, int if_no);
/*
* Load config file
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 42/57] spp_vf: change how to request commands
2017-12-26 1:54 ` Yasufumi Ogawa
` (40 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 41/57] spp_vf: change function names x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 43/57] spp_vf: update command decode procedure x-fn-spp
` (14 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Change the way how to request commands.
spp_nfv command is used instead of requesting via json file.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_dec.c | 503 +++++++++++++++++++-------------------------------
src/vf/command_dec.h | 15 +-
src/vf/command_proc.c | 44 +----
src/vf/spp_config.c | 14 +-
src/vf/spp_config.h | 2 +-
src/vf/spp_vf.c | 38 ++--
src/vf/spp_vf.h | 8 +-
7 files changed, 233 insertions(+), 391 deletions(-)
diff --git a/src/vf/command_dec.c b/src/vf/command_dec.c
index bc8829f..468702f 100644
--- a/src/vf/command_dec.c
+++ b/src/vf/command_dec.c
@@ -4,33 +4,12 @@
#include <rte_log.h>
#include <rte_branch_prediction.h>
-#include <jansson.h>
-
#include "spp_vf.h"
#include "spp_config.h"
#include "command_dec.h"
#define RTE_LOGTYPE_SPP_COMMAND_PROC RTE_LOGTYPE_USER1
-/* command type string list
- do it same as the order of enum command_type */
-static const char *COMMAND_TYPE_STRINGS[] = {
-#if 0 /* not supported yet */
- "add",
- "component",
-#endif
- "classifier_table",
- "flush",
-#if 0 /* not supported yet */
- "forward",
- "stop",
-#endif
- "process",
- "status",
-
- /* termination */ "",
-};
-
/* classifier type string list
do it same as the order of enum spp_classifier_type (spp_vf.h) */
static const char *CLASSIFILER_TYPE_STRINGS[] = {
@@ -40,44 +19,15 @@ static const char *CLASSIFILER_TYPE_STRINGS[] = {
/* termination */ "",
};
-/* forward declaration */
-struct json_value_decode_rule;
-
-/* definition of decode procedure function */
-typedef int (*json_value_decode_proc)(
- void *,
- const json_t *,
- const struct json_value_decode_rule *,
- struct spp_command_decode_error *);
-
-/* rule definition that decode json object to c-struct */
-struct json_value_decode_rule {
- char name[SPP_CMD_NAME_BUFSZ];
- json_type json_type;
- size_t offset;
- json_value_decode_proc decode_proc;
-
- struct {
- json_type json_type;
- size_t element_sz;
- size_t offset_num;
- size_t offset_num_valid;
- } array;
-};
-
-/* get output address for decoded json value */
-#define DR_GET_OUTPUT(output_base, rule__) ((char *)output_base + rule__->offset)
-
/* set decode error */
inline int
set_decode_error(struct spp_command_decode_error *error,
- int error_code,
- const struct json_value_decode_rule *error_rule)
+ const int error_code, const char *error_name)
{
error->code = error_code;
- if (likely(error_rule != NULL))
- strcpy(error->value_name, error_rule->name);
+ if (likely(error_name != NULL))
+ strcpy(error->value_name, error_name);
return error->code;
}
@@ -85,307 +35,242 @@ set_decode_error(struct spp_command_decode_error *error,
/* set decode error */
inline int
set_string_value_decode_error(struct spp_command_decode_error *error,
- const char* value,
- const struct json_value_decode_rule *error_rule)
+ const char* value, const char *error_name)
{
strcpy(error->value, value);
- return set_decode_error(error, SPP_CMD_DERR_BAD_VALUE, error_rule);
+ return set_decode_error(error, SPP_CMD_DERR_BAD_VALUE, error_name);
}
-/* helper */
-#define END_OF_DECODE_RULE {.name = ""},
-#define IS_END_OF_DECODE_RULE(rule) ((rule)->name[0] == '\0')
-
-/* definition helper that enum value decode procedure */
-#define DECODE_ENUM_VALUE(proc_name, enum_type, string_table) \
-static int \
-decode_##proc_name##_value(void *output, const json_t *value_obj, \
- const struct json_value_decode_rule *rule, \
- struct spp_command_decode_error *error) \
-{ \
- int i; \
- enum_type type; \
- const char *str_val = json_string_value(value_obj); \
- \
- for (i = 0; string_table[i][0] != '\0'; ++i) { \
- if (unlikely(strcmp(str_val, string_table[i]) == 0)) { \
- type = i; \
- memcpy(output, &type, sizeof(enum_type)); \
- return 0; \
- } \
- } \
- \
- return set_string_value_decode_error(error, str_val, rule); \
-} \
-
-/* enum value decode procedure for "command_type" */
-DECODE_ENUM_VALUE(command_type, enum spp_command_type, COMMAND_TYPE_STRINGS)
-
-/* enum value decode procedure for "classifier_type" */
-DECODE_ENUM_VALUE(classifier_type, enum spp_classifier_type, CLASSIFILER_TYPE_STRINGS)
-
-#if 0 /* not supported yet */
-/* decode procedure for integer */
-static int
-decode_int_value(void *output, const json_t *value_obj,
- __rte_unused const struct json_value_decode_rule *rule,
- __rte_unused struct spp_command_decode_error *error)
+/* Split command line arguments with spaces */
+static void
+decode_argument_value(char *string, int *argc, char *argv[])
{
- int val = json_integer_value(value_obj);
- memcpy(output, &val, sizeof(int));
+ int cnt = 0;
+ const char *delim = " ";
+ char *argv_tok = NULL;
+
+ argv_tok = strtok(string, delim);
+ while(argv_tok != NULL) {
+ argv[cnt] = argv_tok;
+ cnt++;
+ argv_tok = strtok(NULL, delim);
+ }
+ *argc = cnt;
+}
- return 0;
+/* Get index of array */
+static int
+get_arrary_index(const char *match, const char *list[])
+{
+ int i;
+ for (i = 0; list[i][0] == '\0'; i++) {
+ if (strcmp(list[i], match) == 0)
+ return i;
+ }
+ return -1;
}
-/* decode procedure for string */
+/* decoding procedure of port */
static int
-decode_string_value(void *output, const json_t *value_obj,
- __rte_unused const struct json_value_decode_rule *rule,
- __rte_unused struct spp_command_decode_error *error)
+decode_port_value(void *output, const char *arg_val)
{
- const char* str_val = json_string_value(value_obj);
- strcpy(output, str_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);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad port. val=%s\n", arg_val);
+ return -1;
+ }
return 0;
}
-#endif
-/* decode procedure for mac address string */
+/* decoding procedure of mac address string */
static int
-decode_mac_addr_str_value(void *output, const json_t *value_obj,
- const struct json_value_decode_rule *rule,
- struct spp_command_decode_error *error)
+decode_mac_addr_str_value(void *output, const char *arg_val)
{
- int ret = -1;
- const char* str_val = json_string_value(value_obj);
+ int64_t ret = 0;
+ 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;
ret = spp_config_change_mac_str_to_int64(str_val);
- if (unlikely(ret == -1)) {
+ if (unlikely(ret < 0)) {
RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad mac address string. val=%s\n",
str_val);
- return set_string_value_decode_error(error, str_val, rule);
+ return -1;
}
- strcpy(output, str_val);
-
+ strcpy((char *)output, str_val);
return 0;
}
-/* decode procedure for spp_config_port_info */
+/* decoding procedure of classifier type */
static int
-decode_port_value(void *output, const json_t *value_obj,
- const struct json_value_decode_rule *rule,
- struct spp_command_decode_error *error)
+decode_classifier_type_value(void *output, const char *arg_val)
{
- int ret = -1;
- const char* str_val = json_string_value(value_obj);
- struct spp_config_port_info *port = (struct spp_config_port_info *)output;
-
- if (strcmp(str_val, SPP_CMD_UNUSE) == 0) {
- port->if_type = UNDEF;
- port->if_no = 0;
- return 0;
- }
-
- ret = spp_config_get_if_info(str_val, &port->if_type, &port->if_no);
- if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad port. val=%s\n", str_val);
- return set_string_value_decode_error(error, str_val, rule);
- }
-
- return 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;
+ }
+
+ *(int *)output = ret;
+ return 0;
}
-/* decode json object */
+/* decode procedure for classifier value */
static int
-decode_json_object(void *output, const json_t *parent_obj,
- const struct json_value_decode_rule *rules,
- struct spp_command_decode_error *error)
+decode_classifiert_value_value(void *output, const char *arg_val)
{
- int ret = -1;
- int i, n;
- json_t *obj;
- json_t *value_obj;
- const struct json_value_decode_rule *rule;
-
- void *sub_output;
-
- for (i = 0; unlikely(! IS_END_OF_DECODE_RULE(&rules[i])); ++ i) {
- rule = rules + i;
-
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Get one object. name=%s\n",
- rule->name);
-
- value_obj = json_object_get(parent_obj, rule->name);
- if (unlikely(value_obj == NULL)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "No parameter. "
- "name=%s\n", rule->name);
- return set_decode_error(error, SPP_CMD_DERR_NO_PARAM, rule);
- } else if (unlikely(json_typeof(value_obj) != rule->json_type)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value type. "
- "name=%s\n", rule->name);
- return set_decode_error(error, SPP_CMD_DERR_BAD_TYPE, rule);
- }
-
- switch (rule->json_type) {
- case JSON_ARRAY:
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decode array. num=%lu\n",
- json_array_size(value_obj));
-
- *(int *)((char *)output + rule->array.offset_num) =
- (int)json_array_size(value_obj);
-
- json_array_foreach(value_obj, n, obj) {
- RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decode array element. "
- "index=%d\n", n);
-
- if (unlikely(json_typeof(obj) != rule->array.json_type)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value type. "
- "name=%s, index=%d\n", rule->name, n);
- return set_decode_error(error, SPP_CMD_DERR_BAD_TYPE, rule);
- }
-
- sub_output = DR_GET_OUTPUT(output, rule) +
- (rule->array.element_sz * n);
- ret = (*rule->decode_proc)(sub_output, obj, rule, error);
- if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value. "
- "name=%s, index=%d\n", rule->name, n);
- /* decode error is set in decode function */
- return ret;
- }
-
- *(int *)((char *)output +
- rule->array.offset_num_valid) = n + 1;
- }
+ int ret = -1;
+ struct spp_command_classifier_table *classifier_table = output;
+ switch(classifier_table->type) {
+ case SPP_CLASSIFIER_TYPE_MAC:
+ ret = decode_mac_addr_str_value(classifier_table->value, arg_val);
break;
default:
- sub_output = DR_GET_OUTPUT(output, rule);
- ret = (*rule->decode_proc)(sub_output, value_obj, rule, error);
- if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad value. "
- "name=%s\n", rule->name);
- /* decode error is set in decode function */
- return ret;
- }
break;
- }
}
+ return ret;
+}
- return 0;
+/* decode procedure for classifier port */
+static int
+decode_classifier_port_value(void *output, const char *arg_val)
+{
+ struct spp_config_port_info *port = output;
+
+ if (strcmp(arg_val, SPP_CMD_UNUSE) == 0) {
+ port->if_type = UNDEF;
+ port->if_no = 0;
+ return 0;
+ }
+
+ return decode_port_value(port, arg_val);
}
-/* decode rule for command-base */
-const struct json_value_decode_rule DECODERULE_COMMAND_BASE[] = {
- {
- .name = "command",
- .json_type = JSON_STRING,
- .offset = offsetof(struct spp_command, type),
- .decode_proc = decode_command_type_value,
- },
- END_OF_DECODE_RULE
+/* parameter list for decoding */
+struct decode_parameter_list {
+ const char *name;
+ size_t offset;
+ int (*func)(void *output, const char *arg_val);
};
-#if 0 /* not supported yet */
-/* decode rule for add-command-spec */
-const struct json_value_decode_rule DECODERULE_ADD_COMMAND[] = {
- {
- .name = "ports",
- .json_type = JSON_ARRAY,
- .offset = offsetof(struct spp_command_add, ports),
- .decode_proc = decode_port_value,
-
- .array.element_sz = sizeof(struct spp_config_port_info),
- .array.json_type = JSON_STRING,
- .array.offset_num = offsetof(struct spp_command_add, num_port),
+/* parameter list for each command */
+static struct decode_parameter_list parameter_list[][SPP_CMD_MAX_PARAMETERS] = {
+ { /* classifier_table */
+ {
+ .name = "type",
+ .offset = offsetof(struct spp_command, spec.classifier_table.type),
+ .func = decode_classifier_type_value
+ },
+ {
+ .name = "value",
+ .offset = offsetof(struct spp_command, spec.classifier_table),
+ .func = decode_classifiert_value_value
+ },
+ {
+ .name = "port",
+ .offset = offsetof(struct spp_command, spec.classifier_table.port),
+ .func = decode_classifier_port_value
+ },
+ { NULL, 0, NULL },
},
- END_OF_DECODE_RULE
-};
-#endif
-
-/* decode rule for classifier-table-command-spec */
-const struct json_value_decode_rule DECODERULE_CLASSIFIER_TABLE_COMMAND[] = {
- {
- .name = "type",
- .json_type = JSON_STRING,
- .offset = offsetof(struct spp_command_classifier_table, type),
- .decode_proc = decode_classifier_type_value,
- },{
- .name = "value",
- .json_type = JSON_STRING,
- .offset = offsetof(struct spp_command_classifier_table, value),
- .decode_proc = decode_mac_addr_str_value,
- },{
- .name = "port",
- .json_type = JSON_STRING,
- .offset = offsetof(struct spp_command_classifier_table, port),
- .decode_proc = decode_port_value,
- },
- END_OF_DECODE_RULE
+ { { NULL, 0, NULL } }, /* flush */
+ { { NULL, 0, NULL } }, /* _get_client_id */
+ { { NULL, 0, NULL } }, /* status */
+ { { NULL, 0, NULL } }, /* termination */
};
-/* decode procedure for command */
+/* check by list for each command line argument */
static int
-decode_command_object(void* output, const json_t *parent_obj,
- __rte_unused const struct json_value_decode_rule *rule,
- struct spp_command_decode_error *error)
+check_comand_argment_in_list(struct spp_command_request *request,
+ int argc, char *argv[],
+ struct spp_command_decode_error *error)
{
- int ret = -1;
- struct spp_command *command = (struct spp_command *)output;
- const struct json_value_decode_rule *spec_rules = NULL;
-
- /* decode command-base */
- ret = decode_json_object(command, parent_obj, DECODERULE_COMMAND_BASE, error);
- if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad command. ret=%d\n", ret);
- /* decode error is set in decode_json_object function */
- return ret;
+ int ret = 0;
+ int ci = request->commands[0].type;
+ int pi = 0;
+ static struct decode_parameter_list *list = NULL;
+ for(pi = 1; pi < argc-1; pi++) {
+ list = ¶meter_list[ci][pi];
+ ret = (*list->func)((void *)((char*)&request->commands[0]+list->offset), argv[pi]);
+ if (unlikely(ret < 0)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC,
+ "Bad value. command = %s, name=%s, index=%d\n",
+ argv[0], list->name, pi);
+ return set_string_value_decode_error(error, argv[pi], list->name);
+ }
}
+ return 0;
+}
- /* decode command-specific */
- switch (command->type) {
- case SPP_CMDTYPE_CLASSIFIER_TABLE:
- spec_rules = DECODERULE_CLASSIFIER_TABLE_COMMAND;
- break;
+/* command list for decoding */
+struct decode_command_list {
+ const char *name;
+ int param_min;
+ int param_max;
+ int (*func)(struct spp_command_request *request, int argc, char *argv[],
+ struct spp_command_decode_error *error);
+};
- default:
- /* nothing specific */
- /* (unknown command is already checked) */
- break;
- }
+/* command list */
+static struct decode_command_list command_list[] = {
+ { "classifier_table", 4, 4, check_comand_argment_in_list }, /* classifier_table */
+ { "flush", 1, 1, NULL }, /* flush */
+ { "_get_client_id", 1, 1, NULL }, /* _get_client_id */
+ { "status", 1, 1, NULL }, /* status */
+ { "", 0, 0, NULL } /* termination */
+};
- if (likely(spec_rules != NULL)) {
- ret = decode_json_object(&command->spec, parent_obj, spec_rules, error);
- if (unlikely(ret != 0)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad command. ret=%d\n", ret);
- /* decode error is set in decode_json_object function */
- return ret;
+/* Decode command line arguments */
+static int
+decode_command_argment(struct spp_command_request *request,
+ const char *request_str,
+ struct spp_command_decode_error *error)
+{
+ struct decode_command_list *list = NULL;
+ int i = 0;
+ int argc = 0;
+ char *argv[SPP_CMD_MAX_PARAMETERS];
+ char tmp_str[SPP_CMD_MAX_PARAMETERS*SPP_CMD_VALUE_BUFSZ];
+ memset(argv, 0x00, sizeof(argv));
+ memset(tmp_str, 0x00, sizeof(tmp_str));
+
+ request->num_command = 1;
+
+ strcpy(tmp_str, request_str);
+ decode_argument_value(tmp_str, &argc, argv);
+ RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decode array. num=%d\n", argc);
+
+ for (i = 0; command_list[i].name[0] != '\0'; i++) {
+ list = &command_list[i];
+ if (strcmp(argv[0], list->name) != 0) {
+ continue;
}
+
+ if (unlikely(argc < list->param_min) || unlikely(list->param_max < argc)) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Parameter number out of range."
+ "request_str=%s\n", request_str);
+ return set_decode_error(error, SPP_CMD_DERR_BAD_FORMAT, NULL);
+ }
+
+ request->commands[0].type = i;
+ if (list->func != NULL)
+ return (*list->func)(request, argc, argv, error);
+
+ return 0;
}
- return 0;
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown command. command=%s, request_str=%s\n",
+ argv[0], request_str);
+ return set_string_value_decode_error(error, argv[0], "command");
}
-/* decode rule for command request */
-const struct json_value_decode_rule DECODERULE_REQUEST[] = {
- {
- .name = "commands",
- .json_type = JSON_ARRAY,
- .offset = offsetof(struct spp_command_request, commands),
- .decode_proc = decode_command_object,
-
- .array.element_sz = sizeof(struct spp_command),
- .array.json_type = JSON_OBJECT,
- .array.offset_num = offsetof(struct spp_command_request, num_command),
- .array.offset_num_valid = offsetof(struct spp_command_request, num_valid_command),
- },
- END_OF_DECODE_RULE
-};
-
/* decode request from no-null-terminated string */
int
spp_command_decode_request(struct spp_command_request *request, const char *request_str,
@@ -393,35 +278,21 @@ spp_command_decode_request(struct spp_command_request *request, const char *requ
{
int ret = -1;
int i;
- json_t *top_obj;
- json_error_t json_error;
-
- /* parse json string */
- top_obj = json_loadb(request_str, request_str_len, 0, &json_error);
- if (unlikely(top_obj == NULL)) {
- RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot parse command request. "
- "error=%s, request_str=%.*s\n",
- json_error.text, (int)request_str_len, request_str);
- return set_decode_error(error, SPP_CMD_DERR_BAD_FORMAT, NULL);
- }
- /* decode request object */
- ret = decode_json_object(request, top_obj, DECODERULE_REQUEST, error);
- if (unlikely(ret != 0)) {
+ /* decode request */
+ ret = decode_command_argment(request, request_str, error);
+ if (unlikely(ret < 0)) {
RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot decode command request. "
"ret=%d, request_str=%.*s\n",
ret, (int)request_str_len, request_str);
- /* decode error is set in decode_json_object function */
+ return ret;
}
- /* free json object */
- json_decref(top_obj);
-
/* check getter command */
for (i = 0; i < request->num_valid_command; ++i) {
switch (request->commands[i].type) {
- case SPP_CMDTYPE_PROCESS:
- request->is_requested_process = 1;
+ case SPP_CMDTYPE_CLIENT_ID:
+ request->is_requested_client_id = 1;
break;
case SPP_CMDTYPE_STATUS:
request->is_requested_status = 1;
diff --git a/src/vf/command_dec.h b/src/vf/command_dec.h
index 42a0168..8850485 100644
--- a/src/vf/command_dec.h
+++ b/src/vf/command_dec.h
@@ -4,6 +4,9 @@
/* max number of command per request */
#define SPP_CMD_MAX_COMMANDS 32
+/* maximum number of parameters per command */
+#define SPP_CMD_MAX_PARAMETERS 8
+
/* command name string buffer size (include null char) */
#define SPP_CMD_NAME_BUFSZ 32
@@ -29,17 +32,9 @@ enum spp_command_decode_error_code {
/* command type
do it same as the order of COMMAND_TYPE_STRINGS */
enum spp_command_type {
-#if 0 /* not supported yet yet */
- SPP_CMDTYPE_ADD,
- SPP_CMDTYPE_COMPONENT,
-#endif
SPP_CMDTYPE_CLASSIFIER_TABLE,
SPP_CMDTYPE_FLUSH,
-#if 0 /* not supported yet */
- SPP_CMDTYPE_FORWARD,
- SPP_CMDTYPE_STOP,
-#endif
- SPP_CMDTYPE_PROCESS,
+ SPP_CMDTYPE_CLIENT_ID,
SPP_CMDTYPE_STATUS,
};
@@ -93,7 +88,7 @@ struct spp_command_request {
int num_valid_command;
struct spp_command commands[SPP_CMD_MAX_COMMANDS];
- int is_requested_process;
+ int is_requested_client_id;
int is_requested_status;
};
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index fe18e22..0dd1d56 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -206,18 +206,18 @@ append_response_command_results_object(json_t *parent_obj,
return 0;
}
-/* append process value to specified json object */
+/* append client id value to specified json object */
static int
-append_response_process_value(json_t *parent_obj)
+append_response_client_id_value(json_t *parent_obj)
{
int ret = -1;
json_t *proc_obj;
- proc_obj = json_integer(spp_get_process_id());
+ proc_obj = json_integer(spp_get_client_id());
if (unlikely(proc_obj == NULL))
return -1;
- ret = json_object_set_new(parent_obj, "process", proc_obj);
+ ret = json_object_set_new(parent_obj, "client_id", proc_obj);
if (unlikely(ret != 0))
return -1;
@@ -354,9 +354,9 @@ send_command_result_response(int *sock, const struct spp_command_request *reques
return;
}
- /* append process information value */
- if (request->is_requested_process) {
- ret = append_response_process_value(top_obj);
+ /* append client id information value */
+ if (request->is_requested_client_id) {
+ ret = append_response_client_id_value(top_obj);
if (unlikely(ret != 0)) {
RTE_LOG(ERR, SPP_COMMAND_PROC, "Failed to make command result response.");
json_decref(top_obj);
@@ -459,15 +459,11 @@ spp_command_proc_do(void)
{
int ret = -1;
int msg_ret = -1;
- int i;
static int sock = -1;
static char *msgbuf = NULL;
static size_t msg_len = 0;
- static size_t rb_cnt = 0;
- static size_t lb_cnt = 0;
-
if (unlikely(msgbuf == NULL)) {
msgbuf = spp_strbuf_allocate(CMD_REQ_BUF_INIT_SIZE);
if (unlikely(msgbuf == NULL)) {
@@ -491,29 +487,9 @@ spp_command_proc_do(void)
return -1;
}
- for (i = 0; i < msg_ret; ++i) {
- switch (*(msgbuf + msg_len + i)) {
- case '{':
- ++lb_cnt;
- break;
- case '}':
- ++rb_cnt;
- break;
- }
-
- if (likely(lb_cnt != 0) && unlikely(rb_cnt == lb_cnt)) {
- msg_len += (i + 1);
- ret = process_request(&sock, msgbuf, msg_len);
-
- spp_strbuf_remove_front(msgbuf, msg_len);
- msg_ret = 0;
- msg_len = 0;
- rb_cnt = 0;
- lb_cnt = 0;
- }
- }
-
- msg_len = msg_len + msg_ret;
+ msg_len += (msg_ret + 1);
+ ret = process_request(&sock, msgbuf, msg_len);
+ spp_strbuf_remove_front(msgbuf, msg_len);
return 0;
}
diff --git a/src/vf/spp_config.c b/src/vf/spp_config.c
index 27bce8f..bca455c 100644
--- a/src/vf/spp_config.c
+++ b/src/vf/spp_config.c
@@ -162,18 +162,18 @@ spp_config_get_if_info(const char *port, enum port_type *if_type, int *if_no)
char *endptr = NULL;
/* IF type check */
- if (strncmp(port, SPP_CONFIG_IFTYPE_NIC, strlen(SPP_CONFIG_IFTYPE_NIC)) == 0) {
+ if (strncmp(port, SPP_CONFIG_IFTYPE_NIC ":", strlen(SPP_CONFIG_IFTYPE_NIC)+1) == 0) {
/* NIC */
type = PHY;
- no_str = &port[strlen(SPP_CONFIG_IFTYPE_NIC)];
- } else if (strncmp(port, SPP_CONFIG_IFTYPE_VHOST, strlen(SPP_CONFIG_IFTYPE_VHOST)) == 0) {
+ no_str = &port[strlen(SPP_CONFIG_IFTYPE_NIC)+1];
+ } else if (strncmp(port, SPP_CONFIG_IFTYPE_VHOST ":", strlen(SPP_CONFIG_IFTYPE_VHOST)+1) == 0) {
/* VHOST */
type = VHOST;
- no_str = &port[strlen(SPP_CONFIG_IFTYPE_VHOST)];
- } else if (strncmp(port, SPP_CONFIG_IFTYPE_RING, strlen(SPP_CONFIG_IFTYPE_RING)) == 0) {
+ no_str = &port[strlen(SPP_CONFIG_IFTYPE_VHOST)+1];
+ } else if (strncmp(port, SPP_CONFIG_IFTYPE_RING ":", strlen(SPP_CONFIG_IFTYPE_RING)+1) == 0) {
/* RING */
type = RING;
- no_str = &port[strlen(SPP_CONFIG_IFTYPE_RING)];
+ no_str = &port[strlen(SPP_CONFIG_IFTYPE_RING)+1];
} else {
/* OTHER */
RTE_LOG(ERR, APP, "Unknown interface type. (port = %s)\n", port);
@@ -218,7 +218,7 @@ int spp_config_format_port_string(char *port, enum port_type if_type, int if_no)
return -1;
}
- sprintf(port, "%s%d", if_type_str, if_no);
+ sprintf(port, "%s:%d", if_type_str, if_no);
return 0;
}
diff --git a/src/vf/spp_config.h b/src/vf/spp_config.h
index 7a8bdf6..5722afd 100644
--- a/src/vf/spp_config.h
+++ b/src/vf/spp_config.h
@@ -6,7 +6,7 @@
#define SPP_CONFIG_FILE_PATH "/usr/local/etc/spp/spp.json"
-#define SPP_CONFIG_IFTYPE_NIC "nic"
+#define SPP_CONFIG_IFTYPE_NIC "phy"
#define SPP_CONFIG_IFTYPE_VHOST "vhost"
#define SPP_CONFIG_IFTYPE_RING "ring"
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 18533d1..20a3b40 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -23,13 +23,13 @@ enum SPP_LONGOPT_RETVAL {
/* add below */
SPP_LONGOPT_RETVAL_CONFIG,
- SPP_LONGOPT_RETVAL_PROCESS_ID,
+ SPP_LONGOPT_RETVAL_CLIENT_ID,
SPP_LONGOPT_RETVAL_VHOST_CLIENT
};
/* struct */
struct startup_param {
- int process_id;
+ int client_id;
char server_ip[INET_ADDRSTRLEN];
int server_port;
int vhost_client;
@@ -70,11 +70,11 @@ static void
usage(const char *progname)
{
RTE_LOG(INFO, APP, "Usage: %s [EAL args] --"
- " --process-id PROC_ID"
+ " --client-id CLIENT_ID"
" [--config CONFIG_FILE_PATH]"
" -s SERVER_IP:SERVER_PORT"
" [--vhost-client]\n"
- " --process-id PROCESS_ID : My process ID\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"
@@ -252,23 +252,23 @@ stop_process(int signal) {
}
/*
- * Parses the process ID of the application argument.
+ * Parses the client ID of the application argument.
*/
static int
-parse_app_process_id(const char *process_id_str, int *process_id)
+parse_app_client_id(const char *client_id_str, int *client_id)
{
int id = 0;
char *endptr = NULL;
- id = strtol(process_id_str, &endptr, 0);
- if (unlikely(process_id_str == endptr) || unlikely(*endptr != '\0'))
+ id = strtol(client_id_str, &endptr, 0);
+ if (unlikely(client_id_str == endptr) || unlikely(*endptr != '\0'))
return -1;
- if (id >= SPP_PROCESS_MAX)
+ if (id >= SPP_CLIENT_MAX)
return -1;
- *process_id = id;
- RTE_LOG(DEBUG, APP, "Set process id = %d\n", *process_id);
+ *client_id = id;
+ RTE_LOG(DEBUG, APP, "Set client id = %d\n", *client_id);
return 0;
}
@@ -314,7 +314,7 @@ parse_app_args(int argc, char *argv[])
const char *progname = argv[0];
static struct option lgopts[] = {
{ "config", required_argument, NULL, SPP_LONGOPT_RETVAL_CONFIG },
- { "process-id", required_argument, NULL, SPP_LONGOPT_RETVAL_PROCESS_ID },
+ { "client-id", required_argument, NULL, SPP_LONGOPT_RETVAL_CLIENT_ID },
{ "vhost-client", no_argument, NULL, SPP_LONGOPT_RETVAL_VHOST_CLIENT },
{ 0 },
};
@@ -340,8 +340,8 @@ parse_app_args(int argc, char *argv[])
}
strcpy(config_file_path, optarg);
break;
- case SPP_LONGOPT_RETVAL_PROCESS_ID:
- if (parse_app_process_id(optarg, &g_startup_param.process_id) != 0) {
+ case SPP_LONGOPT_RETVAL_CLIENT_ID:
+ if (parse_app_client_id(optarg, &g_startup_param.client_id) != 0) {
usage(progname);
return -1;
}
@@ -370,8 +370,8 @@ parse_app_args(int argc, char *argv[])
usage(progname);
return -1;
}
- RTE_LOG(INFO, APP, "application arguments value. (process id = %d, config = %s, server = %s:%d, vhost client = %d)\n",
- g_startup_param.process_id,
+ RTE_LOG(INFO, APP, "application arguments value. (client id = %d, config = %s, 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,
@@ -978,12 +978,12 @@ ut_main(int argc, char *argv[])
}
/*
- * Get process ID
+ * Get client ID
*/
int
-spp_get_process_id(void)
+spp_get_client_id(void)
{
- return g_startup_param.process_id;
+ return g_startup_param.client_id;
}
/*
diff --git a/src/vf/spp_vf.h b/src/vf/spp_vf.h
index bbdb904..b0da048 100644
--- a/src/vf/spp_vf.h
+++ b/src/vf/spp_vf.h
@@ -4,7 +4,7 @@
#include "common.h"
#include "spp_config.h"
-#define SPP_PROCESS_MAX 128
+#define SPP_CLIENT_MAX 128
/*
* State on core
@@ -60,10 +60,10 @@ struct spp_core_info {
};
/*
- * Get process ID
- * RETURN : PROCESS ID(0~127)
+ * Get client ID
+ * RETURN : CLIENT ID(0~127)
*/
-int spp_get_process_id(void);
+int spp_get_client_id(void);
/*
* Update Classifier_table
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 43/57] spp_vf: update command decode procedure
2017-12-26 1:54 ` Yasufumi Ogawa
` (41 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 42/57] spp_vf: change how to request commands x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 44/57] spp_vf: remove debug log output procedures x-fn-spp
` (13 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
update command decode procedures due to the change of
command request format (fix bugs caused by the change.)
* Fix bugs in comditional statements and loop index.
* Fix index of received character array.
* Add initializeion of received commands counter.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_dec.c | 21 ++++++++++++---------
src/vf/command_proc.c | 6 ++----
2 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/src/vf/command_dec.c b/src/vf/command_dec.c
index 468702f..75619d9 100644
--- a/src/vf/command_dec.c
+++ b/src/vf/command_dec.c
@@ -63,7 +63,7 @@ static int
get_arrary_index(const char *match, const char *list[])
{
int i;
- for (i = 0; list[i][0] == '\0'; i++) {
+ for (i = 0; list[i][0] != '\0'; i++) {
if (strcmp(list[i], match) == 0)
return i;
}
@@ -113,7 +113,7 @@ decode_classifier_type_value(void *output, const char *arg_val)
{
int ret = 0;
ret = get_arrary_index(arg_val, CLASSIFILER_TYPE_STRINGS);
- if (unlikely(ret < 0)) {
+ if (unlikely(ret <= 0)) {
RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown classifier type. val=%s\n", arg_val);
return -1;
}
@@ -196,13 +196,14 @@ check_comand_argment_in_list(struct spp_command_request *request,
int ci = request->commands[0].type;
int pi = 0;
static struct decode_parameter_list *list = NULL;
- for(pi = 1; pi < argc-1; pi++) {
- list = ¶meter_list[ci][pi];
+ for(pi = 1; pi < argc; pi++) {
+ list = ¶meter_list[ci][pi-1];
+RTE_LOG(ERR, SPP_COMMAND_PROC, "TEST: command=%s, name=%s, index=%d, value=%s\n", argv[0], list->name, pi, argv[pi]);
ret = (*list->func)((void *)((char*)&request->commands[0]+list->offset), argv[pi]);
if (unlikely(ret < 0)) {
RTE_LOG(ERR, SPP_COMMAND_PROC,
- "Bad value. command = %s, name=%s, index=%d\n",
- argv[0], list->name, pi);
+ "Bad value. command=%s, name=%s, index=%d, value=%s\n",
+ argv[0], list->name, pi, argv[pi]);
return set_string_value_decode_error(error, argv[pi], list->name);
}
}
@@ -241,8 +242,6 @@ decode_command_argment(struct spp_command_request *request,
memset(argv, 0x00, sizeof(argv));
memset(tmp_str, 0x00, sizeof(tmp_str));
- request->num_command = 1;
-
strcpy(tmp_str, request_str);
decode_argument_value(tmp_str, &argc, argv);
RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decode array. num=%d\n", argc);
@@ -279,14 +278,18 @@ spp_command_decode_request(struct spp_command_request *request, const char *requ
int ret = -1;
int i;
+RTE_LOG(ERR, SPP_COMMAND_PROC, "ERROR:request_str=%s\n", request_str);
/* decode request */
+ request->num_command = 1;
ret = decode_command_argment(request, request_str, error);
- if (unlikely(ret < 0)) {
+ if (unlikely(ret != 0)) {
RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot decode command request. "
"ret=%d, request_str=%.*s\n",
ret, (int)request_str_len, request_str);
return ret;
}
+ request->num_valid_command = 1;
+RTE_LOG(ERR, SPP_COMMAND_PROC, "ERROR:command type=%d\n", request->commands[0].type);
/* check getter command */
for (i = 0; i < request->num_valid_command; ++i) {
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index 0dd1d56..ef1ae81 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -462,7 +462,6 @@ spp_command_proc_do(void)
static int sock = -1;
static char *msgbuf = NULL;
- static size_t msg_len = 0;
if (unlikely(msgbuf == NULL)) {
msgbuf = spp_strbuf_allocate(CMD_REQ_BUF_INIT_SIZE);
@@ -487,9 +486,8 @@ spp_command_proc_do(void)
return -1;
}
- msg_len += (msg_ret + 1);
- ret = process_request(&sock, msgbuf, msg_len);
- spp_strbuf_remove_front(msgbuf, msg_len);
+ ret = process_request(&sock, msgbuf, msg_ret);
+ spp_strbuf_remove_front(msgbuf, msg_ret);
return 0;
}
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 44/57] spp_vf: remove debug log output procedures
2017-12-26 1:54 ` Yasufumi Ogawa
` (42 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 43/57] spp_vf: update command decode procedure x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 45/57] spp_vf: improve command_decoder program code x-fn-spp
` (12 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Remove procedures for logging information used for debug
since they are for debug only.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_dec.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/vf/command_dec.c b/src/vf/command_dec.c
index 75619d9..c09a342 100644
--- a/src/vf/command_dec.c
+++ b/src/vf/command_dec.c
@@ -198,7 +198,6 @@ check_comand_argment_in_list(struct spp_command_request *request,
static struct decode_parameter_list *list = NULL;
for(pi = 1; pi < argc; pi++) {
list = ¶meter_list[ci][pi-1];
-RTE_LOG(ERR, SPP_COMMAND_PROC, "TEST: command=%s, name=%s, index=%d, value=%s\n", argv[0], list->name, pi, argv[pi]);
ret = (*list->func)((void *)((char*)&request->commands[0]+list->offset), argv[pi]);
if (unlikely(ret < 0)) {
RTE_LOG(ERR, SPP_COMMAND_PROC,
@@ -278,7 +277,6 @@ spp_command_decode_request(struct spp_command_request *request, const char *requ
int ret = -1;
int i;
-RTE_LOG(ERR, SPP_COMMAND_PROC, "ERROR:request_str=%s\n", request_str);
/* decode request */
request->num_command = 1;
ret = decode_command_argment(request, request_str, error);
@@ -289,7 +287,6 @@ RTE_LOG(ERR, SPP_COMMAND_PROC, "ERROR:request_str=%s\n", request_str);
return ret;
}
request->num_valid_command = 1;
-RTE_LOG(ERR, SPP_COMMAND_PROC, "ERROR:command type=%d\n", request->commands[0].type);
/* check getter command */
for (i = 0; i < request->num_valid_command; ++i) {
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 45/57] spp_vf: improve command_decoder program code
2017-12-26 1:54 ` Yasufumi Ogawa
` (43 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 44/57] spp_vf: remove debug log output procedures x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 46/57] spp_vf: fix a bug in status command x-fn-spp
` (11 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Add procedure for error log output
* Add parameter check procedure
* Correct wording (argument->parameter)
* Change strtol to stortol_r.
* Change return type of decode_parameter_value from static void
to static int.
* Fix typos.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_dec.c | 61 +++++++++++++++++++++++++++++++---------------------
1 file changed, 37 insertions(+), 24 deletions(-)
diff --git a/src/vf/command_dec.c b/src/vf/command_dec.c
index c09a342..9363b8f 100644
--- a/src/vf/command_dec.c
+++ b/src/vf/command_dec.c
@@ -41,21 +41,26 @@ set_string_value_decode_error(struct spp_command_decode_error *error,
return set_decode_error(error, SPP_CMD_DERR_BAD_VALUE, error_name);
}
-/* Split command line arguments with spaces */
-static void
-decode_argument_value(char *string, int *argc, char *argv[])
+/* Split command line parameter with spaces */
+static int
+decode_parameter_value(char *string, int max, int *argc, char *argv[])
{
int cnt = 0;
const char *delim = " ";
char *argv_tok = NULL;
+ char *saveptr = NULL;
- argv_tok = strtok(string, delim);
+ argv_tok = strtok_r(string, delim, &saveptr);
while(argv_tok != NULL) {
+ if (cnt >= max)
+ return -1;
argv[cnt] = argv_tok;
cnt++;
- argv_tok = strtok(NULL, delim);
+ argv_tok = strtok_r(NULL, delim, &saveptr);
}
*argc = cnt;
+
+ return 0;
}
/* Get index of array */
@@ -124,7 +129,7 @@ decode_classifier_type_value(void *output, const char *arg_val)
/* decode procedure for classifier value */
static int
-decode_classifiert_value_value(void *output, const char *arg_val)
+decode_classifier_value_value(void *output, const char *arg_val)
{
int ret = -1;
struct spp_command_classifier_table *classifier_table = output;
@@ -153,6 +158,8 @@ decode_classifier_port_value(void *output, const char *arg_val)
return decode_port_value(port, arg_val);
}
+#define DECODE_PARAMETER_LIST_EMPTY { NULL, 0, NULL }
+
/* parameter list for decoding */
struct decode_parameter_list {
const char *name;
@@ -162,7 +169,7 @@ struct decode_parameter_list {
/* parameter list for each command */
static struct decode_parameter_list parameter_list[][SPP_CMD_MAX_PARAMETERS] = {
- { /* classifier_table */
+ { /* classifier_table */
{
.name = "type",
.offset = offsetof(struct spp_command, spec.classifier_table.type),
@@ -171,24 +178,24 @@ static struct decode_parameter_list parameter_list[][SPP_CMD_MAX_PARAMETERS] = {
{
.name = "value",
.offset = offsetof(struct spp_command, spec.classifier_table),
- .func = decode_classifiert_value_value
+ .func = decode_classifier_value_value
},
{
.name = "port",
.offset = offsetof(struct spp_command, spec.classifier_table.port),
.func = decode_classifier_port_value
},
- { NULL, 0, NULL },
+ DECODE_PARAMETER_LIST_EMPTY,
},
- { { NULL, 0, NULL } }, /* flush */
- { { NULL, 0, NULL } }, /* _get_client_id */
- { { NULL, 0, NULL } }, /* status */
- { { NULL, 0, NULL } }, /* termination */
+ { DECODE_PARAMETER_LIST_EMPTY }, /* flush */
+ { DECODE_PARAMETER_LIST_EMPTY }, /* _get_client_id */
+ { DECODE_PARAMETER_LIST_EMPTY }, /* status */
+ { DECODE_PARAMETER_LIST_EMPTY }, /* termination */
};
-/* check by list for each command line argument */
+/* check by list for each command line parameter */
static int
-check_comand_argment_in_list(struct spp_command_request *request,
+decode_comand_parameter_in_list(struct spp_command_request *request,
int argc, char *argv[],
struct spp_command_decode_error *error)
{
@@ -220,19 +227,20 @@ struct decode_command_list {
/* command list */
static struct decode_command_list command_list[] = {
- { "classifier_table", 4, 4, check_comand_argment_in_list }, /* classifier_table */
- { "flush", 1, 1, NULL }, /* flush */
- { "_get_client_id", 1, 1, NULL }, /* _get_client_id */
- { "status", 1, 1, NULL }, /* status */
- { "", 0, 0, NULL } /* termination */
+ { "classifier_table", 4, 4, 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 */
+ { "", 0, 0, NULL } /* termination */
};
-/* Decode command line arguments */
+/* Decode command line parameters */
static int
-decode_command_argment(struct spp_command_request *request,
+decode_command_in_list(struct spp_command_request *request,
const char *request_str,
struct spp_command_decode_error *error)
{
+ int ret = 0;
struct decode_command_list *list = NULL;
int i = 0;
int argc = 0;
@@ -242,7 +250,12 @@ decode_command_argment(struct spp_command_request *request,
memset(tmp_str, 0x00, sizeof(tmp_str));
strcpy(tmp_str, request_str);
- decode_argument_value(tmp_str, &argc, argv);
+ ret = decode_parameter_value(tmp_str, SPP_CMD_MAX_PARAMETERS, &argc, argv);
+ if (ret < 0) {
+ RTE_LOG(ERR, SPP_COMMAND_PROC, "Parameter number over limit."
+ "request_str=%s\n", request_str);
+ return set_decode_error(error, SPP_CMD_DERR_BAD_FORMAT, NULL);
+ }
RTE_LOG(DEBUG, SPP_COMMAND_PROC, "Decode array. num=%d\n", argc);
for (i = 0; command_list[i].name[0] != '\0'; i++) {
@@ -279,7 +292,7 @@ spp_command_decode_request(struct spp_command_request *request, const char *requ
/* decode request */
request->num_command = 1;
- ret = decode_command_argment(request, request_str, error);
+ ret = decode_command_in_list(request, request_str, error);
if (unlikely(ret != 0)) {
RTE_LOG(ERR, SPP_COMMAND_PROC, "Cannot decode command request. "
"ret=%d, request_str=%.*s\n",
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 46/57] spp_vf: fix a bug in status command
2017-12-26 1:54 ` Yasufumi Ogawa
` (44 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 45/57] spp_vf: improve command_decoder program code x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 47/57] spp_vf: add spp_vf.py instead of spp.py x-fn-spp
` (10 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Fix the problem that the default port set by classifier_table command
is not displayed with the status command.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/classifier_mac.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
index 9769b30..a088040 100644
--- a/src/vf/classifier_mac.c
+++ b/src/vf/classifier_mac.c
@@ -554,6 +554,17 @@ int spp_classifier_mac_iterate_table(
RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC,
"Core[%u] Start iterate classifier table.\n", i);
+ if (classifier_info->default_classified >= 0) {
+ port.if_type = (classified_data + classifier_info->default_classified)->if_type;
+ port.if_no = (classified_data + classifier_info->default_classified)->if_no_global;
+
+ (*params->element_proc)(
+ params->opaque,
+ SPP_CLASSIFIER_TYPE_MAC,
+ SPP_CONFIG_DEFAULT_CLASSIFIED_SPEC_STR,
+ &port);
+ }
+
while(1) {
ret = rte_hash_iterate(classifier_info->classifier_table,
&key, &data, &next);
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 47/57] spp_vf: add spp_vf.py instead of spp.py
2017-12-26 1:54 ` Yasufumi Ogawa
` (45 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 46/57] spp_vf: fix a bug in status command x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 48/57] spp_vf: refactor for commnets in spp_vf.c x-fn-spp
` (9 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Add spp_vf.py as a modified version of spp.py.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/spp_vf.py | 443 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 443 insertions(+)
create mode 100755 src/spp_vf.py
diff --git a/src/spp_vf.py b/src/spp_vf.py
new file mode 100755
index 0000000..40310db
--- /dev/null
+++ b/src/spp_vf.py
@@ -0,0 +1,443 @@
+#!/usr/bin/python
+"""Soft Patch Panel"""
+
+from __future__ import print_function
+from Queue import Queue
+from thread import start_new_thread
+from threading import Thread
+import cmd
+import getopt
+import select
+import socket
+import sys
+
+import json
+
+class GrowingList(list):
+ """GrowingList"""
+
+ def __setitem__(self, index, value):
+ if index >= len(self):
+ self.extend([None]*(index + 1 - len(self)))
+ list.__setitem__(self, index, value)
+
+MAX_SECONDARY = 16
+
+# init
+PRIMARY = ''
+SECONDARY_LIST = []
+SECONDARY_COUNT = 0
+
+#init primary comm channel
+MAIN2PRIMARY = Queue()
+PRIMARY2MAIN = Queue()
+
+#init secondary comm channel list
+MAIN2SEC = GrowingList()
+SEC2MAIN = GrowingList()
+
+def connectionthread(name, client_id, conn, m2s, s2m):
+ """Manage secondary process connections"""
+
+ cmd_str = 'hello'
+
+ #infinite loop so that function do not terminate and thread do not end.
+ while True:
+ try:
+ _, _, _ = select.select([conn,], [conn,], [], 5)
+ except select.error:
+ break
+
+ #Sending message to connected secondary
+ try:
+ cmd_str = m2s.get(True)
+ conn.send(cmd_str) #send only takes string
+ except KeyError:
+ break
+ except Exception, excep:
+ print (str(excep))
+ break
+
+ #Receiving from secondary
+ try:
+ data = conn.recv(1024) # 1024 stands for bytes of data to be received
+ if data:
+ s2m.put("recv:" + str(conn.fileno()) + ":" + "{" + data + "}")
+ else:
+ s2m.put("closing:" + str(conn))
+ break
+ except Exception, excep:
+ print (str(excep))
+ break
+
+ SECONDARY_LIST.remove(client_id)
+ conn.close()
+
+def getclientid(conn):
+ """Get client_id from client"""
+
+ try:
+ conn.send("_get_client_id")
+ #conn.send("{\"commands\":[{\"command\":\"process\"}]}")
+ except KeyError:
+ return -1
+
+ data = conn.recv(1024)
+ if data == None:
+ return -1
+
+ #client_id = int(data.strip('\0'))
+ json_dict = json.loads(data)
+ client_id = int(json_dict['client_id'])
+
+ if client_id < 0 or client_id > MAX_SECONDARY:
+ return -1
+
+ print ("secondary id %d" % client_id)
+ return client_id
+
+ found = 0
+ for i in SECONDARY_LIST:
+ if client_id == i:
+ found = 1
+ break
+
+ if found == 0:
+ return client_id
+
+ # client_id in use, find a free one
+ free_client_id = -1
+ for i in range(MAX_SECONDARY):
+ found = -1
+ for j in SECONDARY_LIST:
+ if i == j:
+ found = i
+ break
+ if found == -1:
+ free_client_id = i
+ break
+
+ if free_client_id < 0:
+ return -1
+
+ conn.send("_set_client_id %u" % free_client_id)
+ data = conn.recv(1024)
+
+ return free_client_id
+
+def acceptthread(sock, main2sec, sec2main):
+ """Listen for secondary processes"""
+
+ global SECONDARY_COUNT
+
+ try:
+ while True:
+ #Accepting incoming connections
+ conn, _ = sock.accept()
+
+ client_id = getclientid(conn)
+ if client_id < 0:
+ break
+
+ #Creating new thread.
+ #Calling secondarythread function for this function and passing
+ #conn as argument.
+
+ SECONDARY_LIST.append(client_id)
+ main2sec[client_id] = Queue()
+ sec2main[client_id] = Queue()
+ start_new_thread(connectionthread,
+ ('secondary', client_id, conn,
+ main2sec[client_id],
+ sec2main[client_id], ))
+ SECONDARY_COUNT += 1
+ except Exception, excep:
+ print (str(excep))
+ sock.close()
+
+def command_primary(command):
+ """Send command to primary process"""
+
+ if PRIMARY:
+ MAIN2PRIMARY.put(command)
+ print (PRIMARY2MAIN.get(True))
+ else:
+ print ("primary not started")
+
+def command_secondary(sec_id, command):
+ """Send command to secondary process with sec_id"""
+
+ if sec_id in SECONDARY_LIST:
+ MAIN2SEC[sec_id].put(command)
+ print (SEC2MAIN[sec_id].get(True))
+ else:
+ print ("secondary id %d not exist" % sec_id)
+
+def print_status():
+ """Display information about connected clients"""
+
+ print ("Soft Patch Panel Status :")
+ print ("primary: %d" % PRIMARY)
+ print ("secondary count: %d" % len(SECONDARY_LIST))
+ for i in SECONDARY_LIST:
+ print ("Connected secondary id: %d" % i)
+
+def primarythread(sock, main2primary, primary2main):
+ """Manage primary process connection"""
+
+ global PRIMARY
+ cmd_str = ''
+
+ while True:
+ #waiting for connection
+ PRIMARY = False
+ conn, addr = sock.accept()
+ PRIMARY = True
+
+ while conn:
+ try:
+ _, _, _ = select.select([conn,], [conn,], [], 5)
+ except select.error:
+ break
+
+ #Sending message to connected primary
+ try:
+ cmd_str = main2primary.get(True)
+ conn.send(cmd_str) #send only takes string
+ except KeyError:
+ break
+ except Exception, excep:
+ print (str(excep))
+ break
+
+ #Receiving from primary
+ try:
+ data = conn.recv(1024) # 1024 stands for bytes of data to be received
+ if data:
+ primary2main.put("recv:" + str(addr) + ":" + "{" + data + "}")
+ else:
+ primary2main.put("closing:" + str(addr))
+ conn.close()
+ break
+ except Exception, excep:
+ print (str(excep))
+ break
+
+ print ("primary communication thread end")
+
+def close_all_secondary():
+ """Exit all secondary processes"""
+
+ return;
+
+ global SECONDARY_COUNT
+
+ tmp_list = []
+ for i in SECONDARY_LIST:
+ tmp_list.append(i)
+ for i in tmp_list:
+ command_secondary(i, 'exit')
+ SECONDARY_COUNT = 0
+
+def check_sec_cmds(cmds):
+ """Validate secondary commands before sending"""
+
+ return 1
+
+ level1 = ['status', 'exit', 'forward', 'stop']
+ level2 = ['add', 'patch', 'del']
+ patch_args = ['reset']
+ add_del_args = ['ring', 'vhost']
+ cmdlist = cmds.split(' ')
+ valid = 0
+
+ length = len(cmdlist)
+ if length == 1:
+ if cmdlist[0] in level1:
+ valid = 1
+ elif length == 2:
+ if cmdlist[0] == 'patch':
+ if cmdlist[1] in patch_args:
+ valid = 1
+ elif length == 3:
+ if cmdlist[0] in level2:
+ if cmdlist[0] == 'add' or cmdlist[0] == 'del':
+ if cmdlist[1] in add_del_args:
+ if str.isdigit(cmdlist[2]):
+ valid = 1
+ elif cmdlist[0] == 'patch':
+ if str.isdigit(cmdlist[1]) and str.isdigit(cmdlist[2]):
+ valid = 1
+
+ return valid
+
+class Shell(cmd.Cmd):
+ """SPP command prompt"""
+
+ intro = 'Welcome to the spp. Type help or ? to list commands.\n'
+ prompt = 'spp > '
+ recorded_file = None
+
+ COMMANDS = ['status', 'add', 'patch', 'ring', 'vhost',
+ 'reset', 'exit', 'forward', 'stop', 'clear']
+
+ def complete_pri(self, text, line, begidx, endidx):
+ """Completion for primary process commands"""
+
+ if not text:
+ completions = self.COMMANDS[:]
+ else:
+ completions = [p
+ for p in self.COMMANDS
+ if p.startswith(text)
+ ]
+ return completions
+
+ def complete_sec(self, text, line, begidx, endidx):
+ """Completion for secondary process commands"""
+
+ if not text:
+ completions = self.COMMANDS[:]
+ else:
+ completions = [p
+ for p in self.COMMANDS
+ if p.startswith(text)
+ ]
+ return completions
+
+ def do_status(self, _):
+ """Display Soft Patch Panel Status"""
+
+ print_status()
+
+ def do_pri(self, command):
+ """Send command to primary process"""
+
+ if command and command in self.COMMANDS:
+ command_primary(command)
+ else:
+ print ("primary invalid command")
+
+ def do_sec(self, arg):
+ """Send command to secondary process"""
+
+ cmds = arg.split(';')
+ if len(cmds) < 2:
+ print ("error")
+ elif str.isdigit(cmds[0]):
+ sec_id = int(cmds[0])
+ if check_sec_cmds(cmds[1]):
+ command_secondary(sec_id, cmds[1])
+ else:
+ print ("invalid cmd")
+ else:
+ print (cmds[0])
+ print ("first %s" % cmds[1])
+
+ def do_record(self, arg):
+ """Save future commands to filename: RECORD filename.cmd"""
+
+ self.recorded_file = open(arg, 'w')
+
+ def do_playback(self, arg):
+ """Playback commands from a file: PLAYBACK filename.cmd"""
+
+ self.close()
+ try:
+ with open(arg) as recorded_file:
+ lines = []
+ for line in recorded_file:
+ if line.strip().startswith("#"):
+ continue
+ lines.append(line)
+ self.cmdqueue.extend(lines)
+ except IOError:
+ print ("Error: File does not exist.")
+
+ def precmd(self, line):
+ line = line.lower()
+ if self.recorded_file and 'playback' not in line:
+ print(line, file=self.recorded_file)
+ return line
+
+ def close(self):
+ """Close record file"""
+
+ if self.recorded_file:
+ print("closing file")
+ self.recorded_file.close()
+ self.recorded_file = None
+
+ def do_bye(self, arg):
+ """Stop recording, close SPP, and exit: BYE"""
+
+ cmds = arg.split(' ')
+ if cmds[0] == 'sec':
+ close_all_secondary()
+ elif cmds[0] == 'all':
+ close_all_secondary()
+ command_primary('exit')
+ elif cmds[0] == '':
+ print('Thank you for using Soft Patch Panel')
+ self.close()
+ return True
+
+def main(argv):
+ """main"""
+
+ # Defining server address and port
+ host = '' #'localhost' or '127.0.0.1' or '' are all same
+
+ try:
+ opts, _ = getopt.getopt(argv, "p:s:h", ["help", "primary = ", "secondary"])
+ except getopt.GetoptError:
+ print ('spp.py -p <primary__port_number> -s <secondary_port_number>')
+ sys.exit(2)
+ for opt, arg in opts:
+ if opt in ("-h", "--help"):
+ print ('spp.py -p <primary__port_number> -s <secondary_port_number>')
+ sys.exit()
+ elif opt in ("-p", "--primary"):
+ primary_port = int(arg)
+ print ("primary port : %d" % primary_port)
+ elif opt in ("-s", "--secondary"):
+ secondary_port = int(arg)
+ print ('secondary port : %d' % secondary_port)
+
+ #Creating primary socket object
+ primary_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ #Binding primary socket to a address. bind() takes tuple of host and port.
+ primary_sock.bind((host, primary_port))
+
+ #Listening primary at the address
+ primary_sock.listen(1) #5 denotes the number of clients can queue
+
+ primary_thread = Thread(target=primarythread,
+ args=(primary_sock, MAIN2PRIMARY, PRIMARY2MAIN,))
+ primary_thread.daemon = True
+ primary_thread.start()
+
+ #Creating secondary socket object
+ secondary_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ #Binding secondary socket to a address. bind() takes tuple of host and port.
+ secondary_sock.bind((host, secondary_port))
+
+ #Listening secondary at the address
+ secondary_sock.listen(MAX_SECONDARY)
+
+ # secondary process handling thread
+ start_new_thread(acceptthread, (secondary_sock, MAIN2SEC, SEC2MAIN))
+
+ shell = Shell()
+ shell.cmdloop()
+ shell = None
+
+ primary_sock.shutdown(socket.SHUT_RDWR)
+ primary_sock.close()
+ secondary_sock.shutdown(socket.SHUT_RDWR)
+ secondary_sock.close()
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 48/57] spp_vf: refactor for commnets in spp_vf.c
2017-12-26 1:54 ` Yasufumi Ogawa
` (46 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 47/57] spp_vf: add spp_vf.py instead of spp.py x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 49/57] spp_vf: refactor comments in classifier_mac.c x-fn-spp
` (8 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Update remaining Japanese to English.
* Remove meaningless comments, for instance, 'Get client ID' for
spp_get_client_id() or 'initialize' for init functions.
* Add suplementary comments for more understandable
* Add TODOs for futher revising.
Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_vf.c | 297 ++++++++++++++++++++++++++++----------------------------
1 file changed, 147 insertions(+), 150 deletions(-)
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 20a3b40..33373f5 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -12,7 +12,7 @@
#include "spp_forward.h"
#include "command_proc.h"
-/* define */
+/* TODO(yasufum) add desc how there are used */
#define SPP_CORE_STATUS_CHECK_MAX 5
#define SPP_RING_LATENCY_STATS_SAMPLING_INTERVAL 1000000
@@ -21,13 +21,13 @@ 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
};
-/* struct */
+/* Manage given options as global variable */
struct startup_param {
int client_id;
char server_ip[INET_ADDRSTRLEN];
@@ -35,9 +35,10 @@ 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;
+ 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];
@@ -46,6 +47,8 @@ struct patch_info {
struct spp_core_port_info *tx_core;
};
+/* Manage number of interfaces and patch information as global variable */
+/* TODO(yasufum) refactor, change if to iface */
struct if_info {
int num_nic;
int num_vhost;
@@ -55,17 +58,16 @@ struct if_info {
struct patch_info ring_patchs[RTE_MAX_ETHPORTS];
};
+/* 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];
+static int g_change_core[SPP_CONFIG_CORE_MAX]; /* TODO(yasufum) add desc how it is used and why changed core is kept */
static char config_file_path[PATH_MAX];
-/*
- * print a usage message
- */
+/* Print help message */
static void
usage(const char *progname)
{
@@ -81,16 +83,13 @@ usage(const char *progname)
, progname);
}
-/*
- * Set RING PMD
- */
static int
add_ring_pmd(int ring_id)
{
struct rte_ring *ring;
int ring_port_id;
- /* look up ring, based on user's provided id*/
+ /* Lookup ring of given id */
ring = rte_ring_lookup(get_rx_queue_name(ring_id));
if (unlikely(ring == NULL)) {
RTE_LOG(ERR, APP,
@@ -98,16 +97,13 @@ add_ring_pmd(int ring_id)
return -1;
}
- /* create ring pmd*/
+ /* Create ring pmd */
ring_port_id = rte_eth_from_ring(ring);
RTE_LOG(DEBUG, APP, "ring port id %d\n", ring_port_id);
return ring_port_id;
}
-/*
- * Set VHOST PMD
- */
static int
add_vhost_pmd(int index, int client)
{
@@ -187,27 +183,31 @@ add_vhost_pmd(int index, int client)
return vhost_port_id;
}
-/*
- * Check core 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.
*/
static int
check_core_status(enum spp_core_status status)
{
- int cnt;
+ 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) {
- /* Status mismatch */
+ /* Status is mismatched */
return -1;
}
}
return 0;
}
-/*
- * Wait for core status check
+/**
+ * Run check_core_status() for SPP_CORE_STATUS_CHECK_MAX times with
+ * interval time (1sec)
*/
static int
check_core_status_wait(enum spp_core_status status)
@@ -225,34 +225,35 @@ check_core_status_wait(enum spp_core_status status)
return -1;
}
-/*
- * Set core status
- */
+/* Set all core to given status */
static void
set_core_status(enum spp_core_status status)
{
- int core_cnt = 0;
+ 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;
}
}
-/*
- * Process stop
+/**
+ * Set all of core status to SPP_CORE_STOP_REQUEST if received signal
+ * is SIGTERM or SIGINT
*/
static void
stop_process(int signal) {
if (unlikely(signal != SIGTERM) &&
unlikely(signal != SIGINT)) {
- /* Other signals */
return;
}
set_core_status(SPP_CORE_STOP_REQUEST);
}
-/*
- * Parses the client ID of the application argument.
+/**
+ * Convert string of given client id to inteter
+ *
+ * If succeeded, client id of interger is assigned to client_id and
+ * reuturn 0. Or return -1 if failed.
*/
static int
parse_app_client_id(const char *client_id_str, int *client_id)
@@ -272,9 +273,7 @@ parse_app_client_id(const char *client_id_str, int *client_id)
return 0;
}
-/*
- * Parses server information of application arguments.
- */
+/* Parse options for server ip and port */
static int
parse_app_server(const char *server_str, char *server_ip, int *server_port)
{
@@ -299,9 +298,7 @@ parse_app_server(const char *server_str, char *server_ip, int *server_port)
return 0;
}
-/*
- * Parse the application arguments to the client app.
- */
+/* Parse options for client app */
static int
parse_app_args(int argc, char *argv[])
{
@@ -319,7 +316,10 @@ parse_app_args(int argc, char *argv[])
{ 0 },
};
- /* getoptを使用するとargvが並び変わるみたいなので、コピーを実施 */
+ /**
+ * Save argv to argvopt to aovid loosing the order of options
+ * by getopt_long()
+ */
for (cnt = 0; cnt < argcopt; cnt++) {
argvopt[cnt] = argv[cnt];
}
@@ -327,7 +327,7 @@ parse_app_args(int argc, char *argv[])
/* Clear startup parameters */
memset(&g_startup_param, 0x00, sizeof(g_startup_param));
- /* Check application parameter */
+ /* Check options of application */
optind = 0;
opterr = 0;
while ((opt = getopt_long(argc, argvopt, "s:", lgopts,
@@ -370,7 +370,8 @@ parse_app_args(int argc, char *argv[])
usage(progname);
return -1;
}
- RTE_LOG(INFO, APP, "application arguments value. (client id = %d, config = %s, server = %s:%d, vhost client = %d)\n",
+ RTE_LOG(INFO, APP,
+ "app opts (client_id=%d,config=%s,server=%s:%d,vhost_client=%d)\n",
g_startup_param.client_id,
config_file_path,
g_startup_param.server_ip,
@@ -379,8 +380,13 @@ parse_app_args(int argc, char *argv[])
return 0;
}
-/*
- * IF種別&IF番号のIF情報の領域取得
+/**
+ * Return patch 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.
+ * TODO(yasufum) confirm why it returns not -1 but NULL.
*/
static struct patch_info *
get_if_area(enum port_type if_type, int if_no)
@@ -396,19 +402,20 @@ get_if_area(enum port_type if_type, int if_no)
return &g_if_info.ring_patchs[if_no];
break;
default:
- /* エラー出力は呼び元でチェック */
return NULL;
break;
}
}
-/*
- * IF情報初期化
+/**
+ * Initialize all of patch info by assingning -1
+ *
+ * TODO(yasufum) refactor, change if to iface.
*/
static void
init_if_info(void)
{
- int port_cnt;
+ 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;
@@ -420,8 +427,11 @@ init_if_info(void)
}
}
-/*
- * CORE情報初期化
+/**
+ * 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.
*/
static void
init_core_info(void)
@@ -438,13 +448,15 @@ init_core_info(void)
memset(g_change_core, 0x00, sizeof(g_change_core));
}
-/*
- * Configのプロセス情報から管理情報に設定
+/**
+ * Set properties of g_core_info from config
+ *
+ * TODO(yasufum) refactor, change if to iface.
+ * TODO(yasufum) confirm meaning of funciton name and is typo ?
*/
static int
set_form_proc_info(struct spp_config_area *config)
{
- /* Configのproc_infoから内部管理情報へ設定 */
int core_cnt, rx_start, rx_cnt, tx_start, tx_cnt;
enum port_type if_type;
int if_no;
@@ -459,17 +471,17 @@ set_form_proc_info(struct spp_config_area *config)
continue;
}
- /* Forwardをまとめる事は可、他種別は不可 */
- 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;
- }
+ /* Forwardをまとめる事は可、他種別は不可 */
+ /* TODO(yasufum) confirm what is the purpose and meaning */
+ 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;
+ }
- /* Set CORE type */
core_info->type = core_func->type;
if (!rte_lcore_is_enabled(core_func->core_no)) {
/* CPU mismatch */
@@ -478,7 +490,6 @@ set_form_proc_info(struct spp_config_area *config)
return -1;
}
- /* Set RX port */
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++) {
@@ -488,7 +499,7 @@ set_form_proc_info(struct spp_config_area *config)
core_info->rx_ports[rx_start + rx_cnt].if_type = if_type;
core_info->rx_ports[rx_start + rx_cnt].if_no = if_no;
- /* IF種別とIF番号に対応するIF情報の領域取得 */
+ /* Retrieve patch corresponding to type and number of the interface */
patch_info = get_if_area(if_type, if_no);
patch_info->use_flg = 1;
@@ -499,6 +510,7 @@ set_form_proc_info(struct spp_config_area *config)
}
/* IF情報からCORE情報を変更する場合用に設定 */
+ /* TODO(yasufum) confirm the meaning of this comment */
patch_info->rx_core_no = core_func->core_no;
patch_info->rx_core = &core_info->rx_ports[rx_start + rx_cnt];
}
@@ -513,7 +525,6 @@ set_form_proc_info(struct spp_config_area *config)
core_info->tx_ports[tx_start + tx_cnt].if_type = if_type;
core_info->tx_ports[tx_start + tx_cnt].if_no = if_no;
- /* IF種別とIF番号に対応するIF情報の領域取得 */
patch_info = get_if_area(if_type, if_no);
patch_info->use_flg = 1;
@@ -524,6 +535,7 @@ set_form_proc_info(struct spp_config_area *config)
}
/* IF情報からCORE情報を変更する場合用に設定 */
+ /* TODO(yasufum) confirm the meaning of this comment */
patch_info->tx_core_no = core_func->core_no;
patch_info->tx_core = &core_info->tx_ports[tx_start + tx_cnt];
}
@@ -532,13 +544,15 @@ set_form_proc_info(struct spp_config_area *config)
return 0;
}
-/*
- * ConfigのMACテーブル情報から管理情報に設定
+/**
+ * Load mac table entries from config and setup patches
+ *
+ * TODO(yasufum) refactor, change if to iface.
+ * TODO(yasufum) confirm if additional description for the structure of mac table is needed.
*/
static int
set_from_classifier_table(struct spp_config_area *config)
{
- /* MAC table */
enum port_type if_type;
int if_no = 0;
int mac_cnt = 0;
@@ -550,7 +564,7 @@ set_from_classifier_table(struct spp_config_area *config)
if_type = mac_table->port.if_type;
if_no = mac_table->port.if_no;
- /* IF種別とIF番号に対応するIF情報の領域取得 */
+ /* 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)) {
@@ -559,8 +573,7 @@ set_from_classifier_table(struct spp_config_area *config)
return -1;
}
- /* CORE情報側にもMACアドレスの情報設定 */
- /* MACアドレスは送信側のみに影響する為、送信側のみ設定 */
+ /* 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)) {
@@ -571,8 +584,10 @@ set_from_classifier_table(struct spp_config_area *config)
return 0;
}
-/*
- * NIC用の情報設定
+/**
+ * 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)))
@@ -587,15 +602,14 @@ set_nic_interface(struct spp_config_area *config __attribute__ ((unused)))
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];
- /* Set DPDK port */
patch_info->dpdk_port = nic_cnt;
+ /* TODO(yasufum) confirm why it is needed */
if (patch_info->use_flg == 0) {
/* Not Used */
continue;
}
- /* CORE情報側にもDPDKポート番号の情報設定 */
if (patch_info->rx_core != NULL) {
patch_info->rx_core->dpdk_port = nic_cnt;
}
@@ -603,7 +617,6 @@ set_nic_interface(struct spp_config_area *config __attribute__ ((unused)))
patch_info->tx_core->dpdk_port = nic_cnt;
}
- /* NICの設定数カウント */
nic_num++;
}
@@ -612,17 +625,18 @@ set_nic_interface(struct spp_config_area *config __attribute__ ((unused)))
nic_num, g_if_info.num_nic);
return -1;
}
-
+
return 0;
}
-/*
- * VHOST用の情報設定
+/**
+ * Setup vhost interfaces from config
+ *
+ * TODO(yasufum) refactor, change if to iface.
*/
static int
set_vhost_interface(struct spp_config_area *config)
{
- /* VHOST Setting */
int vhost_cnt, vhost_num = 0;
g_if_info.num_vhost = config->proc.num_vhost;
struct patch_info *patch_info = NULL;
@@ -633,7 +647,6 @@ set_vhost_interface(struct spp_config_area *config)
continue;
}
- /* Set DPDK port */
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",
@@ -642,7 +655,6 @@ set_vhost_interface(struct spp_config_area *config)
}
patch_info->dpdk_port = dpdk_port;
- /* CORE情報側にもDPDKポート番号の情報設定 */
if (patch_info->rx_core != NULL) {
patch_info->rx_core->dpdk_port = dpdk_port;
}
@@ -659,24 +671,26 @@ set_vhost_interface(struct spp_config_area *config)
return 0;
}
-/*
- * RING用の情報設定
+/**
+ * Setup ring interfaces from config
+ *
+ * TODO(yasufum) refactor, change if to iface.
*/
static int
set_ring_interface(struct spp_config_area *config)
{
- /* RING Setting */
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];
+
+ /* TODO(yasufum) confirm why it is needed */
if (patch_info->use_flg == 0) {
/* Not Used */
continue;
}
- /* Set DPDK port */
int dpdk_port = add_ring_pmd(ring_cnt);
if (unlikely(dpdk_port < 0)) {
RTE_LOG(ERR, APP, "RING add failed. (no = %d)\n",
@@ -685,7 +699,6 @@ set_ring_interface(struct spp_config_area *config)
}
patch_info->dpdk_port = dpdk_port;
- /* CORE情報側にもDPDKポート番号の情報設定 */
if (patch_info->rx_core != NULL) {
patch_info->rx_core->dpdk_port = dpdk_port;
}
@@ -702,60 +715,61 @@ set_ring_interface(struct spp_config_area *config)
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)
{
- /* Initialize */
+ /* Initialize interface and core infomation */
init_if_info();
init_core_info();
- /* Set config data */
+ /* Load config for resource assingment and network configuration */
int ret_proc = set_form_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;
}
- /* Set interface data */
int ret_nic = set_nic_interface(config);
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;
}
-#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
+#ifdef SPP_RINGLATENCYSTATS_ENABLE
+/**
+ * Print statistics of time for packet processing in ring interface
+ *
+ * TODO(yasufum) refactor, change if to iface.
+ */
static void
print_ring_latency_stats(void)
{
- /* Clear screen and move to top left */
+ /* Clear screen and move cursor to top left */
const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' };
const char clr[] = { 27, '[', '2', 'J', '\0' };
printf("%s%s", clr, topLeft);
- /* Print per RING */
int ring_cnt, stats_cnt;
struct spp_ringlatencystats_ring_latency_stats stats[RTE_MAX_ETHPORTS];
memset(&stats, 0x00, sizeof(stats));
@@ -787,32 +801,30 @@ print_ring_latency_stats(void)
}
#endif /* SPP_RINGLATENCYSTATS_ENABLE */
-/*
- * VHOST用ソケットファイル削除
+/**
+ * Remove sock file
*/
static void
del_vhost_sockfile(struct patch_info *vhost_patchs)
{
int cnt;
- /* Do not delete for vhost client. */
+ /* Do not rmeove for if it is running in vhost-client mode. */
if (g_startup_param.vhost_client != 0)
return;
for (cnt = 0; cnt < RTE_MAX_ETHPORTS; cnt++) {
if (likely(vhost_patchs[cnt].use_flg == 0)) {
- /* VHOST未使用はスキップ */
+ /* Skip removing if it is not using vhost */
continue;
}
- /* 使用していたVHOSTについて削除を行う */
remove(get_vhost_iface_name(cnt));
}
}
-/*
- * main
- */
+/* TODO(yasufum) refactor, change if to iface. */
+/* TODO(yasufum) change test using ut_main(), or add desccription for what and why use it */
int
#ifndef USE_UT_SPP_VF
main(int argc, char *argv[])
@@ -834,25 +846,23 @@ ut_main(int argc, char *argv[])
signal(SIGTERM, stop_process);
signal(SIGINT, stop_process);
- /* set default config file path */
+ /* Setup config wiht default file path */
strcpy(config_file_path, SPP_CONFIG_FILE_PATH);
unsigned int main_lcore_id = 0xffffffff;
while(1) {
- /* DPDK initialize */
int ret_dpdk = rte_eal_init(argc, argv);
if (unlikely(ret_dpdk < 0)) {
break;
}
- /* Skip dpdk parameters */
argc -= ret_dpdk;
argv += ret_dpdk;
/* Set log level */
rte_log_set_global_level(RTE_LOG_LEVEL);
- /* Parse application parameters */
+ /* Parse spp_vf specific parameters */
int ret_parse = parse_app_args(argc, argv);
if (unlikely(ret_parse != 0)) {
break;
@@ -860,30 +870,25 @@ ut_main(int argc, char *argv[])
RTE_LOG(INFO, APP, "Load config file(%s)\n", config_file_path);
- /* Load config */
int ret_config = spp_config_load_file(config_file_path, 0, &g_config);
if (unlikely(ret_config != 0)) {
break;
}
- /* Get core id. */
+ /* Get lcore id of main thread to set its status after */
main_lcore_id = rte_lcore_id();
- /* 起動パラメータとコンフィグチェック */
- /* 各IF情報設定 */
int ret_manage = init_manage_data(&g_config);
if (unlikely(ret_manage != 0)) {
break;
}
- /* 他機能部初期化 */
- /* MAC振分初期化 */
int ret_classifier_mac_init = spp_classifier_mac_init();
if (unlikely(ret_classifier_mac_init != 0)) {
break;
}
- /* コマンド機能部初期化 */
+ /* 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);
@@ -891,7 +896,7 @@ ut_main(int argc, char *argv[])
break;
}
-#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
+#ifdef SPP_RINGLATENCYSTATS_ENABLE
int ret_ringlatency = spp_ringlatencystats_init(
SPP_RING_LATENCY_STATS_SAMPLING_INTERVAL, g_if_info.num_ring);
if (unlikely(ret_ringlatency != 0)) {
@@ -899,7 +904,7 @@ ut_main(int argc, char *argv[])
}
#endif /* SPP_RINGLATENCYSTATS_ENABLE */
- /* Start thread */
+ /* 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) {
@@ -913,50 +918,48 @@ ut_main(int argc, char *argv[])
}
}
- /* スレッド状態確認 */
+ /* Set the status of main thread to idle */
g_core_info[main_lcore_id].status = SPP_CORE_IDLE;
int ret_wait = check_core_status_wait(SPP_CORE_IDLE);
if (unlikely(ret_wait != 0)) {
break;
}
- /* Start forward */
+ /* Start forwarding */
set_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");
- /* loop */
+ /* 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)) {
#else
{
#endif
- /* コマンド受付 */
+ /* Receive command */
ret_do = spp_command_proc_do();
if (unlikely(ret_do != 0)) {
break;
}
- /* CPUを占有しない様に1秒スリープ */
sleep(1);
-#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
+#ifdef SPP_RINGLATENCYSTATS_ENABLE
print_ring_latency_stats();
#endif /* SPP_RINGLATENCYSTATS_ENABLE */
}
- /* エラー終了 */
+ /* TODO(yasufum) confirm, add why this check is needed because it is same the case of "ret = 0", or remove */
if (unlikely(ret_do != 0)) {
break;
}
- /* 正常終了 */
ret = 0;
break;
}
- /* exit */
+ /* Finalize to exit */
if (main_lcore_id == rte_lcore_id())
{
g_core_info[main_lcore_id].status = SPP_CORE_STOP;
@@ -965,29 +968,29 @@ ut_main(int argc, char *argv[])
RTE_LOG(ERR, APP, "Core did not stop.\n");
}
- /* 使用していたVHOSTのソケットファイルを削除 */
+ /* Remove vhost sock file if it is not running in vhost-client mode */
del_vhost_sockfile(g_if_info.vhost_patchs);
}
- /* 他機能部終了処理 */
-#ifdef SPP_RINGLATENCYSTATS_ENABLE /* RING滞留時間 */
+#ifdef SPP_RINGLATENCYSTATS_ENABLE
spp_ringlatencystats_uninit();
#endif /* SPP_RINGLATENCYSTATS_ENABLE */
+
RTE_LOG(INFO, APP, "spp_vf exit.\n");
return ret;
}
-/*
- * Get client ID
- */
int
spp_get_client_id(void)
{
return g_startup_param.client_id;
}
-/*
- * Check the MAC address used on the interface
+/**
+ * Check mac address used on the interface
+ *
+ * TODO(yasufum) refactor, change if to iface.
+ * TODO(yasufum) confirm, add the reason why this check is needed
*/
static int
check_mac_used_interface(uint64_t mac_addr, enum port_type *if_type, int *if_no)
@@ -1013,9 +1016,6 @@ check_mac_used_interface(uint64_t mac_addr, enum port_type *if_type, int *if_no)
return -1;
}
-/*
- * Update Classifier_table
- */
int
spp_update_classifier_table(
enum spp_classifier_type type,
@@ -1103,18 +1103,16 @@ spp_update_classifier_table(
}
}
- /* 更新コマンドで設定した場合、コア毎に変更有無を保持 */
+ /* TODO(yasufum) add desc how it is used and why changed core is kept */
g_change_core[patch_info->tx_core_no] = 1;
return SPP_RET_OK;
}
-/*
- * Flush SPP component
- */
+/* Flush command to execute it */
int
spp_flush(void)
{
- int core_cnt = 0;
+ int core_cnt = 0; /* increment core id */
int ret_classifier = 0;
struct spp_core_info *core_info = NULL;
@@ -1132,15 +1130,14 @@ spp_flush(void)
}
}
- /* 更新完了により変更したコアをクリア */
+ /* Finally, zero-clear g_change_core */
memset(g_change_core, 0x00, sizeof(g_change_core));
return SPP_RET_OK;
}
-/*
- * Iterate Classifier_table
- */
-int spp_iterate_classifier_table(struct spp_iterate_classifier_table_params *params)
+int
+spp_iterate_classifier_table(
+ struct spp_iterate_classifier_table_params *params)
{
int ret;
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 49/57] spp_vf: refactor comments in classifier_mac.c
2017-12-26 1:54 ` Yasufumi Ogawa
` (47 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 48/57] spp_vf: refactor for commnets in spp_vf.c x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 50/57] spp_vf: refactor comments in spp_forward.c x-fn-spp
` (7 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Add supplemental description for the reason why hash table count is
needed.
* Add TODO for adding explanations of data structures.
Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/classifier_mac.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
index a088040..e2aa715 100644
--- a/src/vf/classifier_mac.c
+++ b/src/vf/classifier_mac.c
@@ -61,6 +61,8 @@ static const size_t HASH_TABLE_NAME_BUF_SZ =
static const size_t ETHER_ADDR_STR_BUF_SZ =
ETHER_ADDR_LEN * 2 + (ETHER_ADDR_LEN - 1) + 1;
+/* TODO(yasufum) add explanation of data structure of classifier and mng info */
+
/* classified data (destination port, target packets, etc) */
struct classified_data {
enum port_type if_type;
@@ -90,10 +92,12 @@ struct classifier_mac_mng_info {
/* classifier information per lcore */
static struct classifier_mac_mng_info g_classifier_mng_info[RTE_MAX_LCORE];
-/* hash table count. use to make hash table name.
- [reason for value]
- it is incremented at the time of use,
- but since we want to start at 0. */
+/**
+ * Hash table count used for making a name of hash table
+ *
+ * This function is required because it is incremented at the time of use,
+ * but since we want to start at 0.
+ */
static rte_atomic16_t g_hash_table_count = RTE_ATOMIC16_INIT(0xff);
static inline int
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 50/57] spp_vf: refactor comments in spp_forward.c
2017-12-26 1:54 ` Yasufumi Ogawa
` (48 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 49/57] spp_vf: refactor comments in classifier_mac.c x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 51/57] spp_vf: refactor for commnets in spp_config.c x-fn-spp
` (6 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Update remaining Japanese to English.
* Add supplemental description for some of comments.
Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_forward.c | 32 +++++++++++++-------------------
1 file changed, 13 insertions(+), 19 deletions(-)
diff --git a/src/vf/spp_forward.c b/src/vf/spp_forward.c
index e153e85..afe7c03 100644
--- a/src/vf/spp_forward.c
+++ b/src/vf/spp_forward.c
@@ -4,17 +4,13 @@
#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;
};
-/*
- * 使用するIF情報を移し替える
- */
+/* Set destination port as source */
static void
set_use_interface(struct spp_core_port_info *dst,
struct spp_core_port_info *src)
@@ -24,8 +20,11 @@ set_use_interface(struct spp_core_port_info *dst,
dst->dpdk_port = src->dpdk_port;
}
-/*
- * Merge/Forward
+/**
+ * Forwarding packets as forwarder or merger
+ *
+ * Behavior of forwarding is defined as core_info->type which is given
+ * as an argument of void and typecasted to spp_config_info.
*/
int
spp_forward(void *arg)
@@ -35,23 +34,21 @@ spp_forward(void *arg)
int if_cnt, rxtx_num = 0;
struct rxtx patch[RTE_MAX_ETHPORTS];
- /* RX/TX Info setting */
+ /* 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) {
- /* FORWARD */
set_use_interface(&patch[if_cnt].tx,
&core_info->tx_ports[if_cnt]);
} else {
- /* MERGE */
set_use_interface(&patch[if_cnt].tx,
&core_info->tx_ports[0]);
}
}
- /* Thread IDLE */
core_info->status = SPP_CORE_IDLE;
RTE_LOG(INFO, FORWARD, "Core[%d] Start. (type = %d)\n", lcore_id,
core_info->type);
@@ -67,29 +64,27 @@ spp_forward(void *arg)
rx = &patch[cnt].rx;
tx = &patch[cnt].tx;
- /* Packet receive */
+ /* 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 /* RING滞留時間 */
+#ifdef SPP_RINGLATENCYSTATS_ENABLE
if (rx->if_type == RING) {
- /* Receive port is RING */
spp_ringlatencystats_calculate_latency(rx->if_no,
bufs, nb_rx);
}
if (tx->if_type == RING) {
- /* Send port is RING */
spp_ringlatencystats_add_time_stamp(tx->if_no,
bufs, nb_rx);
}
#endif /* SPP_RINGLATENCYSTATS_ENABLE */
- /* Send packet */
+ /* Send packets */
nb_tx = rte_eth_tx_burst(tx->dpdk_port, 0, bufs, nb_rx);
- /* Free any unsent packets. */
+ /* 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]);
@@ -99,7 +94,6 @@ spp_forward(void *arg)
}
}
- /* Thread STOP */
RTE_LOG(INFO, FORWARD, "Core[%d] End. (type = %d)\n", lcore_id,
core_info->type);
core_info->status = SPP_CORE_STOP;
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 51/57] spp_vf: refactor for commnets in spp_config.c
2017-12-26 1:54 ` Yasufumi Ogawa
` (49 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 50/57] spp_vf: refactor comments in spp_forward.c x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:55 ` [spp] [PATCH 52/57] spp_vf: refactor no self-explanatory comments x-fn-spp
` (5 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Update remaining Japanese to English.
* Remove meaningless comments, for instance, 'Get client ID' for
spp_get_client_id() or 'initialize' for init functions.
* Add suplementary comments for more understandable
* Add TODOs for futher revising.
* Remove nouse whitespaces.
Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_config.c | 197 ++++++++++++++++++++++------------------------------
1 file changed, 83 insertions(+), 114 deletions(-)
diff --git a/src/vf/spp_config.c b/src/vf/spp_config.c
index bca455c..55129ac 100644
--- a/src/vf/spp_config.c
+++ b/src/vf/spp_config.c
@@ -24,8 +24,12 @@
#define JSONPATH_TX_PORT "$.tx_port"
#define JSONPATH_TX_TABLE "$.tx_port_table"
-/*
+/**
* Instead of json_path_get
+ *
+ * TODO(yasufum) confirm, add instead of what
+ * TODO(yasufum) confirm, add reason why this function is needed
+ * TODO(yasufum) confirm, add roles of obj, new_obj to make it more understandable
*/
json_t *
spp_config_get_path_obj(const json_t *json, const char *path)
@@ -74,69 +78,69 @@ spp_config_get_path_obj(const json_t *json, const char *path)
return new_obj;
}
-/*
+/**
* Get integer data from config
+ *
+ * If target is found, the result is assigned to argument 'value' and
+ * it reutrns 0, or returns -1 if not found.
*/
static int
config_get_int_value(const json_t *obj, const char *path, int *value)
{
- /* 指定パラメータのJsonオブジェクト取得 */
+ /* Use tmp to get target value of integer */
json_t *tmp_obj = spp_config_get_path_obj(obj, path);
if (unlikely(tmp_obj == NULL)) {
- /* 必須でないデータを取得する場合を考慮し、DEBUGログとする。 */
+ /* For debugging, logging a case of null */
RTE_LOG(DEBUG, APP, "No parameter. (path = %s)\n", path);
return -1;
}
- /* Integer type check */
if (unlikely(!json_is_integer(tmp_obj))) {
- /* 必須でないデータを取得する場合を考慮し、DEBUGログとする。 */
+ /* For debugging, logging for other than target type */
RTE_LOG(DEBUG, APP, "Not an integer. (path = %s)\n", path);
return -1;
}
- /* Set to OUT parameter */
*value = json_integer_value(tmp_obj);
RTE_LOG(DEBUG, APP, "get value = %d\n", *value);
return 0;
}
/*
- * Get String data from config
+ * Get string data from config
+ *
+ * If target is found, the result is assigned to argument 'value' and
+ * it reutrns 0, or returns -1 if not found.
*/
static int
config_get_str_value(const json_t *obj, const char *path, char *value)
{
- /* 指定パラメータのJsonオブジェクト取得 */
json_t *tmp_obj = spp_config_get_path_obj(obj, path);
if (unlikely(tmp_obj == NULL)) {
RTE_LOG(DEBUG, APP, "No parameter. (path = %s)\n", path);
return -1;
}
- /* String type check */
if (unlikely(!json_is_string(tmp_obj))) {
+ /* For debugging, logging for other than target type */
RTE_LOG(DEBUG, APP, "Not a string. (path = %s)\n", path);
return -1;
}
- /* Set to OUT parameter */
strcpy(value, json_string_value(tmp_obj));
RTE_LOG(DEBUG, APP, "get value = %s\n", value);
return 0;
}
-/*
- * コンフィグ情報初期化
- */
+/* TODO(yasufum) change function name to be realized doing init, for instance, init_config_area() */
static void
config_init_data(struct spp_config_area *config)
{
- /* 0クリア */
+ /* Clear config area with zero */
memset(config, 0x00, sizeof(struct spp_config_area));
int core_cnt, port_cnt, table_cnt;
- /* IF種別初期設定 */
+ /* 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;
@@ -150,9 +154,13 @@ config_init_data(struct spp_config_area *config)
return;
}
-/*
- * IFの情報からIF種別とIF番号を取得する
- * ("ring0" -> 種別:"ring"、番号:0)
+/**
+ * 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_config_get_if_info(const char *port, enum port_type *if_type, int *if_no)
@@ -161,7 +169,7 @@ spp_config_get_if_info(const char *port, enum port_type *if_type, int *if_no)
const char *no_str = NULL;
char *endptr = NULL;
- /* IF type check */
+ /* Find out which type of interface from port */
if (strncmp(port, SPP_CONFIG_IFTYPE_NIC ":", strlen(SPP_CONFIG_IFTYPE_NIC)+1) == 0) {
/* NIC */
type = PHY;
@@ -180,7 +188,7 @@ spp_config_get_if_info(const char *port, enum port_type *if_type, int *if_no)
return -1;
}
- /* IF番号を文字列から数値変換 */
+ /* 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 */
@@ -188,7 +196,6 @@ spp_config_get_if_info(const char *port, enum port_type *if_type, int *if_no)
return -1;
}
- /* Set OUT parameter */
*if_type = type;
*if_no = ret_no;
@@ -197,8 +204,9 @@ spp_config_get_if_info(const char *port, enum port_type *if_type, int *if_no)
return 0;
}
-/*
- * IF種別とIF番号からIF情報文字列を作成する
+/**
+ * Generate a formatted string of conbination from interface type and
+ * number and assign to given 'port'
*/
int spp_config_format_port_string(char *port, enum port_type if_type, int if_no)
{
@@ -223,8 +231,8 @@ int spp_config_format_port_string(char *port, enum port_type if_type, int if_no)
return 0;
}
-/*
- * MAC addressを文字列から数値へ変換
+/**
+ * Change mac address of 'aa:bb:cc:dd:ee:ff' to int64 and return it
*/
int64_t
spp_config_change_mac_str_to_int64(const char *mac)
@@ -253,14 +261,14 @@ spp_config_change_mac_str_to_int64(const char *mac)
break;
}
- /* 各数値をまとめる */
+ /* Append separated value to the result */
token_val = (int64_t)ret_tol;
ret_mac |= token_val << (token_cnt * 8);
token_cnt++;
str = NULL;
}
- /* 区切り文字が5個以外 */
+ /* Check for mal-formatted address */
if (unlikely(token_cnt != ETHER_ADDR_LEN)) {
RTE_LOG(ERR, APP, "MAC address format error. (mac = %s)\n",
mac);
@@ -272,21 +280,17 @@ spp_config_change_mac_str_to_int64(const char *mac)
return ret_mac;
}
-/*
- * Classifier table読み込み
- */
static int
config_load_classifier_table(const json_t *obj,
struct spp_config_classifier_table *classifier_table)
{
- /* classifier_table用オブジェクト取得 */
json_t *classifier_obj = spp_config_get_path_obj(obj, JSONPATH_CLASSIFIER_TABLE);
if (unlikely(classifier_obj == NULL)) {
RTE_LOG(INFO, APP, "No classifier table.\n");
return 0;
}
- /* name取得 */
+ /* Name of classifier table */
int ret_name = config_get_str_value(classifier_obj, JSONPATH_NAME,
classifier_table->name);
if (unlikely(ret_name != 0)) {
@@ -294,22 +298,20 @@ config_load_classifier_table(const json_t *obj,
return -1;
}
- /* table用オブジェクト取得 */
+ /* Setup classifier as an array */
json_t *array_obj = spp_config_get_path_obj(classifier_obj, JSONPATH_TABLE);
if (unlikely(!array_obj)) {
RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
JSONPATH_TABLE);
return -1;
}
-
- /* table用オブジェクトが配列かチェック */
if (unlikely(!json_is_array(array_obj))) {
RTE_LOG(ERR, APP, "Not an array. (path = %s)\n",
JSONPATH_TABLE);
return -1;
}
- /* table用オブジェクトの要素数取得 */
+ /* Get the number of tables to set an attribute of classifier_table */
int array_num = json_array_size(array_obj);
if (unlikely(array_num <= 0) ||
unlikely(array_num > SPP_CONFIG_MAC_TABLE_MAX)) {
@@ -319,14 +321,14 @@ config_load_classifier_table(const json_t *obj,
}
classifier_table->num_table = array_num;
- /* テーブルの各要素毎にデータ取得 */
+ /* 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;
for (table_cnt = 0; table_cnt < array_num; table_cnt++) {
tmp_table = &classifier_table->mac_tables[table_cnt];
- /* 要素取得 */
+ /* Get contents from the table */
json_t *elements_obj = json_array_get(array_obj, table_cnt);
if (unlikely(elements_obj == NULL)) {
RTE_LOG(ERR, APP,
@@ -335,7 +337,6 @@ config_load_classifier_table(const json_t *obj,
return -1;
}
- /* MACアドレス(文字列)取得 */
int ret_mac = config_get_str_value(elements_obj, JSONPATH_MAC,
tmp_table->mac_addr_str);
if (unlikely(ret_mac != 0)) {
@@ -345,13 +346,16 @@ 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 (unlikely(strcmp(tmp_table->mac_addr_str,
SPP_CONFIG_DEFAULT_CLASSIFIED_SPEC_STR) == 0))
strcpy(tmp_table->mac_addr_str,
SPP_CONFIG_DEFAULT_CLASSIFIED_DMY_ADDR_STR);
- /* MACアドレス数値変換 */
+ /* Convert mac address to integer */
int64_t ret_mac64 = spp_config_change_mac_str_to_int64(
tmp_table->mac_addr_str);
if (unlikely(ret_mac64 == -1)) {
@@ -362,7 +366,7 @@ config_load_classifier_table(const json_t *obj,
}
tmp_table->mac_addr = ret_mac64;
- /* IF情報取得 */
+ /* Extract a set of port type and number of interface */
int ret_if_str = config_get_str_value(elements_obj,
JSONPATH_PORT, if_str);
if (unlikely(ret_if_str != 0)) {
@@ -371,8 +375,7 @@ config_load_classifier_table(const json_t *obj,
table_cnt, JSONPATH_PORT);
return -1;
}
-
- /* IF種別とIF番号に分割 */
+ /* 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)) {
@@ -386,8 +389,8 @@ config_load_classifier_table(const json_t *obj,
return 0;
}
-/*
- * 処理種別を文字列から数値変換
+/**
+ * Return the type of forwarder as a member of enum of spp_core_type
*/
static enum spp_core_type
config_change_core_type(const char *core_type)
@@ -398,19 +401,17 @@ config_change_core_type(const char *core_type)
return SPP_CONFIG_CLASSIFIER_MAC;
} else if (strncmp(core_type, CONFIG_CORE_TYPE_MERGE,
strlen(CONFIG_CORE_TYPE_MERGE)+1) == 0) {
- /* Merge */
+ /* Merger */
return SPP_CONFIG_MERGE;
} else if (strncmp(core_type, CONFIG_CORE_TYPE_FORWARD,
strlen(CONFIG_CORE_TYPE_FORWARD)+1) == 0) {
- /* Forward */
+ /* Forwarder */
return SPP_CONFIG_FORWARD;
}
return SPP_CONFIG_UNUSE;
}
-/*
- * 受信ポート取得
- */
+/* Set behavior of rx port for forwarder, merger or classifier */
static int
config_set_rx_port(enum spp_core_type type, json_t *obj,
struct spp_config_functions *functions)
@@ -418,8 +419,7 @@ config_set_rx_port(enum spp_core_type type, json_t *obj,
struct spp_config_port_info *tmp_rx_port = NULL;
char if_str[SPP_CONFIG_STR_LEN];
if (type == SPP_CONFIG_MERGE) {
- /* Merge */
- /* 受信ポート用オブジェクト取得 */
+ /* Merger */
json_t *array_obj = spp_config_get_path_obj(obj, JSONPATH_RX_PORT);
if (unlikely(!array_obj)) {
RTE_LOG(ERR, APP, "Json object get failed. (path = %s, route = merge)\n",
@@ -427,14 +427,13 @@ config_set_rx_port(enum spp_core_type type, json_t *obj,
return -1;
}
- /* 受信ポート用オブジェクトが配列かチェック */
if (unlikely(!json_is_array(array_obj))) {
RTE_LOG(ERR, APP, "Not an array. (path = %s, route = merge)\n",
JSONPATH_TABLE);
return -1;
}
- /* 受信ポート用オブジェクトの要素数取得 */
+ /* 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)) {
@@ -444,12 +443,11 @@ config_set_rx_port(enum spp_core_type type, json_t *obj,
}
functions->num_rx_port = port_num;
- /* 要素毎にデータ取得 */
+ /* Get interface type and number of each of entries for merging */
int array_cnt = 0;
for (array_cnt = 0; array_cnt < port_num; array_cnt++) {
tmp_rx_port = &functions->rx_ports[array_cnt];
- /* 要素取得 */
json_t *elements_obj = json_array_get(array_obj, array_cnt);
if (unlikely(elements_obj == NULL)) {
RTE_LOG(ERR, APP,
@@ -458,7 +456,6 @@ config_set_rx_port(enum spp_core_type type, json_t *obj,
return -1;
}
- /* String type check */
if (unlikely(!json_is_string(elements_obj))) {
RTE_LOG(ERR, APP, "Not a string. (path = %s, No = %d, route = merge)\n",
JSONPATH_RX_PORT, array_cnt);
@@ -466,7 +463,7 @@ config_set_rx_port(enum spp_core_type type, json_t *obj,
}
strcpy(if_str, json_string_value(elements_obj));
- /* IF種別とIF番号に分割 */
+ /* Separate combination of interface type and number to each */
int ret_if = spp_config_get_if_info(if_str, &tmp_rx_port->if_type,
&tmp_rx_port->if_no);
if (unlikely(ret_if != 0)) {
@@ -477,18 +474,18 @@ config_set_rx_port(enum spp_core_type type, json_t *obj,
}
}
} else {
- /* Classifier/Forward */
+ /* Classifier or forwarder */
tmp_rx_port = &functions->rx_ports[0];
functions->num_rx_port = 1;
- /* 受信ポート取得 */
+ /* Get receiving port */
int ret_rx_port = config_get_str_value(obj, JSONPATH_RX_PORT, if_str);
if (unlikely(ret_rx_port != 0)) {
RTE_LOG(ERR, APP, "RX port get failed.\n");
return -1;
}
- /* IF種別とIF番号に分割 */
+ /* Separate it to interface type and number */
int ret_if = spp_config_get_if_info(if_str, &tmp_rx_port->if_type,
&tmp_rx_port->if_no);
if (unlikely(ret_if != 0)) {
@@ -501,9 +498,7 @@ config_set_rx_port(enum spp_core_type type, json_t *obj,
return 0;
}
-/*
- * 送信先ポート情報取得
- */
+/* Set behavior of tx port for forwarder, merger or classifier */
static int
config_set_tx_port(enum spp_core_type type, json_t *obj,
struct spp_config_functions *functions,
@@ -513,11 +508,11 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
struct spp_config_port_info *tmp_tx_port = NULL;
char if_str[SPP_CONFIG_STR_LEN];
if ((type == SPP_CONFIG_MERGE) || (type == SPP_CONFIG_FORWARD)) {
- /* Merge or Forward */
+ /* Merger or forwarder */
tmp_tx_port = &functions->tx_ports[0];
functions->num_tx_port = 1;
- /* 送信ポート取得 */
+ /* Get receiving port */
int ret_tx_port = config_get_str_value(obj,
JSONPATH_TX_PORT, if_str);
if (unlikely(ret_tx_port != 0)) {
@@ -525,7 +520,7 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
return -1;
}
- /* IF種別とIF番号に分割 */
+ /* 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)) {
@@ -538,23 +533,17 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
/* Classifier */
json_t *table_obj = spp_config_get_path_obj(obj, JSONPATH_TX_TABLE);
if (unlikely(table_obj != NULL)) {
- /* Classifier Tableから取得 */
functions->num_tx_port = classifier_table->num_table;
struct spp_config_mac_table_element *tmp_mac_table = NULL;
for (cnt = 0; cnt < classifier_table->num_table; cnt++) {
tmp_tx_port = &functions->tx_ports[cnt];
tmp_mac_table = &classifier_table->mac_tables[cnt];
- /* MAC振り分けテーブルより設定 */
tmp_tx_port->if_type = tmp_mac_table->port.if_type;
tmp_tx_port->if_no = tmp_mac_table->port.if_no;
}
-
- }
- else
- {
- /* tx_portパラメータより取得 */
- /* 送信ポート用オブジェクト取得 */
+ } else {
+ /* Get sending ports if table_obj is NULL */
json_t *array_obj = spp_config_get_path_obj(obj, JSONPATH_TX_PORT);
if (unlikely(array_obj == NULL)) {
RTE_LOG(ERR, APP, "Json object get failed. (path = %s, route = classifier)\n",
@@ -562,14 +551,13 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
return -1;
}
- /* 送信ポート用オブジェクトが配列かチェック */
if (unlikely(!json_is_array(array_obj))) {
RTE_LOG(ERR, APP, "Not an array. (path = %s, route = classifier)\n",
JSONPATH_TX_PORT);
return -1;
}
- /* 受信ポート用オブジェクトの要素数取得 */
+ /* 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,12 +567,10 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
}
functions->num_tx_port = port_num;
- /* 要素毎にデータ取得 */
int array_cnt = 0;
for (array_cnt = 0; array_cnt < port_num; array_cnt++) {
tmp_tx_port = &functions->tx_ports[array_cnt];
- /* 要素取得 */
json_t *elements_obj = json_array_get(array_obj, array_cnt);
if (unlikely(elements_obj == NULL)) {
RTE_LOG(ERR, APP,
@@ -593,7 +579,7 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
return -1;
}
- /* String type check */
+ /* 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);
@@ -601,7 +587,7 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
}
strcpy(if_str, json_string_value(elements_obj));
- /* IF種別とIF番号に分割 */
+ /* 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)) {
@@ -617,16 +603,13 @@ config_set_tx_port(enum spp_core_type type, json_t *obj,
return 0;
}
-/*
- * プロセス情報取得
- */
static int
config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *config)
{
struct spp_config_proc_info *proc = &config->proc;
struct spp_config_classifier_table *classifier_table = &config->classifier_table;
- /* proc_table用オブジェクト取得 */
+ /* TODO(yasufum) add comment after updating definition of the function in spp_config.c */
json_t *proc_table_obj = spp_config_get_path_obj(obj, JSONPATH_PROC_TABLE);
if (unlikely(proc_table_obj == NULL)) {
RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
@@ -634,14 +617,14 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
return -1;
}
- /* table用オブジェクトが配列かチェック */
+ /* Return error code if it is not an array_obj */
if (unlikely(!json_is_array(proc_table_obj))) {
RTE_LOG(ERR, APP, "Not an array. (path = %s)\n",
JSONPATH_TABLE);
return -1;
}
- /* table用オブジェクトの要素数取得 */
+ /* Check if the size of array is not over node_id */
int proc_table_num = json_array_size(proc_table_obj);
if (unlikely(proc_table_num < node_id)) {
RTE_LOG(ERR, APP, "No process data. (Size = %d, Node = %d)\n",
@@ -649,7 +632,7 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
return -1;
}
- /* 要素取得 */
+ /* Get proc_obj for attributes */
json_t *proc_obj = json_array_get(proc_table_obj, node_id);
if (unlikely(proc_obj == NULL)) {
RTE_LOG(ERR, APP, "Process data get failed. (Node = %d)\n",
@@ -657,14 +640,14 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
return -1;
}
- /* name取得 */
+ /* Name of proc */
int ret_name = config_get_str_value(proc_obj, JSONPATH_NAME, proc->name);
if (unlikely(ret_name != 0)) {
RTE_LOG(ERR, APP, "Process name get failed.\n");
return -1;
}
- /* VHOST数取得 */
+ /* Number of vhost interfaces of proc */
int ret_vhost = config_get_int_value(proc_obj, JSONPATH_NUM_VHOST,
&proc->num_vhost);
if (unlikely(ret_vhost != 0)) {
@@ -672,7 +655,7 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
return -1;
}
- /* RING数取得 */
+ /* Number of ring interfaces of proc */
int ret_ring = config_get_int_value(proc_obj, JSONPATH_NUM_RING,
&proc->num_ring);
if (unlikely(ret_ring != 0)) {
@@ -680,7 +663,7 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
return -1;
}
- /* functions用オブジェクト取得 */
+ /* Get the number of operator functions */
json_t *array_obj = spp_config_get_path_obj(proc_obj, JSONPATH_FUNCTIONS);
if (unlikely(!array_obj)) {
RTE_LOG(ERR, APP, "Json object get failed. (path = %s)\n",
@@ -688,14 +671,12 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
return -1;
}
- /* functions用オブジェクトが配列かチェック */
if (unlikely(!json_is_array(array_obj))) {
RTE_LOG(ERR, APP, "Not an array. (path = %s)\n",
JSONPATH_FUNCTIONS);
return -1;
}
- /* functions用オブジェクトの要素数取得 */
int array_num = json_array_size(array_obj);
if (unlikely(array_num <= 0) ||
unlikely(array_num > SPP_CONFIG_CORE_MAX)) {
@@ -705,14 +686,13 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
}
proc->num_func = array_num;
- /* 要素毎にデータ取得 */
+ /* Get each of operator functions */
struct spp_config_functions *tmp_functions = NULL;
char core_type_str[SPP_CONFIG_STR_LEN];
int array_cnt = 0;
for (array_cnt = 0; array_cnt < array_num; array_cnt++) {
tmp_functions = &proc->functions[array_cnt];
- /* 要素取得 */
json_t *elements_obj = json_array_get(array_obj, array_cnt);
if (unlikely(elements_obj == NULL)) {
RTE_LOG(ERR, APP,
@@ -721,7 +701,7 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
return -1;
}
- /* CORE番号取得 */
+ /* Get number and type of the core */
int ret_core = config_get_int_value(elements_obj, JSONPATH_CORE_NO,
&tmp_functions->core_no);
if (unlikely(ret_core != 0)) {
@@ -730,7 +710,6 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
return -1;
}
- /* 処理種別取得 */
int ret_core_type = config_get_str_value(elements_obj,
JSONPATH_CORE_TYPE, core_type_str);
if (unlikely(ret_core_type != 0)) {
@@ -739,7 +718,7 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
return -1;
}
- /* 処理種別を数値に変換 */
+ /* Convert the type of core to a member of enum spp_core_type */
enum spp_core_type core_type = config_change_core_type(core_type_str);
if (unlikely(core_type == SPP_CONFIG_UNUSE)) {
RTE_LOG(ERR, APP,
@@ -749,7 +728,7 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
}
tmp_functions->type = core_type;
- /* 受信ポート取得 */
+ /* Get rx and tx ports */
int ret_rx_port = config_set_rx_port(core_type, elements_obj,
tmp_functions);
if (unlikely(ret_rx_port != 0)) {
@@ -758,7 +737,6 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
return -1;
}
- /* 送信ポート取得 */
int ret_tx_port = config_set_tx_port(core_type, elements_obj,
tmp_functions, classifier_table);
if (unlikely(ret_tx_port != 0)) {
@@ -771,18 +749,11 @@ config_load_proc_info(const json_t *obj, int node_id, struct spp_config_area *co
return 0;
}
-/*
- * Load config file
- * OK : 0
- * NG : -1
- */
int
spp_config_load_file(const char* config_file_path, int node_id, struct spp_config_area *config)
{
- /* Config initialize */
config_init_data(config);
-
- /* Config load */
+
json_error_t json_error;
json_t *conf_obj = json_load_file(config_file_path, 0, &json_error);
if (unlikely(conf_obj == NULL)) {
@@ -792,7 +763,6 @@ spp_config_load_file(const char* config_file_path, int node_id, struct spp_confi
return -1;
}
- /* classifier table */
int ret_classifier = config_load_classifier_table(conf_obj,
&config->classifier_table);
if (unlikely(ret_classifier != 0)) {
@@ -801,7 +771,6 @@ spp_config_load_file(const char* config_file_path, int node_id, struct spp_confi
return -1;
}
- /* proc info */
int ret_proc = config_load_proc_info(conf_obj, node_id, config);
if (unlikely(ret_proc != 0)) {
RTE_LOG(ERR, APP, "Process table load failed.\n");
@@ -809,7 +778,7 @@ spp_config_load_file(const char* config_file_path, int node_id, struct spp_confi
return -1;
}
- /* Config object release */
+ /* Finally, release config object */
json_decref(conf_obj);
return 0;
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 52/57] spp_vf: refactor no self-explanatory comments
2017-12-26 1:54 ` Yasufumi Ogawa
` (50 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 51/57] spp_vf: refactor for commnets in spp_config.c x-fn-spp
@ 2017-12-28 4:55 ` x-fn-spp
2017-12-28 4:56 ` [spp] [PATCH 53/57] spp_vf: correct typo of function name x-fn-spp
` (4 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:55 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_vf.c | 25 ++++++++++---------------
1 file changed, 10 insertions(+), 15 deletions(-)
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 33373f5..44cd720 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -384,9 +384,9 @@ parse_app_args(int argc, char *argv[])
* Return patch 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.
- * TODO(yasufum) confirm why it returns not -1 but NULL.
*/
static struct patch_info *
get_if_area(enum port_type if_type, int if_no)
@@ -471,8 +471,9 @@ set_form_proc_info(struct spp_config_area *config)
continue;
}
- /* Forwardをまとめる事は可、他種別は不可 */
- /* TODO(yasufum) confirm what is the purpose and meaning */
+ /* 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))) {
@@ -509,8 +510,7 @@ set_form_proc_info(struct spp_config_area *config)
return -1;
}
- /* IF情報からCORE情報を変更する場合用に設定 */
- /* TODO(yasufum) confirm the meaning of this comment */
+ /* 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];
}
@@ -534,8 +534,7 @@ set_form_proc_info(struct spp_config_area *config)
return -1;
}
- /* IF情報からCORE情報を変更する場合用に設定 */
- /* TODO(yasufum) confirm the meaning of this comment */
+ /* 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];
}
@@ -548,7 +547,6 @@ set_form_proc_info(struct spp_config_area *config)
* Load mac table entries from config and setup patches
*
* TODO(yasufum) refactor, change if to iface.
- * TODO(yasufum) confirm if additional description for the structure of mac table is needed.
*/
static int
set_from_classifier_table(struct spp_config_area *config)
@@ -604,9 +602,8 @@ set_nic_interface(struct spp_config_area *config __attribute__ ((unused)))
patch_info = &g_if_info.nic_patchs[nic_cnt];
patch_info->dpdk_port = nic_cnt;
- /* TODO(yasufum) confirm why it is needed */
+ /* Skip for no used nic */
if (patch_info->use_flg == 0) {
- /* Not Used */
continue;
}
@@ -685,9 +682,8 @@ set_ring_interface(struct spp_config_area *config)
for (ring_cnt = 0; ring_cnt < RTE_MAX_ETHPORTS; ring_cnt++) {
patch_info = &g_if_info.ring_patchs[ring_cnt];
- /* TODO(yasufum) confirm why it is needed */
if (patch_info->use_flg == 0) {
- /* Not Used */
+ /* Skip for no used nic */
continue;
}
@@ -825,6 +821,7 @@ del_vhost_sockfile(struct patch_info *vhost_patchs)
/* 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. */
int
#ifndef USE_UT_SPP_VF
main(int argc, char *argv[])
@@ -950,7 +947,6 @@ ut_main(int argc, char *argv[])
#endif /* SPP_RINGLATENCYSTATS_ENABLE */
}
- /* TODO(yasufum) confirm, add why this check is needed because it is same the case of "ret = 0", or remove */
if (unlikely(ret_do != 0)) {
break;
}
@@ -987,10 +983,9 @@ spp_get_client_id(void)
}
/**
- * Check mac address used on the interface
+ * Check mac address used on the interface for registering or removing
*
* TODO(yasufum) refactor, change if to iface.
- * TODO(yasufum) confirm, add the reason why this check is needed
*/
static int
check_mac_used_interface(uint64_t mac_addr, enum port_type *if_type, int *if_no)
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 53/57] spp_vf: correct typo of function name
2017-12-26 1:54 ` Yasufumi Ogawa
` (51 preceding siblings ...)
2017-12-28 4:55 ` [spp] [PATCH 52/57] spp_vf: refactor no self-explanatory comments x-fn-spp
@ 2017-12-28 4:56 ` x-fn-spp
2017-12-28 4:56 ` [spp] [PATCH 54/57] spp_vf: support new command x-fn-spp
` (3 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:56 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Change 'set_form_proc_info' to 'set_from_proc_info'.
Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/spp_vf.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index 44cd720..c7268e5 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -452,10 +452,9 @@ init_core_info(void)
* Set properties of g_core_info from config
*
* TODO(yasufum) refactor, change if to iface.
- * TODO(yasufum) confirm meaning of funciton name and is typo ?
*/
static int
-set_form_proc_info(struct spp_config_area *config)
+set_from_proc_info(struct spp_config_area *config)
{
int core_cnt, rx_start, rx_cnt, tx_start, tx_cnt;
enum port_type if_type;
@@ -725,7 +724,7 @@ init_manage_data(struct spp_config_area *config)
init_core_info();
/* Load config for resource assingment and network configuration */
- int ret_proc = set_form_proc_info(config);
+ int ret_proc = set_from_proc_info(config);
if (unlikely(ret_proc != 0)) {
return -1;
}
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 54/57] spp_vf: support new command
2017-12-26 1:54 ` Yasufumi Ogawa
` (52 preceding siblings ...)
2017-12-28 4:56 ` [spp] [PATCH 53/57] spp_vf: correct typo of function name x-fn-spp
@ 2017-12-28 4:56 ` x-fn-spp
2017-12-28 4:56 ` [spp] [PATCH 55/57] spp_vf: add display of status command x-fn-spp
` (2 subsequent siblings)
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:56 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
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 <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
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 <rte_branch_prediction.h>
#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 <jansson.h>
#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 <rte_cycles.h>
+
#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 <rte_eth_ring.h>
#include <rte_eth_vhost.h>
#include <rte_memzone.h>
+#include <rte_cycles.h>
#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
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 55/57] spp_vf: add display of status command
2017-12-26 1:54 ` Yasufumi Ogawa
` (53 preceding siblings ...)
2017-12-28 4:56 ` [spp] [PATCH 54/57] spp_vf: support new command x-fn-spp
@ 2017-12-28 4:56 ` x-fn-spp
2017-12-28 4:56 ` [spp] [PATCH 56/57] spp_vf: fix " x-fn-spp
2017-12-28 4:56 ` [spp] [PATCH 57/57] spp_vf: fix l2 multicast packet forwarding x-fn-spp
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:56 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
* Display client ID.
* Display information for each port.
* Display information for each core.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/spp_vf.py | 25 ++++--
src/vf/classifier_mac.c | 86 +++++++++++++++---
src/vf/classifier_mac.h | 10 +++
src/vf/command_dec.c | 2 +-
src/vf/command_proc.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++--
src/vf/spp_forward.c | 73 ++++++++++++---
src/vf/spp_forward.h | 8 +-
src/vf/spp_vf.c | 51 +++++++++++
src/vf/spp_vf.h | 30 +++++++
9 files changed, 479 insertions(+), 38 deletions(-)
diff --git a/src/spp_vf.py b/src/spp_vf.py
index 505a142..a96b987 100755
--- a/src/spp_vf.py
+++ b/src/spp_vf.py
@@ -40,6 +40,7 @@ def connectionthread(name, client_id, conn, m2s, s2m):
"""Manage secondary process connections"""
cmd_str = 'hello'
+ recv_str = 'recv'
#infinite loop so that function do not terminate and thread do not end.
while True:
@@ -60,12 +61,24 @@ def connectionthread(name, client_id, conn, m2s, s2m):
#Receiving from secondary
try:
- data = conn.recv(2048) # 2048 stands for bytes of data to be received
- if data:
- s2m.put("recv:" + str(conn.fileno()) + ":" + "{" + data + "}")
- else:
- s2m.put("closing:" + str(conn))
+ recv_str = ""
+ while True:
+ data = conn.recv(1024) # 1024 stands for bytes of data to be received
+ if data:
+ recv_str = recv_str + data
+ if len(data) < 1024:
+ break
+ else:
+ break
+ if len(recv_str) > 0:
+ recv_str = "recv:" + str(conn.fileno()) + ":len:" + str(len(recv_str)) + ":\n{" + recv_str + "}\n"
+
+ if not data:
+ s2m.put(recv_str + "closing:" + str(conn))
break
+
+ #s2m.put("recv:" + str(conn.fileno()) + ":{" + recv_str + "}")
+ s2m.put(recv_str)
except Exception, excep:
print (str(excep))
break
@@ -212,7 +225,7 @@ def primarythread(sock, main2primary, primary2main):
#Receiving from primary
try:
- data = conn.recv(2048) # 2048 stands for bytes of data to be received
+ data = conn.recv(1024) # 1024 stands for bytes of data to be received
if data:
primary2main.put("recv:" + str(addr) + ":" + "{" + data + "}")
else:
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
index 937a8c0..2dc6071 100644
--- a/src/vf/classifier_mac.c
+++ b/src/vf/classifier_mac.c
@@ -67,21 +67,23 @@ static const size_t ETHER_ADDR_STR_BUF_SZ =
struct classified_data {
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 */
+ int if_no_global; /* id for interface generated by spp_vf */
+ uint8_t port; /* id for port generated 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 */
struct classifier_mac_info {
- struct rte_hash *classifier_table;
- int num_active_classified;
- int active_classifieds[RTE_MAX_ETHPORTS];
- int default_classified;
- int n_classified_data_tx;
- struct classified_data classified_data_rx;
+ char name[SPP_NAME_STR_LEN]; /* component name */
+ struct rte_hash *classifier_table; /* hash table keeps classifier_table */
+ int num_active_classified; /* number of valid classification */
+ int active_classifieds[RTE_MAX_ETHPORTS]; /* index of valid classification */
+ int default_classified; /* index of default classification */
+ int n_classified_data_tx; /* number of transmission ports */
+ struct classified_data classified_data_rx; /* recive port handled by classifier */
struct classified_data classified_data_tx[RTE_MAX_ETHPORTS];
+ /* transmission ports handled by classifier */
};
/* classifier management information */
@@ -126,7 +128,13 @@ init_classifier_info(struct classifier_mac_info *classifier_info,
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) {
+ if (component_info->num_rx_port == 0) {
+ classified_data_rx->if_type = UNDEF;
+ classified_data_rx->if_no = 0;
+ classified_data_rx->if_no_global = 0;
+ classified_data_rx->port = 0;
+ classified_data_rx->num_pkt = 0;
+ } else {
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;
@@ -273,6 +281,8 @@ uninit_classifier(struct classifier_mac_mng_info *classifier_mng_info)
if (classifier_mng_info->info[i].classifier_table != NULL){
rte_hash_free(classifier_mng_info->info[i].classifier_table);
classifier_mng_info->info[i].classifier_table = NULL;
+ classifier_mng_info->ref_index = 0;
+ classifier_mng_info->upd_index = 0;
}
}
}
@@ -478,6 +488,7 @@ spp_classifier_mac_update(struct spp_component_info *component_info)
"Cannot update classifer mac. ret=%d\n", ret);
return ret;
}
+ memcpy(classifier_info->name, component_info->name, SPP_NAME_STR_LEN);
/* change index of reference side */
classifier_mng_info->upd_index = classifier_mng_info->ref_index;
@@ -548,6 +559,9 @@ spp_classifier_mac_do(int id)
prev_tsc = cur_tsc;
}
+ if (classified_data_rx->if_type == UNDEF)
+ continue;
+
/* retrieve packets */
n_rx = rte_eth_rx_burst(classified_data_rx->port, 0,
rx_pkts, MAX_PKT_BURST);
@@ -573,8 +587,60 @@ spp_classifier_mac_do(int id)
return 0;
}
+/* classifier iterate component information */
+int
+spp_classifier_component_info_iterate(unsigned int lcore_id, int id,
+ struct spp_iterate_core_params *params)
+{
+ int ret = -1;
+ int i, num_tx, num_rx = 0;
+ struct classifier_mac_mng_info *classifier_mng_info;
+ struct classifier_mac_info *classifier_info;
+ struct classified_data *classified_data;
+ struct spp_port_index rx_ports[RTE_MAX_ETHPORTS];
+ struct spp_port_index tx_ports[RTE_MAX_ETHPORTS];
+
+ classifier_mng_info = g_classifier_mng_info + id;
+ if (! is_used_mng_info(classifier_mng_info)) {
+ RTE_LOG(ERR, SPP_CLASSIFIER_MAC,
+ "Component[%d] Not used. (status)(core = %d, type = %d)\n",
+ id, lcore_id, SPP_COMPONENT_CLASSIFIER_MAC);
+ return -1;
+ }
+
+ classifier_info = classifier_mng_info->info +
+ classifier_mng_info->ref_index;
+
+ classified_data = classifier_info->classified_data_tx;
+
+ memset(rx_ports, 0x00, sizeof(rx_ports));
+ if (classifier_info->classified_data_rx.if_type != UNDEF) {
+ num_rx = 1;
+ rx_ports[0].if_type = classifier_info->classified_data_rx.if_type;
+ rx_ports[0].if_no = classifier_info->classified_data_rx.if_no_global;
+ }
+
+ memset(tx_ports, 0x00, sizeof(tx_ports));
+ num_tx = classifier_info->n_classified_data_tx;
+ for (i = 0; i < num_tx; i++) {
+ tx_ports[i].if_type = classified_data[i].if_type;
+ tx_ports[i].if_no = classified_data[i].if_no_global;
+ }
+
+ /* Set the information with the function specified by the command. */
+ ret = (*params->element_proc)(
+ params->opaque, lcore_id,
+ classifier_info->name, SPP_TYPE_CLASSIFIER_MAC_STR,
+ num_rx, rx_ports, num_tx, tx_ports);
+ if (unlikely(ret != 0))
+ return -1;
+
+ return 0;
+}
+
/* classifier(mac address) iterate classifier table. */
-int spp_classifier_mac_iterate_table(
+int
+spp_classifier_mac_iterate_table(
struct spp_iterate_classifier_table_params *params)
{
int ret, i;
diff --git a/src/vf/classifier_mac.h b/src/vf/classifier_mac.h
index f182668..b38ce70 100644
--- a/src/vf/classifier_mac.h
+++ b/src/vf/classifier_mac.h
@@ -29,6 +29,16 @@ int spp_classifier_mac_update(struct spp_component_info *component_info);
*/
int spp_classifier_mac_do(int id);
+/*
+ * classifier iterate component information
+ *
+ * @ret_val 0 succeeded.
+ * @ret_val -1 failed.
+ */
+int
+spp_classifier_component_info_iterate(unsigned int lcore_id, int id,
+ struct spp_iterate_core_params *params);
+
/**
* classifier(mac address) iterate classifier table.
*/
diff --git a/src/vf/command_dec.c b/src/vf/command_dec.c
index 166901c..56360e9 100644
--- a/src/vf/command_dec.c
+++ b/src/vf/command_dec.c
@@ -566,7 +566,7 @@ static struct decode_command_list command_list[] = {
{ "_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 */
+ { "component", 3, 5, decode_comand_parameter_in_list }, /* component */
{ "port", 5, 5, decode_comand_parameter_in_list }, /* port */
{ "", 0, 0, NULL } /* termination */
};
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index 0a45874..6159e87 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -243,9 +243,191 @@ append_response_client_id_value(json_t *parent_obj)
return 0;
}
+/* append client-id value */
+static int
+append_client_id_value(json_t *parent_obj)
+{
+ int ret = -1;
+ ret = json_object_set_new(parent_obj, "client-id",
+ json_integer(spp_get_client_id()));
+ if (unlikely(ret != 0))
+ return -1;
+
+ return 0;
+}
+
+/* append interface array */
+static int
+append_interface_array(json_t *parent_obj, const char *name,
+ const enum port_type type)
+{
+ int ret = -1;
+ int i = 0;
+ json_t *array_obj;
+ array_obj = json_array();
+ if (unlikely(array_obj == NULL))
+ return -1;
+
+ for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+ if (!spp_check_flush_port(type, i))
+ continue;
+
+ ret = json_array_append_new(array_obj, json_integer(i));
+ if (unlikely(ret != 0)) {
+ json_decref(array_obj);
+ return -1;
+ }
+ }
+
+ ret = json_object_set_new(parent_obj, name, array_obj);
+ if (unlikely(ret != 0)) {
+ json_decref(array_obj);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* append interface value */
+static int
+append_interface_value(json_t *parent_obj)
+{
+ int ret = -1;
+ ret = append_interface_array(parent_obj, "phy", PHY);
+ if (unlikely(ret != 0))
+ return -1;
+
+ ret = append_interface_array(parent_obj, "vhost", VHOST);
+ if (unlikely(ret != 0))
+ return -1;
+
+ ret = append_interface_array(parent_obj, "ring", RING);
+ if (unlikely(ret != 0))
+ return -1;
+
+ return 0;
+}
+
+/* append port array */
+static int
+apeend_port_array(json_t *parent_obj, const char *name,
+ const int num, const struct spp_port_index *ports)
+{
+ int ret = -1;
+ int i = 0;
+ char port_str[64];
+ json_t *array_obj;
+ array_obj = json_array();
+ if (unlikely(array_obj == NULL))
+ return -1;
+
+ for (i = 0; i < num; i++) {
+ spp_format_port_string(port_str, ports[i].if_type,
+ ports[i].if_no);
+ ret = json_array_append_new(array_obj, json_string(port_str));
+ if (unlikely(ret != 0)) {
+ json_decref(array_obj);
+ return -1;
+ }
+ }
+
+ ret = json_object_set_new(parent_obj, name, array_obj);
+ if (unlikely(ret != 0)) {
+ json_decref(array_obj);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* append core element value */
+static int
+append_core_element_value(
+ void *opaque, const unsigned int lcore_id,
+ const char *name, const char *type,
+ const int num_rx, const struct spp_port_index *rx_ports,
+ const int num_tx, const struct spp_port_index *tx_ports)
+{
+ int ret = -1;
+ json_t *parent_obj = (json_t *)opaque;
+ json_t *tab_obj;
+
+ tab_obj = json_object();
+ if (unlikely(tab_obj == NULL))
+ return -1;
+
+ ret = json_object_set_new(tab_obj, "core", json_integer(lcore_id));
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
+
+ ret = json_object_set_new(tab_obj, "name", json_string(name));
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
+
+ ret = json_object_set_new(tab_obj, "type", json_string(type));
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
+
+ ret = apeend_port_array(tab_obj, "rx_port", num_rx, rx_ports);
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
+
+ ret = apeend_port_array(tab_obj, "tx_port", num_tx, tx_ports);
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
+
+ ret = json_array_append_new(parent_obj, tab_obj);
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* append core value */
+static int
+append_response_core_value(json_t *parent_obj)
+{
+ int ret = -1;
+ json_t *tab_obj;
+ struct spp_iterate_core_params itr_params;
+
+ tab_obj = json_array();
+ if (unlikely(tab_obj == NULL))
+ return -1;
+
+ itr_params.opaque = tab_obj;
+ itr_params.element_proc = append_core_element_value;
+
+ ret = spp_iterate_core_info(&itr_params);
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
+
+ ret = json_object_set_new(parent_obj, "core", tab_obj);
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
+
+ return 0;
+}
+
/* append classifier element value */
-static
-int append_classifier_element_value(
+static int
+append_classifier_element_value(
void *opaque,
__rte_unused enum spp_classifier_type type,
const char *data,
@@ -265,12 +447,12 @@ int append_classifier_element_value(
return 0;
}
-/* append info value(status response) to specified json object */
+/* append classifier_table value */
static int
-append_response_info_value(json_t *parent_obj)
+append_response_classifier_value(json_t *parent_obj)
{
int ret = -1;
- json_t *info_obj, *tab_obj;
+ json_t *tab_obj;
struct spp_iterate_classifier_table_params itr_params;
/* create classifier_table array */
@@ -287,16 +469,48 @@ append_response_info_value(json_t *parent_obj)
return -1;
}
+ ret = json_object_set_new(parent_obj, "classifier_table", tab_obj);
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* append info value(status response) to specified json object */
+static int
+append_response_info_value(json_t *parent_obj)
+{
+ int ret = -1;
+ json_t *info_obj;
+
/* set classifier_table object in info object */
info_obj = json_object();
- if (unlikely(info_obj == NULL)) {
- json_decref(tab_obj);
+ if (unlikely(info_obj == NULL))
+ return -1;
+
+ ret = append_client_id_value(info_obj);
+ if (unlikely(ret != 0)) {
+ json_decref(info_obj);
return -1;
}
- ret = json_object_set_new(info_obj, "classifier_table", tab_obj);
+ ret = append_interface_value(info_obj);
if (unlikely(ret != 0)) {
- json_decref(tab_obj);
+ json_decref(info_obj);
+ return -1;
+ }
+
+ ret = append_response_core_value(info_obj);
+ if (unlikely(ret != 0)) {
+ json_decref(info_obj);
+ return -1;
+ }
+
+ ret = append_response_classifier_value(info_obj);
+ if (unlikely(ret != 0)) {
+ json_decref(info_obj);
return -1;
}
diff --git a/src/vf/spp_forward.c b/src/vf/spp_forward.c
index 8a0980a..dbe96dc 100644
--- a/src/vf/spp_forward.c
+++ b/src/vf/spp_forward.c
@@ -12,15 +12,19 @@ struct forward_rxtx {
struct spp_port_info tx;
};
+/* Information on the path used for forward. */
struct forward_path {
- int num;
+ char name[SPP_NAME_STR_LEN]; /* component name */
+ volatile enum spp_component_type type; /* component type */
+ int num; /* number of receive ports */
struct forward_rxtx ports[RTE_MAX_ETHPORTS];
+ /* port used for transfer */
};
+/* Information for forward. */
struct forward_info {
- enum spp_component_type type;
- volatile int ref_index;
- volatile int upd_index;
+ volatile int ref_index; /* index to reference area */
+ volatile int upd_index; /* index to update area */
struct forward_path path[SPP_INFO_AREA_MAX];
};
@@ -42,8 +46,6 @@ spp_forward_init(void)
static void
clear_forward_info(int id)
{
- struct forward_info *info = &g_forward_info[id];
- info->type = SPP_COMPONENT_UNUSE;
memset(&g_forward_info[id].path, 0x00, sizeof(struct forward_path));
}
@@ -75,10 +77,11 @@ spp_forward_update(struct spp_component_info *component)
clear_forward_info(component->component_id);
RTE_LOG(INFO, FORWARD,
- "Component[%d] Start update component. (type = %d)\n",
- component->component_id, component->type);
+ "Component[%d] Start update component. (name = %s, type = %d)\n",
+ component->component_id, component->name, component->type);
- info->type = component->type;
+ memcpy(&path->name, component->name, SPP_NAME_STR_LEN);
+ path->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],
@@ -93,8 +96,9 @@ spp_forward_update(struct spp_component_info *component)
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);
+ RTE_LOG(INFO, FORWARD,
+ "Component[%d] Complete update component. (name = %s, type = %d)\n",
+ component->component_id, component->name, component->type);
return 0;
}
@@ -160,3 +164,50 @@ spp_forward(int id)
}
return 0;
}
+
+/* Merge/Forward iterate component information */
+int
+spp_forward_core_info_iterate(unsigned int lcore_id, int id,
+ struct spp_iterate_core_params *params)
+{
+ int ret = -1;
+ int cnt, num_tx;
+ const char *component_type = NULL;
+ struct forward_info *info = &g_forward_info[id];
+ struct forward_path *path = &info->path[info->ref_index];
+ struct spp_port_index rx_ports[RTE_MAX_ETHPORTS];
+ struct spp_port_index tx_ports[RTE_MAX_ETHPORTS];
+
+ if (unlikely(path->type == SPP_COMPONENT_UNUSE)) {
+ RTE_LOG(ERR, FORWARD,
+ "Component[%d] Not used. (status)(core = %d, type = %d)\n",
+ id, lcore_id, path->type);
+ return -1;
+ }
+
+ if (path->type == SPP_COMPONENT_MERGE)
+ component_type = SPP_TYPE_MERGE_STR;
+ else
+ component_type = SPP_TYPE_FORWARD_STR;
+
+ memset(rx_ports, 0x00, sizeof(rx_ports));
+ for (cnt = 0; cnt < path->num; cnt++) {
+ rx_ports[cnt].if_type = path->ports[cnt].rx.if_type;
+ rx_ports[cnt].if_no = path->ports[cnt].rx.if_no;
+ }
+
+ memset(tx_ports, 0x00, sizeof(tx_ports));
+ num_tx = (path->num > 0)?1:0;
+ tx_ports[0].if_type = path->ports[0].tx.if_type;
+ tx_ports[0].if_no = path->ports[0].tx.if_no;
+
+ /* Set the information with the function specified by the command. */
+ ret = (*params->element_proc)(
+ params->opaque, lcore_id,
+ path->name, component_type,
+ path->num, rx_ports, num_tx, tx_ports);
+ if (unlikely(ret != 0))
+ return -1;
+
+ return 0;
+}
diff --git a/src/vf/spp_forward.h b/src/vf/spp_forward.h
index 729dbe8..ed0744d 100644
--- a/src/vf/spp_forward.h
+++ b/src/vf/spp_forward.h
@@ -1,11 +1,13 @@
#ifndef __SPP_FORWARD_H__
#define __SPP_FORWARD_H__
-
+/* Clear info */
void spp_forward_init(void);
+/* Clear info for one element. */
void spp_forward_init_info(int id);
+/* Update forward info */
int spp_forward_update(struct spp_component_info *component);
/*
@@ -13,4 +15,8 @@ int spp_forward_update(struct spp_component_info *component);
*/
int spp_forward(int id);
+/* Merge/Forward iterate component information */
+int spp_forward_core_info_iterate(unsigned int lcore_id, int id,
+ struct spp_iterate_core_params *params);
+
#endif /* __SPP_FORWARD_H__ */
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index d6eb7b2..f97c348 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -488,6 +488,7 @@ set_nic_interface(void)
}
for (nic_cnt = 0; nic_cnt < g_if_info.num_nic; nic_cnt++) {
+ g_if_info.nic[nic_cnt].if_type = PHY;
g_if_info.nic[nic_cnt].dpdk_port = nic_cnt;
}
@@ -842,6 +843,16 @@ spp_check_added_port(enum port_type if_type, int if_no)
}
/*
+ * Check if port has been flushed.
+ */
+int
+spp_check_flush_port(enum port_type if_type, int if_no)
+{
+ struct spp_port_info *port = get_if_area(if_type, if_no);
+ return port->dpdk_port >= 0;
+}
+
+/*
* Check if component is using port.
*/
int
@@ -1068,6 +1079,7 @@ spp_update_component(
core->num++;
ret = SPP_RET_OK;
tmp_lcore_id = lcore_id;
+ g_change_component[component_id] = 1;
break;
case SPP_CMD_ACTION_STOP:
@@ -1091,6 +1103,7 @@ spp_update_component(
core->type = SPP_COMPONENT_UNUSE;
ret = SPP_RET_OK;
+ g_change_component[component_id] = 0;
break;
default:
@@ -1320,6 +1333,44 @@ spp_flush(void)
return SPP_RET_OK;
}
+/* Iterate core infomartion */
+int
+spp_iterate_core_info(struct spp_iterate_core_params *params)
+{
+ int ret;
+ int core_cnt, cnt;
+ struct core_info *core = NULL;
+
+ for (core_cnt = 0; core_cnt < RTE_MAX_LCORE; core_cnt++) {
+ if (spp_get_core_status(core_cnt) == SPP_CORE_UNUSE)
+ continue;
+
+ core = get_core_info(core_cnt);
+ for (cnt = 0; cnt < core->num; cnt++) {
+ if (core->type == SPP_COMPONENT_CLASSIFIER_MAC) {
+ ret = spp_classifier_component_info_iterate(
+ core_cnt,
+ core->id[cnt],
+ params);
+ } else {
+ ret = spp_forward_core_info_iterate(
+ core_cnt,
+ core->id[cnt],
+ params);
+ }
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, APP, "Cannot iterate core information. "
+ "(core = %d, type = %d)\n",
+ core_cnt, core->type);
+ return SPP_RET_NG;
+ }
+ }
+ }
+
+ return SPP_RET_OK;
+}
+
+/* Iterate Classifier_table */
int
spp_iterate_classifier_table(
struct spp_iterate_classifier_table_params *params)
diff --git a/src/vf/spp_vf.h b/src/vf/spp_vf.h
index 90a2886..9e846ef 100644
--- a/src/vf/spp_vf.h
+++ b/src/vf/spp_vf.h
@@ -3,6 +3,10 @@
#include "common.h"
+#define SPP_TYPE_CLASSIFIER_MAC_STR "classifier_mac"
+#define SPP_TYPE_MERGE_STR "merge"
+#define SPP_TYPE_FORWARD_STR "forward"
+
#define SPP_IFTYPE_NIC_STR "phy"
#define SPP_IFTYPE_VHOST_STR "vhost"
#define SPP_IFTYPE_RING_STR "ring"
@@ -162,6 +166,26 @@ int spp_update_port(
*/
int spp_flush(void);
+/* definition of iterated core element procedure function */
+typedef int (*spp_iterate_core_element_proc)(
+ void *opaque,
+ const unsigned int lcore_id,
+ const char *name,
+ const char *type,
+ const int num_rx,
+ const struct spp_port_index *rx_ports,
+ const int num_tx,
+ const struct spp_port_index *tx_ports);
+
+/* iterate core information parameters */
+struct spp_iterate_core_params {
+ void *opaque;
+ spp_iterate_core_element_proc element_proc;
+};
+
+/* Iterate core infomartion */
+int spp_iterate_core_info(struct spp_iterate_core_params *params);
+
/* definition of iterated classifier element procedure function */
typedef int (*spp_iterate_classifier_element_proc)(
void *opaque,
@@ -221,6 +245,12 @@ int spp_check_mac_used_port(uint64_t mac_addr, enum port_type if_type, int if_no
int spp_check_added_port(enum port_type if_type, int if_no);
/*
+ * Check if port has been flushed.
+ * RETURN : True if port has been flushed.
+ */
+int spp_check_flush_port(enum port_type if_type, int if_no);
+
+/*
* Check if component is using port.
* OK : match component ID
* NG : SPP_RET_NG
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 56/57] spp_vf: fix status command
2017-12-26 1:54 ` Yasufumi Ogawa
` (54 preceding siblings ...)
2017-12-28 4:56 ` [spp] [PATCH 55/57] spp_vf: add display of status command x-fn-spp
@ 2017-12-28 4:56 ` x-fn-spp
2017-12-28 4:56 ` [spp] [PATCH 57/57] spp_vf: fix l2 multicast packet forwarding x-fn-spp
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:56 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Fix to display "unuse" even when the core is unused.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/command_proc.c | 33 ++++++++++++++++++++-------------
src/vf/spp_vf.c | 28 +++++++++++++++++++++-------
src/vf/spp_vf.h | 1 +
3 files changed, 42 insertions(+), 20 deletions(-)
diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c
index 6159e87..ec2da51 100644
--- a/src/vf/command_proc.c
+++ b/src/vf/command_proc.c
@@ -349,6 +349,7 @@ append_core_element_value(
const int num_tx, const struct spp_port_index *tx_ports)
{
int ret = -1;
+ int unuse_flg = 0;
json_t *parent_obj = (json_t *)opaque;
json_t *tab_obj;
@@ -356,16 +357,20 @@ append_core_element_value(
if (unlikely(tab_obj == NULL))
return -1;
+ unuse_flg = strcmp(type, SPP_TYPE_UNUSE_STR);
+
ret = json_object_set_new(tab_obj, "core", json_integer(lcore_id));
if (unlikely(ret != 0)) {
json_decref(tab_obj);
return -1;
}
- ret = json_object_set_new(tab_obj, "name", json_string(name));
- if (unlikely(ret != 0)) {
- json_decref(tab_obj);
- return -1;
+ if (unuse_flg) {
+ ret = json_object_set_new(tab_obj, "name", json_string(name));
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
}
ret = json_object_set_new(tab_obj, "type", json_string(type));
@@ -374,16 +379,18 @@ append_core_element_value(
return -1;
}
- ret = apeend_port_array(tab_obj, "rx_port", num_rx, rx_ports);
- if (unlikely(ret != 0)) {
- json_decref(tab_obj);
- return -1;
- }
+ if (unuse_flg) {
+ ret = apeend_port_array(tab_obj, "rx_port", num_rx, rx_ports);
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
- ret = apeend_port_array(tab_obj, "tx_port", num_tx, tx_ports);
- if (unlikely(ret != 0)) {
- json_decref(tab_obj);
- return -1;
+ ret = apeend_port_array(tab_obj, "tx_port", num_tx, tx_ports);
+ if (unlikely(ret != 0)) {
+ json_decref(tab_obj);
+ return -1;
+ }
}
ret = json_array_append_new(parent_obj, tab_obj);
diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c
index f97c348..7626ba7 100644
--- a/src/vf/spp_vf.c
+++ b/src/vf/spp_vf.c
@@ -1338,30 +1338,44 @@ int
spp_iterate_core_info(struct spp_iterate_core_params *params)
{
int ret;
- int core_cnt, cnt;
+ int lcore_id, cnt;
struct core_info *core = NULL;
- for (core_cnt = 0; core_cnt < RTE_MAX_LCORE; core_cnt++) {
- if (spp_get_core_status(core_cnt) == SPP_CORE_UNUSE)
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (spp_get_core_status(lcore_id) == SPP_CORE_UNUSE)
continue;
- core = get_core_info(core_cnt);
+ core = get_core_info(lcore_id);
+ if (core->num == 0) {
+ ret = (*params->element_proc)(
+ params->opaque, lcore_id,
+ "", SPP_TYPE_UNUSE_STR,
+ 0, NULL, 0, NULL);
+ if (unlikely(ret != 0)) {
+ RTE_LOG(ERR, APP, "Cannot iterate core information. "
+ "(core = %d, type = %d)\n",
+ lcore_id, SPP_COMPONENT_UNUSE);
+ return SPP_RET_NG;
+ }
+ continue;
+ }
+
for (cnt = 0; cnt < core->num; cnt++) {
if (core->type == SPP_COMPONENT_CLASSIFIER_MAC) {
ret = spp_classifier_component_info_iterate(
- core_cnt,
+ lcore_id,
core->id[cnt],
params);
} else {
ret = spp_forward_core_info_iterate(
- core_cnt,
+ lcore_id,
core->id[cnt],
params);
}
if (unlikely(ret != 0)) {
RTE_LOG(ERR, APP, "Cannot iterate core information. "
"(core = %d, type = %d)\n",
- core_cnt, core->type);
+ lcore_id, core->type);
return SPP_RET_NG;
}
}
diff --git a/src/vf/spp_vf.h b/src/vf/spp_vf.h
index 9e846ef..ea2baf1 100644
--- a/src/vf/spp_vf.h
+++ b/src/vf/spp_vf.h
@@ -6,6 +6,7 @@
#define SPP_TYPE_CLASSIFIER_MAC_STR "classifier_mac"
#define SPP_TYPE_MERGE_STR "merge"
#define SPP_TYPE_FORWARD_STR "forward"
+#define SPP_TYPE_UNUSE_STR "unuse"
#define SPP_IFTYPE_NIC_STR "phy"
#define SPP_IFTYPE_VHOST_STR "vhost"
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread
* [spp] [PATCH 57/57] spp_vf: fix l2 multicast packet forwarding
2017-12-26 1:54 ` Yasufumi Ogawa
` (55 preceding siblings ...)
2017-12-28 4:56 ` [spp] [PATCH 56/57] spp_vf: fix " x-fn-spp
@ 2017-12-28 4:56 ` x-fn-spp
56 siblings, 0 replies; 97+ messages in thread
From: x-fn-spp @ 2017-12-28 4:56 UTC (permalink / raw)
To: spp
From: Hiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>
Since ref_cnt was added extra when sending the multicast packet,
it is fixed so as to subtract the extra.
Signed-off-by: Kentaro Watanabe <watanabe.kentaro.z01@as.ntt-tx.co.jp>
Signed-off-by: Yasufum Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/vf/classifier_mac.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c
index 2dc6071..333b581 100644
--- a/src/vf/classifier_mac.c
+++ b/src/vf/classifier_mac.c
@@ -372,7 +372,7 @@ handle_l2multicast_packet(struct rte_mbuf *pkt,
return;
}
- rte_mbuf_refcnt_update(pkt, classifier_info->num_active_classified);
+ rte_mbuf_refcnt_update(pkt, (classifier_info->num_active_classified - 1));
for (i= 0; i < classifier_info->num_active_classified; i++) {
push_packet(pkt, classified_data +
--
1.9.1
^ permalink raw reply [flat|nested] 97+ messages in thread