From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id E1BE21C12A for ; Wed, 27 Jun 2018 18:31:42 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 Jun 2018 09:31:42 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789689" Received: from silpixa00381635.ir.intel.com (HELO silpixa00381635.ger.corp.intel.com) ([10.237.222.149]) by fmsmga005.fm.intel.com with ESMTP; 27 Jun 2018 09:31:41 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:13 +0100 Message-Id: <20180627163123.135686-14-jasvinder.singh@intel.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20180627163123.135686-1-jasvinder.singh@intel.com> References: <20180615165224.25004-2-jasvinder.singh@intel.com> <20180627163123.135686-1-jasvinder.singh@intel.com> Subject: [dpdk-dev] [PATCH v3 13/23] net/softnic: add connection agent X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 27 Jun 2018 16:31:43 -0000 Add connection agent to enable connectivity with external agen (e.g. telnet, netcat, Python script, etc). Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- config/common_base | 2 +- config/common_linuxapp | 1 + drivers/net/softnic/Makefile | 12 +- drivers/net/softnic/conn.c | 332 +++++++++++++++++++++ drivers/net/softnic/conn.h | 49 +++ drivers/net/softnic/rte_eth_softnic.c | 79 ++++- drivers/net/softnic/rte_eth_softnic.h | 16 + drivers/net/softnic/rte_eth_softnic_internals.h | 3 + ...nic_version.map => rte_eth_softnic_version.map} | 6 + 9 files changed, 496 insertions(+), 4 deletions(-) create mode 100644 drivers/net/softnic/conn.c create mode 100644 drivers/net/softnic/conn.h rename drivers/net/softnic/{rte_pmd_softnic_version.map => rte_eth_softnic_version.map} (52%) diff --git a/config/common_base b/config/common_base index fcf3a1f..5ee514e 100644 --- a/config/common_base +++ b/config/common_base @@ -426,7 +426,7 @@ CONFIG_RTE_PMD_RING_MAX_TX_RINGS=16 # # Compile SOFTNIC PMD # -CONFIG_RTE_LIBRTE_PMD_SOFTNIC=y +CONFIG_RTE_LIBRTE_PMD_SOFTNIC=n # # Compile the TAP PMD diff --git a/config/common_linuxapp b/config/common_linuxapp index daa49d4..37e8f69 100644 --- a/config/common_linuxapp +++ b/config/common_linuxapp @@ -17,6 +17,7 @@ CONFIG_RTE_LIBRTE_VHOST_NUMA=y CONFIG_RTE_LIBRTE_PMD_VHOST=y CONFIG_RTE_LIBRTE_IFC_PMD=y CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y +CONFIG_RTE_LIBRTE_PMD_SOFTNIC=y CONFIG_RTE_LIBRTE_PMD_TAP=y CONFIG_RTE_LIBRTE_AVP_PMD=y CONFIG_RTE_LIBRTE_VDEV_NETVSC_PMD=y diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile index cb95414..a9045f0 100644 --- a/drivers/net/softnic/Makefile +++ b/drivers/net/softnic/Makefile @@ -16,7 +16,7 @@ LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_sched LDLIBS += -lrte_bus_vdev -EXPORT_MAP := rte_pmd_softnic_version.map +EXPORT_MAP := rte_eth_softnic_version.map LIBABIVER := 1 @@ -34,10 +34,20 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_pipeline.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_thread.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_cli.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += parser.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += conn.c # # Export include files # SYMLINK-y-include += rte_eth_softnic.h +ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +$(info Softnic PMD can only operate in a linuxapp environment, \ +please change the definition of the RTE_TARGET environment variable) +all: +clean: +else + include $(RTE_SDK)/mk/rte.lib.mk + +endif diff --git a/drivers/net/softnic/conn.c b/drivers/net/softnic/conn.c new file mode 100644 index 0000000..f34fbac --- /dev/null +++ b/drivers/net/softnic/conn.c @@ -0,0 +1,332 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include +#include +#include +#include +#include + +#define __USE_GNU +#include + +#include +#include +#include +#include + +#include "conn.h" + +#define MSG_CMD_TOO_LONG "Command too long." + +struct conn { + char *welcome; + char *prompt; + char *buf; + char *msg_in; + char *msg_out; + size_t buf_size; + size_t msg_in_len_max; + size_t msg_out_len_max; + size_t msg_in_len; + int fd_server; + int fd_client_group; + conn_msg_handle_t msg_handle; + void *msg_handle_arg; +}; + +struct conn * +conn_init(struct conn_params *p) +{ + struct sockaddr_in server_address; + struct conn *conn; + int fd_server, fd_client_group, status; + + memset(&server_address, 0, sizeof(server_address)); + + /* Check input arguments */ + if (p == NULL || + p->welcome == NULL || + p->prompt == NULL || + p->addr == NULL || + p->buf_size == 0 || + p->msg_in_len_max == 0 || + p->msg_out_len_max == 0 || + p->msg_handle == NULL) + return NULL; + + status = inet_aton(p->addr, &server_address.sin_addr); + if (status == 0) + return NULL; + + /* Memory allocation */ + conn = calloc(1, sizeof(struct conn)); + if (conn == NULL) + return NULL; + + conn->welcome = calloc(1, CONN_WELCOME_LEN_MAX + 1); + conn->prompt = calloc(1, CONN_PROMPT_LEN_MAX + 1); + conn->buf = calloc(1, p->buf_size); + conn->msg_in = calloc(1, p->msg_in_len_max + 1); + conn->msg_out = calloc(1, p->msg_out_len_max + 1); + + if (conn->welcome == NULL || + conn->prompt == NULL || + conn->buf == NULL || + conn->msg_in == NULL || + conn->msg_out == NULL) { + conn_free(conn); + return NULL; + } + + /* Server socket */ + server_address.sin_family = AF_INET; + server_address.sin_port = htons(p->port); + + fd_server = socket(AF_INET, + SOCK_STREAM | SOCK_NONBLOCK, + 0); + if (fd_server == -1) { + conn_free(conn); + return NULL; + } + + status = bind(fd_server, + (struct sockaddr *)&server_address, + sizeof(server_address)); + if (status == -1) { + conn_free(conn); + close(fd_server); + return NULL; + } + + status = listen(fd_server, 16); + if (status == -1) { + conn_free(conn); + close(fd_server); + return NULL; + } + + /* Client group */ + fd_client_group = epoll_create(1); + if (fd_client_group == -1) { + conn_free(conn); + close(fd_server); + return NULL; + } + + /* Fill in */ + strncpy(conn->welcome, p->welcome, CONN_WELCOME_LEN_MAX); + strncpy(conn->prompt, p->prompt, CONN_PROMPT_LEN_MAX); + conn->buf_size = p->buf_size; + conn->msg_in_len_max = p->msg_in_len_max; + conn->msg_out_len_max = p->msg_out_len_max; + conn->msg_in_len = 0; + conn->fd_server = fd_server; + conn->fd_client_group = fd_client_group; + conn->msg_handle = p->msg_handle; + conn->msg_handle_arg = p->msg_handle_arg; + + return conn; +} + +void +conn_free(struct conn *conn) +{ + if (conn == NULL) + return; + + if (conn->fd_client_group) + close(conn->fd_client_group); + + if (conn->fd_server) + close(conn->fd_server); + + free(conn->msg_out); + free(conn->msg_in); + free(conn->prompt); + free(conn->welcome); + free(conn); +} + +int +conn_poll_for_conn(struct conn *conn) +{ + struct sockaddr_in client_address; + struct epoll_event event; + socklen_t client_address_length; + int fd_client, status; + + /* Check input arguments */ + if (conn == NULL) + return -1; + + /* Server socket */ + client_address_length = sizeof(client_address); + fd_client = accept4(conn->fd_server, + (struct sockaddr *)&client_address, + &client_address_length, + SOCK_NONBLOCK); + if (fd_client == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + return 0; + + return -1; + } + + /* Client group */ + event.events = EPOLLIN | EPOLLRDHUP | EPOLLHUP; + event.data.fd = fd_client; + + status = epoll_ctl(conn->fd_client_group, + EPOLL_CTL_ADD, + fd_client, + &event); + if (status == -1) { + close(fd_client); + return -1; + } + + /* Client */ + status = write(fd_client, + conn->welcome, + strlen(conn->welcome)); + if (status == -1) { + close(fd_client); + return -1; + } + + status = write(fd_client, + conn->prompt, + strlen(conn->prompt)); + if (status == -1) { + close(fd_client); + return -1; + } + + return 0; +} + +static int +data_event_handle(struct conn *conn, + int fd_client) +{ + ssize_t len, i, status; + + /* Read input message */ + + len = read(fd_client, + conn->buf, + conn->buf_size); + if (len == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + return 0; + + return -1; + } + if (len == 0) + return 0; + + /* Handle input messages */ + for (i = 0; i < len; i++) { + if (conn->buf[i] == '\n') { + size_t n; + + conn->msg_in[conn->msg_in_len] = 0; + conn->msg_out[0] = 0; + + conn->msg_handle(conn->msg_in, + conn->msg_out, + conn->msg_out_len_max, + conn->msg_handle_arg); + + n = strlen(conn->msg_out); + if (n) { + status = write(fd_client, + conn->msg_out, + n); + if (status == -1) + return status; + } + + conn->msg_in_len = 0; + } else if (conn->msg_in_len < conn->msg_in_len_max) { + conn->msg_in[conn->msg_in_len] = conn->buf[i]; + conn->msg_in_len++; + } else { + status = write(fd_client, + MSG_CMD_TOO_LONG, + strlen(MSG_CMD_TOO_LONG)); + if (status == -1) + return status; + + conn->msg_in_len = 0; + } + } + + /* Write prompt */ + status = write(fd_client, + conn->prompt, + strlen(conn->prompt)); + if (status == -1) + return status; + + return 0; +} + +static int +control_event_handle(struct conn *conn, + int fd_client) +{ + int status; + + status = epoll_ctl(conn->fd_client_group, + EPOLL_CTL_DEL, + fd_client, + NULL); + if (status == -1) + return -1; + + status = close(fd_client); + if (status == -1) + return -1; + + return 0; +} + +int +conn_poll_for_msg(struct conn *conn) +{ + struct epoll_event event; + int fd_client, status, status_data = 0, status_control = 0; + + /* Check input arguments */ + if (conn == NULL) + return -1; + + /* Client group */ + status = epoll_wait(conn->fd_client_group, + &event, + 1, + 0); + if (status == -1) + return -1; + if (status == 0) + return 0; + + fd_client = event.data.fd; + + /* Data available */ + if (event.events & EPOLLIN) + status_data = data_event_handle(conn, fd_client); + + /* Control events */ + if (event.events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP)) + status_control = control_event_handle(conn, fd_client); + + if (status_data || status_control) + return -1; + + return 0; +} diff --git a/drivers/net/softnic/conn.h b/drivers/net/softnic/conn.h new file mode 100644 index 0000000..c82eb8f --- /dev/null +++ b/drivers/net/softnic/conn.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef __INCLUDE_CONN_H__ +#define __INCLUDE_CONN_H__ + +#include + +struct conn; + +#ifndef CONN_WELCOME_LEN_MAX +#define CONN_WELCOME_LEN_MAX 1024 +#endif + +#ifndef CONN_PROMPT_LEN_MAX +#define CONN_PROMPT_LEN_MAX 16 +#endif + +typedef void (*conn_msg_handle_t)(char *msg_in, + char *msg_out, + size_t msg_out_len_max, + void *arg); + +struct conn_params { + const char *welcome; + const char *prompt; + const char *addr; + uint16_t port; + size_t buf_size; + size_t msg_in_len_max; + size_t msg_out_len_max; + conn_msg_handle_t msg_handle; + void *msg_handle_arg; +}; + +struct conn * +conn_init(struct conn_params *p); + +void +conn_free(struct conn *conn); + +int +conn_poll_for_conn(struct conn *conn); + +int +conn_poll_for_msg(struct conn *conn); + +#endif diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c index aed3acd..ed72648 100644 --- a/drivers/net/softnic/rte_eth_softnic.c +++ b/drivers/net/softnic/rte_eth_softnic.c @@ -19,8 +19,6 @@ #include "rte_eth_softnic_internals.h" #define PMD_PARAM_FIRMWARE "firmware" -#define PMD_PARAM_CPU_ID "cpu_id" -#define PMD_PARAM_SCRIPT "script" #define PMD_PARAM_CONN_PORT "conn_port" #define PMD_PARAM_CPU_ID "cpu_id" #define PMD_PARAM_TM_N_QUEUES "tm_n_queues" @@ -31,6 +29,7 @@ static const char *pmd_valid_args[] = { PMD_PARAM_FIRMWARE, + PMD_PARAM_CONN_PORT, PMD_PARAM_CPU_ID, PMD_PARAM_TM_N_QUEUES, PMD_PARAM_TM_QSIZE0, @@ -40,6 +39,25 @@ static const char *pmd_valid_args[] = { NULL }; +static const char welcome[] = + "\n" + "Welcome to Soft NIC!\n" + "\n"; + +static const char prompt[] = "softnic> "; + +struct conn_params conn_params_default = { + .welcome = welcome, + .prompt = prompt, + .addr = "0.0.0.0", + .port = 0, + .buf_size = 1024 * 1024, + .msg_in_len_max = 1024, + .msg_out_len_max = 1024 * 1024, + .msg_handle = cli_process, + .msg_handle_arg = NULL, +}; + static const struct rte_eth_dev_info pmd_dev_info = { .min_rx_bufsize = 0, .max_rx_pktlen = UINT32_MAX, @@ -239,6 +257,21 @@ pmd_init(struct pmd_params *params) return NULL; } + if (params->conn_port) { + struct conn_params conn_params; + + memcpy(&conn_params, &conn_params_default, sizeof(conn_params)); + conn_params.port = p->params.conn_port; + conn_params.msg_handle_arg = p; + + p->conn = conn_init(&conn_params); + if (p->conn == NULL) { + thread_free(p); + rte_free(p); + return NULL; + } + } + return p; } @@ -248,6 +281,9 @@ pmd_free(struct pmd_internals *p) if (p == NULL) return; + if (p->params.conn_port) + conn_free(p->conn); + thread_free(p); pipeline_free(p); table_action_profile_free(p); @@ -327,6 +363,17 @@ get_uint32(const char *key __rte_unused, const char *value, void *extra_args) } static int +get_uint16(const char *key __rte_unused, const char *value, void *extra_args) +{ + if (!value || !extra_args) + return -EINVAL; + + *(uint16_t *)extra_args = strtoull(value, NULL, 0); + + return 0; +} + +static int pmd_parse_args(struct pmd_params *p, const char *params) { struct rte_kvargs *kvlist; @@ -354,6 +401,14 @@ pmd_parse_args(struct pmd_params *p, const char *params) goto out_free; } + /* Connection listening port (optional) */ + if (rte_kvargs_count(kvlist, PMD_PARAM_CONN_PORT) == 1) { + ret = rte_kvargs_process(kvlist, PMD_PARAM_CONN_PORT, + &get_uint16, &p->conn_port); + if (ret < 0) + goto out_free; + } + /* CPU ID (optional) */ if (rte_kvargs_count(kvlist, PMD_PARAM_CPU_ID) == 1) { ret = rte_kvargs_process(kvlist, PMD_PARAM_CPU_ID, @@ -477,6 +532,7 @@ static struct rte_vdev_driver pmd_softnic_drv = { RTE_PMD_REGISTER_VDEV(net_softnic, pmd_softnic_drv); RTE_PMD_REGISTER_PARAM_STRING(net_softnic, PMD_PARAM_FIRMWARE "= " + PMD_PARAM_CONN_PORT "= " PMD_PARAM_CPU_ID "= " PMD_PARAM_TM_N_QUEUES "= " PMD_PARAM_TM_QSIZE0 "= " @@ -494,3 +550,22 @@ pmd_softnic_init_log(void) if (pmd_softnic_logtype >= 0) rte_log_set_level(pmd_softnic_logtype, RTE_LOG_NOTICE); } + +int +rte_pmd_softnic_manage(uint16_t port_id) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + struct pmd_internals *softnic; + +#ifdef RTE_LIBRTE_ETHDEV_DEBUG + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0); +#endif + + softnic = dev->data->dev_private; + + conn_poll_for_conn(softnic->conn); + + conn_poll_for_msg(softnic->conn); + + return 0; +} diff --git a/drivers/net/softnic/rte_eth_softnic.h b/drivers/net/softnic/rte_eth_softnic.h index 98b0828..048dfe6 100644 --- a/drivers/net/softnic/rte_eth_softnic.h +++ b/drivers/net/softnic/rte_eth_softnic.h @@ -16,6 +16,11 @@ extern "C" { #define SOFTNIC_FIRMWARE "firmware.cli" #endif +/** TCP connection port (0 = no connectivity). */ +#ifndef SOFTNIC_CONN_PORT +#define SOFTNIC_CONN_PORT 0 +#endif + /** NUMA node ID. */ #ifndef SOFTNIC_CPU_ID #define SOFTNIC_CPU_ID 0 @@ -42,6 +47,17 @@ extern "C" { int rte_pmd_softnic_run(uint16_t port_id); +/** + * Soft NIC manage. + * + * @param port_id + * Port ID of the Soft NIC device. + * @return + * Zero on success, error code otherwise. + */ +int __rte_experimental +rte_pmd_softnic_manage(uint16_t port_id); + #ifdef __cplusplus } #endif diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index 5d38f2f..155450e 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -22,6 +22,7 @@ #include #include "rte_eth_softnic.h" +#include "conn.h" #define NAME_SIZE 64 @@ -32,6 +33,7 @@ struct pmd_params { const char *name; const char *firmware; + uint16_t conn_port; uint32_t cpu_id; /** Traffic Management (TM) */ @@ -488,6 +490,7 @@ struct pmd_internals { struct tm_internals tm; /**< Traffic Management */ } soft; + struct conn *conn; struct mempool_list mempool_list; struct swq_list swq_list; struct link_list link_list; diff --git a/drivers/net/softnic/rte_pmd_softnic_version.map b/drivers/net/softnic/rte_eth_softnic_version.map similarity index 52% rename from drivers/net/softnic/rte_pmd_softnic_version.map rename to drivers/net/softnic/rte_eth_softnic_version.map index fb2cb68..bc44b06 100644 --- a/drivers/net/softnic/rte_pmd_softnic_version.map +++ b/drivers/net/softnic/rte_eth_softnic_version.map @@ -5,3 +5,9 @@ DPDK_17.11 { local: *; }; + +EXPERIMENTAL { + global: + + rte_pmd_softnic_manage; +}; -- 2.9.3