Add connection agent to enable connectivity with external agen
(e.g. telnet, netcat, Python script, etc).

Signed-off-by: Cristian Dumitrescu <cristian.dumitre...@intel.com>
Signed-off-by: Jasvinder Singh <jasvinder.si...@intel.com>
---
 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 721e59b..90c3946 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..990cf40
--- /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 <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#define __USE_GNU
+#include <sys/socket.h>
+
+#include <sys/epoll.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#include "conn.h"
+
+#define MSG_CMD_TOO_LONG "Command too long."
+
+struct softnic_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;
+       softnic_conn_msg_handle_t msg_handle;
+       void *msg_handle_arg;
+};
+
+struct softnic_conn *
+softnic_conn_init(struct softnic_conn_params *p)
+{
+       struct sockaddr_in server_address;
+       struct softnic_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 softnic_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) {
+               softnic_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) {
+               softnic_conn_free(conn);
+               return NULL;
+       }
+
+       status = bind(fd_server,
+               (struct sockaddr *)&server_address,
+               sizeof(server_address));
+       if (status == -1) {
+               softnic_conn_free(conn);
+               close(fd_server);
+               return NULL;
+       }
+
+       status = listen(fd_server, 16);
+       if (status == -1) {
+               softnic_conn_free(conn);
+               close(fd_server);
+               return NULL;
+       }
+
+       /* Client group */
+       fd_client_group = epoll_create(1);
+       if (fd_client_group == -1) {
+               softnic_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
+softnic_conn_free(struct softnic_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
+softnic_conn_poll_for_conn(struct softnic_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 softnic_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 softnic_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
+softnic_conn_poll_for_msg(struct softnic_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..631edee
--- /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 <stdint.h>
+
+struct softnic_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 (*softnic_conn_msg_handle_t)(char *msg_in,
+       char *msg_out,
+       size_t msg_out_len_max,
+       void *arg);
+
+struct softnic_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;
+       softnic_conn_msg_handle_t msg_handle;
+       void *msg_handle_arg;
+};
+
+struct softnic_conn *
+softnic_conn_init(struct softnic_conn_params *p);
+
+void
+softnic_conn_free(struct softnic_conn *conn);
+
+int
+softnic_conn_poll_for_conn(struct softnic_conn *conn);
+
+int
+softnic_conn_poll_for_msg(struct softnic_conn *conn);
+
+#endif
diff --git a/drivers/net/softnic/rte_eth_softnic.c 
b/drivers/net/softnic/rte_eth_softnic.c
index d154112..0c719eb 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 softnic_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 = softnic_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 softnic_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 = softnic_conn_init(&conn_params);
+               if (p->conn == NULL) {
+                       softnic_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)
+               softnic_conn_free(p->conn);
+
        softnic_thread_free(p);
        softnic_pipeline_free(p);
        softnic_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 "=<string> "
+       PMD_PARAM_CONN_PORT "=<uint16> "
        PMD_PARAM_CPU_ID "=<uint32> "
        PMD_PARAM_TM_N_QUEUES "=<uint32> "
        PMD_PARAM_TM_QSIZE0 "=<uint32> "
@@ -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;
+
+       softnic_conn_poll_for_conn(softnic->conn);
+
+       softnic_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 d459571..c2bd637 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -22,6 +22,7 @@
 #include <rte_tm_driver.h>
 
 #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 softnic_conn *conn;
        struct softnic_mempool_list mempool_list;
        struct softnic_swq_list swq_list;
        struct softnic_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

Reply via email to