#include <rte_errno.h>
#include <rte_ring.h>
#include <rte_tm_driver.h>
+#include <rte_mtr_driver.h>
#include "rte_eth_softnic.h"
#include "rte_eth_softnic_internals.h"
#define PMD_PARAM_FIRMWARE "firmware"
+#define PMD_PARAM_CONN_PORT "conn_port"
#define PMD_PARAM_CPU_ID "cpu_id"
-
-static const char *pmd_valid_args[] = {
+#define PMD_PARAM_SC "sc"
+#define PMD_PARAM_TM_N_QUEUES "tm_n_queues"
+#define PMD_PARAM_TM_QSIZE0 "tm_qsize0"
+#define PMD_PARAM_TM_QSIZE1 "tm_qsize1"
+#define PMD_PARAM_TM_QSIZE2 "tm_qsize2"
+#define PMD_PARAM_TM_QSIZE3 "tm_qsize3"
+#define PMD_PARAM_TM_QSIZE4 "tm_qsize4"
+#define PMD_PARAM_TM_QSIZE5 "tm_qsize5"
+#define PMD_PARAM_TM_QSIZE6 "tm_qsize6"
+#define PMD_PARAM_TM_QSIZE7 "tm_qsize7"
+#define PMD_PARAM_TM_QSIZE8 "tm_qsize8"
+#define PMD_PARAM_TM_QSIZE9 "tm_qsize9"
+#define PMD_PARAM_TM_QSIZE10 "tm_qsize10"
+#define PMD_PARAM_TM_QSIZE11 "tm_qsize11"
+#define PMD_PARAM_TM_QSIZE12 "tm_qsize12"
+
+
+static const char * const pmd_valid_args[] = {
PMD_PARAM_FIRMWARE,
+ PMD_PARAM_CONN_PORT,
PMD_PARAM_CPU_ID,
+ PMD_PARAM_SC,
+ PMD_PARAM_TM_N_QUEUES,
+ PMD_PARAM_TM_QSIZE0,
+ PMD_PARAM_TM_QSIZE1,
+ PMD_PARAM_TM_QSIZE2,
+ PMD_PARAM_TM_QSIZE3,
+ PMD_PARAM_TM_QSIZE4,
+ PMD_PARAM_TM_QSIZE5,
+ PMD_PARAM_TM_QSIZE6,
+ PMD_PARAM_TM_QSIZE7,
+ PMD_PARAM_TM_QSIZE8,
+ PMD_PARAM_TM_QSIZE9,
+ PMD_PARAM_TM_QSIZE10,
+ PMD_PARAM_TM_QSIZE11,
+ PMD_PARAM_TM_QSIZE12,
NULL
};
-static const struct rte_eth_dev_info pmd_dev_info = {
- .min_rx_bufsize = 0,
- .max_rx_pktlen = UINT32_MAX,
- .max_rx_queues = UINT16_MAX,
- .max_tx_queues = UINT16_MAX,
- .rx_desc_lim = {
- .nb_max = UINT16_MAX,
- .nb_min = 0,
- .nb_align = 1,
- },
- .tx_desc_lim = {
- .nb_max = UINT16_MAX,
- .nb_min = 0,
- .nb_align = 1,
- },
- .rx_offload_capa = DEV_RX_OFFLOAD_CRC_STRIP,
+static const char welcome[] =
+ "\n"
+ "Welcome to Soft NIC!\n"
+ "\n";
+
+static const char prompt[] = "softnic> ";
+
+static const 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 int pmd_softnic_logtype;
pmd_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
struct rte_eth_dev_info *dev_info)
{
- memcpy(dev_info, &pmd_dev_info, sizeof(*dev_info));
+ dev_info->max_rx_pktlen = UINT32_MAX;
+ dev_info->max_rx_queues = UINT16_MAX;
+ dev_info->max_tx_queues = UINT16_MAX;
}
static int
pmd_rx_queue_setup(struct rte_eth_dev *dev,
uint16_t rx_queue_id,
uint16_t nb_rx_desc,
- unsigned int socket_id,
+ unsigned int socket_id __rte_unused,
const struct rte_eth_rxconf *rx_conf __rte_unused,
struct rte_mempool *mb_pool __rte_unused)
{
- uint32_t size = RTE_ETH_NAME_MAX_LEN + strlen("_rxq") + 4;
- char name[size];
- struct rte_ring *r;
-
- snprintf(name, sizeof(name), "%s_rxq%04x",
- dev->data->name,
- rx_queue_id);
-
- r = rte_ring_create(name,
- nb_rx_desc,
- socket_id,
- RING_F_SP_ENQ | RING_F_SC_DEQ);
- if (r == NULL)
+ char name[NAME_SIZE];
+ struct pmd_internals *p = dev->data->dev_private;
+ struct softnic_swq *swq;
+
+ struct softnic_swq_params params = {
+ .size = nb_rx_desc,
+ };
+
+ snprintf(name, sizeof(name), "RXQ%u", rx_queue_id);
+
+ swq = softnic_swq_create(p,
+ name,
+ ¶ms);
+ if (swq == NULL)
return -1;
- dev->data->rx_queues[rx_queue_id] = r;
+ dev->data->rx_queues[rx_queue_id] = swq->r;
return 0;
}
pmd_tx_queue_setup(struct rte_eth_dev *dev,
uint16_t tx_queue_id,
uint16_t nb_tx_desc,
- unsigned int socket_id,
+ unsigned int socket_id __rte_unused,
const struct rte_eth_txconf *tx_conf __rte_unused)
{
- uint32_t size = RTE_ETH_NAME_MAX_LEN + strlen("_txq") + 4;
- char name[size];
- struct rte_ring *r;
-
- snprintf(name, sizeof(name), "%s_txq%04x",
- dev->data->name,
- tx_queue_id);
-
- r = rte_ring_create(name,
- nb_tx_desc,
- socket_id,
- RING_F_SP_ENQ | RING_F_SC_DEQ);
- if (r == NULL)
+ char name[NAME_SIZE];
+ struct pmd_internals *p = dev->data->dev_private;
+ struct softnic_swq *swq;
+
+ struct softnic_swq_params params = {
+ .size = nb_tx_desc,
+ };
+
+ snprintf(name, sizeof(name), "TXQ%u", tx_queue_id);
+
+ swq = softnic_swq_create(p,
+ name,
+ ¶ms);
+ if (swq == NULL)
return -1;
- dev->data->tx_queues[tx_queue_id] = r;
+ dev->data->tx_queues[tx_queue_id] = swq->r;
return 0;
}
static int
pmd_dev_start(struct rte_eth_dev *dev)
{
+ struct pmd_internals *p = dev->data->dev_private;
+ int status;
+
+ /* Firmware */
+ status = softnic_cli_script_process(p,
+ p->params.firmware,
+ conn_params_default.msg_in_len_max,
+ conn_params_default.msg_out_len_max);
+ if (status)
+ return status;
+
+ /* Link UP */
dev->data->dev_link.link_status = ETH_LINK_UP;
return 0;
static void
pmd_dev_stop(struct rte_eth_dev *dev)
{
+ struct pmd_internals *p = dev->data->dev_private;
+
+ /* Link DOWN */
dev->data->dev_link.link_status = ETH_LINK_DOWN;
+
+ /* Firmware */
+ softnic_pipeline_disable_all(p);
+ softnic_pipeline_free(p);
+ softnic_table_action_profile_free(p);
+ softnic_port_in_action_profile_free(p);
+ softnic_tap_free(p);
+ softnic_tmgr_free(p);
+ softnic_link_free(p);
+ softnic_softnic_swq_free_keep_rxq_txq(p);
+ softnic_mempool_free(p);
+
+ tm_hierarchy_free(p);
+ softnic_mtr_free(p);
}
static void
-pmd_dev_close(struct rte_eth_dev *dev)
+pmd_dev_close(struct rte_eth_dev *dev __rte_unused)
{
- uint32_t i;
-
- /* RX queues */
- for (i = 0; i < dev->data->nb_rx_queues; i++)
- rte_ring_free((struct rte_ring *)dev->data->rx_queues[i]);
-
- /* TX queues */
- for (i = 0; i < dev->data->nb_tx_queues; i++)
- rte_ring_free((struct rte_ring *)dev->data->tx_queues[i]);
+ return;
}
static int
return 0;
}
+static int
+pmd_filter_ctrl(struct rte_eth_dev *dev __rte_unused,
+ enum rte_filter_type filter_type,
+ enum rte_filter_op filter_op,
+ void *arg)
+{
+ if (filter_type == RTE_ETH_FILTER_GENERIC &&
+ filter_op == RTE_ETH_FILTER_GET) {
+ *(const void **)arg = &pmd_flow_ops;
+ return 0;
+ }
+
+ return -ENOTSUP;
+}
+
static int
pmd_tm_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
{
- *(const struct rte_tm_ops **)arg = NULL;
+ *(const struct rte_tm_ops **)arg = &pmd_tm_ops;
+
+ return 0;
+}
+
+static int
+pmd_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
+{
+ *(const struct rte_mtr_ops **)arg = &pmd_mtr_ops;
return 0;
}
.dev_infos_get = pmd_dev_infos_get,
.rx_queue_setup = pmd_rx_queue_setup,
.tx_queue_setup = pmd_tx_queue_setup,
+ .filter_ctrl = pmd_filter_ctrl,
.tm_ops_get = pmd_tm_ops_get,
+ .mtr_ops_get = pmd_mtr_ops_get,
};
static uint16_t
NULL);
}
-int
-rte_pmd_softnic_run(uint16_t port_id __rte_unused)
-{
- return 0;
-}
-
static void *
pmd_init(struct pmd_params *params)
{
struct pmd_internals *p;
+ int status;
p = rte_zmalloc_socket(params->name,
sizeof(struct pmd_internals),
if (p == NULL)
return NULL;
+ /* Params */
memcpy(&p->params, params, sizeof(p->params));
+ /* Resources */
+ tm_hierarchy_init(p);
+ softnic_mtr_init(p);
+
+ softnic_mempool_init(p);
+ softnic_swq_init(p);
+ softnic_link_init(p);
+ softnic_tmgr_init(p);
+ softnic_tap_init(p);
+ softnic_cryptodev_init(p);
+ softnic_port_in_action_profile_init(p);
+ softnic_table_action_profile_init(p);
+ softnic_pipeline_init(p);
+
+ status = softnic_thread_init(p);
+ if (status) {
+ rte_free(p);
+ 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;
}
static void
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);
+ softnic_port_in_action_profile_free(p);
+ softnic_tap_free(p);
+ softnic_tmgr_free(p);
+ softnic_link_free(p);
+ softnic_swq_free(p);
+ softnic_mempool_free(p);
+
+ tm_hierarchy_free(p);
+ softnic_mtr_free(p);
+
rte_free(p);
}
-static struct ether_addr eth_addr = {
+static struct rte_ether_addr eth_addr = {
.addr_bytes = {0},
};
return 0;
}
+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)
{
memset(p, 0, sizeof(*p));
p->firmware = SOFTNIC_FIRMWARE;
p->cpu_id = SOFTNIC_CPU_ID;
+ p->sc = SOFTNIC_SC;
+ p->tm.n_queues = SOFTNIC_TM_N_QUEUES;
+ p->tm.qsize[0] = SOFTNIC_TM_QUEUE_SIZE;
+ p->tm.qsize[1] = SOFTNIC_TM_QUEUE_SIZE;
+ p->tm.qsize[2] = SOFTNIC_TM_QUEUE_SIZE;
+ p->tm.qsize[3] = SOFTNIC_TM_QUEUE_SIZE;
+ p->tm.qsize[4] = SOFTNIC_TM_QUEUE_SIZE;
+ p->tm.qsize[5] = SOFTNIC_TM_QUEUE_SIZE;
+ p->tm.qsize[6] = SOFTNIC_TM_QUEUE_SIZE;
+ p->tm.qsize[7] = SOFTNIC_TM_QUEUE_SIZE;
+ p->tm.qsize[8] = SOFTNIC_TM_QUEUE_SIZE;
+ p->tm.qsize[9] = SOFTNIC_TM_QUEUE_SIZE;
+ p->tm.qsize[10] = SOFTNIC_TM_QUEUE_SIZE;
+ p->tm.qsize[11] = SOFTNIC_TM_QUEUE_SIZE;
+ p->tm.qsize[12] = SOFTNIC_TM_QUEUE_SIZE;
/* Firmware script (optional) */
if (rte_kvargs_count(kvlist, PMD_PARAM_FIRMWARE) == 1) {
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,
goto out_free;
}
+ /* Service cores (optional) */
+ if (rte_kvargs_count(kvlist, PMD_PARAM_SC) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_SC,
+ &get_uint32, &p->sc);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ /* TM number of queues (optional) */
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_N_QUEUES) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_N_QUEUES,
+ &get_uint32, &p->tm.n_queues);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ /* TM queue size 0 .. 3 (optional) */
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE0) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE0,
+ &get_uint32, &p->tm.qsize[0]);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE1) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE1,
+ &get_uint32, &p->tm.qsize[1]);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE2) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE2,
+ &get_uint32, &p->tm.qsize[2]);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE3) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE3,
+ &get_uint32, &p->tm.qsize[3]);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE4) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE4,
+ &get_uint32, &p->tm.qsize[4]);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE5) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE5,
+ &get_uint32, &p->tm.qsize[5]);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE6) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE6,
+ &get_uint32, &p->tm.qsize[6]);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE7) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE7,
+ &get_uint32, &p->tm.qsize[7]);
+ if (ret < 0)
+ goto out_free;
+ }
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE8) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE8,
+ &get_uint32, &p->tm.qsize[8]);
+ if (ret < 0)
+ goto out_free;
+ }
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE9) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE9,
+ &get_uint32, &p->tm.qsize[9]);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE10) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE10,
+ &get_uint32, &p->tm.qsize[10]);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE11) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE11,
+ &get_uint32, &p->tm.qsize[11]);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE12) == 1) {
+ ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE12,
+ &get_uint32, &p->tm.qsize[12]);
+ if (ret < 0)
+ goto out_free;
+ }
+
out_free:
rte_kvargs_free(kvlist);
return ret;
pmd_remove(struct rte_vdev_device *vdev)
{
struct rte_eth_dev *dev = NULL;
- struct pmd_internals *p;
if (!vdev)
return -EINVAL;
dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev));
if (dev == NULL)
return -ENODEV;
- p = dev->data->dev_private;
/* Free device data structures*/
- rte_free(dev->data);
+ pmd_free(dev->data->dev_private);
+ dev->data->dev_private = NULL; /* already freed */
+ dev->data->mac_addrs = NULL; /* statically allocated */
rte_eth_dev_release_port(dev);
- pmd_free(p);
return 0;
}
RTE_PMD_REGISTER_VDEV(net_softnic, pmd_softnic_drv);
RTE_PMD_REGISTER_PARAM_STRING(net_softnic,
PMD_PARAM_FIRMWARE "=<string> "
- PMD_PARAM_CPU_ID "=<uint32>");
+ PMD_PARAM_CONN_PORT "=<uint16> "
+ PMD_PARAM_CPU_ID "=<uint32> "
+ PMD_PARAM_TM_N_QUEUES "=<uint32> "
+ PMD_PARAM_TM_QSIZE0 "=<uint32> "
+ PMD_PARAM_TM_QSIZE1 "=<uint32> "
+ PMD_PARAM_TM_QSIZE2 "=<uint32> "
+ PMD_PARAM_TM_QSIZE3 "=<uint32>"
+ PMD_PARAM_TM_QSIZE4 "=<uint32> "
+ PMD_PARAM_TM_QSIZE5 "=<uint32> "
+ PMD_PARAM_TM_QSIZE6 "=<uint32> "
+ PMD_PARAM_TM_QSIZE7 "=<uint32> "
+ PMD_PARAM_TM_QSIZE8 "=<uint32> "
+ PMD_PARAM_TM_QSIZE9 "=<uint32> "
+ PMD_PARAM_TM_QSIZE10 "=<uint32> "
+ PMD_PARAM_TM_QSIZE11 "=<uint32>"
+ PMD_PARAM_TM_QSIZE12 "=<uint32>"
+);
+
RTE_INIT(pmd_softnic_init_log)
{
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;
+}