[spp] [PATCH v3 05/17] spp_primary: add support of multi-queue
x-fn-spp-ml at ntt-tx.co.jp
x-fn-spp-ml at ntt-tx.co.jp
Tue Feb 25 06:56:27 CET 2020
From: Hideyuki Yamashita <yamashita.hideyuki at ntt-tx.co.jp>
Multi-queue support is provided for both tx and rx of physical NIC.
To initialize physical NIC with multi-queue mode, startup parameters of
the primary process should be newly introduced.
Signed-off-by: Hideyuki Yamashita <yamashita.hideyuki at ntt-tx.co.jp>
Signed-off-by: Naoki Takada <ntakada14 at gmail.com>
---
src/primary/Makefile | 10 ++++
src/primary/args.c | 138 ++++++++++++++++++++++++++++++++++++++++++-
src/primary/args.h | 3 +
src/primary/init.c | 8 ++-
src/primary/init.h | 3 +-
src/primary/main.c | 40 ++++++++++---
6 files changed, 189 insertions(+), 13 deletions(-)
diff --git a/src/primary/Makefile b/src/primary/Makefile
index ace6228..35ae788 100644
--- a/src/primary/Makefile
+++ b/src/primary/Makefile
@@ -20,12 +20,22 @@ APP = spp_primary
# TODO: revise to not use functions in secondary's.
SPP_SEC_DIR = ../shared/secondary
+SPP_FLOW_DIR = ./flow
+SPP_FLOW_SRC = flow.c attr.c common.c
+SPP_FLOW_PTN_DIR = $(SPP_FLOW_DIR)/pattern
+SPP_FLOW_PTN_SRC = eth.c vlan.c
+SPP_FLOW_ACT_DIR = $(SPP_FLOW_DIR)/action
+SPP_FLOW_ACT_SRC = jump.c queue.c of_push_vlan.c of_set_vlan_vid.c
+SPP_FLOW_ACT_SRC += of_set_vlan_pcp.c
# all source are stored in SRCS-y
SRCS-y := main.c init.c args.c
SRCS-y += ../shared/common.c ../shared/basic_forwarder.c ../shared/port_manager.c
SRCS-y += $(SPP_SEC_DIR)/add_port.c
SRCS-y += $(SPP_SEC_DIR)/utils.c
+SRCS-y += $(addprefix $(SPP_FLOW_DIR)/,$(SPP_FLOW_SRC))
+SRCS-y += $(addprefix $(SPP_FLOW_PTN_DIR)/,$(SPP_FLOW_PTN_SRC))
+SRCS-y += $(addprefix $(SPP_FLOW_ACT_DIR)/,$(SPP_FLOW_ACT_SRC))
INC := $(wildcard *.h)
diff --git a/src/primary/args.c b/src/primary/args.c
index 346bcbf..e9d1c58 100644
--- a/src/primary/args.c
+++ b/src/primary/args.c
@@ -29,10 +29,12 @@ int do_forwarding;
enum {
CMD_LINE_OPT_MIN_NUM = 256,
CMD_OPT_DISP_STATS,
+ CMD_OPT_PORT_NUM, /* For `--port-num` */
};
struct option lgopts[] = {
{"disp-stats", no_argument, NULL, CMD_OPT_DISP_STATS},
+ {"port-num", required_argument, NULL, CMD_OPT_PORT_NUM},
{0}
};
@@ -45,9 +47,14 @@ static void
usage(void)
{
RTE_LOG(INFO, PRIMARY,
- "%s [EAL options] -- -p PORTMASK -n NUM_CLIENTS [-s NUM_SOCKETS]\n"
+ "%s [EAL options] -- -p PORTMASK -n NUM_CLIENTS [-s NUM_SOCKETS]"
+ " [--port-num NUM_PORT"
+ " rxq NUM_RX_QUEUE txq NUM_TX_QUEUE]...\n"
" -p PORTMASK: hexadecimal bitmask of ports to use\n"
" -n NUM_RINGS: number of ring ports used from secondaries\n"
+ " --port-num NUM_PORT: number of ports for multi-queue setting\n"
+ " rxq NUM_RX_QUEUE: number of receive queues\n"
+ " txq NUM_TX_QUEUE number of transmit queues\n"
, progname);
}
@@ -131,6 +138,120 @@ parse_nof_rings(uint16_t *num_clients, const char *clients)
return 0;
}
+/* Extract the number of queues from startup option. */
+static int
+parse_nof_queues(struct port_queue *arg_queues, const char *str_port_num,
+ int option_index, uint16_t max_ports, int argc, char *argv[])
+{
+ char *end = NULL;
+ unsigned long temp;
+ uint16_t port_num, rxq, txq;
+
+
+ if (str_port_num == NULL || *str_port_num == '\0') {
+ RTE_LOG(ERR, PRIMARY,
+ "PORT_NUM is not specified(%s:%d)\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ /* Parameter check of port_num */
+ temp = strtoul(str_port_num, &end, 10);
+ if (end == NULL || *end != '\0') {
+ RTE_LOG(ERR, PRIMARY,
+ "PORT_NUM is not a number(%s:%d)\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ port_num = (uint16_t)temp;
+
+ if (port_num > max_ports) {
+ RTE_LOG(ERR, PRIMARY,
+ "PORT_NUM exceeds the number of available ports"
+ "(%s:%d)\n",
+ __func__, __LINE__);
+ return 1;
+ }
+
+ /* Check if both 'rxq' and 'txq' are inclued in parameter string. */
+ if (option_index + 3 > argc) {
+ RTE_LOG(ERR, PRIMARY,
+ "rxq NUM_RX_QUEUE txq NUM_TX_QUEUE is not specified"
+ "(%s:%d)\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ if (strcmp(argv[option_index], "rxq")) {
+ RTE_LOG(ERR, PRIMARY,
+ "rxq is not specified in the --port_num option"
+ "(%s:%d)\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ /* Parameter check of rxq */
+ temp = strtoul(argv[option_index + 1], &end, 10);
+ if (end == NULL || *end != '\0' || temp == 0) {
+ RTE_LOG(ERR, PRIMARY,
+ "NUM_RX_QUEUE is not a number(%s:%d)\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ rxq = (uint16_t)temp;
+
+ if (strcmp(argv[option_index + 2], "txq")) {
+ RTE_LOG(ERR, PRIMARY,
+ "txq is not specified in the --port_num option"
+ "(%s:%d)\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ /* Parameter check of txq */
+ temp = strtoul(argv[option_index + 3], &end, 10);
+ if (end == NULL || *end != '\0' || temp == 0) {
+ RTE_LOG(ERR, PRIMARY,
+ "NUM_TX_QUEUE is not a number(%s:%d)\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ txq = (uint16_t)temp;
+
+ arg_queues[port_num].rxq = rxq;
+ arg_queues[port_num].txq = txq;
+
+ return 0;
+}
+
+/**
+ * Set the number of queues for port_id.
+ * If not specified number of queue is set as 1.
+ */
+static int
+set_nof_queues(struct port_info *ports, struct port_queue *arg_queues)
+{
+ int index;
+ uint16_t port_id, rxq, txq;
+
+ for (index = 0; index < ports->num_ports; index++) {
+ port_id = ports->id[index];
+
+ if (arg_queues[port_id].rxq == 0 ||
+ arg_queues[port_id].txq == 0) {
+ rxq = 1;
+ txq = 1;
+ } else {
+ rxq = arg_queues[port_id].rxq;
+ txq = arg_queues[port_id].txq;
+ }
+
+ ports->queue_info[index].rxq = rxq;
+ ports->queue_info[index].txq = txq;
+ }
+ return 0;
+}
+
/**
* The application specific arguments follow the DPDK-specific
* arguments which are stripped by the DPDK init. This function
@@ -143,6 +264,7 @@ parse_app_args(uint16_t max_ports, int argc, char *argv[])
int option_index, opt;
char **argvopt = argv;
int ret;
+ struct port_queue arg_queues[RTE_MAX_ETHPORTS] = { 0 };
progname = argv[0];
@@ -171,6 +293,14 @@ parse_app_args(uint16_t max_ports, int argc, char *argv[])
return -1;
}
break;
+ case CMD_OPT_PORT_NUM:
+ ret = parse_nof_queues(arg_queues, optarg, optind,
+ max_ports, argc, argv);
+ if (ret != 0) {
+ usage();
+ return -1;
+ }
+ break;
default:
RTE_LOG(ERR,
PRIMARY, "ERROR: Unknown option '%c'\n", opt);
@@ -184,5 +314,11 @@ parse_app_args(uint16_t max_ports, int argc, char *argv[])
return -1;
}
+ ret = set_nof_queues(ports, arg_queues);
+ if (ret != 0) {
+ usage();
+ return -1;
+ }
+
return 0;
}
diff --git a/src/primary/args.h b/src/primary/args.h
index 644cd56..f73772c 100644
--- a/src/primary/args.h
+++ b/src/primary/args.h
@@ -13,6 +13,9 @@ extern uint16_t num_rings;
extern char *server_ip;
extern int server_port;
+/* Return value definition for getopt_long(). Only for long option. */
+#define SPP_LONGOPT_RETVAL_PORT_NUM 1 /* For `--port-num` */
+
/**
* Set flg from given argument.
*
diff --git a/src/primary/init.c b/src/primary/init.c
index 9e47fcf..e9c12f1 100644
--- a/src/primary/init.c
+++ b/src/primary/init.c
@@ -160,7 +160,9 @@ init(int argc, char *argv[])
/* now initialise the ports we will use */
if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
for (count = 0; count < ports->num_ports; count++) {
- retval = init_port(ports->id[count], pktmbuf_pool);
+ retval = init_port(ports->id[count], pktmbuf_pool,
+ ports->queue_info[count].rxq,
+ ports->queue_info[count].txq);
if (retval != 0)
rte_exit(EXIT_FAILURE,
"Cannot initialise port %d\n", count);
@@ -254,7 +256,8 @@ check_all_ports_link_status(struct port_info *ports, uint16_t port_num,
* - start the port and report its status to stdout
*/
int
-init_port(uint16_t port_num, struct rte_mempool *pktmbuf_pool)
+init_port(uint16_t port_num, struct rte_mempool *pktmbuf_pool,
+ uint16_t rx_rings, uint16_t tx_rings)
{
/* for port configuration all features are off by default */
const struct rte_eth_conf port_conf = {
@@ -262,7 +265,6 @@ init_port(uint16_t port_num, struct rte_mempool *pktmbuf_pool)
.mq_mode = ETH_MQ_RX_RSS,
},
};
- const uint16_t rx_rings = 1, tx_rings = 1;
const uint16_t rx_ring_size = RTE_MP_RX_DESC_DEFAULT;
const uint16_t tx_ring_size = RTE_MP_TX_DESC_DEFAULT;
uint16_t q;
diff --git a/src/primary/init.h b/src/primary/init.h
index 6344377..5384154 100644
--- a/src/primary/init.h
+++ b/src/primary/init.h
@@ -50,6 +50,7 @@ int init(int argc, char *argv[]);
void check_all_ports_link_status(struct port_info *ports, uint16_t port_num,
uint32_t port_mask);
-int init_port(uint16_t port_num, struct rte_mempool *pktmbuf_pool);
+int init_port(uint16_t port_num, struct rte_mempool *pktmbuf_pool,
+ uint16_t rx_rings, uint16_t tx_rings);
#endif /* ifndef _PRIMARY_INIT_H_ */
diff --git a/src/primary/main.c b/src/primary/main.c
index d3828e8..ca81636 100644
--- a/src/primary/main.c
+++ b/src/primary/main.c
@@ -16,6 +16,7 @@
#include "args.h"
#include "init.h"
#include "primary.h"
+#include "primary/flow/flow.h"
#include "shared/port_manager.h"
#include "shared/secondary/add_port.h"
@@ -23,10 +24,10 @@
/*
* Buffer sizes of status message of primary. Total number of size
- * must be equal to MSG_SIZE 2048 defined in `shared/common.h`.
+ * must be equal to MSG_SIZE 32768 defined in `shared/common.h`.
*/
#define PRI_BUF_SIZE_LCORE 128
-#define PRI_BUF_SIZE_PHY 512
+#define PRI_BUF_SIZE_PHY 30720
#define PRI_BUF_SIZE_RING (MSG_SIZE - PRI_BUF_SIZE_LCORE - PRI_BUF_SIZE_PHY)
#define SPP_PATH_LEN 1024 /* seems enough for path of spp procs */
@@ -639,9 +640,10 @@ forwarder_status_json(char *str)
static int
phy_port_stats_json(char *str)
{
- int i;
- int buf_size = 256; /* size of temp buffer */
- char phy_port[buf_size];
+ int i, ret;
+ int buf_size = PRI_BUF_SIZE_PHY - 512; /* size of temp buffer */
+ char phy_port[PRI_BUF_SIZE_PHY];
+ char flow[buf_size];
char buf_phy_ports[PRI_BUF_SIZE_PHY];
memset(phy_port, '\0', sizeof(phy_port));
memset(buf_phy_ports, '\0', sizeof(buf_phy_ports));
@@ -651,16 +653,29 @@ phy_port_stats_json(char *str)
RTE_LOG(DEBUG, PRIMARY, "Size of buf_phy_ports str: %d\n",
(int)strlen(buf_phy_ports));
- memset(phy_port, '\0', buf_size);
+ memset(phy_port, '\0', PRI_BUF_SIZE_PHY);
+ memset(flow, '\0', buf_size);
+
+ ret = append_flow_json(i, buf_size, flow);
+ if (ret != 0) {
+ sprintf(buf_phy_ports + strlen(buf_phy_ports) - 1,
+ "%s", "");
+ break;
+ }
sprintf(phy_port, "{\"id\":%u,\"eth\":\"%s\","
"\"rx\":%"PRIu64",\"tx\":%"PRIu64","
- "\"tx_drop\":%"PRIu64"}",
+ "\"tx_drop\":%"PRIu64","
+ "\"nof_queues\":{\"rx\":%d,\"tx\":%d},"
+ "\"flow\":%s}",
ports->id[i],
get_printable_mac_addr(ports->id[i]),
ports->port_stats[i].rx,
ports->port_stats[i].tx,
- ports->port_stats[i].tx_drop);
+ ports->port_stats[i].tx_drop,
+ ports->queue_info[i].rxq,
+ ports->queue_info[i].txq,
+ flow);
int cur_buf_size = (int)strlen(buf_phy_ports) +
(int)strlen(phy_port);
@@ -948,8 +963,10 @@ parse_command(char *str)
char patch_set[64] = { 0 }; /* "{\"src\":\"%s:%d\",\"dst\":...}" */
char *p_type;
int p_id;
+ char tmp_response[MSG_SIZE];
memset(sec_name, '\0', 16);
+ memset(tmp_response, '\0', MSG_SIZE);
/* tokenize the user commands from controller */
token_list[max_token] = strtok(str, " ");
@@ -1150,6 +1167,13 @@ parse_command(char *str)
sprintf(str, "{%s:%s,%s:%s}",
"\"result\"", "\"succeeded\"",
"\"command\"", "\"clear\"");
+
+ } else if (!strcmp(token_list[0], "flow")) {
+ RTE_LOG(DEBUG, PRIMARY, "'%s' command received.\n",
+ token_list[0]);
+ ret = parse_flow(token_list, tmp_response);
+ memset(str, '\0', MSG_SIZE);
+ strncpy(str, tmp_response, MSG_SIZE-1);
}
return ret;
--
2.17.1
More information about the spp
mailing list