From patchwork Wed Jun 27 16:31:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41696 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id E52841C122; Wed, 27 Jun 2018 18:31:34 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id D7ACA1C0BD for ; Wed, 27 Jun 2018 18:31:27 +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:26 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789554" 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:25 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:01 +0100 Message-Id: <20180627163123.135686-2-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 01/23] net/softnic: restructuring 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Rework the softnic implementation to have flexiblity in enabling more features to its receive and transmit data path. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/rte_eth_softnic.c | 607 ++++-------------------- drivers/net/softnic/rte_eth_softnic.h | 34 +- drivers/net/softnic/rte_eth_softnic_internals.h | 101 +--- drivers/net/softnic/rte_eth_softnic_tm.c | 100 +--- 4 files changed, 120 insertions(+), 722 deletions(-) diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c index 6b3c13e..ccf3bd4 100644 --- a/drivers/net/softnic/rte_eth_softnic.c +++ b/drivers/net/softnic/rte_eth_softnic.c @@ -13,40 +13,17 @@ #include #include #include -#include #include #include "rte_eth_softnic.h" #include "rte_eth_softnic_internals.h" -#define DEV_HARD(p) \ - (&rte_eth_devices[p->hard.port_id]) - -#define PMD_PARAM_SOFT_TM "soft_tm" -#define PMD_PARAM_SOFT_TM_RATE "soft_tm_rate" -#define PMD_PARAM_SOFT_TM_NB_QUEUES "soft_tm_nb_queues" -#define PMD_PARAM_SOFT_TM_QSIZE0 "soft_tm_qsize0" -#define PMD_PARAM_SOFT_TM_QSIZE1 "soft_tm_qsize1" -#define PMD_PARAM_SOFT_TM_QSIZE2 "soft_tm_qsize2" -#define PMD_PARAM_SOFT_TM_QSIZE3 "soft_tm_qsize3" -#define PMD_PARAM_SOFT_TM_ENQ_BSZ "soft_tm_enq_bsz" -#define PMD_PARAM_SOFT_TM_DEQ_BSZ "soft_tm_deq_bsz" - -#define PMD_PARAM_HARD_NAME "hard_name" -#define PMD_PARAM_HARD_TX_QUEUE_ID "hard_tx_queue_id" +#define PMD_PARAM_FIRMWARE "firmware" +#define PMD_PARAM_CPU_ID "cpu_id" static const char *pmd_valid_args[] = { - PMD_PARAM_SOFT_TM, - PMD_PARAM_SOFT_TM_RATE, - PMD_PARAM_SOFT_TM_NB_QUEUES, - PMD_PARAM_SOFT_TM_QSIZE0, - PMD_PARAM_SOFT_TM_QSIZE1, - PMD_PARAM_SOFT_TM_QSIZE2, - PMD_PARAM_SOFT_TM_QSIZE3, - PMD_PARAM_SOFT_TM_ENQ_BSZ, - PMD_PARAM_SOFT_TM_DEQ_BSZ, - PMD_PARAM_HARD_NAME, - PMD_PARAM_HARD_TX_QUEUE_ID, + PMD_PARAM_FIRMWARE, + PMD_PARAM_CPU_ID, NULL }; @@ -81,50 +58,35 @@ pmd_dev_infos_get(struct rte_eth_dev *dev __rte_unused, } static int -pmd_dev_configure(struct rte_eth_dev *dev) +pmd_dev_configure(struct rte_eth_dev *dev __rte_unused) { - struct pmd_internals *p = dev->data->dev_private; - struct rte_eth_dev *hard_dev = DEV_HARD(p); - - if (dev->data->nb_rx_queues > hard_dev->data->nb_rx_queues) - return -1; - - if (p->params.hard.tx_queue_id >= hard_dev->data->nb_tx_queues) - return -1; - return 0; } static int pmd_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, - uint16_t nb_rx_desc __rte_unused, + uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf __rte_unused, struct rte_mempool *mb_pool __rte_unused) { - struct pmd_internals *p = dev->data->dev_private; - - if (p->params.soft.intrusive == 0) { - struct pmd_rx_queue *rxq; - - rxq = rte_zmalloc_socket(p->params.soft.name, - sizeof(struct pmd_rx_queue), 0, socket_id); - if (rxq == NULL) - return -ENOMEM; + uint32_t size = RTE_ETH_NAME_MAX_LEN + strlen("_rxq") + 4; + char name[size]; + struct rte_ring *r; - rxq->hard.port_id = p->hard.port_id; - rxq->hard.rx_queue_id = rx_queue_id; - dev->data->rx_queues[rx_queue_id] = rxq; - } else { - struct rte_eth_dev *hard_dev = DEV_HARD(p); - void *rxq = hard_dev->data->rx_queues[rx_queue_id]; + snprintf(name, sizeof(name), "%s_rxq%04x", + dev->data->name, + rx_queue_id); - if (rxq == NULL) - return -1; + r = rte_ring_create(name, + nb_rx_desc, + socket_id, + RING_F_SP_ENQ | RING_F_SC_DEQ); + if (r == NULL) + return -1; - dev->data->rx_queues[rx_queue_id] = rxq; - } + dev->data->rx_queues[rx_queue_id] = r; return 0; } @@ -140,8 +102,12 @@ pmd_tx_queue_setup(struct rte_eth_dev *dev, 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, + 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) return -1; @@ -153,36 +119,15 @@ pmd_tx_queue_setup(struct rte_eth_dev *dev, static int pmd_dev_start(struct rte_eth_dev *dev) { - struct pmd_internals *p = dev->data->dev_private; - - if (tm_used(dev)) { - int status = tm_start(p); - - if (status) - return status; - } - dev->data->dev_link.link_status = ETH_LINK_UP; - if (p->params.soft.intrusive) { - struct rte_eth_dev *hard_dev = DEV_HARD(p); - - /* The hard_dev->rx_pkt_burst should be stable by now */ - dev->rx_pkt_burst = hard_dev->rx_pkt_burst; - } - return 0; } static void pmd_dev_stop(struct rte_eth_dev *dev) { - struct pmd_internals *p = dev->data->dev_private; - dev->data->dev_link.link_status = ETH_LINK_DOWN; - - if (tm_used(dev)) - tm_stop(p); } static void @@ -190,6 +135,10 @@ pmd_dev_close(struct rte_eth_dev *dev) { 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]); @@ -203,10 +152,9 @@ pmd_link_update(struct rte_eth_dev *dev __rte_unused, } static int -pmd_tm_ops_get(struct rte_eth_dev *dev, void *arg) +pmd_tm_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg) { - *(const struct rte_tm_ops **)arg = - (tm_enabled(dev)) ? &pmd_tm_ops : NULL; + *(const struct rte_tm_ops **)arg = NULL; return 0; } @@ -228,12 +176,10 @@ pmd_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { - struct pmd_rx_queue *rx_queue = rxq; - - return rte_eth_rx_burst(rx_queue->hard.port_id, - rx_queue->hard.rx_queue_id, - rx_pkts, - nb_pkts); + return (uint16_t)rte_ring_sc_dequeue_burst(rxq, + (void **)rx_pkts, + nb_pkts, + NULL); } static uint16_t @@ -241,148 +187,12 @@ pmd_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { - return (uint16_t)rte_ring_enqueue_burst(txq, + return (uint16_t)rte_ring_sp_enqueue_burst(txq, (void **)tx_pkts, nb_pkts, NULL); } -static __rte_always_inline int -run_default(struct rte_eth_dev *dev) -{ - struct pmd_internals *p = dev->data->dev_private; - - /* Persistent context: Read Only (update not required) */ - struct rte_mbuf **pkts = p->soft.def.pkts; - uint16_t nb_tx_queues = dev->data->nb_tx_queues; - - /* Persistent context: Read - Write (update required) */ - uint32_t txq_pos = p->soft.def.txq_pos; - uint32_t pkts_len = p->soft.def.pkts_len; - uint32_t flush_count = p->soft.def.flush_count; - - /* Not part of the persistent context */ - uint32_t pos; - uint16_t i; - - /* Soft device TXQ read, Hard device TXQ write */ - for (i = 0; i < nb_tx_queues; i++) { - struct rte_ring *txq = dev->data->tx_queues[txq_pos]; - - /* Read soft device TXQ burst to packet enqueue buffer */ - pkts_len += rte_ring_sc_dequeue_burst(txq, - (void **)&pkts[pkts_len], - DEFAULT_BURST_SIZE, - NULL); - - /* Increment soft device TXQ */ - txq_pos++; - if (txq_pos >= nb_tx_queues) - txq_pos = 0; - - /* Hard device TXQ write when complete burst is available */ - if (pkts_len >= DEFAULT_BURST_SIZE) { - for (pos = 0; pos < pkts_len; ) - pos += rte_eth_tx_burst(p->hard.port_id, - p->params.hard.tx_queue_id, - &pkts[pos], - (uint16_t)(pkts_len - pos)); - - pkts_len = 0; - flush_count = 0; - break; - } - } - - if (flush_count >= FLUSH_COUNT_THRESHOLD) { - for (pos = 0; pos < pkts_len; ) - pos += rte_eth_tx_burst(p->hard.port_id, - p->params.hard.tx_queue_id, - &pkts[pos], - (uint16_t)(pkts_len - pos)); - - pkts_len = 0; - flush_count = 0; - } - - p->soft.def.txq_pos = txq_pos; - p->soft.def.pkts_len = pkts_len; - p->soft.def.flush_count = flush_count + 1; - - return 0; -} - -static __rte_always_inline int -run_tm(struct rte_eth_dev *dev) -{ - struct pmd_internals *p = dev->data->dev_private; - - /* Persistent context: Read Only (update not required) */ - struct rte_sched_port *sched = p->soft.tm.sched; - struct rte_mbuf **pkts_enq = p->soft.tm.pkts_enq; - struct rte_mbuf **pkts_deq = p->soft.tm.pkts_deq; - uint32_t enq_bsz = p->params.soft.tm.enq_bsz; - uint32_t deq_bsz = p->params.soft.tm.deq_bsz; - uint16_t nb_tx_queues = dev->data->nb_tx_queues; - - /* Persistent context: Read - Write (update required) */ - uint32_t txq_pos = p->soft.tm.txq_pos; - uint32_t pkts_enq_len = p->soft.tm.pkts_enq_len; - uint32_t flush_count = p->soft.tm.flush_count; - - /* Not part of the persistent context */ - uint32_t pkts_deq_len, pos; - uint16_t i; - - /* Soft device TXQ read, TM enqueue */ - for (i = 0; i < nb_tx_queues; i++) { - struct rte_ring *txq = dev->data->tx_queues[txq_pos]; - - /* Read TXQ burst to packet enqueue buffer */ - pkts_enq_len += rte_ring_sc_dequeue_burst(txq, - (void **)&pkts_enq[pkts_enq_len], - enq_bsz, - NULL); - - /* Increment TXQ */ - txq_pos++; - if (txq_pos >= nb_tx_queues) - txq_pos = 0; - - /* TM enqueue when complete burst is available */ - if (pkts_enq_len >= enq_bsz) { - rte_sched_port_enqueue(sched, pkts_enq, pkts_enq_len); - - pkts_enq_len = 0; - flush_count = 0; - break; - } - } - - if (flush_count >= FLUSH_COUNT_THRESHOLD) { - if (pkts_enq_len) - rte_sched_port_enqueue(sched, pkts_enq, pkts_enq_len); - - pkts_enq_len = 0; - flush_count = 0; - } - - p->soft.tm.txq_pos = txq_pos; - p->soft.tm.pkts_enq_len = pkts_enq_len; - p->soft.tm.flush_count = flush_count + 1; - - /* TM dequeue, Hard device TXQ write */ - pkts_deq_len = rte_sched_port_dequeue(sched, pkts_deq, deq_bsz); - - for (pos = 0; pos < pkts_deq_len; ) - pos += rte_eth_tx_burst(p->hard.port_id, - p->params.hard.tx_queue_id, - &pkts_deq[pos], - (uint16_t)(pkts_deq_len - pos)); - - return 0; -} - int rte_pmd_softnic_run(uint16_t port_id) { @@ -392,92 +202,23 @@ rte_pmd_softnic_run(uint16_t port_id) RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0); #endif - return (tm_used(dev)) ? run_tm(dev) : run_default(dev); -} - -static struct ether_addr eth_addr = { .addr_bytes = {0} }; - -static uint32_t -eth_dev_speed_max_mbps(uint32_t speed_capa) -{ - uint32_t rate_mbps[32] = { - ETH_SPEED_NUM_NONE, - ETH_SPEED_NUM_10M, - ETH_SPEED_NUM_10M, - ETH_SPEED_NUM_100M, - ETH_SPEED_NUM_100M, - ETH_SPEED_NUM_1G, - ETH_SPEED_NUM_2_5G, - ETH_SPEED_NUM_5G, - ETH_SPEED_NUM_10G, - ETH_SPEED_NUM_20G, - ETH_SPEED_NUM_25G, - ETH_SPEED_NUM_40G, - ETH_SPEED_NUM_50G, - ETH_SPEED_NUM_56G, - ETH_SPEED_NUM_100G, - }; - - uint32_t pos = (speed_capa) ? (31 - __builtin_clz(speed_capa)) : 0; - return rate_mbps[pos]; -} - -static int -default_init(struct pmd_internals *p, - struct pmd_params *params, - int numa_node) -{ - p->soft.def.pkts = rte_zmalloc_socket(params->soft.name, - 2 * DEFAULT_BURST_SIZE * sizeof(struct rte_mbuf *), - 0, - numa_node); - - if (p->soft.def.pkts == NULL) - return -ENOMEM; - + dev = dev; return 0; } -static void -default_free(struct pmd_internals *p) -{ - rte_free(p->soft.def.pkts); -} - static void * -pmd_init(struct pmd_params *params, int numa_node) +pmd_init(struct pmd_params *params) { struct pmd_internals *p; - int status; - p = rte_zmalloc_socket(params->soft.name, + p = rte_zmalloc_socket(params->name, sizeof(struct pmd_internals), 0, - numa_node); + params->cpu_id); if (p == NULL) return NULL; memcpy(&p->params, params, sizeof(p->params)); - rte_eth_dev_get_port_by_name(params->hard.name, &p->hard.port_id); - - /* Default */ - status = default_init(p, params, numa_node); - if (status) { - free(p->params.hard.name); - rte_free(p); - return NULL; - } - - /* Traffic Management (TM)*/ - if (params->soft.flags & PMD_FEATURE_TM) { - status = tm_init(p, params, numa_node); - if (status) { - default_free(p); - free(p->params.hard.name); - rte_free(p); - return NULL; - } - } return p; } @@ -485,57 +226,44 @@ pmd_init(struct pmd_params *params, int numa_node) static void pmd_free(struct pmd_internals *p) { - if (p->params.soft.flags & PMD_FEATURE_TM) - tm_free(p); - - default_free(p); - - free(p->params.hard.name); rte_free(p); } +static struct ether_addr eth_addr = { + .addr_bytes = {0}, +}; + static int pmd_ethdev_register(struct rte_vdev_device *vdev, struct pmd_params *params, void *dev_private) { - struct rte_eth_dev_info hard_info; - struct rte_eth_dev *soft_dev; - uint32_t hard_speed; - int numa_node; - uint16_t hard_port_id; - - rte_eth_dev_get_port_by_name(params->hard.name, &hard_port_id); - rte_eth_dev_info_get(hard_port_id, &hard_info); - hard_speed = eth_dev_speed_max_mbps(hard_info.speed_capa); - numa_node = rte_eth_dev_socket_id(hard_port_id); + struct rte_eth_dev *dev; /* Ethdev entry allocation */ - soft_dev = rte_eth_dev_allocate(params->soft.name); - if (!soft_dev) + dev = rte_eth_dev_allocate(params->name); + if (!dev) return -ENOMEM; /* dev */ - soft_dev->rx_pkt_burst = (params->soft.intrusive) ? - NULL : /* set up later */ - pmd_rx_pkt_burst; - soft_dev->tx_pkt_burst = pmd_tx_pkt_burst; - soft_dev->tx_pkt_prepare = NULL; - soft_dev->dev_ops = &pmd_ops; - soft_dev->device = &vdev->device; + dev->rx_pkt_burst = pmd_rx_pkt_burst; + dev->tx_pkt_burst = pmd_tx_pkt_burst; + dev->tx_pkt_prepare = NULL; + dev->dev_ops = &pmd_ops; + dev->device = &vdev->device; /* dev->data */ - soft_dev->data->dev_private = dev_private; - soft_dev->data->dev_link.link_speed = hard_speed; - soft_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; - soft_dev->data->dev_link.link_autoneg = ETH_LINK_FIXED; - soft_dev->data->dev_link.link_status = ETH_LINK_DOWN; - soft_dev->data->mac_addrs = ð_addr; - soft_dev->data->promiscuous = 1; - soft_dev->data->kdrv = RTE_KDRV_NONE; - soft_dev->data->numa_node = numa_node; - - rte_eth_dev_probing_finish(soft_dev); + dev->data->dev_private = dev_private; + dev->data->dev_link.link_speed = ETH_SPEED_NUM_100G; + dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; + dev->data->dev_link.link_autoneg = ETH_LINK_FIXED; + dev->data->dev_link.link_status = ETH_LINK_DOWN; + dev->data->mac_addrs = ð_addr; + dev->data->promiscuous = 1; + dev->data->kdrv = RTE_KDRV_NONE; + dev->data->numa_node = params->cpu_id; + + rte_eth_dev_probing_finish(dev); return 0; } @@ -566,10 +294,10 @@ get_uint32(const char *key __rte_unused, const char *value, void *extra_args) } static int -pmd_parse_args(struct pmd_params *p, const char *name, const char *params) +pmd_parse_args(struct pmd_params *p, const char *params) { struct rte_kvargs *kvlist; - int i, ret; + int ret = 0; kvlist = rte_kvargs_parse(params, pmd_valid_args); if (kvlist == NULL) @@ -577,141 +305,21 @@ pmd_parse_args(struct pmd_params *p, const char *name, const char *params) /* Set default values */ memset(p, 0, sizeof(*p)); - p->soft.name = name; - p->soft.intrusive = INTRUSIVE; - p->soft.tm.rate = 0; - p->soft.tm.nb_queues = SOFTNIC_SOFT_TM_NB_QUEUES; - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - p->soft.tm.qsize[i] = SOFTNIC_SOFT_TM_QUEUE_SIZE; - p->soft.tm.enq_bsz = SOFTNIC_SOFT_TM_ENQ_BSZ; - p->soft.tm.deq_bsz = SOFTNIC_SOFT_TM_DEQ_BSZ; - p->hard.tx_queue_id = SOFTNIC_HARD_TX_QUEUE_ID; - - /* SOFT: TM (optional) */ - if (rte_kvargs_count(kvlist, PMD_PARAM_SOFT_TM) == 1) { - char *s; - - ret = rte_kvargs_process(kvlist, PMD_PARAM_SOFT_TM, - &get_string, &s); - if (ret < 0) - goto out_free; - - if (strcmp(s, "on") == 0) - p->soft.flags |= PMD_FEATURE_TM; - else if (strcmp(s, "off") == 0) - p->soft.flags &= ~PMD_FEATURE_TM; - else - ret = -EINVAL; - - free(s); - if (ret) - goto out_free; - } - - /* SOFT: TM rate (measured in bytes/second) (optional) */ - if (rte_kvargs_count(kvlist, PMD_PARAM_SOFT_TM_RATE) == 1) { - ret = rte_kvargs_process(kvlist, PMD_PARAM_SOFT_TM_RATE, - &get_uint32, &p->soft.tm.rate); - if (ret < 0) - goto out_free; + p->firmware = SOFTNIC_FIRMWARE; + p->cpu_id = SOFTNIC_CPU_ID; - p->soft.flags |= PMD_FEATURE_TM; - } - - /* SOFT: TM number of queues (optional) */ - if (rte_kvargs_count(kvlist, PMD_PARAM_SOFT_TM_NB_QUEUES) == 1) { - ret = rte_kvargs_process(kvlist, PMD_PARAM_SOFT_TM_NB_QUEUES, - &get_uint32, &p->soft.tm.nb_queues); - if (ret < 0) - goto out_free; - - p->soft.flags |= PMD_FEATURE_TM; - } - - /* SOFT: TM queue size 0 .. 3 (optional) */ - if (rte_kvargs_count(kvlist, PMD_PARAM_SOFT_TM_QSIZE0) == 1) { - uint32_t qsize; - - ret = rte_kvargs_process(kvlist, PMD_PARAM_SOFT_TM_QSIZE0, - &get_uint32, &qsize); - if (ret < 0) - goto out_free; - - p->soft.tm.qsize[0] = (uint16_t)qsize; - p->soft.flags |= PMD_FEATURE_TM; - } - - if (rte_kvargs_count(kvlist, PMD_PARAM_SOFT_TM_QSIZE1) == 1) { - uint32_t qsize; - - ret = rte_kvargs_process(kvlist, PMD_PARAM_SOFT_TM_QSIZE1, - &get_uint32, &qsize); + /* Firmware script (optional) */ + if (rte_kvargs_count(kvlist, PMD_PARAM_FIRMWARE) == 1) { + ret = rte_kvargs_process(kvlist, PMD_PARAM_FIRMWARE, + &get_string, &p->firmware); if (ret < 0) goto out_free; - - p->soft.tm.qsize[1] = (uint16_t)qsize; - p->soft.flags |= PMD_FEATURE_TM; } - if (rte_kvargs_count(kvlist, PMD_PARAM_SOFT_TM_QSIZE2) == 1) { - uint32_t qsize; - - ret = rte_kvargs_process(kvlist, PMD_PARAM_SOFT_TM_QSIZE2, - &get_uint32, &qsize); - if (ret < 0) - goto out_free; - - p->soft.tm.qsize[2] = (uint16_t)qsize; - p->soft.flags |= PMD_FEATURE_TM; - } - - if (rte_kvargs_count(kvlist, PMD_PARAM_SOFT_TM_QSIZE3) == 1) { - uint32_t qsize; - - ret = rte_kvargs_process(kvlist, PMD_PARAM_SOFT_TM_QSIZE3, - &get_uint32, &qsize); - if (ret < 0) - goto out_free; - - p->soft.tm.qsize[3] = (uint16_t)qsize; - p->soft.flags |= PMD_FEATURE_TM; - } - - /* SOFT: TM enqueue burst size (optional) */ - if (rte_kvargs_count(kvlist, PMD_PARAM_SOFT_TM_ENQ_BSZ) == 1) { - ret = rte_kvargs_process(kvlist, PMD_PARAM_SOFT_TM_ENQ_BSZ, - &get_uint32, &p->soft.tm.enq_bsz); - if (ret < 0) - goto out_free; - - p->soft.flags |= PMD_FEATURE_TM; - } - - /* SOFT: TM dequeue burst size (optional) */ - if (rte_kvargs_count(kvlist, PMD_PARAM_SOFT_TM_DEQ_BSZ) == 1) { - ret = rte_kvargs_process(kvlist, PMD_PARAM_SOFT_TM_DEQ_BSZ, - &get_uint32, &p->soft.tm.deq_bsz); - if (ret < 0) - goto out_free; - - p->soft.flags |= PMD_FEATURE_TM; - } - - /* HARD: name (mandatory) */ - if (rte_kvargs_count(kvlist, PMD_PARAM_HARD_NAME) == 1) { - ret = rte_kvargs_process(kvlist, PMD_PARAM_HARD_NAME, - &get_string, &p->hard.name); - if (ret < 0) - goto out_free; - } else { - ret = -EINVAL; - goto out_free; - } - - /* HARD: tx_queue_id (optional) */ - if (rte_kvargs_count(kvlist, PMD_PARAM_HARD_TX_QUEUE_ID) == 1) { - ret = rte_kvargs_process(kvlist, PMD_PARAM_HARD_TX_QUEUE_ID, - &get_uint32, &p->hard.tx_queue_id); + /* CPU ID (optional) */ + if (rte_kvargs_count(kvlist, PMD_PARAM_CPU_ID) == 1) { + ret = rte_kvargs_process(kvlist, PMD_PARAM_CPU_ID, + &get_uint32, &p->cpu_id); if (ret < 0) goto out_free; } @@ -726,68 +334,31 @@ pmd_probe(struct rte_vdev_device *vdev) { struct pmd_params p; const char *params; - int status; + int status = 0; - struct rte_eth_dev_info hard_info; - uint32_t hard_speed; - uint16_t hard_port_id; - int numa_node; void *dev_private; - struct rte_eth_dev *eth_dev; const char *name = rte_vdev_device_name(vdev); PMD_LOG(INFO, "Probing device \"%s\"", name); /* Parse input arguments */ params = rte_vdev_device_args(vdev); - - if (rte_eal_process_type() == RTE_PROC_SECONDARY && - strlen(params) == 0) { - eth_dev = rte_eth_dev_attach_secondary(name); - if (!eth_dev) { - PMD_LOG(ERR, "Failed to probe %s", name); - return -1; - } - /* TODO: request info from primary to set up Rx and Tx */ - eth_dev->dev_ops = &pmd_ops; - rte_eth_dev_probing_finish(eth_dev); - return 0; - } - if (!params) return -EINVAL; - status = pmd_parse_args(&p, rte_vdev_device_name(vdev), params); + status = pmd_parse_args(&p, params); if (status) return status; - /* Check input arguments */ - if (rte_eth_dev_get_port_by_name(p.hard.name, &hard_port_id)) - return -EINVAL; - - rte_eth_dev_info_get(hard_port_id, &hard_info); - hard_speed = eth_dev_speed_max_mbps(hard_info.speed_capa); - numa_node = rte_eth_dev_socket_id(hard_port_id); - - if (p.hard.tx_queue_id >= hard_info.max_tx_queues) - return -EINVAL; - - if (p.soft.flags & PMD_FEATURE_TM) { - status = tm_params_check(&p, hard_speed); - - if (status) - return status; - } + p.name = name; /* Allocate and initialize soft ethdev private data */ - dev_private = pmd_init(&p, numa_node); + dev_private = pmd_init(&p); if (dev_private == NULL) return -ENOMEM; /* Register soft ethdev */ - PMD_LOG(INFO, - "Creating soft ethdev \"%s\" for hard ethdev \"%s\"", - p.soft.name, p.hard.name); + PMD_LOG(INFO, "Creating soft ethdev \"%s\"", p.name); status = pmd_ethdev_register(vdev, &p, dev_private); if (status) { @@ -807,8 +378,7 @@ pmd_remove(struct rte_vdev_device *vdev) if (!vdev) return -EINVAL; - PMD_LOG(INFO, "Removing device \"%s\"", - rte_vdev_device_name(vdev)); + PMD_LOG(INFO, "Removing device \"%s\"", rte_vdev_device_name(vdev)); /* Find the ethdev entry */ dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev)); @@ -817,9 +387,9 @@ pmd_remove(struct rte_vdev_device *vdev) p = dev->data->dev_private; /* Free device data structures*/ - pmd_free(p); rte_free(dev->data); rte_eth_dev_release_port(dev); + pmd_free(p); return 0; } @@ -831,17 +401,8 @@ 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_SOFT_TM "=on|off " - PMD_PARAM_SOFT_TM_RATE "= " - PMD_PARAM_SOFT_TM_NB_QUEUES "= " - PMD_PARAM_SOFT_TM_QSIZE0 "= " - PMD_PARAM_SOFT_TM_QSIZE1 "= " - PMD_PARAM_SOFT_TM_QSIZE2 "= " - PMD_PARAM_SOFT_TM_QSIZE3 "= " - PMD_PARAM_SOFT_TM_ENQ_BSZ "= " - PMD_PARAM_SOFT_TM_DEQ_BSZ "= " - PMD_PARAM_HARD_NAME "= " - PMD_PARAM_HARD_TX_QUEUE_ID "="); + PMD_PARAM_FIRMWARE "= " + PMD_PARAM_CPU_ID "="); RTE_INIT(pmd_softnic_init_log); static void diff --git a/drivers/net/softnic/rte_eth_softnic.h b/drivers/net/softnic/rte_eth_softnic.h index 9a2c7ba..fb1d170 100644 --- a/drivers/net/softnic/rte_eth_softnic.h +++ b/drivers/net/softnic/rte_eth_softnic.h @@ -11,37 +11,23 @@ extern "C" { #endif -#ifndef SOFTNIC_SOFT_TM_NB_QUEUES -#define SOFTNIC_SOFT_TM_NB_QUEUES 65536 +/** Firmware. */ +#ifndef SOFTNIC_FIRMWARE +#define SOFTNIC_FIRMWARE "firmware.cli" #endif -#ifndef SOFTNIC_SOFT_TM_QUEUE_SIZE -#define SOFTNIC_SOFT_TM_QUEUE_SIZE 64 -#endif - -#ifndef SOFTNIC_SOFT_TM_ENQ_BSZ -#define SOFTNIC_SOFT_TM_ENQ_BSZ 32 -#endif - -#ifndef SOFTNIC_SOFT_TM_DEQ_BSZ -#define SOFTNIC_SOFT_TM_DEQ_BSZ 24 -#endif - -#ifndef SOFTNIC_HARD_TX_QUEUE_ID -#define SOFTNIC_HARD_TX_QUEUE_ID 0 +/** NUMA node ID. */ +#ifndef SOFTNIC_CPU_ID +#define SOFTNIC_CPU_ID 0 #endif /** - * Run the traffic management function on the softnic device - * - * This function read the packets from the softnic input queues, insert into - * QoS scheduler queues based on mbuf sched field value and transmit the - * scheduled packets out through the hard device interface. + * Soft NIC run. * - * @param portid - * port id of the soft device. + * @param port_id + * Port ID of the Soft NIC device. * @return - * zero. + * Zero on success, error code otherwise. */ int diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index 050e3e7..6ae5954 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -5,9 +5,11 @@ #ifndef __INCLUDE_RTE_ETH_SOFTNIC_INTERNALS_H__ #define __INCLUDE_RTE_ETH_SOFTNIC_INTERNALS_H__ +#include #include #include +#include #include #include #include @@ -18,62 +20,16 @@ * PMD Parameters */ -enum pmd_feature { - PMD_FEATURE_TM = 1, /**< Traffic Management (TM) */ -}; - -#ifndef INTRUSIVE -#define INTRUSIVE 0 -#endif - struct pmd_params { - /** Parameters for the soft device (to be created) */ - struct { - const char *name; /**< Name */ - uint32_t flags; /**< Flags */ - - /** 0 = Access hard device though API only (potentially slower, - * but safer); - * 1 = Access hard device private data structures is allowed - * (potentially faster). - */ - int intrusive; - - /** Traffic Management (TM) */ - struct { - uint32_t rate; /**< Rate (bytes/second) */ - uint32_t nb_queues; /**< Number of queues */ - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /**< Queue size per traffic class */ - uint32_t enq_bsz; /**< Enqueue burst size */ - uint32_t deq_bsz; /**< Dequeue burst size */ - } tm; - } soft; + const char *name; + const char *firmware; + uint32_t cpu_id; - /** Parameters for the hard device (existing) */ + /** Traffic Management (TM) */ struct { - char *name; /**< Name */ - uint16_t tx_queue_id; /**< TX queue ID */ - } hard; -}; - -/** - * Default Internals - */ - -#ifndef DEFAULT_BURST_SIZE -#define DEFAULT_BURST_SIZE 32 -#endif - -#ifndef FLUSH_COUNT_THRESHOLD -#define FLUSH_COUNT_THRESHOLD (1 << 17) -#endif - -struct default_internals { - struct rte_mbuf **pkts; - uint32_t pkts_len; - uint32_t txq_pos; - uint32_t flush_count; + uint32_t n_queues; /**< Number of queues */ + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + } tm; }; /** @@ -185,14 +141,7 @@ struct tm_internals { /** Blueprints */ struct tm_params params; - - /** Run-time */ struct rte_sched_port *sched; - struct rte_mbuf **pkts_enq; - struct rte_mbuf **pkts_deq; - uint32_t pkts_enq_len; - uint32_t txq_pos; - uint32_t flush_count; }; /** @@ -204,22 +153,8 @@ struct pmd_internals { /** Soft device */ struct { - struct default_internals def; /**< Default */ struct tm_internals tm; /**< Traffic Management */ } soft; - - /** Hard device */ - struct { - uint16_t port_id; - } hard; -}; - -struct pmd_rx_queue { - /** Hard device */ - struct { - uint16_t port_id; - uint16_t rx_queue_id; - } hard; }; /** @@ -228,9 +163,6 @@ struct pmd_rx_queue { extern const struct rte_tm_ops pmd_tm_ops; int -tm_params_check(struct pmd_params *params, uint32_t hard_rate); - -int tm_init(struct pmd_internals *p, struct pmd_params *params, int numa_node); void @@ -243,20 +175,9 @@ void tm_stop(struct pmd_internals *p); static inline int -tm_enabled(struct rte_eth_dev *dev) +tm_used(struct rte_eth_dev *dev __rte_unused) { - struct pmd_internals *p = dev->data->dev_private; - - return (p->params.soft.flags & PMD_FEATURE_TM); -} - -static inline int -tm_used(struct rte_eth_dev *dev) -{ - struct pmd_internals *p = dev->data->dev_private; - - return (p->params.soft.flags & PMD_FEATURE_TM) && - p->soft.tm.h.n_tm_nodes[TM_NODE_LEVEL_PORT]; + return 0; } #endif /* __INCLUDE_RTE_ETH_SOFTNIC_INTERNALS_H__ */ diff --git a/drivers/net/softnic/rte_eth_softnic_tm.c b/drivers/net/softnic/rte_eth_softnic_tm.c index 11d638a..8da8310 100644 --- a/drivers/net/softnic/rte_eth_softnic_tm.c +++ b/drivers/net/softnic/rte_eth_softnic_tm.c @@ -15,50 +15,6 @@ #define SUBPORT_TC_PERIOD 10 #define PIPE_TC_PERIOD 40 -int -tm_params_check(struct pmd_params *params, uint32_t hard_rate) -{ - uint64_t hard_rate_bytes_per_sec = (uint64_t)hard_rate * BYTES_IN_MBPS; - uint32_t i; - - /* rate */ - if (params->soft.tm.rate) { - if (params->soft.tm.rate > hard_rate_bytes_per_sec) - return -EINVAL; - } else { - params->soft.tm.rate = - (hard_rate_bytes_per_sec > UINT32_MAX) ? - UINT32_MAX : hard_rate_bytes_per_sec; - } - - /* nb_queues */ - if (params->soft.tm.nb_queues == 0) - return -EINVAL; - - if (params->soft.tm.nb_queues < RTE_SCHED_QUEUES_PER_PIPE) - params->soft.tm.nb_queues = RTE_SCHED_QUEUES_PER_PIPE; - - params->soft.tm.nb_queues = - rte_align32pow2(params->soft.tm.nb_queues); - - /* qsize */ - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (params->soft.tm.qsize[i] == 0) - return -EINVAL; - - params->soft.tm.qsize[i] = - rte_align32pow2(params->soft.tm.qsize[i]); - } - - /* enq_bsz, deq_bsz */ - if (params->soft.tm.enq_bsz == 0 || - params->soft.tm.deq_bsz == 0 || - params->soft.tm.deq_bsz >= params->soft.tm.enq_bsz) - return -EINVAL; - - return 0; -} - static void tm_hierarchy_init(struct pmd_internals *p) { @@ -134,30 +90,9 @@ tm_hierarchy_uninit(struct pmd_internals *p) int tm_init(struct pmd_internals *p, - struct pmd_params *params, - int numa_node) + struct pmd_params *params __rte_unused, + int numa_node __rte_unused) { - uint32_t enq_bsz = params->soft.tm.enq_bsz; - uint32_t deq_bsz = params->soft.tm.deq_bsz; - - p->soft.tm.pkts_enq = rte_zmalloc_socket(params->soft.name, - 2 * enq_bsz * sizeof(struct rte_mbuf *), - 0, - numa_node); - - if (p->soft.tm.pkts_enq == NULL) - return -ENOMEM; - - p->soft.tm.pkts_deq = rte_zmalloc_socket(params->soft.name, - deq_bsz * sizeof(struct rte_mbuf *), - 0, - numa_node); - - if (p->soft.tm.pkts_deq == NULL) { - rte_free(p->soft.tm.pkts_enq); - return -ENOMEM; - } - tm_hierarchy_init(p); return 0; @@ -167,8 +102,6 @@ void tm_free(struct pmd_internals *p) { tm_hierarchy_uninit(p); - rte_free(p->soft.tm.pkts_enq); - rte_free(p->soft.tm.pkts_deq); } int @@ -384,7 +317,7 @@ static uint32_t tm_level_get_max_nodes(struct rte_eth_dev *dev, enum tm_node_level level) { struct pmd_internals *p = dev->data->dev_private; - uint32_t n_queues_max = p->params.soft.tm.nb_queues; + uint32_t n_queues_max = p->params.tm.n_queues; uint32_t n_tc_max = n_queues_max / RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; uint32_t n_pipes_max = n_tc_max / RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; uint32_t n_subports_max = n_pipes_max; @@ -429,7 +362,7 @@ pmd_tm_node_type_get(struct rte_eth_dev *dev, NULL, rte_strerror(EINVAL)); - *is_leaf = node_id < p->params.soft.tm.nb_queues; + *is_leaf = node_id < p->params.tm.n_queues; return 0; } @@ -1362,7 +1295,7 @@ node_add_check_port(struct rte_eth_dev *dev, params->shaper_profile_id); /* node type: non-leaf */ - if (node_id < p->params.soft.tm.nb_queues) + if (node_id < p->params.tm.n_queues) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_NODE_ID, @@ -1385,12 +1318,9 @@ node_add_check_port(struct rte_eth_dev *dev, NULL, rte_strerror(EINVAL)); - /* Shaper must be valid. - * Shaper profile peak rate must fit the configured port rate. - */ + /* Shaper must be valid */ if (params->shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE || - sp == NULL || - sp->params.peak.rate > p->params.soft.tm.rate) + sp == NULL) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID, @@ -1437,7 +1367,7 @@ node_add_check_subport(struct rte_eth_dev *dev, struct pmd_internals *p = dev->data->dev_private; /* node type: non-leaf */ - if (node_id < p->params.soft.tm.nb_queues) + if (node_id < p->params.tm.n_queues) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_NODE_ID, @@ -1509,7 +1439,7 @@ node_add_check_pipe(struct rte_eth_dev *dev, struct pmd_internals *p = dev->data->dev_private; /* node type: non-leaf */ - if (node_id < p->params.soft.tm.nb_queues) + if (node_id < p->params.tm.n_queues) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_NODE_ID, @@ -1586,7 +1516,7 @@ node_add_check_tc(struct rte_eth_dev *dev, struct pmd_internals *p = dev->data->dev_private; /* node type: non-leaf */ - if (node_id < p->params.soft.tm.nb_queues) + if (node_id < p->params.tm.n_queues) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_NODE_ID, @@ -1659,7 +1589,7 @@ node_add_check_queue(struct rte_eth_dev *dev, struct pmd_internals *p = dev->data->dev_private; /* node type: leaf */ - if (node_id >= p->params.soft.tm.nb_queues) + if (node_id >= p->params.tm.n_queues) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_NODE_ID, @@ -2548,10 +2478,10 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) .n_subports_per_port = root->n_children, .n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], - .qsize = {p->params.soft.tm.qsize[0], - p->params.soft.tm.qsize[1], - p->params.soft.tm.qsize[2], - p->params.soft.tm.qsize[3], + .qsize = {p->params.tm.qsize[0], + p->params.tm.qsize[1], + p->params.tm.qsize[2], + p->params.tm.qsize[3], }, .pipe_profiles = t->pipe_profiles, .n_pipe_profiles = t->n_pipe_profiles, From patchwork Wed Jun 27 16:31:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41697 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 061311C12B; Wed, 27 Jun 2018 18:31:37 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id ACCBA1C10F for ; Wed, 27 Jun 2018 18:31:29 +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:28 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789567" 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:26 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:02 +0100 Message-Id: <20180627163123.135686-3-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 02/23] net/softnic: add software queue object 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add swq object implementation to the softnic. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/Makefile | 1 + drivers/net/softnic/rte_eth_softnic.c | 7 ++ drivers/net/softnic/rte_eth_softnic_internals.h | 39 ++++++++++ drivers/net/softnic/rte_eth_softnic_swq.c | 97 +++++++++++++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 drivers/net/softnic/rte_eth_softnic_swq.c diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile index 97ac884..5da7842 100644 --- a/drivers/net/softnic/Makefile +++ b/drivers/net/softnic/Makefile @@ -22,6 +22,7 @@ LIBABIVER := 1 # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_swq.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tm.c # diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c index ccf3bd4..9fff795 100644 --- a/drivers/net/softnic/rte_eth_softnic.c +++ b/drivers/net/softnic/rte_eth_softnic.c @@ -218,14 +218,21 @@ pmd_init(struct pmd_params *params) if (p == NULL) return NULL; + /* Params */ memcpy(&p->params, params, sizeof(p->params)); + /* Resources */ + swq_init(p); return p; } static void pmd_free(struct pmd_internals *p) { + if (p == NULL) + return; + + swq_free(p); rte_free(p); } diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index 6ae5954..5c857b3 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -7,8 +7,10 @@ #include #include +#include #include +#include #include #include #include @@ -16,6 +18,8 @@ #include "rte_eth_softnic.h" +#define NAME_SIZE 64 + /** * PMD Parameters */ @@ -33,6 +37,21 @@ struct pmd_params { }; /** + * SWQ + */ +struct swq_params { + uint32_t size; +}; + +struct swq { + TAILQ_ENTRY(swq) node; + char name[NAME_SIZE]; + struct rte_ring *r; +}; + +TAILQ_HEAD(swq_list, swq); + +/** * Traffic Management (TM) Internals */ @@ -155,9 +174,29 @@ struct pmd_internals { struct { struct tm_internals tm; /**< Traffic Management */ } soft; + + struct swq_list swq_list; }; /** + * SWQ + */ +int +swq_init(struct pmd_internals *p); + +void +swq_free(struct pmd_internals *p); + +struct swq * +swq_find(struct pmd_internals *p, + const char *name); + +struct swq * +swq_create(struct pmd_internals *p, + const char *name, + struct swq_params *params); + +/** * Traffic Management (TM) Operation */ extern const struct rte_tm_ops pmd_tm_ops; diff --git a/drivers/net/softnic/rte_eth_softnic_swq.c b/drivers/net/softnic/rte_eth_softnic_swq.c new file mode 100644 index 0000000..3e810f3 --- /dev/null +++ b/drivers/net/softnic/rte_eth_softnic_swq.c @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include +#include + +#include + +#include "rte_eth_softnic_internals.h" + +int +swq_init(struct pmd_internals *p) +{ + TAILQ_INIT(&p->swq_list); + + return 0; +} + +void +swq_free(struct pmd_internals *p) +{ + for ( ; ; ) { + struct swq *swq; + + swq = TAILQ_FIRST(&p->swq_list); + if (swq == NULL) + break; + + TAILQ_REMOVE(&p->swq_list, swq, node); + rte_ring_free(swq->r); + free(swq); + } +} + +struct swq * +swq_find(struct pmd_internals *p, + const char *name) +{ + struct swq *swq; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(swq, &p->swq_list, node) + if (strcmp(swq->name, name) == 0) + return swq; + + return NULL; +} + +struct swq * +swq_create(struct pmd_internals *p, + const char *name, + struct swq_params *params) +{ + char ring_name[NAME_SIZE]; + struct swq *swq; + struct rte_ring *r; + unsigned int flags = RING_F_SP_ENQ | RING_F_SC_DEQ; + + /* Check input params */ + if (name == NULL || + swq_find(p, name) || + params == NULL || + params->size == 0) + return NULL; + + /* Resource create */ + snprintf(ring_name, sizeof(ring_name), "%s_%s", + p->params.name, + name); + + r = rte_ring_create(ring_name, + params->size, + p->params.cpu_id, + flags); + + if (r == NULL) + return NULL; + + /* Node allocation */ + swq = calloc(1, sizeof(struct swq)); + if (swq == NULL) { + rte_ring_free(r); + return NULL; + } + + /* Node fill in */ + strlcpy(swq->name, name, sizeof(swq->name)); + swq->r = r; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&p->swq_list, swq, node); + + return swq; +} From patchwork Wed Jun 27 16:31:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41698 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 0496F1C134; Wed, 27 Jun 2018 18:31:39 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 7FAD31C10F for ; Wed, 27 Jun 2018 18:31:30 +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:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789577" 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:28 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:03 +0100 Message-Id: <20180627163123.135686-4-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 03/23] net/softnic: add link object 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add link object implementation to the softnic. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/Makefile | 1 + drivers/net/softnic/rte_eth_softnic.c | 4 + drivers/net/softnic/rte_eth_softnic_internals.h | 37 ++++++++++ drivers/net/softnic/rte_eth_softnic_link.c | 98 +++++++++++++++++++++++++ 4 files changed, 140 insertions(+) create mode 100644 drivers/net/softnic/rte_eth_softnic_link.c diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile index 5da7842..3a7a10f 100644 --- a/drivers/net/softnic/Makefile +++ b/drivers/net/softnic/Makefile @@ -23,6 +23,7 @@ LIBABIVER := 1 # SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_swq.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_link.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tm.c # diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c index 9fff795..e1c6a25 100644 --- a/drivers/net/softnic/rte_eth_softnic.c +++ b/drivers/net/softnic/rte_eth_softnic.c @@ -223,6 +223,8 @@ pmd_init(struct pmd_params *params) /* Resources */ swq_init(p); + link_init(p); + return p; } @@ -232,7 +234,9 @@ pmd_free(struct pmd_internals *p) if (p == NULL) return; + link_free(p); swq_free(p); + rte_free(p); } diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index 5c857b3..2163979 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -52,6 +52,24 @@ struct swq { TAILQ_HEAD(swq_list, swq); /** + * LINK + */ +struct link_params { + const char *dev_name; + uint16_t port_id; /**< Valid only when *dev_name* is NULL. */ +}; + +struct link { + TAILQ_ENTRY(link) node; + char name[NAME_SIZE]; + uint16_t port_id; + uint32_t n_rxq; + uint32_t n_txq; +}; + +TAILQ_HEAD(link_list, link); + +/** * Traffic Management (TM) Internals */ @@ -176,6 +194,7 @@ struct pmd_internals { } soft; struct swq_list swq_list; + struct link_list link_list; }; /** @@ -197,6 +216,24 @@ swq_create(struct pmd_internals *p, struct swq_params *params); /** + * LINK + */ +int +link_init(struct pmd_internals *p); + +void +link_free(struct pmd_internals *p); + +struct link * +link_find(struct pmd_internals *p, + const char *name); + +struct link * +link_create(struct pmd_internals *p, + const char *name, + struct link_params *params); + +/** * Traffic Management (TM) Operation */ extern const struct rte_tm_ops pmd_tm_ops; diff --git a/drivers/net/softnic/rte_eth_softnic_link.c b/drivers/net/softnic/rte_eth_softnic_link.c new file mode 100644 index 0000000..709344c --- /dev/null +++ b/drivers/net/softnic/rte_eth_softnic_link.c @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include +#include + +#include +#include + +#include "rte_eth_softnic_internals.h" + +int +link_init(struct pmd_internals *p) +{ + TAILQ_INIT(&p->link_list); + + return 0; +} + +void +link_free(struct pmd_internals *p) +{ + for ( ; ; ) { + struct link *link; + + link = TAILQ_FIRST(&p->link_list); + if (link == NULL) + break; + + TAILQ_REMOVE(&p->link_list, link, node); + free(link); + } +} + +struct link * +link_find(struct pmd_internals *p, + const char *name) +{ + struct link *link; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(link, &p->link_list, node) + if (strcmp(link->name, name) == 0) + return link; + + return NULL; +} + +struct link * +link_create(struct pmd_internals *p, + const char *name, + struct link_params *params) +{ + struct rte_eth_dev_info port_info; + struct link *link; + uint16_t port_id; + + /* Check input params */ + if (name == NULL || + link_find(p, name) || + params == NULL) + return NULL; + + port_id = params->port_id; + if (params->dev_name) { + int status; + + status = rte_eth_dev_get_port_by_name(params->dev_name, + &port_id); + + if (status) + return NULL; + } else { + if (!rte_eth_dev_is_valid_port(port_id)) + return NULL; + } + + rte_eth_dev_info_get(port_id, &port_info); + + /* Node allocation */ + link = calloc(1, sizeof(struct link)); + if (link == NULL) + return NULL; + + /* Node fill in */ + strlcpy(link->name, name, sizeof(link->name)); + link->port_id = port_id; + link->n_rxq = port_info.nb_rx_queues; + link->n_txq = port_info.nb_tx_queues; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&p->link_list, link, node); + + return link; +} From patchwork Wed Jun 27 16:31:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41699 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id E5E6C1C13A; Wed, 27 Jun 2018 18:31:40 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id D1EE71C122 for ; Wed, 27 Jun 2018 18:31:31 +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:30 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789585" 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:29 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:04 +0100 Message-Id: <20180627163123.135686-5-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 04/23] net/softnic: add mempool object 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add mempool object implementation to the softnic. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/Makefile | 1 + drivers/net/softnic/rte_eth_softnic.c | 2 + drivers/net/softnic/rte_eth_softnic_internals.h | 38 +++++++++ drivers/net/softnic/rte_eth_softnic_mempool.c | 103 ++++++++++++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 drivers/net/softnic/rte_eth_softnic_mempool.c diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile index 3a7a10f..b211559 100644 --- a/drivers/net/softnic/Makefile +++ b/drivers/net/softnic/Makefile @@ -22,6 +22,7 @@ LIBABIVER := 1 # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_mempool.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_swq.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_link.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tm.c diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c index e1c6a25..5d5dd8e 100644 --- a/drivers/net/softnic/rte_eth_softnic.c +++ b/drivers/net/softnic/rte_eth_softnic.c @@ -222,6 +222,7 @@ pmd_init(struct pmd_params *params) memcpy(&p->params, params, sizeof(p->params)); /* Resources */ + mempool_init(p); swq_init(p); link_init(p); @@ -236,6 +237,7 @@ pmd_free(struct pmd_internals *p) link_free(p); swq_free(p); + mempool_free(p); rte_free(p); } diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index 2163979..35fb140 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -37,6 +38,24 @@ struct pmd_params { }; /** + * MEMPOOL + */ +struct mempool_params { + uint32_t buffer_size; + uint32_t pool_size; + uint32_t cache_size; +}; + +struct mempool { + TAILQ_ENTRY(mempool) node; + char name[NAME_SIZE]; + struct rte_mempool *m; + uint32_t buffer_size; +}; + +TAILQ_HEAD(mempool_list, mempool); + +/** * SWQ */ struct swq_params { @@ -193,11 +212,30 @@ struct pmd_internals { struct tm_internals tm; /**< Traffic Management */ } soft; + struct mempool_list mempool_list; struct swq_list swq_list; struct link_list link_list; }; /** + * MEMPOOL + */ +int +mempool_init(struct pmd_internals *p); + +void +mempool_free(struct pmd_internals *p); + +struct mempool * +mempool_find(struct pmd_internals *p, + const char *name); + +struct mempool * +mempool_create(struct pmd_internals *p, + const char *name, + struct mempool_params *params); + +/** * SWQ */ int diff --git a/drivers/net/softnic/rte_eth_softnic_mempool.c b/drivers/net/softnic/rte_eth_softnic_mempool.c new file mode 100644 index 0000000..ff2de67 --- /dev/null +++ b/drivers/net/softnic/rte_eth_softnic_mempool.c @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include +#include + +#include +#include + +#include "rte_eth_softnic_internals.h" + +#define BUFFER_SIZE_MIN (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) + +int +mempool_init(struct pmd_internals *p) +{ + TAILQ_INIT(&p->mempool_list); + + return 0; +} + +void +mempool_free(struct pmd_internals *p) +{ + for ( ; ; ) { + struct mempool *mempool; + + mempool = TAILQ_FIRST(&p->mempool_list); + if (mempool == NULL) + break; + + TAILQ_REMOVE(&p->mempool_list, mempool, node); + rte_mempool_free(mempool->m); + free(mempool); + } +} + +struct mempool * +mempool_find(struct pmd_internals *p, + const char *name) +{ + struct mempool *mempool; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(mempool, &p->mempool_list, node) + if (strcmp(mempool->name, name) == 0) + return mempool; + + return NULL; +} + +struct mempool * +mempool_create(struct pmd_internals *p, + const char *name, + struct mempool_params *params) +{ + char mempool_name[NAME_SIZE]; + struct mempool *mempool; + struct rte_mempool *m; + + /* Check input params */ + if (name == NULL || + mempool_find(p, name) || + params == NULL || + params->buffer_size < BUFFER_SIZE_MIN || + params->pool_size == 0) + return NULL; + + /* Resource create */ + snprintf(mempool_name, sizeof(mempool_name), "%s_%s", + p->params.name, + name); + + m = rte_pktmbuf_pool_create(mempool_name, + params->pool_size, + params->cache_size, + 0, + params->buffer_size - sizeof(struct rte_mbuf), + p->params.cpu_id); + + if (m == NULL) + return NULL; + + /* Node allocation */ + mempool = calloc(1, sizeof(struct mempool)); + if (mempool == NULL) { + rte_mempool_free(m); + return NULL; + } + + /* Node fill in */ + strlcpy(mempool->name, name, sizeof(mempool->name)); + mempool->m = m; + mempool->buffer_size = params->buffer_size; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&p->mempool_list, mempool, node); + + return mempool; +} From patchwork Wed Jun 27 16:31:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41700 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 631481C138; Wed, 27 Jun 2018 18:31:43 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id A59201C122 for ; Wed, 27 Jun 2018 18:31:32 +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:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789590" 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:31 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:05 +0100 Message-Id: <20180627163123.135686-6-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 05/23] net/softnic: add tap object 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add tap object implementation to the softnic. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/Makefile | 1 + drivers/net/softnic/rte_eth_softnic.c | 2 + drivers/net/softnic/rte_eth_softnic_internals.h | 29 ++++++ drivers/net/softnic/rte_eth_softnic_tap.c | 118 ++++++++++++++++++++++++ 4 files changed, 150 insertions(+) create mode 100644 drivers/net/softnic/rte_eth_softnic_tap.c diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile index b211559..677a5b1 100644 --- a/drivers/net/softnic/Makefile +++ b/drivers/net/softnic/Makefile @@ -26,6 +26,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_mempool.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_swq.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_link.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tm.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tap.c # # Export include files diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c index 5d5dd8e..6dd8463 100644 --- a/drivers/net/softnic/rte_eth_softnic.c +++ b/drivers/net/softnic/rte_eth_softnic.c @@ -225,6 +225,7 @@ pmd_init(struct pmd_params *params) mempool_init(p); swq_init(p); link_init(p); + tap_init(p); return p; } @@ -235,6 +236,7 @@ pmd_free(struct pmd_internals *p) if (p == NULL) return; + tap_free(p); link_free(p); swq_free(p); mempool_free(p); diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index 35fb140..6b7004c 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -201,6 +201,17 @@ struct tm_internals { }; /** + * TAP + */ +struct tap { + TAILQ_ENTRY(tap) node; + char name[NAME_SIZE]; + int fd; +}; + +TAILQ_HEAD(tap_list, tap); + +/** * PMD Internals */ struct pmd_internals { @@ -215,6 +226,7 @@ struct pmd_internals { struct mempool_list mempool_list; struct swq_list swq_list; struct link_list link_list; + struct tap_list tap_list; }; /** @@ -294,4 +306,21 @@ tm_used(struct rte_eth_dev *dev __rte_unused) return 0; } +/** + * TAP + */ +int +tap_init(struct pmd_internals *p); + +void +tap_free(struct pmd_internals *p); + +struct tap * +tap_find(struct pmd_internals *p, + const char *name); + +struct tap * +tap_create(struct pmd_internals *p, + const char *name); + #endif /* __INCLUDE_RTE_ETH_SOFTNIC_INTERNALS_H__ */ diff --git a/drivers/net/softnic/rte_eth_softnic_tap.c b/drivers/net/softnic/rte_eth_softnic_tap.c new file mode 100644 index 0000000..96771e8 --- /dev/null +++ b/drivers/net/softnic/rte_eth_softnic_tap.c @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include +#ifdef RTE_EXEC_ENV_LINUXAPP +#include +#include +#endif +#include + +#include +#include +#include +#include +#include + +#include + +#include "rte_eth_softnic_internals.h" + +#define TAP_DEV "/dev/net/tun" + +int +tap_init(struct pmd_internals *p) +{ + TAILQ_INIT(&p->tap_list); + + return 0; +} + +void +tap_free(struct pmd_internals *p) +{ + for ( ; ; ) { + struct tap *tap; + + tap = TAILQ_FIRST(&p->tap_list); + if (tap == NULL) + break; + + TAILQ_REMOVE(&p->tap_list, tap, node); + free(tap); + } +} + +struct tap * +tap_find(struct pmd_internals *p, + const char *name) +{ + struct tap *tap; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(tap, &p->tap_list, node) + if (strcmp(tap->name, name) == 0) + return tap; + + return NULL; +} + +#ifndef RTE_EXEC_ENV_LINUXAPP + +struct tap * +tap_create(struct pmd_internals *p __rte_unused, + const char *name __rte_unused) +{ + return NULL; +} + +#else + +struct tap * +tap_create(struct pmd_internals *p, + const char *name) +{ + struct tap *tap; + struct ifreq ifr; + int fd, status; + + /* Check input params */ + if (name == NULL || + tap_find(p, name)) + return NULL; + + /* Resource create */ + fd = open(TAP_DEV, O_RDWR | O_NONBLOCK); + if (fd < 0) + return NULL; + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* No packet information */ + snprintf(ifr.ifr_name, IFNAMSIZ, "%s", name); + + status = ioctl(fd, TUNSETIFF, (void *)&ifr); + if (status < 0) { + close(fd); + return NULL; + } + + /* Node allocation */ + tap = calloc(1, sizeof(struct tap)); + if (tap == NULL) { + close(fd); + return NULL; + } + /* Node fill in */ + strlcpy(tap->name, name, sizeof(tap->name)); + tap->fd = fd; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&p->tap_list, tap, node); + + return tap; +} + +#endif From patchwork Wed Jun 27 16:31:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41701 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id D3A591C195; Wed, 27 Jun 2018 18:31:55 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id C801B1C0BD for ; Wed, 27 Jun 2018 18:31:33 +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:33 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789607" 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:31 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:06 +0100 Message-Id: <20180627163123.135686-7-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 06/23] net/softnic: add traffic manager object 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add traffic manager(tmgr) object to the softnic. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/rte_eth_softnic.c | 70 +++++++++++++++- drivers/net/softnic/rte_eth_softnic.h | 11 ++- drivers/net/softnic/rte_eth_softnic_internals.h | 39 +++++++-- drivers/net/softnic/rte_eth_softnic_tm.c | 103 +++++++++++++++++++++--- 4 files changed, 201 insertions(+), 22 deletions(-) diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c index 6dd8463..d7580f6 100644 --- a/drivers/net/softnic/rte_eth_softnic.c +++ b/drivers/net/softnic/rte_eth_softnic.c @@ -20,10 +20,23 @@ #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" +#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" static const char *pmd_valid_args[] = { PMD_PARAM_FIRMWARE, PMD_PARAM_CPU_ID, + PMD_PARAM_TM_N_QUEUES, + PMD_PARAM_TM_QSIZE0, + PMD_PARAM_TM_QSIZE1, + PMD_PARAM_TM_QSIZE2, + PMD_PARAM_TM_QSIZE3, NULL }; @@ -154,7 +167,7 @@ pmd_link_update(struct rte_eth_dev *dev __rte_unused, 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; } @@ -225,6 +238,8 @@ pmd_init(struct pmd_params *params) mempool_init(p); swq_init(p); link_init(p); + tm_init(p); + tmgr_init(p); tap_init(p); return p; @@ -237,6 +252,8 @@ pmd_free(struct pmd_internals *p) return; tap_free(p); + tmgr_free(p); + tm_free(p); link_free(p); swq_free(p); mempool_free(p); @@ -322,6 +339,11 @@ 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->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; /* Firmware script (optional) */ if (rte_kvargs_count(kvlist, PMD_PARAM_FIRMWARE) == 1) { @@ -339,6 +361,43 @@ pmd_parse_args(struct pmd_params *p, const char *params) 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; + } + out_free: rte_kvargs_free(kvlist); return ret; @@ -417,9 +476,16 @@ 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_CPU_ID "="); + PMD_PARAM_CPU_ID "= " + PMD_PARAM_TM_N_QUEUES "= " + PMD_PARAM_TM_QSIZE0 "= " + PMD_PARAM_TM_QSIZE1 "= " + PMD_PARAM_TM_QSIZE2 "= " + PMD_PARAM_TM_QSIZE3 "=" +); RTE_INIT(pmd_softnic_init_log); + static void pmd_softnic_init_log(void) { diff --git a/drivers/net/softnic/rte_eth_softnic.h b/drivers/net/softnic/rte_eth_softnic.h index fb1d170..98b0828 100644 --- a/drivers/net/softnic/rte_eth_softnic.h +++ b/drivers/net/softnic/rte_eth_softnic.h @@ -21,6 +21,16 @@ extern "C" { #define SOFTNIC_CPU_ID 0 #endif +/** Traffic Manager: Number of scheduler queues. */ +#ifndef SOFTNIC_TM_N_QUEUES +#define SOFTNIC_TM_N_QUEUES (64 * 1024) +#endif + +/** Traffic Manager: Scheduler queue size (per traffic class). */ +#ifndef SOFTNIC_TM_QUEUE_SIZE +#define SOFTNIC_TM_QUEUE_SIZE 64 +#endif + /** * Soft NIC run. * @@ -29,7 +39,6 @@ extern "C" { * @return * Zero on success, error code otherwise. */ - int rte_pmd_softnic_run(uint16_t port_id); diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index 6b7004c..e724cba 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -89,7 +89,7 @@ struct link { TAILQ_HEAD(link_list, link); /** - * Traffic Management (TM) Internals + * TMGR */ #ifndef TM_MAX_SUBPORTS @@ -200,6 +200,14 @@ struct tm_internals { struct rte_sched_port *sched; }; +struct tmgr_port { + TAILQ_ENTRY(tmgr_port) node; + char name[NAME_SIZE]; + struct rte_sched_port *s; +}; + +TAILQ_HEAD(tmgr_port_list, tmgr_port); + /** * TAP */ @@ -218,7 +226,6 @@ struct pmd_internals { /** Params */ struct pmd_params params; - /** Soft device */ struct { struct tm_internals tm; /**< Traffic Management */ } soft; @@ -226,6 +233,7 @@ struct pmd_internals { struct mempool_list mempool_list; struct swq_list swq_list; struct link_list link_list; + struct tmgr_port_list tmgr_port_list; struct tap_list tap_list; }; @@ -284,12 +292,25 @@ link_create(struct pmd_internals *p, struct link_params *params); /** - * Traffic Management (TM) Operation + * TMGR */ -extern const struct rte_tm_ops pmd_tm_ops; +int +tmgr_init(struct pmd_internals *p); + +void +tmgr_free(struct pmd_internals *p); + +struct tmgr_port * +tmgr_port_find(struct pmd_internals *p, + const char *name); + +struct tmgr_port * +tmgr_port_create(struct pmd_internals *p, + const char *name, + struct rte_sched_port *sched); int -tm_init(struct pmd_internals *p, struct pmd_params *params, int numa_node); +tm_init(struct pmd_internals *p); void tm_free(struct pmd_internals *p); @@ -301,11 +322,15 @@ void tm_stop(struct pmd_internals *p); static inline int -tm_used(struct rte_eth_dev *dev __rte_unused) +tm_used(struct rte_eth_dev *dev) { - return 0; + struct pmd_internals *p = dev->data->dev_private; + + return p->soft.tm.h.n_tm_nodes[TM_NODE_LEVEL_PORT]; } +extern const struct rte_tm_ops pmd_tm_ops; + /** * TAP */ diff --git a/drivers/net/softnic/rte_eth_softnic_tm.c b/drivers/net/softnic/rte_eth_softnic_tm.c index 8da8310..dd7ab3a 100644 --- a/drivers/net/softnic/rte_eth_softnic_tm.c +++ b/drivers/net/softnic/rte_eth_softnic_tm.c @@ -7,14 +7,83 @@ #include #include +#include #include "rte_eth_softnic_internals.h" #include "rte_eth_softnic.h" -#define BYTES_IN_MBPS (1000 * 1000 / 8) #define SUBPORT_TC_PERIOD 10 #define PIPE_TC_PERIOD 40 +int +tmgr_init(struct pmd_internals *p) +{ + TAILQ_INIT(&p->tmgr_port_list); + + return 0; +} + +void +tmgr_free(struct pmd_internals *p) +{ + for ( ; ; ) { + struct tmgr_port *tmgr_port; + + tmgr_port = TAILQ_FIRST(&p->tmgr_port_list); + if (tmgr_port == NULL) + break; + + TAILQ_REMOVE(&p->tmgr_port_list, tmgr_port, node); + free(tmgr_port); + } +} + +struct tmgr_port * +tmgr_port_find(struct pmd_internals *p, + const char *name) +{ + struct tmgr_port *tmgr_port; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(tmgr_port, &p->tmgr_port_list, node) + if (strcmp(tmgr_port->name, name) == 0) + return tmgr_port; + + return NULL; +} + +struct tmgr_port * +tmgr_port_create(struct pmd_internals *p, + const char *name, + struct rte_sched_port *sched) +{ + struct tmgr_port *tmgr_port; + + /* Check input params */ + if (name == NULL || + tmgr_port_find(p, name) || + sched == NULL) + return NULL; + + /* Resource */ + + /* Node allocation */ + tmgr_port = calloc(1, sizeof(struct tmgr_port)); + if (tmgr_port == NULL) + return NULL; + + /* Node fill in */ + strlcpy(tmgr_port->name, name, sizeof(tmgr_port->name)); + tmgr_port->s = sched; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&p->tmgr_port_list, tmgr_port, node); + + return tmgr_port; +} + static void tm_hierarchy_init(struct pmd_internals *p) { @@ -89,9 +158,7 @@ tm_hierarchy_uninit(struct pmd_internals *p) } int -tm_init(struct pmd_internals *p, - struct pmd_params *params __rte_unused, - int numa_node __rte_unused) +tm_init(struct pmd_internals *p) { tm_hierarchy_init(p); @@ -107,7 +174,9 @@ tm_free(struct pmd_internals *p) int tm_start(struct pmd_internals *p) { + struct tmgr_port *tmgr_port; struct tm_params *t = &p->soft.tm.params; + struct rte_sched_port *sched; uint32_t n_subports, subport_id; int status; @@ -116,8 +185,8 @@ tm_start(struct pmd_internals *p) return -1; /* Port */ - p->soft.tm.sched = rte_sched_port_config(&t->port_params); - if (p->soft.tm.sched == NULL) + sched = rte_sched_port_config(&t->port_params); + if (sched == NULL) return -1; /* Subport */ @@ -127,11 +196,11 @@ tm_start(struct pmd_internals *p) t->port_params.n_pipes_per_subport; uint32_t pipe_id; - status = rte_sched_subport_config(p->soft.tm.sched, + status = rte_sched_subport_config(sched, subport_id, &t->subport_params[subport_id]); if (status) { - rte_sched_port_free(p->soft.tm.sched); + rte_sched_port_free(sched); return -1; } @@ -145,26 +214,36 @@ tm_start(struct pmd_internals *p) if (profile_id < 0) continue; - status = rte_sched_pipe_config(p->soft.tm.sched, + status = rte_sched_pipe_config(sched, subport_id, pipe_id, profile_id); if (status) { - rte_sched_port_free(p->soft.tm.sched); + rte_sched_port_free(sched); return -1; } } } + tmgr_port = tmgr_port_create(p, "TMGR", sched); + if (tmgr_port == NULL) { + rte_sched_port_free(sched); + return -1; + } + + /* Commit */ + p->soft.tm.sched = sched; + return 0; } void tm_stop(struct pmd_internals *p) { - if (p->soft.tm.sched) + if (p->soft.tm.sched) { rte_sched_port_free(p->soft.tm.sched); - + p->soft.tm.sched = NULL; + } /* Unfreeze hierarchy */ p->soft.tm.hierarchy_frozen = 0; } From patchwork Wed Jun 27 16:31:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41702 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 7C82C1C1A0; Wed, 27 Jun 2018 18:31:57 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 8F04C1C127 for ; Wed, 27 Jun 2018 18:31:35 +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:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789620" 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:33 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:07 +0100 Message-Id: <20180627163123.135686-8-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 07/23] net/softnic: add port action profile 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add pipeline's port action profile implementation to the softnic. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/Makefile | 3 + drivers/net/softnic/hash_func.h | 359 ++++++++++++++++++++++++ drivers/net/softnic/hash_func_arm64.h | 261 +++++++++++++++++ drivers/net/softnic/rte_eth_softnic.c | 2 + drivers/net/softnic/rte_eth_softnic_action.c | 162 +++++++++++ drivers/net/softnic/rte_eth_softnic_internals.h | 38 +++ mk/rte.app.mk | 2 + 7 files changed, 827 insertions(+) create mode 100644 drivers/net/softnic/hash_func.h create mode 100644 drivers/net/softnic/hash_func_arm64.h create mode 100644 drivers/net/softnic/rte_eth_softnic_action.c diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile index 677a5b1..82f1eb5 100644 --- a/drivers/net/softnic/Makefile +++ b/drivers/net/softnic/Makefile @@ -8,8 +8,10 @@ include $(RTE_SDK)/mk/rte.vars.mk # LIB = librte_pmd_softnic.a +CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) +LDLIBS += -lrte_pipeline LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_sched LDLIBS += -lrte_bus_vdev @@ -27,6 +29,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_swq.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_link.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tm.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tap.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_action.c # # Export include files diff --git a/drivers/net/softnic/hash_func.h b/drivers/net/softnic/hash_func.h new file mode 100644 index 0000000..198d2b2 --- /dev/null +++ b/drivers/net/softnic/hash_func.h @@ -0,0 +1,359 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef __INCLUDE_HASH_FUNC_H__ +#define __INCLUDE_HASH_FUNC_H__ + +#include + +static inline uint64_t +hash_xor_key8(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t xor0; + + xor0 = seed ^ (k[0] & m[0]); + + return (xor0 >> 32) ^ xor0; +} + +static inline uint64_t +hash_xor_key16(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t xor0; + + xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]); + + return (xor0 >> 32) ^ xor0; +} + +static inline uint64_t +hash_xor_key24(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t xor0; + + xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]); + + xor0 ^= k[2] & m[2]; + + return (xor0 >> 32) ^ xor0; +} + +static inline uint64_t +hash_xor_key32(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t xor0, xor1; + + xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]); + xor1 = (k[2] & m[2]) ^ (k[3] & m[3]); + + xor0 ^= xor1; + + return (xor0 >> 32) ^ xor0; +} + +static inline uint64_t +hash_xor_key40(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t xor0, xor1; + + xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]); + xor1 = (k[2] & m[2]) ^ (k[3] & m[3]); + + xor0 ^= xor1; + + xor0 ^= k[4] & m[4]; + + return (xor0 >> 32) ^ xor0; +} + +static inline uint64_t +hash_xor_key48(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t xor0, xor1, xor2; + + xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]); + xor1 = (k[2] & m[2]) ^ (k[3] & m[3]); + xor2 = (k[4] & m[4]) ^ (k[5] & m[5]); + + xor0 ^= xor1; + + xor0 ^= xor2; + + return (xor0 >> 32) ^ xor0; +} + +static inline uint64_t +hash_xor_key56(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t xor0, xor1, xor2; + + xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]); + xor1 = (k[2] & m[2]) ^ (k[3] & m[3]); + xor2 = (k[4] & m[4]) ^ (k[5] & m[5]); + + xor0 ^= xor1; + xor2 ^= k[6] & m[6]; + + xor0 ^= xor2; + + return (xor0 >> 32) ^ xor0; +} + +static inline uint64_t +hash_xor_key64(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t xor0, xor1, xor2, xor3; + + xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]); + xor1 = (k[2] & m[2]) ^ (k[3] & m[3]); + xor2 = (k[4] & m[4]) ^ (k[5] & m[5]); + xor3 = (k[6] & m[6]) ^ (k[7] & m[7]); + + xor0 ^= xor1; + xor2 ^= xor3; + + xor0 ^= xor2; + + return (xor0 >> 32) ^ xor0; +} + +#if defined(RTE_ARCH_X86_64) + +#include + +static inline uint64_t +hash_crc_key8(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t crc0; + + crc0 = _mm_crc32_u64(seed, k[0] & m[0]); + + return crc0; +} + +static inline uint64_t +hash_crc_key16(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t k0, crc0, crc1; + + k0 = k[0] & m[0]; + + crc0 = _mm_crc32_u64(k0, seed); + crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]); + + crc0 ^= crc1; + + return crc0; +} + +static inline uint64_t +hash_crc_key24(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t k0, k2, crc0, crc1; + + k0 = k[0] & m[0]; + k2 = k[2] & m[2]; + + crc0 = _mm_crc32_u64(k0, seed); + crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]); + + crc0 = _mm_crc32_u64(crc0, k2); + + crc0 ^= crc1; + + return crc0; +} + +static inline uint64_t +hash_crc_key32(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t k0, k2, crc0, crc1, crc2, crc3; + + k0 = k[0] & m[0]; + k2 = k[2] & m[2]; + + crc0 = _mm_crc32_u64(k0, seed); + crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]); + + crc2 = _mm_crc32_u64(k2, k[3] & m[3]); + crc3 = k2 >> 32; + + crc0 = _mm_crc32_u64(crc0, crc1); + crc1 = _mm_crc32_u64(crc2, crc3); + + crc0 ^= crc1; + + return crc0; +} + +static inline uint64_t +hash_crc_key40(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t k0, k2, crc0, crc1, crc2, crc3; + + k0 = k[0] & m[0]; + k2 = k[2] & m[2]; + + crc0 = _mm_crc32_u64(k0, seed); + crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]); + + crc2 = _mm_crc32_u64(k2, k[3] & m[3]); + crc3 = _mm_crc32_u64(k2 >> 32, k[4] & m[4]); + + crc0 = _mm_crc32_u64(crc0, crc1); + crc1 = _mm_crc32_u64(crc2, crc3); + + crc0 ^= crc1; + + return crc0; +} + +static inline uint64_t +hash_crc_key48(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t k0, k2, k5, crc0, crc1, crc2, crc3; + + k0 = k[0] & m[0]; + k2 = k[2] & m[2]; + k5 = k[5] & m[5]; + + crc0 = _mm_crc32_u64(k0, seed); + crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]); + + crc2 = _mm_crc32_u64(k2, k[3] & m[3]); + crc3 = _mm_crc32_u64(k2 >> 32, k[4] & m[4]); + + crc0 = _mm_crc32_u64(crc0, (crc1 << 32) ^ crc2); + crc1 = _mm_crc32_u64(crc3, k5); + + crc0 ^= crc1; + + return crc0; +} + +static inline uint64_t +hash_crc_key56(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t k0, k2, k5, crc0, crc1, crc2, crc3, crc4, crc5; + + k0 = k[0] & m[0]; + k2 = k[2] & m[2]; + k5 = k[5] & m[5]; + + crc0 = _mm_crc32_u64(k0, seed); + crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]); + + crc2 = _mm_crc32_u64(k2, k[3] & m[3]); + crc3 = _mm_crc32_u64(k2 >> 32, k[4] & m[4]); + + crc4 = _mm_crc32_u64(k5, k[6] & m[6]); + crc5 = k5 >> 32; + + crc0 = _mm_crc32_u64(crc0, (crc1 << 32) ^ crc2); + crc1 = _mm_crc32_u64(crc3, (crc4 << 32) ^ crc5); + + crc0 ^= crc1; + + return crc0; +} + +static inline uint64_t +hash_crc_key64(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint64_t k0, k2, k5, crc0, crc1, crc2, crc3, crc4, crc5; + + k0 = k[0] & m[0]; + k2 = k[2] & m[2]; + k5 = k[5] & m[5]; + + crc0 = _mm_crc32_u64(k0, seed); + crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]); + + crc2 = _mm_crc32_u64(k2, k[3] & m[3]); + crc3 = _mm_crc32_u64(k2 >> 32, k[4] & m[4]); + + crc4 = _mm_crc32_u64(k5, k[6] & m[6]); + crc5 = _mm_crc32_u64(k5 >> 32, k[7] & m[7]); + + crc0 = _mm_crc32_u64(crc0, (crc1 << 32) ^ crc2); + crc1 = _mm_crc32_u64(crc3, (crc4 << 32) ^ crc5); + + crc0 ^= crc1; + + return crc0; +} + +#define hash_default_key8 hash_crc_key8 +#define hash_default_key16 hash_crc_key16 +#define hash_default_key24 hash_crc_key24 +#define hash_default_key32 hash_crc_key32 +#define hash_default_key40 hash_crc_key40 +#define hash_default_key48 hash_crc_key48 +#define hash_default_key56 hash_crc_key56 +#define hash_default_key64 hash_crc_key64 + +#elif defined(RTE_ARCH_ARM64) +#include "hash_func_arm64.h" +#else + +#define hash_default_key8 hash_xor_key8 +#define hash_default_key16 hash_xor_key16 +#define hash_default_key24 hash_xor_key24 +#define hash_default_key32 hash_xor_key32 +#define hash_default_key40 hash_xor_key40 +#define hash_default_key48 hash_xor_key48 +#define hash_default_key56 hash_xor_key56 +#define hash_default_key64 hash_xor_key64 + +#endif + +#endif diff --git a/drivers/net/softnic/hash_func_arm64.h b/drivers/net/softnic/hash_func_arm64.h new file mode 100644 index 0000000..ae6c0f4 --- /dev/null +++ b/drivers/net/softnic/hash_func_arm64.h @@ -0,0 +1,261 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2017 Linaro Limited. 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. + */ +#ifndef __HASH_FUNC_ARM64_H__ +#define __HASH_FUNC_ARM64_H__ + +#define _CRC32CX(crc, val) \ + __asm__("crc32cx %w[c], %w[c], %x[v]":[c] "+r" (crc):[v] "r" (val)) + +static inline uint64_t +hash_crc_key8(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key; + uint64_t *m = mask; + uint32_t crc0; + + crc0 = seed; + _CRC32CX(crc0, k[0] & m[0]); + + return crc0; +} + +static inline uint64_t +hash_crc_key16(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key, k0; + uint64_t *m = mask; + uint32_t crc0, crc1; + + k0 = k[0] & m[0]; + + crc0 = k0; + _CRC32CX(crc0, seed); + crc1 = k0 >> 32; + _CRC32CX(crc1, k[1] & m[1]); + + crc0 ^= crc1; + + return crc0; +} + +static inline uint64_t +hash_crc_key24(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key, k0, k2; + uint64_t *m = mask; + uint32_t crc0, crc1; + + k0 = k[0] & m[0]; + k2 = k[2] & m[2]; + + crc0 = k0; + _CRC32CX(crc0, seed); + crc1 = k0 >> 32; + _CRC32CX(crc1, k[1] & m[1]); + + _CRC32CX(crc0, k2); + + crc0 ^= crc1; + + return crc0; +} + +static inline uint64_t +hash_crc_key32(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key, k0, k2; + uint64_t *m = mask; + uint32_t crc0, crc1, crc2, crc3; + + k0 = k[0] & m[0]; + k2 = k[2] & m[2]; + + crc0 = k0; + _CRC32CX(crc0, seed); + crc1 = k0 >> 32; + _CRC32CX(crc1, k[1] & m[1]); + + crc2 = k2; + _CRC32CX(crc2, k[3] & m[3]); + crc3 = k2 >> 32; + + _CRC32CX(crc0, crc1); + _CRC32CX(crc2, crc3); + + crc0 ^= crc2; + + return crc0; +} + +static inline uint64_t +hash_crc_key40(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key, k0, k2; + uint64_t *m = mask; + uint32_t crc0, crc1, crc2, crc3; + + k0 = k[0] & m[0]; + k2 = k[2] & m[2]; + + crc0 = k0; + _CRC32CX(crc0, seed); + crc1 = k0 >> 32; + _CRC32CX(crc1, k[1] & m[1]); + + crc2 = k2; + _CRC32CX(crc2, k[3] & m[3]); + crc3 = k2 >> 32; + _CRC32CX(crc3, k[4] & m[4]); + + _CRC32CX(crc0, crc1); + _CRC32CX(crc2, crc3); + + crc0 ^= crc2; + + return crc0; +} + +static inline uint64_t +hash_crc_key48(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key, k0, k2, k5; + uint64_t *m = mask; + uint32_t crc0, crc1, crc2, crc3; + + k0 = k[0] & m[0]; + k2 = k[2] & m[2]; + k5 = k[5] & m[5]; + + crc0 = k0; + _CRC32CX(crc0, seed); + crc1 = k0 >> 32; + _CRC32CX(crc1, k[1] & m[1]); + + crc2 = k2; + _CRC32CX(crc2, k[3] & m[3]); + crc3 = k2 >> 32; + _CRC32CX(crc3, k[4] & m[4]); + + _CRC32CX(crc0, ((uint64_t)crc1 << 32) ^ crc2); + _CRC32CX(crc3, k5); + + crc0 ^= crc3; + + return crc0; +} + +static inline uint64_t +hash_crc_key56(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key, k0, k2, k5; + uint64_t *m = mask; + uint32_t crc0, crc1, crc2, crc3, crc4, crc5; + + k0 = k[0] & m[0]; + k2 = k[2] & m[2]; + k5 = k[5] & m[5]; + + crc0 = k0; + _CRC32CX(crc0, seed); + crc1 = k0 >> 32; + _CRC32CX(crc1, k[1] & m[1]); + + crc2 = k2; + _CRC32CX(crc2, k[3] & m[3]); + crc3 = k2 >> 32; + _CRC32CX(crc3, k[4] & m[4]); + + crc4 = k5; + _CRC32CX(crc4, k[6] & m[6]); + crc5 = k5 >> 32; + + _CRC32CX(crc0, ((uint64_t)crc1 << 32) ^ crc2); + _CRC32CX(crc3, ((uint64_t)crc4 << 32) ^ crc5); + + crc0 ^= crc3; + + return crc0; +} + +static inline uint64_t +hash_crc_key64(void *key, void *mask, __rte_unused uint32_t key_size, + uint64_t seed) +{ + uint64_t *k = key, k0, k2, k5; + uint64_t *m = mask; + uint32_t crc0, crc1, crc2, crc3, crc4, crc5; + + k0 = k[0] & m[0]; + k2 = k[2] & m[2]; + k5 = k[5] & m[5]; + + crc0 = k0; + _CRC32CX(crc0, seed); + crc1 = k0 >> 32; + _CRC32CX(crc1, k[1] & m[1]); + + crc2 = k2; + _CRC32CX(crc2, k[3] & m[3]); + crc3 = k2 >> 32; + _CRC32CX(crc3, k[4] & m[4]); + + crc4 = k5; + _CRC32CX(crc4, k[6] & m[6]); + crc5 = k5 >> 32; + _CRC32CX(crc5, k[7] & m[7]); + + _CRC32CX(crc0, ((uint64_t)crc1 << 32) ^ crc2); + _CRC32CX(crc3, ((uint64_t)crc4 << 32) ^ crc5); + + crc0 ^= crc3; + + return crc0; +} + +#define hash_default_key8 hash_crc_key8 +#define hash_default_key16 hash_crc_key16 +#define hash_default_key24 hash_crc_key24 +#define hash_default_key32 hash_crc_key32 +#define hash_default_key40 hash_crc_key40 +#define hash_default_key48 hash_crc_key48 +#define hash_default_key56 hash_crc_key56 +#define hash_default_key64 hash_crc_key64 + +#endif diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c index d7580f6..87463c3 100644 --- a/drivers/net/softnic/rte_eth_softnic.c +++ b/drivers/net/softnic/rte_eth_softnic.c @@ -241,6 +241,7 @@ pmd_init(struct pmd_params *params) tm_init(p); tmgr_init(p); tap_init(p); + port_in_action_profile_init(p); return p; } @@ -251,6 +252,7 @@ pmd_free(struct pmd_internals *p) if (p == NULL) return; + port_in_action_profile_free(p); tap_free(p); tmgr_free(p); tm_free(p); diff --git a/drivers/net/softnic/rte_eth_softnic_action.c b/drivers/net/softnic/rte_eth_softnic_action.c new file mode 100644 index 0000000..ace87ed --- /dev/null +++ b/drivers/net/softnic/rte_eth_softnic_action.c @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include +#include +#include + +#include + +#include "hash_func.h" +#include "rte_eth_softnic_internals.h" + +/** + * Input port + */ +int +port_in_action_profile_init(struct pmd_internals *p) +{ + TAILQ_INIT(&p->port_in_action_profile_list); + + return 0; +} + +void +port_in_action_profile_free(struct pmd_internals *p) +{ + for ( ; ; ) { + struct port_in_action_profile *profile; + + profile = TAILQ_FIRST(&p->port_in_action_profile_list); + if (profile == NULL) + break; + + TAILQ_REMOVE(&p->port_in_action_profile_list, profile, node); + free(profile); + } +} + +struct port_in_action_profile * +port_in_action_profile_find(struct pmd_internals *p, + const char *name) +{ + struct port_in_action_profile *profile; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(profile, &p->port_in_action_profile_list, node) + if (strcmp(profile->name, name) == 0) + return profile; + + return NULL; +} + +struct port_in_action_profile * +port_in_action_profile_create(struct pmd_internals *p, + const char *name, + struct port_in_action_profile_params *params) +{ + struct port_in_action_profile *profile; + struct rte_port_in_action_profile *ap; + int status; + + /* Check input params */ + if (name == NULL || + port_in_action_profile_find(p, name) || + params == NULL) + return NULL; + + if ((params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) && + params->lb.f_hash == NULL) { + switch (params->lb.key_size) { + case 8: + params->lb.f_hash = hash_default_key8; + break; + + case 16: + params->lb.f_hash = hash_default_key16; + break; + + case 24: + params->lb.f_hash = hash_default_key24; + break; + + case 32: + params->lb.f_hash = hash_default_key32; + break; + + case 40: + params->lb.f_hash = hash_default_key40; + break; + + case 48: + params->lb.f_hash = hash_default_key48; + break; + + case 56: + params->lb.f_hash = hash_default_key56; + break; + + case 64: + params->lb.f_hash = hash_default_key64; + break; + + default: + return NULL; + } + + params->lb.seed = 0; + } + + /* Resource */ + ap = rte_port_in_action_profile_create(0); + if (ap == NULL) + return NULL; + + if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_FLTR)) { + status = rte_port_in_action_profile_action_register(ap, + RTE_PORT_IN_ACTION_FLTR, + ¶ms->fltr); + + if (status) { + rte_port_in_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) { + status = rte_port_in_action_profile_action_register(ap, + RTE_PORT_IN_ACTION_LB, + ¶ms->lb); + + if (status) { + rte_port_in_action_profile_free(ap); + return NULL; + } + } + + status = rte_port_in_action_profile_freeze(ap); + if (status) { + rte_port_in_action_profile_free(ap); + return NULL; + } + + /* Node allocation */ + profile = calloc(1, sizeof(struct port_in_action_profile)); + if (profile == NULL) { + rte_port_in_action_profile_free(ap); + return NULL; + } + + /* Node fill in */ + strlcpy(profile->name, name, sizeof(profile->name)); + memcpy(&profile->params, params, sizeof(*params)); + profile->ap = ap; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&p->port_in_action_profile_list, profile, node); + + return profile; +} diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index e724cba..0906b6d 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -220,6 +221,24 @@ struct tap { TAILQ_HEAD(tap_list, tap); /** + * Input port action + */ +struct port_in_action_profile_params { + uint64_t action_mask; + struct rte_port_in_action_fltr_config fltr; + struct rte_port_in_action_lb_config lb; +}; + +struct port_in_action_profile { + TAILQ_ENTRY(port_in_action_profile) node; + char name[NAME_SIZE]; + struct port_in_action_profile_params params; + struct rte_port_in_action_profile *ap; +}; + +TAILQ_HEAD(port_in_action_profile_list, port_in_action_profile); + +/** * PMD Internals */ struct pmd_internals { @@ -235,6 +254,7 @@ struct pmd_internals { struct link_list link_list; struct tmgr_port_list tmgr_port_list; struct tap_list tap_list; + struct port_in_action_profile_list port_in_action_profile_list; }; /** @@ -348,4 +368,22 @@ struct tap * tap_create(struct pmd_internals *p, const char *name); +/** + * Input port action + */ +int +port_in_action_profile_init(struct pmd_internals *p); + +void +port_in_action_profile_free(struct pmd_internals *p); + +struct port_in_action_profile * +port_in_action_profile_find(struct pmd_internals *p, + const char *name); + +struct port_in_action_profile * +port_in_action_profile_create(struct pmd_internals *p, + const char *name, + struct port_in_action_profile_params *params); + #endif /* __INCLUDE_RTE_ETH_SOFTNIC_INTERNALS_H__ */ diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 87a0c80..a9d65d9 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -31,7 +31,9 @@ _LDLIBS-y += -L$(RTE_SDK_BIN)/lib # Order is important: from higher level to lower level # _LDLIBS-$(CONFIG_RTE_LIBRTE_FLOW_CLASSIFY) += -lrte_flow_classify +_LDLIBS-$(CONFIG_RTE_LIBRTE_PIPELINE) += --whole-archive _LDLIBS-$(CONFIG_RTE_LIBRTE_PIPELINE) += -lrte_pipeline +_LDLIBS-$(CONFIG_RTE_LIBRTE_PIPELINE) += --no-whole-archive _LDLIBS-$(CONFIG_RTE_LIBRTE_TABLE) += -lrte_table _LDLIBS-$(CONFIG_RTE_LIBRTE_PORT) += -lrte_port From patchwork Wed Jun 27 16:31:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41703 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 6EBDE1C1A6; Wed, 27 Jun 2018 18:31:59 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 678D81C0D1 for ; Wed, 27 Jun 2018 18:31:36 +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:35 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789630" 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:34 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:08 +0100 Message-Id: <20180627163123.135686-9-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 08/23] net/softnic: add table action profile 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add pipeline's table action profile implementation to the softnic. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/rte_eth_softnic.c | 2 + drivers/net/softnic/rte_eth_softnic_action.c | 227 ++++++++++++++++++++++++ drivers/net/softnic/rte_eth_softnic_internals.h | 44 +++++ 3 files changed, 273 insertions(+) diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c index 87463c3..1da4333 100644 --- a/drivers/net/softnic/rte_eth_softnic.c +++ b/drivers/net/softnic/rte_eth_softnic.c @@ -242,6 +242,7 @@ pmd_init(struct pmd_params *params) tmgr_init(p); tap_init(p); port_in_action_profile_init(p); + table_action_profile_init(p); return p; } @@ -252,6 +253,7 @@ pmd_free(struct pmd_internals *p) if (p == NULL) return; + table_action_profile_free(p); port_in_action_profile_free(p); tap_free(p); tmgr_free(p); diff --git a/drivers/net/softnic/rte_eth_softnic_action.c b/drivers/net/softnic/rte_eth_softnic_action.c index ace87ed..91f3128 100644 --- a/drivers/net/softnic/rte_eth_softnic_action.c +++ b/drivers/net/softnic/rte_eth_softnic_action.c @@ -160,3 +160,230 @@ port_in_action_profile_create(struct pmd_internals *p, return profile; } + +/** + * Table + */ +int +table_action_profile_init(struct pmd_internals *p) +{ + TAILQ_INIT(&p->table_action_profile_list); + + return 0; +} + +void +table_action_profile_free(struct pmd_internals *p) +{ + for ( ; ; ) { + struct table_action_profile *profile; + + profile = TAILQ_FIRST(&p->table_action_profile_list); + if (profile == NULL) + break; + + TAILQ_REMOVE(&p->table_action_profile_list, profile, node); + free(profile); + } +} + +struct table_action_profile * +table_action_profile_find(struct pmd_internals *p, + const char *name) +{ + struct table_action_profile *profile; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(profile, &p->table_action_profile_list, node) + if (strcmp(profile->name, name) == 0) + return profile; + + return NULL; +} + +struct table_action_profile * +table_action_profile_create(struct pmd_internals *p, + const char *name, + struct table_action_profile_params *params) +{ + struct table_action_profile *profile; + struct rte_table_action_profile *ap; + int status; + + /* Check input params */ + if (name == NULL || + table_action_profile_find(p, name) || + params == NULL || + ((params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) == 0)) + return NULL; + + if ((params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) && + params->lb.f_hash == NULL) { + switch (params->lb.key_size) { + case 8: + params->lb.f_hash = hash_default_key8; + break; + + case 16: + params->lb.f_hash = hash_default_key16; + break; + + case 24: + params->lb.f_hash = hash_default_key24; + break; + + case 32: + params->lb.f_hash = hash_default_key32; + break; + + case 40: + params->lb.f_hash = hash_default_key40; + break; + + case 48: + params->lb.f_hash = hash_default_key48; + break; + + case 56: + params->lb.f_hash = hash_default_key56; + break; + + case 64: + params->lb.f_hash = hash_default_key64; + break; + + default: + return NULL; + } + + params->lb.seed = 0; + } + + /* Resource */ + ap = rte_table_action_profile_create(¶ms->common); + if (ap == NULL) + return NULL; + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_FWD, + NULL); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_LB, + ¶ms->lb); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_MTR, + ¶ms->mtr); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_TM, + ¶ms->tm); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_ENCAP, + ¶ms->encap); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_NAT, + ¶ms->nat); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_TTL, + ¶ms->ttl); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_STATS, + ¶ms->stats); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_TIME, + NULL); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + status = rte_table_action_profile_freeze(ap); + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + + /* Node allocation */ + profile = calloc(1, sizeof(struct table_action_profile)); + if (profile == NULL) { + rte_table_action_profile_free(ap); + return NULL; + } + + /* Node fill in */ + strlcpy(profile->name, name, sizeof(profile->name)); + memcpy(&profile->params, params, sizeof(*params)); + profile->ap = ap; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&p->table_action_profile_list, profile, node); + + return profile; +} diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index 0906b6d..569c75d 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -239,6 +240,30 @@ struct port_in_action_profile { TAILQ_HEAD(port_in_action_profile_list, port_in_action_profile); /** + * Table action + */ +struct table_action_profile_params { + uint64_t action_mask; + struct rte_table_action_common_config common; + struct rte_table_action_lb_config lb; + struct rte_table_action_mtr_config mtr; + struct rte_table_action_tm_config tm; + struct rte_table_action_encap_config encap; + struct rte_table_action_nat_config nat; + struct rte_table_action_ttl_config ttl; + struct rte_table_action_stats_config stats; +}; + +struct table_action_profile { + TAILQ_ENTRY(table_action_profile) node; + char name[NAME_SIZE]; + struct table_action_profile_params params; + struct rte_table_action_profile *ap; +}; + +TAILQ_HEAD(table_action_profile_list, table_action_profile); + +/** * PMD Internals */ struct pmd_internals { @@ -255,6 +280,7 @@ struct pmd_internals { struct tmgr_port_list tmgr_port_list; struct tap_list tap_list; struct port_in_action_profile_list port_in_action_profile_list; + struct table_action_profile_list table_action_profile_list; }; /** @@ -386,4 +412,22 @@ port_in_action_profile_create(struct pmd_internals *p, const char *name, struct port_in_action_profile_params *params); +/** + * Table action + */ +int +table_action_profile_init(struct pmd_internals *p); + +void +table_action_profile_free(struct pmd_internals *p); + +struct table_action_profile * +table_action_profile_find(struct pmd_internals *p, + const char *name); + +struct table_action_profile * +table_action_profile_create(struct pmd_internals *p, + const char *name, + struct table_action_profile_params *params); + #endif /* __INCLUDE_RTE_ETH_SOFTNIC_INTERNALS_H__ */ From patchwork Wed Jun 27 16:31:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41704 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 48E571C1AB; Wed, 27 Jun 2018 18:32:01 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id D96DC1C132 for ; Wed, 27 Jun 2018 18:31:38 +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:37 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789645" 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:36 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:09 +0100 Message-Id: <20180627163123.135686-10-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 09/23] net/softnic: add pipeline object 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add pipeline object implementation to the softnic. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/Makefile | 3 +- drivers/net/softnic/rte_eth_softnic.c | 2 + drivers/net/softnic/rte_eth_softnic_internals.h | 196 +++++ drivers/net/softnic/rte_eth_softnic_pipeline.c | 954 ++++++++++++++++++++++++ mk/rte.app.mk | 4 + 5 files changed, 1158 insertions(+), 1 deletion(-) create mode 100644 drivers/net/softnic/rte_eth_softnic_pipeline.c diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile index 82f1eb5..2397fbd 100644 --- a/drivers/net/softnic/Makefile +++ b/drivers/net/softnic/Makefile @@ -11,7 +11,7 @@ LIB = librte_pmd_softnic.a CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -LDLIBS += -lrte_pipeline +LDLIBS += -lrte_pipeline -lrte_port -lrte_table LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_sched LDLIBS += -lrte_bus_vdev @@ -30,6 +30,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_link.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tm.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tap.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_action.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_pipeline.c # # Export include files diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c index 1da4333..882cddb 100644 --- a/drivers/net/softnic/rte_eth_softnic.c +++ b/drivers/net/softnic/rte_eth_softnic.c @@ -243,6 +243,7 @@ pmd_init(struct pmd_params *params) tap_init(p); port_in_action_profile_init(p); table_action_profile_init(p); + pipeline_init(p); return p; } @@ -253,6 +254,7 @@ pmd_free(struct pmd_internals *p) if (p == NULL) return; + pipeline_free(p); table_action_profile_free(p); port_in_action_profile_free(p); tap_free(p); diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index 569c75d..b90f6ae 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -16,6 +16,8 @@ #include #include #include +#include + #include #include @@ -264,6 +266,160 @@ struct table_action_profile { TAILQ_HEAD(table_action_profile_list, table_action_profile); /** + * Pipeline + */ +struct pipeline_params { + uint32_t timer_period_ms; + uint32_t offset_port_id; +}; + +enum port_in_type { + PORT_IN_RXQ, + PORT_IN_SWQ, + PORT_IN_TMGR, + PORT_IN_TAP, + PORT_IN_SOURCE, +}; + +struct port_in_params { + /* Read */ + enum port_in_type type; + const char *dev_name; + union { + struct { + uint16_t queue_id; + } rxq; + + struct { + const char *mempool_name; + uint32_t mtu; + } tap; + + struct { + const char *mempool_name; + const char *file_name; + uint32_t n_bytes_per_pkt; + } source; + }; + uint32_t burst_size; + + /* Action */ + const char *action_profile_name; +}; + +enum port_out_type { + PORT_OUT_TXQ, + PORT_OUT_SWQ, + PORT_OUT_TMGR, + PORT_OUT_TAP, + PORT_OUT_SINK, +}; + +struct port_out_params { + enum port_out_type type; + const char *dev_name; + union { + struct { + uint16_t queue_id; + } txq; + + struct { + const char *file_name; + uint32_t max_n_pkts; + } sink; + }; + uint32_t burst_size; + int retry; + uint32_t n_retries; +}; + +enum table_type { + TABLE_ACL, + TABLE_ARRAY, + TABLE_HASH, + TABLE_LPM, + TABLE_STUB, +}; + +struct table_acl_params { + uint32_t n_rules; + uint32_t ip_header_offset; + int ip_version; +}; + +struct table_array_params { + uint32_t n_keys; + uint32_t key_offset; +}; + +struct table_hash_params { + uint32_t n_keys; + uint32_t key_offset; + uint32_t key_size; + uint8_t *key_mask; + uint32_t n_buckets; + int extendable_bucket; +}; + +struct table_lpm_params { + uint32_t n_rules; + uint32_t key_offset; + uint32_t key_size; +}; + +struct table_params { + /* Match */ + enum table_type match_type; + union { + struct table_acl_params acl; + struct table_array_params array; + struct table_hash_params hash; + struct table_lpm_params lpm; + } match; + + /* Action */ + const char *action_profile_name; +}; + +struct port_in { + struct port_in_params params; + struct port_in_action_profile *ap; + struct rte_port_in_action *a; +}; + +struct table { + struct table_params params; + struct table_action_profile *ap; + struct rte_table_action *a; +}; + +struct pipeline { + TAILQ_ENTRY(pipeline) node; + char name[NAME_SIZE]; + + struct rte_pipeline *p; + struct port_in port_in[RTE_PIPELINE_PORT_IN_MAX]; + struct table table[RTE_PIPELINE_TABLE_MAX]; + uint32_t n_ports_in; + uint32_t n_ports_out; + uint32_t n_tables; + + struct rte_ring *msgq_req; + struct rte_ring *msgq_rsp; + uint32_t timer_period_ms; + + int enabled; + uint32_t thread_id; + uint32_t cpu_id; +}; + +TAILQ_HEAD(pipeline_list, pipeline); + +#ifndef TABLE_RULE_ACTION_SIZE_MAX +#define TABLE_RULE_ACTION_SIZE_MAX 2048 +#endif + +/** * PMD Internals */ struct pmd_internals { @@ -281,6 +437,7 @@ struct pmd_internals { struct tap_list tap_list; struct port_in_action_profile_list port_in_action_profile_list; struct table_action_profile_list table_action_profile_list; + struct pipeline_list pipeline_list; }; /** @@ -430,4 +587,43 @@ table_action_profile_create(struct pmd_internals *p, const char *name, struct table_action_profile_params *params); +/** + * Pipeline + */ +int +pipeline_init(struct pmd_internals *p); + +void +pipeline_free(struct pmd_internals *p); + +struct pipeline * +pipeline_find(struct pmd_internals *p, const char *name); + +struct pipeline * +pipeline_create(struct pmd_internals *p, + const char *name, + struct pipeline_params *params); + +int +pipeline_port_in_create(struct pmd_internals *p, + const char *pipeline_name, + struct port_in_params *params, + int enabled); + +int +pipeline_port_in_connect_to_table(struct pmd_internals *p, + const char *pipeline_name, + uint32_t port_id, + uint32_t table_id); + +int +pipeline_port_out_create(struct pmd_internals *p, + const char *pipeline_name, + struct port_out_params *params); + +int +pipeline_table_create(struct pmd_internals *p, + const char *pipeline_name, + struct table_params *params); + #endif /* __INCLUDE_RTE_ETH_SOFTNIC_INTERNALS_H__ */ diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c new file mode 100644 index 0000000..f1a2925 --- /dev/null +++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c @@ -0,0 +1,954 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "rte_eth_softnic_internals.h" + +#include "hash_func.h" + +#ifndef PIPELINE_MSGQ_SIZE +#define PIPELINE_MSGQ_SIZE 64 +#endif + +#ifndef TABLE_LPM_NUMBER_TBL8 +#define TABLE_LPM_NUMBER_TBL8 256 +#endif + +int +pipeline_init(struct pmd_internals *p) +{ + TAILQ_INIT(&p->pipeline_list); + + return 0; +} + +void +pipeline_free(struct pmd_internals *p) +{ + for ( ; ; ) { + struct pipeline *pipeline; + + pipeline = TAILQ_FIRST(&p->pipeline_list); + if (pipeline == NULL) + break; + + TAILQ_REMOVE(&p->pipeline_list, pipeline, node); + rte_ring_free(pipeline->msgq_req); + rte_ring_free(pipeline->msgq_rsp); + rte_pipeline_free(pipeline->p); + free(pipeline); + } +} + +struct pipeline * +pipeline_find(struct pmd_internals *p, + const char *name) +{ + struct pipeline *pipeline; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(pipeline, &p->pipeline_list, node) + if (strcmp(name, pipeline->name) == 0) + return pipeline; + + return NULL; +} + +struct pipeline * +pipeline_create(struct pmd_internals *softnic, + const char *name, + struct pipeline_params *params) +{ + char resource_name[NAME_MAX]; + struct rte_pipeline_params pp; + struct pipeline *pipeline; + struct rte_pipeline *p; + struct rte_ring *msgq_req; + struct rte_ring *msgq_rsp; + + /* Check input params */ + if (name == NULL || + pipeline_find(softnic, name) || + params == NULL || + params->timer_period_ms == 0) + return NULL; + + /* Resource create */ + snprintf(resource_name, sizeof(resource_name), "%s-%s-REQ", + softnic->params.name, + name); + + msgq_req = rte_ring_create(resource_name, + PIPELINE_MSGQ_SIZE, + softnic->params.cpu_id, + RING_F_SP_ENQ | RING_F_SC_DEQ); + if (msgq_req == NULL) + return NULL; + + snprintf(resource_name, sizeof(resource_name), "%s-%s-RSP", + softnic->params.name, + name); + + msgq_rsp = rte_ring_create(resource_name, + PIPELINE_MSGQ_SIZE, + softnic->params.cpu_id, + RING_F_SP_ENQ | RING_F_SC_DEQ); + if (msgq_rsp == NULL) { + rte_ring_free(msgq_req); + return NULL; + } + + snprintf(resource_name, sizeof(resource_name), "%s_%s", + softnic->params.name, + name); + + pp.name = resource_name; + pp.socket_id = (int)softnic->params.cpu_id; + pp.offset_port_id = params->offset_port_id; + + p = rte_pipeline_create(&pp); + if (p == NULL) { + rte_ring_free(msgq_rsp); + rte_ring_free(msgq_req); + return NULL; + } + + /* Node allocation */ + pipeline = calloc(1, sizeof(struct pipeline)); + if (pipeline == NULL) { + rte_pipeline_free(p); + rte_ring_free(msgq_rsp); + rte_ring_free(msgq_req); + return NULL; + } + + /* Node fill in */ + strlcpy(pipeline->name, name, sizeof(pipeline->name)); + pipeline->p = p; + pipeline->n_ports_in = 0; + pipeline->n_ports_out = 0; + pipeline->n_tables = 0; + pipeline->msgq_req = msgq_req; + pipeline->msgq_rsp = msgq_rsp; + pipeline->timer_period_ms = params->timer_period_ms; + pipeline->enabled = 0; + pipeline->cpu_id = softnic->params.cpu_id; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&softnic->pipeline_list, pipeline, node); + + return pipeline; +} + +int +pipeline_port_in_create(struct pmd_internals *softnic, + const char *pipeline_name, + struct port_in_params *params, + int enabled) +{ + struct rte_pipeline_port_in_params p; + + union { + struct rte_port_ethdev_reader_params ethdev; + struct rte_port_ring_reader_params ring; + struct rte_port_sched_reader_params sched; + struct rte_port_fd_reader_params fd; + struct rte_port_source_params source; + } pp; + + struct pipeline *pipeline; + struct port_in *port_in; + struct port_in_action_profile *ap; + struct rte_port_in_action *action; + uint32_t port_id; + int status; + + memset(&p, 0, sizeof(p)); + memset(&pp, 0, sizeof(pp)); + + /* Check input params */ + if (pipeline_name == NULL || + params == NULL || + params->burst_size == 0 || + params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX) + return -1; + + pipeline = pipeline_find(softnic, pipeline_name); + if (pipeline == NULL) + return -1; + + ap = NULL; + if (params->action_profile_name) { + ap = port_in_action_profile_find(softnic, + params->action_profile_name); + if (ap == NULL) + return -1; + } + + switch (params->type) { + case PORT_IN_RXQ: + { + struct link *link; + + link = link_find(softnic, params->dev_name); + if (link == NULL) + return -1; + + if (params->rxq.queue_id >= link->n_rxq) + return -1; + + pp.ethdev.port_id = link->port_id; + pp.ethdev.queue_id = params->rxq.queue_id; + + p.ops = &rte_port_ethdev_reader_ops; + p.arg_create = &pp.ethdev; + break; + } + + case PORT_IN_SWQ: + { + struct swq *swq; + + swq = swq_find(softnic, params->dev_name); + if (swq == NULL) + return -1; + + pp.ring.ring = swq->r; + + p.ops = &rte_port_ring_reader_ops; + p.arg_create = &pp.ring; + break; + } + + case PORT_IN_TMGR: + { + struct tmgr_port *tmgr_port; + + tmgr_port = tmgr_port_find(softnic, params->dev_name); + if (tmgr_port == NULL) + return -1; + + pp.sched.sched = tmgr_port->s; + + p.ops = &rte_port_sched_reader_ops; + p.arg_create = &pp.sched; + break; + } + + case PORT_IN_TAP: + { + struct tap *tap; + struct mempool *mempool; + + tap = tap_find(softnic, params->dev_name); + mempool = mempool_find(softnic, params->tap.mempool_name); + if (tap == NULL || mempool == NULL) + return -1; + + pp.fd.fd = tap->fd; + pp.fd.mempool = mempool->m; + pp.fd.mtu = params->tap.mtu; + + p.ops = &rte_port_fd_reader_ops; + p.arg_create = &pp.fd; + break; + } + + case PORT_IN_SOURCE: + { + struct mempool *mempool; + + mempool = mempool_find(softnic, params->source.mempool_name); + if (mempool == NULL) + return -1; + + pp.source.mempool = mempool->m; + pp.source.file_name = params->source.file_name; + pp.source.n_bytes_per_pkt = params->source.n_bytes_per_pkt; + + p.ops = &rte_port_source_ops; + p.arg_create = &pp.source; + break; + } + + default: + return -1; + } + + p.burst_size = params->burst_size; + + /* Resource create */ + action = NULL; + p.f_action = NULL; + p.arg_ah = NULL; + + if (ap) { + action = rte_port_in_action_create(ap->ap, + softnic->params.cpu_id); + if (action == NULL) + return -1; + + status = rte_port_in_action_params_get(action, + &p); + if (status) { + rte_port_in_action_free(action); + return -1; + } + } + + status = rte_pipeline_port_in_create(pipeline->p, + &p, + &port_id); + if (status) { + rte_port_in_action_free(action); + return -1; + } + + if (enabled) + rte_pipeline_port_in_enable(pipeline->p, port_id); + + /* Pipeline */ + port_in = &pipeline->port_in[pipeline->n_ports_in]; + memcpy(&port_in->params, params, sizeof(*params)); + port_in->ap = ap; + port_in->a = action; + pipeline->n_ports_in++; + + return 0; +} + +int +pipeline_port_in_connect_to_table(struct pmd_internals *softnic, + const char *pipeline_name, + uint32_t port_id, + uint32_t table_id) +{ + struct pipeline *pipeline; + int status; + + /* Check input params */ + if (pipeline_name == NULL) + return -1; + + pipeline = pipeline_find(softnic, pipeline_name); + if (pipeline == NULL || + port_id >= pipeline->n_ports_in || + table_id >= pipeline->n_tables) + return -1; + + /* Resource */ + status = rte_pipeline_port_in_connect_to_table(pipeline->p, + port_id, + table_id); + + return status; +} + +int +pipeline_port_out_create(struct pmd_internals *softnic, + const char *pipeline_name, + struct port_out_params *params) +{ + struct rte_pipeline_port_out_params p; + + union { + struct rte_port_ethdev_writer_params ethdev; + struct rte_port_ring_writer_params ring; + struct rte_port_sched_writer_params sched; + struct rte_port_fd_writer_params fd; + struct rte_port_sink_params sink; + } pp; + + union { + struct rte_port_ethdev_writer_nodrop_params ethdev; + struct rte_port_ring_writer_nodrop_params ring; + struct rte_port_fd_writer_nodrop_params fd; + } pp_nodrop; + + struct pipeline *pipeline; + uint32_t port_id; + int status; + + memset(&p, 0, sizeof(p)); + memset(&pp, 0, sizeof(pp)); + memset(&pp_nodrop, 0, sizeof(pp_nodrop)); + + /* Check input params */ + if (pipeline_name == NULL || + params == NULL || + params->burst_size == 0 || + params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX) + return -1; + + pipeline = pipeline_find(softnic, pipeline_name); + if (pipeline == NULL) + return -1; + + switch (params->type) { + case PORT_OUT_TXQ: + { + struct link *link; + + link = link_find(softnic, params->dev_name); + if (link == NULL) + return -1; + + if (params->txq.queue_id >= link->n_txq) + return -1; + + pp.ethdev.port_id = link->port_id; + pp.ethdev.queue_id = params->txq.queue_id; + pp.ethdev.tx_burst_sz = params->burst_size; + + pp_nodrop.ethdev.port_id = link->port_id; + pp_nodrop.ethdev.queue_id = params->txq.queue_id; + pp_nodrop.ethdev.tx_burst_sz = params->burst_size; + pp_nodrop.ethdev.n_retries = params->n_retries; + + if (params->retry == 0) { + p.ops = &rte_port_ethdev_writer_ops; + p.arg_create = &pp.ethdev; + } else { + p.ops = &rte_port_ethdev_writer_nodrop_ops; + p.arg_create = &pp_nodrop.ethdev; + } + break; + } + + case PORT_OUT_SWQ: + { + struct swq *swq; + + swq = swq_find(softnic, params->dev_name); + if (swq == NULL) + return -1; + + pp.ring.ring = swq->r; + pp.ring.tx_burst_sz = params->burst_size; + + pp_nodrop.ring.ring = swq->r; + pp_nodrop.ring.tx_burst_sz = params->burst_size; + pp_nodrop.ring.n_retries = params->n_retries; + + if (params->retry == 0) { + p.ops = &rte_port_ring_writer_ops; + p.arg_create = &pp.ring; + } else { + p.ops = &rte_port_ring_writer_nodrop_ops; + p.arg_create = &pp_nodrop.ring; + } + break; + } + + case PORT_OUT_TMGR: + { + struct tmgr_port *tmgr_port; + + tmgr_port = tmgr_port_find(softnic, params->dev_name); + if (tmgr_port == NULL) + return -1; + + pp.sched.sched = tmgr_port->s; + pp.sched.tx_burst_sz = params->burst_size; + + p.ops = &rte_port_sched_writer_ops; + p.arg_create = &pp.sched; + break; + } + + case PORT_OUT_TAP: + { + struct tap *tap; + + tap = tap_find(softnic, params->dev_name); + if (tap == NULL) + return -1; + + pp.fd.fd = tap->fd; + pp.fd.tx_burst_sz = params->burst_size; + + pp_nodrop.fd.fd = tap->fd; + pp_nodrop.fd.tx_burst_sz = params->burst_size; + pp_nodrop.fd.n_retries = params->n_retries; + + if (params->retry == 0) { + p.ops = &rte_port_fd_writer_ops; + p.arg_create = &pp.fd; + } else { + p.ops = &rte_port_fd_writer_nodrop_ops; + p.arg_create = &pp_nodrop.fd; + } + break; + } + + case PORT_OUT_SINK: + { + pp.sink.file_name = params->sink.file_name; + pp.sink.max_n_pkts = params->sink.max_n_pkts; + + p.ops = &rte_port_sink_ops; + p.arg_create = &pp.sink; + break; + } + + default: + return -1; + } + + p.f_action = NULL; + p.arg_ah = NULL; + + /* Resource create */ + status = rte_pipeline_port_out_create(pipeline->p, + &p, + &port_id); + + if (status) + return -1; + + /* Pipeline */ + pipeline->n_ports_out++; + + return 0; +} + +static const struct rte_acl_field_def table_acl_field_format_ipv4[] = { + /* Protocol */ + [0] = { + .type = RTE_ACL_FIELD_TYPE_BITMASK, + .size = sizeof(uint8_t), + .field_index = 0, + .input_index = 0, + .offset = offsetof(struct ipv4_hdr, next_proto_id), + }, + + /* Source IP address (IPv4) */ + [1] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 1, + .input_index = 1, + .offset = offsetof(struct ipv4_hdr, src_addr), + }, + + /* Destination IP address (IPv4) */ + [2] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 2, + .input_index = 2, + .offset = offsetof(struct ipv4_hdr, dst_addr), + }, + + /* Source Port */ + [3] = { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = 3, + .input_index = 3, + .offset = sizeof(struct ipv4_hdr) + + offsetof(struct tcp_hdr, src_port), + }, + + /* Destination Port */ + [4] = { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = 4, + .input_index = 3, + .offset = sizeof(struct ipv4_hdr) + + offsetof(struct tcp_hdr, dst_port), + }, +}; + +static const struct rte_acl_field_def table_acl_field_format_ipv6[] = { + /* Protocol */ + [0] = { + .type = RTE_ACL_FIELD_TYPE_BITMASK, + .size = sizeof(uint8_t), + .field_index = 0, + .input_index = 0, + .offset = offsetof(struct ipv6_hdr, proto), + }, + + /* Source IP address (IPv6) */ + [1] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 1, + .input_index = 1, + .offset = offsetof(struct ipv6_hdr, src_addr[0]), + }, + + [2] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 2, + .input_index = 2, + .offset = offsetof(struct ipv6_hdr, src_addr[4]), + }, + + [3] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 3, + .input_index = 3, + .offset = offsetof(struct ipv6_hdr, src_addr[8]), + }, + + [4] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 4, + .input_index = 4, + .offset = offsetof(struct ipv6_hdr, src_addr[12]), + }, + + /* Destination IP address (IPv6) */ + [5] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 5, + .input_index = 5, + .offset = offsetof(struct ipv6_hdr, dst_addr[0]), + }, + + [6] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 6, + .input_index = 6, + .offset = offsetof(struct ipv6_hdr, dst_addr[4]), + }, + + [7] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 7, + .input_index = 7, + .offset = offsetof(struct ipv6_hdr, dst_addr[8]), + }, + + [8] = { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = 8, + .input_index = 8, + .offset = offsetof(struct ipv6_hdr, dst_addr[12]), + }, + + /* Source Port */ + [9] = { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = 9, + .input_index = 9, + .offset = sizeof(struct ipv6_hdr) + + offsetof(struct tcp_hdr, src_port), + }, + + /* Destination Port */ + [10] = { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = 10, + .input_index = 9, + .offset = sizeof(struct ipv6_hdr) + + offsetof(struct tcp_hdr, dst_port), + }, +}; + +int +pipeline_table_create(struct pmd_internals *softnic, + const char *pipeline_name, + struct table_params *params) +{ + char name[NAME_MAX]; + struct rte_pipeline_table_params p; + + union { + struct rte_table_acl_params acl; + struct rte_table_array_params array; + struct rte_table_hash_params hash; + struct rte_table_lpm_params lpm; + struct rte_table_lpm_ipv6_params lpm_ipv6; + } pp; + + struct pipeline *pipeline; + struct table *table; + struct table_action_profile *ap; + struct rte_table_action *action; + uint32_t table_id; + int status; + + memset(&p, 0, sizeof(p)); + memset(&pp, 0, sizeof(pp)); + + /* Check input params */ + if (pipeline_name == NULL || + params == NULL) + return -1; + + pipeline = pipeline_find(softnic, pipeline_name); + if (pipeline == NULL || + pipeline->n_tables >= RTE_PIPELINE_TABLE_MAX) + return -1; + + ap = NULL; + if (params->action_profile_name) { + ap = table_action_profile_find(softnic, + params->action_profile_name); + if (ap == NULL) + return -1; + } + + snprintf(name, NAME_MAX, "%s_%s_table%u", + softnic->params.name, pipeline_name, pipeline->n_tables); + + switch (params->match_type) { + case TABLE_ACL: + { + uint32_t ip_header_offset = params->match.acl.ip_header_offset - + (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM); + uint32_t i; + + if (params->match.acl.n_rules == 0) + return -1; + + pp.acl.name = name; + pp.acl.n_rules = params->match.acl.n_rules; + if (params->match.acl.ip_version) { + memcpy(&pp.acl.field_format, + &table_acl_field_format_ipv4, + sizeof(table_acl_field_format_ipv4)); + pp.acl.n_rule_fields = + RTE_DIM(table_acl_field_format_ipv4); + } else { + memcpy(&pp.acl.field_format, + &table_acl_field_format_ipv6, + sizeof(table_acl_field_format_ipv6)); + pp.acl.n_rule_fields = + RTE_DIM(table_acl_field_format_ipv6); + } + + for (i = 0; i < pp.acl.n_rule_fields; i++) + pp.acl.field_format[i].offset += ip_header_offset; + + p.ops = &rte_table_acl_ops; + p.arg_create = &pp.acl; + break; + } + + case TABLE_ARRAY: + { + if (params->match.array.n_keys == 0) + return -1; + + pp.array.n_entries = params->match.array.n_keys; + pp.array.offset = params->match.array.key_offset; + + p.ops = &rte_table_array_ops; + p.arg_create = &pp.array; + break; + } + + case TABLE_HASH: + { + struct rte_table_ops *ops; + rte_table_hash_op_hash f_hash; + + if (params->match.hash.n_keys == 0) + return -1; + + switch (params->match.hash.key_size) { + case 8: + f_hash = hash_default_key8; + break; + case 16: + f_hash = hash_default_key16; + break; + case 24: + f_hash = hash_default_key24; + break; + case 32: + f_hash = hash_default_key32; + break; + case 40: + f_hash = hash_default_key40; + break; + case 48: + f_hash = hash_default_key48; + break; + case 56: + f_hash = hash_default_key56; + break; + case 64: + f_hash = hash_default_key64; + break; + default: + return -1; + } + + pp.hash.name = name; + pp.hash.key_size = params->match.hash.key_size; + pp.hash.key_offset = params->match.hash.key_offset; + pp.hash.key_mask = params->match.hash.key_mask; + pp.hash.n_keys = params->match.hash.n_keys; + pp.hash.n_buckets = params->match.hash.n_buckets; + pp.hash.f_hash = f_hash; + pp.hash.seed = 0; + + if (params->match.hash.extendable_bucket) + switch (params->match.hash.key_size) { + case 8: + ops = &rte_table_hash_key8_ext_ops; + break; + case 16: + ops = &rte_table_hash_key16_ext_ops; + break; + default: + ops = &rte_table_hash_ext_ops; + } + else + switch (params->match.hash.key_size) { + case 8: + ops = &rte_table_hash_key8_lru_ops; + break; + case 16: + ops = &rte_table_hash_key16_lru_ops; + break; + default: + ops = &rte_table_hash_lru_ops; + } + + p.ops = ops; + p.arg_create = &pp.hash; + break; + } + + case TABLE_LPM: + { + if (params->match.lpm.n_rules == 0) + return -1; + + switch (params->match.lpm.key_size) { + case 4: + { + pp.lpm.name = name; + pp.lpm.n_rules = params->match.lpm.n_rules; + pp.lpm.number_tbl8s = TABLE_LPM_NUMBER_TBL8; + pp.lpm.flags = 0; + pp.lpm.entry_unique_size = p.action_data_size + + sizeof(struct rte_pipeline_table_entry); + pp.lpm.offset = params->match.lpm.key_offset; + + p.ops = &rte_table_lpm_ops; + p.arg_create = &pp.lpm; + break; + } + + case 16: + { + pp.lpm_ipv6.name = name; + pp.lpm_ipv6.n_rules = params->match.lpm.n_rules; + pp.lpm_ipv6.number_tbl8s = TABLE_LPM_NUMBER_TBL8; + pp.lpm_ipv6.entry_unique_size = p.action_data_size + + sizeof(struct rte_pipeline_table_entry); + pp.lpm_ipv6.offset = params->match.lpm.key_offset; + + p.ops = &rte_table_lpm_ipv6_ops; + p.arg_create = &pp.lpm_ipv6; + break; + } + + default: + return -1; + } + + break; + } + + case TABLE_STUB: + { + p.ops = &rte_table_stub_ops; + p.arg_create = NULL; + break; + } + + default: + return -1; + } + + /* Resource create */ + action = NULL; + p.f_action_hit = NULL; + p.f_action_miss = NULL; + p.arg_ah = NULL; + + if (ap) { + action = rte_table_action_create(ap->ap, + softnic->params.cpu_id); + if (action == NULL) + return -1; + + status = rte_table_action_table_params_get(action, + &p); + if (status || + ((p.action_data_size + + sizeof(struct rte_pipeline_table_entry)) > + TABLE_RULE_ACTION_SIZE_MAX)) { + rte_table_action_free(action); + return -1; + } + } + + if (params->match_type == TABLE_LPM) { + if (params->match.lpm.key_size == 4) + pp.lpm.entry_unique_size = p.action_data_size + + sizeof(struct rte_pipeline_table_entry); + + if (params->match.lpm.key_size == 16) + pp.lpm_ipv6.entry_unique_size = p.action_data_size + + sizeof(struct rte_pipeline_table_entry); + } + + status = rte_pipeline_table_create(pipeline->p, + &p, + &table_id); + if (status) { + rte_table_action_free(action); + return -1; + } + + /* Pipeline */ + table = &pipeline->table[pipeline->n_tables]; + memcpy(&table->params, params, sizeof(*params)); + table->ap = ap; + table->a = action; + pipeline->n_tables++; + + return 0; +} diff --git a/mk/rte.app.mk b/mk/rte.app.mk index a9d65d9..9889aee 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -34,8 +34,12 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_FLOW_CLASSIFY) += -lrte_flow_classify _LDLIBS-$(CONFIG_RTE_LIBRTE_PIPELINE) += --whole-archive _LDLIBS-$(CONFIG_RTE_LIBRTE_PIPELINE) += -lrte_pipeline _LDLIBS-$(CONFIG_RTE_LIBRTE_PIPELINE) += --no-whole-archive +_LDLIBS-$(CONFIG_RTE_LIBRTE_TABLE) += --whole-archive _LDLIBS-$(CONFIG_RTE_LIBRTE_TABLE) += -lrte_table +_LDLIBS-$(CONFIG_RTE_LIBRTE_TABLE) += --no-whole-archive +_LDLIBS-$(CONFIG_RTE_LIBRTE_PORT) += --whole-archive _LDLIBS-$(CONFIG_RTE_LIBRTE_PORT) += -lrte_port +_LDLIBS-$(CONFIG_RTE_LIBRTE_PORT) += --no-whole-archive _LDLIBS-$(CONFIG_RTE_LIBRTE_PDUMP) += -lrte_pdump _LDLIBS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += -lrte_distributor From patchwork Wed Jun 27 16:31:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41705 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 3FE851C1B3; Wed, 27 Jun 2018 18:32:03 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 0D0961C138 for ; Wed, 27 Jun 2018 18:31:39 +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:38 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789658" 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:37 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:10 +0100 Message-Id: <20180627163123.135686-11-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 10/23] net/softnic: add thread 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add thread data structure and init function to run softnic pipelines objects. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/Makefile | 1 + drivers/net/softnic/rte_eth_softnic.c | 8 +++ drivers/net/softnic/rte_eth_softnic_internals.h | 69 +++++++++++++++++++ drivers/net/softnic/rte_eth_softnic_thread.c | 90 +++++++++++++++++++++++++ 4 files changed, 168 insertions(+) create mode 100644 drivers/net/softnic/rte_eth_softnic_thread.c diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile index 2397fbd..d002062 100644 --- a/drivers/net/softnic/Makefile +++ b/drivers/net/softnic/Makefile @@ -31,6 +31,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tm.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tap.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_action.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_pipeline.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_thread.c # # Export include files diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c index 882cddb..a2782d7 100644 --- a/drivers/net/softnic/rte_eth_softnic.c +++ b/drivers/net/softnic/rte_eth_softnic.c @@ -223,6 +223,7 @@ static void * pmd_init(struct pmd_params *params) { struct pmd_internals *p; + int status; p = rte_zmalloc_socket(params->name, sizeof(struct pmd_internals), @@ -245,6 +246,12 @@ pmd_init(struct pmd_params *params) table_action_profile_init(p); pipeline_init(p); + status = thread_init(p); + if (status) { + rte_free(p); + return NULL; + } + return p; } @@ -254,6 +261,7 @@ pmd_free(struct pmd_internals *p) if (p == NULL) return; + thread_free(p); pipeline_free(p); table_action_profile_free(p); port_in_action_profile_free(p); diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index b90f6ae..6714c53 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -415,10 +415,68 @@ struct pipeline { TAILQ_HEAD(pipeline_list, pipeline); +/** + * Thread + */ +#ifndef THREAD_PIPELINES_MAX +#define THREAD_PIPELINES_MAX 256 +#endif + +#ifndef THREAD_MSGQ_SIZE +#define THREAD_MSGQ_SIZE 64 +#endif + +#ifndef THREAD_TIMER_PERIOD_MS +#define THREAD_TIMER_PERIOD_MS 100 +#endif + +/** + * Master thead: data plane thread context + */ +struct thread { + struct rte_ring *msgq_req; + struct rte_ring *msgq_rsp; + + uint32_t enabled; +}; + +/** + * Data plane threads: context + */ #ifndef TABLE_RULE_ACTION_SIZE_MAX #define TABLE_RULE_ACTION_SIZE_MAX 2048 #endif +struct table_data { + struct rte_table_action *a; +}; + +struct pipeline_data { + struct rte_pipeline *p; + struct table_data table_data[RTE_PIPELINE_TABLE_MAX]; + uint32_t n_tables; + + struct rte_ring *msgq_req; + struct rte_ring *msgq_rsp; + uint64_t timer_period; /* Measured in CPU cycles. */ + uint64_t time_next; + + uint8_t buffer[TABLE_RULE_ACTION_SIZE_MAX]; +}; + +struct thread_data { + struct rte_pipeline *p[THREAD_PIPELINES_MAX]; + uint32_t n_pipelines; + + struct pipeline_data pipeline_data[THREAD_PIPELINES_MAX]; + struct rte_ring *msgq_req; + struct rte_ring *msgq_rsp; + uint64_t timer_period; /* Measured in CPU cycles. */ + uint64_t time_next; + uint64_t time_next_min; + uint64_t iter; +} __rte_cache_aligned; + /** * PMD Internals */ @@ -438,6 +496,8 @@ struct pmd_internals { struct port_in_action_profile_list port_in_action_profile_list; struct table_action_profile_list table_action_profile_list; struct pipeline_list pipeline_list; + struct thread thread[RTE_MAX_LCORE]; + struct thread_data thread_data[RTE_MAX_LCORE]; }; /** @@ -626,4 +686,13 @@ pipeline_table_create(struct pmd_internals *p, const char *pipeline_name, struct table_params *params); +/** + * Thread + */ +int +thread_init(struct pmd_internals *p); + +void +thread_free(struct pmd_internals *p); + #endif /* __INCLUDE_RTE_ETH_SOFTNIC_INTERNALS_H__ */ diff --git a/drivers/net/softnic/rte_eth_softnic_thread.c b/drivers/net/softnic/rte_eth_softnic_thread.c new file mode 100644 index 0000000..4da1383 --- /dev/null +++ b/drivers/net/softnic/rte_eth_softnic_thread.c @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include + +#include +#include +#include + +#include "rte_eth_softnic_internals.h" + +/** + * Master thread: data plane thread init + */ +void +thread_free(struct pmd_internals *softnic) +{ + uint32_t i; + + RTE_LCORE_FOREACH_SLAVE(i) { + struct thread *t = &softnic->thread[i]; + + /* MSGQs */ + if (t->msgq_req) + rte_ring_free(t->msgq_req); + + if (t->msgq_rsp) + rte_ring_free(t->msgq_rsp); + } +} + +int +thread_init(struct pmd_internals *softnic) +{ + uint32_t i; + + RTE_LCORE_FOREACH_SLAVE(i) { + char ring_name[NAME_MAX]; + struct rte_ring *msgq_req, *msgq_rsp; + struct thread *t = &softnic->thread[i]; + struct thread_data *t_data = &softnic->thread_data[i]; + uint32_t cpu_id = rte_lcore_to_socket_id(i); + + /* MSGQs */ + snprintf(ring_name, sizeof(ring_name), "%s-TH%u-REQ", + softnic->params.name, + i); + + msgq_req = rte_ring_create(ring_name, + THREAD_MSGQ_SIZE, + cpu_id, + RING_F_SP_ENQ | RING_F_SC_DEQ); + + if (msgq_req == NULL) { + thread_free(softnic); + return -1; + } + + snprintf(ring_name, sizeof(ring_name), "%s-TH%u-RSP", + softnic->params.name, + i); + + msgq_rsp = rte_ring_create(ring_name, + THREAD_MSGQ_SIZE, + cpu_id, + RING_F_SP_ENQ | RING_F_SC_DEQ); + + if (msgq_rsp == NULL) { + thread_free(softnic); + return -1; + } + + /* Master thread records */ + t->msgq_req = msgq_req; + t->msgq_rsp = msgq_rsp; + t->enabled = 1; + + /* Data plane thread records */ + t_data->n_pipelines = 0; + t_data->msgq_req = msgq_req; + t_data->msgq_rsp = msgq_rsp; + t_data->timer_period = + (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000; + t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period; + t_data->time_next_min = t_data->time_next; + } + + return 0; +} From patchwork Wed Jun 27 16:31:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41706 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 9338B1C1B9; Wed, 27 Jun 2018 18:32:05 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id AFEC01C124 for ; Wed, 27 Jun 2018 18:31:40 +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:39 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789669" 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:38 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:11 +0100 Message-Id: <20180627163123.135686-12-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 11/23] net/softnic: add softnic run API 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Implements softnic API function to run pipeline objects. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/rte_eth_softnic.c | 13 -- drivers/net/softnic/rte_eth_softnic_thread.c | 195 +++++++++++++++++++++++++++ 2 files changed, 195 insertions(+), 13 deletions(-) diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c index a2782d7..aed3acd 100644 --- a/drivers/net/softnic/rte_eth_softnic.c +++ b/drivers/net/softnic/rte_eth_softnic.c @@ -206,19 +206,6 @@ pmd_tx_pkt_burst(void *txq, NULL); } -int -rte_pmd_softnic_run(uint16_t port_id) -{ - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - -#ifdef RTE_LIBRTE_ETHDEV_DEBUG - RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0); -#endif - - dev = dev; - return 0; -} - static void * pmd_init(struct pmd_params *params) { diff --git a/drivers/net/softnic/rte_eth_softnic_thread.c b/drivers/net/softnic/rte_eth_softnic_thread.c index 4da1383..e8c4916 100644 --- a/drivers/net/softnic/rte_eth_softnic_thread.c +++ b/drivers/net/softnic/rte_eth_softnic_thread.c @@ -88,3 +88,198 @@ thread_init(struct pmd_internals *softnic) return 0; } + +/** + * Master thread & data plane threads: message passing + */ +enum thread_req_type { + THREAD_REQ_MAX +}; + +struct thread_msg_req { + enum thread_req_type type; +}; + +struct thread_msg_rsp { + int status; +}; + +/** + * Data plane threads: message handling + */ +static inline struct thread_msg_req * +thread_msg_recv(struct rte_ring *msgq_req) +{ + struct thread_msg_req *req; + + int status = rte_ring_sc_dequeue(msgq_req, (void **)&req); + + if (status != 0) + return NULL; + + return req; +} + +static inline void +thread_msg_send(struct rte_ring *msgq_rsp, + struct thread_msg_rsp *rsp) +{ + int status; + + do { + status = rte_ring_sp_enqueue(msgq_rsp, rsp); + } while (status == -ENOBUFS); +} + +static void +thread_msg_handle(struct thread_data *t) +{ + for ( ; ; ) { + struct thread_msg_req *req; + struct thread_msg_rsp *rsp; + + req = thread_msg_recv(t->msgq_req); + if (req == NULL) + break; + + switch (req->type) { + default: + rsp = (struct thread_msg_rsp *)req; + rsp->status = -1; + } + + thread_msg_send(t->msgq_rsp, rsp); + } +} + +/** + * Master thread & data plane threads: message passing + */ +enum pipeline_req_type { + PIPELINE_REQ_MAX +}; + +struct pipeline_msg_req { + enum pipeline_req_type type; +}; + +struct pipeline_msg_rsp { + int status; +}; + +/** + * Data plane threads: message handling + */ +static inline struct pipeline_msg_req * +pipeline_msg_recv(struct rte_ring *msgq_req) +{ + struct pipeline_msg_req *req; + + int status = rte_ring_sc_dequeue(msgq_req, (void **)&req); + + if (status != 0) + return NULL; + + return req; +} + +static inline void +pipeline_msg_send(struct rte_ring *msgq_rsp, + struct pipeline_msg_rsp *rsp) +{ + int status; + + do { + status = rte_ring_sp_enqueue(msgq_rsp, rsp); + } while (status == -ENOBUFS); +} + +static void +pipeline_msg_handle(struct pipeline_data *p) +{ + for ( ; ; ) { + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + + req = pipeline_msg_recv(p->msgq_req); + if (req == NULL) + break; + + switch (req->type) { + default: + rsp = (struct pipeline_msg_rsp *)req; + rsp->status = -1; + } + + pipeline_msg_send(p->msgq_rsp, rsp); + } +} + +/** + * Data plane threads: main + */ +int +rte_pmd_softnic_run(uint16_t port_id) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + struct pmd_internals *softnic; + struct thread_data *t; + uint32_t thread_id, j; + +#ifdef RTE_LIBRTE_ETHDEV_DEBUG + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0); +#endif + + softnic = dev->data->dev_private; + thread_id = rte_lcore_id(); + t = &softnic->thread_data[thread_id]; + t->iter++; + + /* Data Plane */ + for (j = 0; j < t->n_pipelines; j++) + rte_pipeline_run(t->p[j]); + + /* Control Plane */ + if ((t->iter & 0xFLLU) == 0) { + uint64_t time = rte_get_tsc_cycles(); + uint64_t time_next_min = UINT64_MAX; + + if (time < t->time_next_min) + return 0; + + /* Pipeline message queues */ + for (j = 0; j < t->n_pipelines; j++) { + struct pipeline_data *p = + &t->pipeline_data[j]; + uint64_t time_next = p->time_next; + + if (time_next <= time) { + pipeline_msg_handle(p); + rte_pipeline_flush(p->p); + time_next = time + p->timer_period; + p->time_next = time_next; + } + + if (time_next < time_next_min) + time_next_min = time_next; + } + + /* Thread message queues */ + { + uint64_t time_next = t->time_next; + + if (time_next <= time) { + thread_msg_handle(t); + time_next = time + t->timer_period; + t->time_next = time_next; + } + + if (time_next < time_next_min) + time_next_min = time_next; + } + + t->time_next_min = time_next_min; + } + + return 0; +} From patchwork Wed Jun 27 16:31:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41707 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 7C3CC1C1BF; Wed, 27 Jun 2018 18:32:07 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 793E41C190 for ; Wed, 27 Jun 2018 18:31:41 +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:41 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789676" 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:39 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:12 +0100 Message-Id: <20180627163123.135686-13-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 12/23] net/softnic: add cli interface 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add interface for softnic cli commands. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/Makefile | 2 + drivers/net/softnic/parser.c | 685 ++++++++++++++++++++++++ drivers/net/softnic/parser.h | 66 +++ drivers/net/softnic/rte_eth_softnic_cli.c | 119 ++++ drivers/net/softnic/rte_eth_softnic_internals.h | 15 + 5 files changed, 887 insertions(+) create mode 100644 drivers/net/softnic/parser.c create mode 100644 drivers/net/softnic/parser.h create mode 100644 drivers/net/softnic/rte_eth_softnic_cli.c diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile index d002062..cb95414 100644 --- a/drivers/net/softnic/Makefile +++ b/drivers/net/softnic/Makefile @@ -32,6 +32,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tap.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_action.c 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 # # Export include files diff --git a/drivers/net/softnic/parser.c b/drivers/net/softnic/parser.c new file mode 100644 index 0000000..7087b87 --- /dev/null +++ b/drivers/net/softnic/parser.c @@ -0,0 +1,685 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2016 Intel Corporation. + * Copyright (c) 2009, Olivier MATZ + * All rights reserved. + */ + +/* For inet_pton4() and inet_pton6() functions: + * + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "parser.h" + +static uint32_t +get_hex_val(char c) +{ + switch (c) { + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + return c - '0'; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + return c - 'A' + 10; + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return c - 'a' + 10; + default: + return 0; + } +} + +int +softnic_parser_read_arg_bool(const char *p) +{ + p = skip_white_spaces(p); + int result = -EINVAL; + + if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) || + ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) { + p += 3; + result = 1; + } + + if (((p[0] == 'o') && (p[1] == 'n')) || + ((p[0] == 'O') && (p[1] == 'N'))) { + p += 2; + result = 1; + } + + if (((p[0] == 'n') && (p[1] == 'o')) || + ((p[0] == 'N') && (p[1] == 'O'))) { + p += 2; + result = 0; + } + + if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) || + ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) { + p += 3; + result = 0; + } + + p = skip_white_spaces(p); + + if (p[0] != '\0') + return -EINVAL; + + return result; +} + +int +softnic_parser_read_uint64(uint64_t *value, const char *p) +{ + char *next; + uint64_t val; + + p = skip_white_spaces(p); + if (!isdigit(*p)) + return -EINVAL; + + val = strtoul(p, &next, 10); + if (p == next) + return -EINVAL; + + p = next; + switch (*p) { + case 'T': + val *= 1024ULL; + /* fall through */ + case 'G': + val *= 1024ULL; + /* fall through */ + case 'M': + val *= 1024ULL; + /* fall through */ + case 'k': + case 'K': + val *= 1024ULL; + p++; + break; + } + + p = skip_white_spaces(p); + if (*p != '\0') + return -EINVAL; + + *value = val; + return 0; +} + +int +softnic_parser_read_uint64_hex(uint64_t *value, const char *p) +{ + char *next; + uint64_t val; + + p = skip_white_spaces(p); + + val = strtoul(p, &next, 16); + if (p == next) + return -EINVAL; + + p = skip_white_spaces(next); + if (*p != '\0') + return -EINVAL; + + *value = val; + return 0; +} + +int +softnic_parser_read_uint32(uint32_t *value, const char *p) +{ + uint64_t val = 0; + int ret = softnic_parser_read_uint64(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT32_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +softnic_parser_read_uint32_hex(uint32_t *value, const char *p) +{ + uint64_t val = 0; + int ret = softnic_parser_read_uint64_hex(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT32_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +softnic_parser_read_uint16(uint16_t *value, const char *p) +{ + uint64_t val = 0; + int ret = softnic_parser_read_uint64(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT16_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +softnic_parser_read_uint16_hex(uint16_t *value, const char *p) +{ + uint64_t val = 0; + int ret = softnic_parser_read_uint64_hex(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT16_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +softnic_parser_read_uint8(uint8_t *value, const char *p) +{ + uint64_t val = 0; + int ret = softnic_parser_read_uint64(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT8_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +softnic_parser_read_uint8_hex(uint8_t *value, const char *p) +{ + uint64_t val = 0; + int ret = softnic_parser_read_uint64_hex(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT8_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +softnic_parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens) +{ + uint32_t i; + + if (string == NULL || + tokens == NULL || + (*n_tokens < 1)) + return -EINVAL; + + for (i = 0; i < *n_tokens; i++) { + tokens[i] = strtok_r(string, PARSE_DELIMITER, &string); + if (tokens[i] == NULL) + break; + } + + if (i == *n_tokens && + strtok_r(string, PARSE_DELIMITER, &string) != NULL) + return -E2BIG; + + *n_tokens = i; + return 0; +} + +int +softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size) +{ + char *c; + uint32_t len, i; + + /* Check input parameters */ + if (src == NULL || + dst == NULL || + size == NULL || + (*size == 0)) + return -1; + + len = strlen(src); + if (((len & 3) != 0) || + (len > (*size) * 2)) + return -1; + *size = len / 2; + + for (c = src; *c != 0; c++) { + if ((((*c) >= '0') && ((*c) <= '9')) || + (((*c) >= 'A') && ((*c) <= 'F')) || + (((*c) >= 'a') && ((*c) <= 'f'))) + continue; + + return -1; + } + + /* Convert chars to bytes */ + for (i = 0; i < *size; i++) + dst[i] = get_hex_val(src[2 * i]) * 16 + + get_hex_val(src[2 * i + 1]); + + return 0; +} + +int +softnic_parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels) +{ + uint32_t n_max_labels = *n_labels, count = 0; + + /* Check for void list of labels */ + if (strcmp(string, "") == 0) { + *n_labels = 0; + return 0; + } + + /* At least one label should be present */ + for ( ; (*string != '\0'); ) { + char *next; + int value; + + if (count >= n_max_labels) + return -1; + + if (count > 0) { + if (string[0] != ':') + return -1; + + string++; + } + + value = strtol(string, &next, 10); + if (next == string) + return -1; + string = next; + + labels[count++] = (uint32_t)value; + } + + *n_labels = count; + return 0; +} + +#define INADDRSZ 4 +#define IN6ADDRSZ 16 + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(const char *src, unsigned char *dst) +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + unsigned char tmp[INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + pch = strchr(digits, ch); + if (pch != NULL) { + unsigned int new = *tp * 10 + (pch - digits); + + if (new > 255) + return 0; + if (!saw_digit) { + if (++octets > 4) + return 0; + saw_digit = 1; + } + *tp = (unsigned char)new; + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return 0; + *++tp = 0; + saw_digit = 0; + } else + return 0; + } + if (octets < 4) + return 0; + + memcpy(dst, tmp, INADDRSZ); + return 1; +} + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(const char *src, unsigned char *dst) +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0; + const char *xdigits = 0, *curtok = 0; + int ch = 0, saw_xdigit = 0, count_xdigit = 0; + unsigned int val = 0; + unsigned int dbloct_count = 0; + + memset((tp = tmp), '\0', IN6ADDRSZ); + endp = tp + IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return 0; + curtok = src; + saw_xdigit = count_xdigit = 0; + val = 0; + + while ((ch = *src++) != '\0') { + const char *pch; + + pch = strchr((xdigits = xdigits_l), ch); + if (pch == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + if (count_xdigit >= 4) + return 0; + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return 0; + saw_xdigit = 1; + count_xdigit++; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return 0; + colonp = tp; + continue; + } else if (*src == '\0') { + return 0; + } + if (tp + sizeof(int16_t) > endp) + return 0; + *tp++ = (unsigned char)((val >> 8) & 0xff); + *tp++ = (unsigned char)(val & 0xff); + saw_xdigit = 0; + count_xdigit = 0; + val = 0; + dbloct_count++; + continue; + } + if (ch == '.' && ((tp + INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += INADDRSZ; + saw_xdigit = 0; + dbloct_count += 2; + break; /* '\0' was seen by inet_pton4(). */ + } + return 0; + } + if (saw_xdigit) { + if (tp + sizeof(int16_t) > endp) + return 0; + *tp++ = (unsigned char)((val >> 8) & 0xff); + *tp++ = (unsigned char)(val & 0xff); + dbloct_count++; + } + if (colonp != NULL) { + /* if we already have 8 double octets, having a colon means error */ + if (dbloct_count == 8) + return 0; + + /* Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + for (i = 1; i <= n; i++) { + endp[-i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return 0; + memcpy(dst, tmp, IN6ADDRSZ); + return 1; +} + +static struct ether_addr * +my_ether_aton(const char *a) +{ + int i; + char *end; + unsigned long o[ETHER_ADDR_LEN]; + static struct ether_addr ether_addr; + + i = 0; + do { + errno = 0; + o[i] = strtoul(a, &end, 16); + if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0)) + return NULL; + a = end + 1; + } while (++i != sizeof(o) / sizeof(o[0]) && end[0] != 0); + + /* Junk at the end of line */ + if (end[0] != 0) + return NULL; + + /* Support the format XX:XX:XX:XX:XX:XX */ + if (i == ETHER_ADDR_LEN) { + while (i-- != 0) { + if (o[i] > UINT8_MAX) + return NULL; + ether_addr.addr_bytes[i] = (uint8_t)o[i]; + } + /* Support the format XXXX:XXXX:XXXX */ + } else if (i == ETHER_ADDR_LEN / 2) { + while (i-- != 0) { + if (o[i] > UINT16_MAX) + return NULL; + ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8); + ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff); + } + /* unknown format */ + } else + return NULL; + + return (struct ether_addr *)ðer_addr; +} + +int +softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4) +{ + if (strlen(token) >= INET_ADDRSTRLEN) + return -EINVAL; + + if (inet_pton4(token, (unsigned char *)ipv4) != 1) + return -EINVAL; + + return 0; +} + +int +softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6) +{ + if (strlen(token) >= INET6_ADDRSTRLEN) + return -EINVAL; + + if (inet_pton6(token, (unsigned char *)ipv6) != 1) + return -EINVAL; + + return 0; +} + +int +softnic_parse_mac_addr(const char *token, struct ether_addr *addr) +{ + struct ether_addr *tmp; + + tmp = my_ether_aton(token); + if (tmp == NULL) + return -1; + + memcpy(addr, tmp, sizeof(struct ether_addr)); + return 0; +} + +int +softnic_parse_cpu_core(const char *entry, + struct softnic_cpu_core_params *p) +{ + size_t num_len; + char num[8]; + + uint32_t s = 0, c = 0, h = 0, val; + uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0; + const char *next = skip_white_spaces(entry); + char type; + + if (p == NULL) + return -EINVAL; + + /* Expect or [sX][cY][h]. At least one parameter is required. */ + while (*next != '\0') { + /* If everything parsed nothing should left */ + if (s_parsed && c_parsed && h_parsed) + return -EINVAL; + + type = *next; + switch (type) { + case 's': + case 'S': + if (s_parsed || c_parsed || h_parsed) + return -EINVAL; + s_parsed = 1; + next++; + break; + case 'c': + case 'C': + if (c_parsed || h_parsed) + return -EINVAL; + c_parsed = 1; + next++; + break; + case 'h': + case 'H': + if (h_parsed) + return -EINVAL; + h_parsed = 1; + next++; + break; + default: + /* If it start from digit it must be only core id. */ + if (!isdigit(*next) || s_parsed || c_parsed || h_parsed) + return -EINVAL; + + type = 'C'; + } + + for (num_len = 0; *next != '\0'; next++, num_len++) { + if (num_len == RTE_DIM(num)) + return -EINVAL; + + if (!isdigit(*next)) + break; + + num[num_len] = *next; + } + + if (num_len == 0 && type != 'h' && type != 'H') + return -EINVAL; + + if (num_len != 0 && (type == 'h' || type == 'H')) + return -EINVAL; + + num[num_len] = '\0'; + val = strtol(num, NULL, 10); + + h = 0; + switch (type) { + case 's': + case 'S': + s = val; + break; + case 'c': + case 'C': + c = val; + break; + case 'h': + case 'H': + h = 1; + break; + } + } + + p->socket_id = s; + p->core_id = c; + p->thread_id = h; + return 0; +} diff --git a/drivers/net/softnic/parser.h b/drivers/net/softnic/parser.h new file mode 100644 index 0000000..5ab4763 --- /dev/null +++ b/drivers/net/softnic/parser.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2016 Intel Corporation + */ + +#ifndef __INCLUDE_SOFTNIC_PARSER_H__ +#define __INCLUDE_SOFTNIC_PARSER_H__ + +#include + +#include +#include + +#define PARSE_DELIMITER " \f\n\r\t\v" + +#define skip_white_spaces(pos) \ +({ \ + __typeof__(pos) _p = (pos); \ + for ( ; isspace(*_p); _p++) \ + ; \ + _p; \ +}) + +static inline size_t +skip_digits(const char *src) +{ + size_t i; + + for (i = 0; isdigit(src[i]); i++) + ; + + return i; +} + +int softnic_parser_read_arg_bool(const char *p); + +int softnic_parser_read_uint64(uint64_t *value, const char *p); +int softnic_parser_read_uint32(uint32_t *value, const char *p); +int softnic_parser_read_uint16(uint16_t *value, const char *p); +int softnic_parser_read_uint8(uint8_t *value, const char *p); + +int softnic_parser_read_uint64_hex(uint64_t *value, const char *p); +int softnic_parser_read_uint32_hex(uint32_t *value, const char *p); +int softnic_parser_read_uint16_hex(uint16_t *value, const char *p); +int softnic_parser_read_uint8_hex(uint8_t *value, const char *p); + +int softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size); + +int softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4); +int softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6); +int softnic_parse_mac_addr(const char *token, struct ether_addr *addr); +int softnic_parse_mpls_labels(char *string, + uint32_t *labels, uint32_t *n_labels); + +struct softnic_cpu_core_params { + uint32_t socket_id; + uint32_t core_id; + uint32_t thread_id; +}; + +int softnic_parse_cpu_core(const char *entry, + struct softnic_cpu_core_params *p); + +int softnic_parse_tokenize_string(char *string, + char *tokens[], uint32_t *n_tokens); + +#endif diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c new file mode 100644 index 0000000..00b9daa --- /dev/null +++ b/drivers/net/softnic/rte_eth_softnic_cli.c @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include +#include +#include +#include + +#include "rte_eth_softnic_internals.h" +#include "parser.h" + +#ifndef CMD_MAX_TOKENS +#define CMD_MAX_TOKENS 256 +#endif + +#define MSG_OUT_OF_MEMORY "Not enough memory.\n" +#define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n" +#define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n" +#define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n" +#define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n" +#define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n" +#define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n" +#define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n" +#define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n" +#define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n" +#define MSG_CMD_FAIL "Command \"%s\" failed.\n" + +static int +is_comment(char *in) +{ + if ((strlen(in) && index("!#%;", in[0])) || + (strncmp(in, "//", 2) == 0) || + (strncmp(in, "--", 2) == 0)) + return 1; + + return 0; +} + +void +cli_process(char *in, char *out, size_t out_size, void *arg) +{ + char *tokens[CMD_MAX_TOKENS]; + uint32_t n_tokens = RTE_DIM(tokens); + int status; + + arg = arg; + + if (is_comment(in)) + return; + + status = softnic_parse_tokenize_string(in, tokens, &n_tokens); + if (status) { + snprintf(out, out_size, MSG_ARG_TOO_MANY, ""); + return; + } + + if (n_tokens == 0) + return; + + snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); +} + +int +cli_script_process(struct pmd_internals *softnic, + const char *file_name, + size_t msg_in_len_max, + size_t msg_out_len_max) +{ + char *msg_in = NULL, *msg_out = NULL; + FILE *f = NULL; + + /* Check input arguments */ + if (file_name == NULL || + strlen(file_name) == 0 || + msg_in_len_max == 0 || + msg_out_len_max == 0) + return -EINVAL; + + msg_in = malloc(msg_in_len_max + 1); + msg_out = malloc(msg_out_len_max + 1); + if (msg_in == NULL || + msg_out == NULL) { + free(msg_out); + free(msg_in); + return -ENOMEM; + } + + /* Open input file */ + f = fopen(file_name, "r"); + if (f == NULL) { + free(msg_out); + free(msg_in); + return -EIO; + } + + /* Read file */ + for ( ; ; ) { + if (fgets(msg_in, msg_in_len_max + 1, f) == NULL) + break; + + printf("%s", msg_in); + msg_out[0] = 0; + + cli_process(msg_in, + msg_out, + msg_out_len_max, + softnic); + + if (strlen(msg_out)) + printf("%s", msg_out); + } + + /* Close file */ + fclose(f); + free(msg_out); + free(msg_in); + return 0; +} diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index 6714c53..5d38f2f 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -695,4 +695,19 @@ thread_init(struct pmd_internals *p); void thread_free(struct pmd_internals *p); +/** + * CLI + */ +void +cli_process(char *in, + char *out, + size_t out_size, + void *arg); + +int +cli_script_process(struct pmd_internals *softnic, + const char *file_name, + size_t msg_in_len_max, + size_t msg_out_len_max); + #endif /* __INCLUDE_RTE_ETH_SOFTNIC_INTERNALS_H__ */ From patchwork Wed Jun 27 16:31:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41708 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 6892B1C1CE; Wed, 27 Jun 2018 18:32:09 +0200 (CEST) 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 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; +}; From patchwork Wed Jun 27 16:31:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41709 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 398631C1D2; Wed, 27 Jun 2018 18:32:11 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 57A461C199 for ; Wed, 27 Jun 2018 18:31:47 +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:46 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789704" 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:42 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:14 +0100 Message-Id: <20180627163123.135686-15-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 14/23] net/softnic: add cli to create softnic objects 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add cli commands to create softnic objects such as mempool, swq, pipeline, etc. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/rte_eth_softnic_cli.c | 1646 ++++++++++++++++++++++- drivers/net/softnic/rte_eth_softnic_internals.h | 85 ++ drivers/net/softnic/rte_eth_softnic_thread.c | 165 +++ 3 files changed, 1894 insertions(+), 2 deletions(-) diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c index 00b9daa..a0d715b 100644 --- a/drivers/net/softnic/rte_eth_softnic_cli.c +++ b/drivers/net/softnic/rte_eth_softnic_cli.c @@ -37,15 +37,1569 @@ is_comment(char *in) return 0; } +/** + * mempool + * buffer + * pool + * cache + */ +static void +cmd_mempool(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct mempool_params p; + char *name; + struct mempool *mempool; + + if (n_tokens != 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + name = tokens[1]; + + if (strcmp(tokens[2], "buffer") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer"); + return; + } + + if (softnic_parser_read_uint32(&p.buffer_size, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size"); + return; + } + + if (strcmp(tokens[4], "pool") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool"); + return; + } + + if (softnic_parser_read_uint32(&p.pool_size, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "pool_size"); + return; + } + + if (strcmp(tokens[6], "cache") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache"); + return; + } + + if (softnic_parser_read_uint32(&p.cache_size, tokens[7]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "cache_size"); + return; + } + + mempool = mempool_create(softnic, name, &p); + if (mempool == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +/** + * link + * dev | port + */ +static void +cmd_link(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct link_params p; + struct link *link; + char *name; + + memset(&p, 0, sizeof(p)); + + if (n_tokens != 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + name = tokens[1]; + + if (strcmp(tokens[2], "dev") == 0) { + p.dev_name = tokens[3]; + } else if (strcmp(tokens[2], "port") == 0) { + p.dev_name = NULL; + + if (softnic_parser_read_uint16(&p.port_id, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port"); + return; + } + + link = link_create(softnic, name, &p); + if (link == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +/** + * swq + * size + */ +static void +cmd_swq(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct swq_params p; + char *name; + struct swq *swq; + + if (n_tokens != 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + name = tokens[1]; + + if (strcmp(tokens[2], "size") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); + return; + } + + if (softnic_parser_read_uint32(&p.size, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "size"); + return; + } + + swq = swq_create(softnic, name, &p); + if (swq == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +/** + * tap + */ +static void +cmd_tap(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *name; + struct tap *tap; + + if (n_tokens != 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + name = tokens[1]; + + tap = tap_create(softnic, name); + if (tap == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +/** + * port in action profile + * [filter match | mismatch offset mask key port ] + * [balance offset mask port ... ] + */ +static void +cmd_port_in_action_profile(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct port_in_action_profile_params p; + struct port_in_action_profile *ap; + char *name; + uint32_t t0; + + memset(&p, 0, sizeof(p)); + + if (n_tokens < 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (strcmp(tokens[1], "in") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); + return; + } + + if (strcmp(tokens[2], "action") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action"); + return; + } + + if (strcmp(tokens[3], "profile") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); + return; + } + + name = tokens[4]; + + t0 = 5; + + if (t0 < n_tokens && + (strcmp(tokens[t0], "filter") == 0)) { + uint32_t size; + + if (n_tokens < t0 + 10) { + snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter"); + return; + } + + if (strcmp(tokens[t0 + 1], "match") == 0) { + p.fltr.filter_on_match = 1; + } else if (strcmp(tokens[t0 + 1], "mismatch") == 0) { + p.fltr.filter_on_match = 0; + } else { + snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch"); + return; + } + + if (strcmp(tokens[t0 + 2], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (softnic_parser_read_uint32(&p.fltr.key_offset, + tokens[t0 + 3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); + return; + } + + if (strcmp(tokens[t0 + 4], "mask") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); + return; + } + + size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE; + if ((softnic_parse_hex_string(tokens[t0 + 5], + p.fltr.key_mask, &size) != 0) || + size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); + return; + } + + if (strcmp(tokens[t0 + 6], "key") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key"); + return; + } + + size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE; + if ((softnic_parse_hex_string(tokens[t0 + 7], + p.fltr.key, &size) != 0) || + size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_value"); + return; + } + + if (strcmp(tokens[t0 + 8], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (softnic_parser_read_uint32(&p.fltr.port_id, + tokens[t0 + 9]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + + p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR; + t0 += 10; + } /* filter */ + + if (t0 < n_tokens && + (strcmp(tokens[t0], "balance") == 0)) { + uint32_t i; + + if (n_tokens < t0 + 22) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "port in action profile balance"); + return; + } + + if (strcmp(tokens[t0 + 1], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (softnic_parser_read_uint32(&p.lb.key_offset, + tokens[t0 + 2]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); + return; + } + + if (strcmp(tokens[t0 + 3], "mask") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); + return; + } + + p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX; + if (softnic_parse_hex_string(tokens[t0 + 4], + p.lb.key_mask, &p.lb.key_size) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); + return; + } + + if (strcmp(tokens[t0 + 5], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + for (i = 0; i < 16; i++) + if (softnic_parser_read_uint32(&p.lb.port_id[i], + tokens[t0 + 6 + i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + + p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB; + t0 += 22; + } /* balance */ + + if (t0 < n_tokens) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + ap = port_in_action_profile_create(softnic, name, &p); + if (ap == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +/** + * table action profile + * ipv4 | ipv6 + * offset + * fwd + * [balance offset mask outoffset ] + * [meter srtcm | trtcm + * tc + * stats none | pkts | bytes | both] + * [tm spp pps ] + * [encap ether | vlan | qinq | mpls | pppoe] + * [nat src | dst + * proto udp | tcp] + * [ttl drop | fwd + * stats none | pkts] + * [stats pkts | bytes | both] + * [time] + */ +static void +cmd_table_action_profile(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct table_action_profile_params p; + struct table_action_profile *ap; + char *name; + uint32_t t0; + + memset(&p, 0, sizeof(p)); + + if (n_tokens < 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (strcmp(tokens[1], "action") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action"); + return; + } + + if (strcmp(tokens[2], "profile") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); + return; + } + + name = tokens[3]; + + if (strcmp(tokens[4], "ipv4") == 0) { + p.common.ip_version = 1; + } else if (strcmp(tokens[4], "ipv6") == 0) { + p.common.ip_version = 0; + } else { + snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6"); + return; + } + + if (strcmp(tokens[5], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (softnic_parser_read_uint32(&p.common.ip_offset, + tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset"); + return; + } + + if (strcmp(tokens[7], "fwd") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD; + + t0 = 8; + if (t0 < n_tokens && + (strcmp(tokens[t0], "balance") == 0)) { + if (n_tokens < t0 + 7) { + snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance"); + return; + } + + if (strcmp(tokens[t0 + 1], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (softnic_parser_read_uint32(&p.lb.key_offset, + tokens[t0 + 2]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); + return; + } + + if (strcmp(tokens[t0 + 3], "mask") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); + return; + } + + p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX; + if (softnic_parse_hex_string(tokens[t0 + 4], + p.lb.key_mask, &p.lb.key_size) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); + return; + } + + if (strcmp(tokens[t0 + 5], "outoffset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset"); + return; + } + + if (softnic_parser_read_uint32(&p.lb.out_offset, + tokens[t0 + 6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "out_offset"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB; + t0 += 7; + } /* balance */ + + if (t0 < n_tokens && + (strcmp(tokens[t0], "meter") == 0)) { + if (n_tokens < t0 + 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "table action profile meter"); + return; + } + + if (strcmp(tokens[t0 + 1], "srtcm") == 0) { + p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM; + } else if (strcmp(tokens[t0 + 1], "trtcm") == 0) { + p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM; + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "srtcm or trtcm"); + return; + } + + if (strcmp(tokens[t0 + 2], "tc") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc"); + return; + } + + if (softnic_parser_read_uint32(&p.mtr.n_tc, + tokens[t0 + 3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_tc"); + return; + } + + if (strcmp(tokens[t0 + 4], "stats") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); + return; + } + + if (strcmp(tokens[t0 + 5], "none") == 0) { + p.mtr.n_packets_enabled = 0; + p.mtr.n_bytes_enabled = 0; + } else if (strcmp(tokens[t0 + 5], "pkts") == 0) { + p.mtr.n_packets_enabled = 1; + p.mtr.n_bytes_enabled = 0; + } else if (strcmp(tokens[t0 + 5], "bytes") == 0) { + p.mtr.n_packets_enabled = 0; + p.mtr.n_bytes_enabled = 1; + } else if (strcmp(tokens[t0 + 5], "both") == 0) { + p.mtr.n_packets_enabled = 1; + p.mtr.n_bytes_enabled = 1; + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "none or pkts or bytes or both"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR; + t0 += 6; + } /* meter */ + + if (t0 < n_tokens && + (strcmp(tokens[t0], "tm") == 0)) { + if (n_tokens < t0 + 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "table action profile tm"); + return; + } + + if (strcmp(tokens[t0 + 1], "spp") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp"); + return; + } + + if (softnic_parser_read_uint32(&p.tm.n_subports_per_port, + tokens[t0 + 2]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "n_subports_per_port"); + return; + } + + if (strcmp(tokens[t0 + 3], "pps") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); + return; + } + + if (softnic_parser_read_uint32(&p.tm.n_pipes_per_subport, + tokens[t0 + 4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "n_pipes_per_subport"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM; + t0 += 5; + } /* tm */ + + if (t0 < n_tokens && + (strcmp(tokens[t0], "encap") == 0)) { + if (n_tokens < t0 + 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "action profile encap"); + return; + } + + if (strcmp(tokens[t0 + 1], "ether") == 0) { + p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER; + } else if (strcmp(tokens[t0 + 1], "vlan") == 0) { + p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN; + } else if (strcmp(tokens[t0 + 1], "qinq") == 0) { + p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ; + } else if (strcmp(tokens[t0 + 1], "mpls") == 0) { + p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS; + } else if (strcmp(tokens[t0 + 1], "pppoe") == 0) { + p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE; + } else { + snprintf(out, out_size, MSG_ARG_MISMATCH, "encap"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP; + t0 += 2; + } /* encap */ + + if (t0 < n_tokens && + (strcmp(tokens[t0], "nat") == 0)) { + if (n_tokens < t0 + 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "table action profile nat"); + return; + } + + if (strcmp(tokens[t0 + 1], "src") == 0) { + p.nat.source_nat = 1; + } else if (strcmp(tokens[t0 + 1], "dst") == 0) { + p.nat.source_nat = 0; + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "src or dst"); + return; + } + + if (strcmp(tokens[t0 + 2], "proto") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto"); + return; + } + + if (strcmp(tokens[t0 + 3], "tcp") == 0) { + p.nat.proto = 0x06; + } else if (strcmp(tokens[t0 + 3], "udp") == 0) { + p.nat.proto = 0x11; + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "tcp or udp"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT; + t0 += 4; + } /* nat */ + + if (t0 < n_tokens && + (strcmp(tokens[t0], "ttl") == 0)) { + if (n_tokens < t0 + 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "table action profile ttl"); + return; + } + + if (strcmp(tokens[t0 + 1], "drop") == 0) { + p.ttl.drop = 1; + } else if (strcmp(tokens[t0 + 1], "fwd") == 0) { + p.ttl.drop = 0; + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "drop or fwd"); + return; + } + + if (strcmp(tokens[t0 + 2], "stats") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); + return; + } + + if (strcmp(tokens[t0 + 3], "none") == 0) { + p.ttl.n_packets_enabled = 0; + } else if (strcmp(tokens[t0 + 3], "pkts") == 0) { + p.ttl.n_packets_enabled = 1; + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "none or pkts"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL; + t0 += 4; + } /* ttl */ + + if (t0 < n_tokens && + (strcmp(tokens[t0], "stats") == 0)) { + if (n_tokens < t0 + 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "table action profile stats"); + return; + } + + if (strcmp(tokens[t0 + 1], "pkts") == 0) { + p.stats.n_packets_enabled = 1; + p.stats.n_bytes_enabled = 0; + } else if (strcmp(tokens[t0 + 1], "bytes") == 0) { + p.stats.n_packets_enabled = 0; + p.stats.n_bytes_enabled = 1; + } else if (strcmp(tokens[t0 + 1], "both") == 0) { + p.stats.n_packets_enabled = 1; + p.stats.n_bytes_enabled = 1; + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "pkts or bytes or both"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS; + t0 += 2; + } /* stats */ + + if (t0 < n_tokens && + (strcmp(tokens[t0], "time") == 0)) { + p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME; + t0 += 1; + } /* time */ + + if (t0 < n_tokens) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + ap = table_action_profile_create(softnic, name, &p); + if (ap == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +/** + * pipeline + * period + * offset_port_id + */ +static void +cmd_pipeline(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct pipeline_params p; + char *name; + struct pipeline *pipeline; + + if (n_tokens != 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + name = tokens[1]; + + if (strcmp(tokens[2], "period") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period"); + return; + } + + if (softnic_parser_read_uint32(&p.timer_period_ms, + tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms"); + return; + } + + if (strcmp(tokens[4], "offset_port_id") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id"); + return; + } + + if (softnic_parser_read_uint32(&p.offset_port_id, + tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id"); + return; + } + + pipeline = pipeline_create(softnic, name, &p); + if (pipeline == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +/** + * pipeline port in + * bsz + * link rxq + * | swq + * | tmgr + * | tap mempool mtu + * | source mempool file bpp + * [action ] + * [disabled] + */ +static void +cmd_pipeline_port_in(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct port_in_params p; + char *pipeline_name; + uint32_t t0; + int enabled, status; + + if (n_tokens < 7) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (strcmp(tokens[3], "in") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); + return; + } + + if (strcmp(tokens[4], "bsz") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); + return; + } + + if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "burst_size"); + return; + } + + t0 = 6; + + if (strcmp(tokens[t0], "link") == 0) { + if (n_tokens < t0 + 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port in link"); + return; + } + + p.type = PORT_IN_RXQ; + + p.dev_name = tokens[t0 + 1]; + + if (strcmp(tokens[t0 + 2], "rxq") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq"); + return; + } + + if (softnic_parser_read_uint16(&p.rxq.queue_id, + tokens[t0 + 3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "queue_id"); + return; + } + t0 += 4; + } else if (strcmp(tokens[t0], "swq") == 0) { + if (n_tokens < t0 + 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port in swq"); + return; + } + + p.type = PORT_IN_SWQ; + + p.dev_name = tokens[t0 + 1]; + + t0 += 2; + } else if (strcmp(tokens[t0], "tmgr") == 0) { + if (n_tokens < t0 + 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port in tmgr"); + return; + } + + p.type = PORT_IN_TMGR; + + p.dev_name = tokens[t0 + 1]; + + t0 += 2; + } else if (strcmp(tokens[t0], "tap") == 0) { + if (n_tokens < t0 + 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port in tap"); + return; + } + + p.type = PORT_IN_TAP; + + p.dev_name = tokens[t0 + 1]; + + if (strcmp(tokens[t0 + 2], "mempool") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "mempool"); + return; + } + + p.tap.mempool_name = tokens[t0 + 3]; + + if (strcmp(tokens[t0 + 4], "mtu") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "mtu"); + return; + } + + if (softnic_parser_read_uint32(&p.tap.mtu, + tokens[t0 + 5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); + return; + } + + t0 += 6; + } else if (strcmp(tokens[t0], "source") == 0) { + if (n_tokens < t0 + 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port in source"); + return; + } + + p.type = PORT_IN_SOURCE; + + p.dev_name = NULL; + + if (strcmp(tokens[t0 + 1], "mempool") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "mempool"); + return; + } + + p.source.mempool_name = tokens[t0 + 2]; + + if (strcmp(tokens[t0 + 3], "file") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "file"); + return; + } + + p.source.file_name = tokens[t0 + 4]; + + if (strcmp(tokens[t0 + 5], "bpp") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "bpp"); + return; + } + + if (softnic_parser_read_uint32(&p.source.n_bytes_per_pkt, + tokens[t0 + 6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "n_bytes_per_pkt"); + return; + } + + t0 += 7; + } else { + snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); + return; + } + + p.action_profile_name = NULL; + if (n_tokens > t0 && + (strcmp(tokens[t0], "action") == 0)) { + if (n_tokens < t0 + 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, "action"); + return; + } + + p.action_profile_name = tokens[t0 + 1]; + + t0 += 2; + } + + enabled = 1; + if (n_tokens > t0 && + (strcmp(tokens[t0], "disabled") == 0)) { + enabled = 0; + + t0 += 1; + } + + if (n_tokens != t0) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + status = pipeline_port_in_create(softnic, + pipeline_name, + &p, + enabled); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +/** + * pipeline port out + * bsz + * link txq + * | swq + * | tmgr + * | tap + * | sink [file pkts ] + */ +static void +cmd_pipeline_port_out(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct port_out_params p; + char *pipeline_name; + int status; + + memset(&p, 0, sizeof(p)); + + if (n_tokens < 7) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (strcmp(tokens[3], "out") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out"); + return; + } + + if (strcmp(tokens[4], "bsz") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); + return; + } + + if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "burst_size"); + return; + } + + if (strcmp(tokens[6], "link") == 0) { + if (n_tokens != 10) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port out link"); + return; + } + + p.type = PORT_OUT_TXQ; + + p.dev_name = tokens[7]; + + if (strcmp(tokens[8], "txq") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq"); + return; + } + + if (softnic_parser_read_uint16(&p.txq.queue_id, + tokens[9]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "queue_id"); + return; + } + } else if (strcmp(tokens[6], "swq") == 0) { + if (n_tokens != 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port out swq"); + return; + } + + p.type = PORT_OUT_SWQ; + + p.dev_name = tokens[7]; + } else if (strcmp(tokens[6], "tmgr") == 0) { + if (n_tokens != 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port out tmgr"); + return; + } + + p.type = PORT_OUT_TMGR; + + p.dev_name = tokens[7]; + } else if (strcmp(tokens[6], "tap") == 0) { + if (n_tokens != 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port out tap"); + return; + } + + p.type = PORT_OUT_TAP; + + p.dev_name = tokens[7]; + } else if (strcmp(tokens[6], "sink") == 0) { + if ((n_tokens != 7) && (n_tokens != 11)) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port out sink"); + return; + } + + p.type = PORT_OUT_SINK; + + p.dev_name = NULL; + + if (n_tokens == 7) { + p.sink.file_name = NULL; + p.sink.max_n_pkts = 0; + } else { + if (strcmp(tokens[7], "file") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "file"); + return; + } + + p.sink.file_name = tokens[8]; + + if (strcmp(tokens[9], "pkts") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts"); + return; + } + + if (softnic_parser_read_uint32(&p.sink.max_n_pkts, + tokens[10]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts"); + return; + } + } + } else { + snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); + return; + } + + status = pipeline_port_out_create(softnic, pipeline_name, &p); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +/** + * pipeline table + * match + * acl + * ipv4 | ipv6 + * offset + * size + * | array + * offset + * size + * | hash + * ext | lru + * key + * mask + * offset + * buckets + * size + * | lpm + * ipv4 | ipv6 + * offset + * size + * | stub + * [action ] + */ +static void +cmd_pipeline_table(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX]; + struct table_params p; + char *pipeline_name; + uint32_t t0; + int status; + + if (n_tokens < 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "table") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); + return; + } + + if (strcmp(tokens[3], "match") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); + return; + } + + t0 = 4; + if (strcmp(tokens[t0], "acl") == 0) { + if (n_tokens < t0 + 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline table acl"); + return; + } + + p.match_type = TABLE_ACL; + + if (strcmp(tokens[t0 + 1], "ipv4") == 0) { + p.match.acl.ip_version = 1; + } else if (strcmp(tokens[t0 + 1], "ipv6") == 0) { + p.match.acl.ip_version = 0; + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "ipv4 or ipv6"); + return; + } + + if (strcmp(tokens[t0 + 2], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (softnic_parser_read_uint32(&p.match.acl.ip_header_offset, + tokens[t0 + 3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "ip_header_offset"); + return; + } + + if (strcmp(tokens[t0 + 4], "size") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); + return; + } + + if (softnic_parser_read_uint32(&p.match.acl.n_rules, + tokens[t0 + 5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); + return; + } + + t0 += 6; + } else if (strcmp(tokens[t0], "array") == 0) { + if (n_tokens < t0 + 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline table array"); + return; + } + + p.match_type = TABLE_ARRAY; + + if (strcmp(tokens[t0 + 1], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (softnic_parser_read_uint32(&p.match.array.key_offset, + tokens[t0 + 2]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); + return; + } + + if (strcmp(tokens[t0 + 3], "size") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); + return; + } + + if (softnic_parser_read_uint32(&p.match.array.n_keys, + tokens[t0 + 4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_keys"); + return; + } + + t0 += 5; + } else if (strcmp(tokens[t0], "hash") == 0) { + uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX; + + if (n_tokens < t0 + 12) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline table hash"); + return; + } + + p.match_type = TABLE_HASH; + + if (strcmp(tokens[t0 + 1], "ext") == 0) { + p.match.hash.extendable_bucket = 1; + } else if (strcmp(tokens[t0 + 1], "lru") == 0) { + p.match.hash.extendable_bucket = 0; + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "ext or lru"); + return; + } + + if (strcmp(tokens[t0 + 2], "key") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key"); + return; + } + + if ((softnic_parser_read_uint32(&p.match.hash.key_size, + tokens[t0 + 3]) != 0) || + p.match.hash.key_size == 0 || + p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_size"); + return; + } + + if (strcmp(tokens[t0 + 4], "mask") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); + return; + } + + if ((softnic_parse_hex_string(tokens[t0 + 5], + key_mask, &key_mask_size) != 0) || + key_mask_size != p.match.hash.key_size) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); + return; + } + p.match.hash.key_mask = key_mask; + + if (strcmp(tokens[t0 + 6], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (softnic_parser_read_uint32(&p.match.hash.key_offset, + tokens[t0 + 7]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); + return; + } + + if (strcmp(tokens[t0 + 8], "buckets") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets"); + return; + } + + if (softnic_parser_read_uint32(&p.match.hash.n_buckets, + tokens[t0 + 9]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets"); + return; + } + + if (strcmp(tokens[t0 + 10], "size") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); + return; + } + + if (softnic_parser_read_uint32(&p.match.hash.n_keys, + tokens[t0 + 11]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_keys"); + return; + } + + t0 += 12; + } else if (strcmp(tokens[t0], "lpm") == 0) { + if (n_tokens < t0 + 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline table lpm"); + return; + } + + p.match_type = TABLE_LPM; + + if (strcmp(tokens[t0 + 1], "ipv4") == 0) { + p.match.lpm.key_size = 4; + } else if (strcmp(tokens[t0 + 1], "ipv6") == 0) { + p.match.lpm.key_size = 16; + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "ipv4 or ipv6"); + return; + } + + if (strcmp(tokens[t0 + 2], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (softnic_parser_read_uint32(&p.match.lpm.key_offset, + tokens[t0 + 3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); + return; + } + + if (strcmp(tokens[t0 + 4], "size") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); + return; + } + + if (softnic_parser_read_uint32(&p.match.lpm.n_rules, + tokens[t0 + 5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); + return; + } + + t0 += 6; + } else if (strcmp(tokens[t0], "stub") == 0) { + p.match_type = TABLE_STUB; + + t0 += 1; + } else { + snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); + return; + } + + p.action_profile_name = NULL; + if (n_tokens > t0 && + (strcmp(tokens[t0], "action") == 0)) { + if (n_tokens < t0 + 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, "action"); + return; + } + + p.action_profile_name = tokens[t0 + 1]; + + t0 += 2; + } + + if (n_tokens > t0) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + status = pipeline_table_create(softnic, pipeline_name, &p); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +/** + * pipeline port in table + */ +static void +cmd_pipeline_port_in_table(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *pipeline_name; + uint32_t port_id, table_id; + int status; + + if (n_tokens != 7) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (strcmp(tokens[3], "in") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); + return; + } + + if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + + if (strcmp(tokens[5], "table") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); + return; + } + + if (softnic_parser_read_uint32(&table_id, tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); + return; + } + + status = pipeline_port_in_connect_to_table(softnic, + pipeline_name, + port_id, + table_id); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +/** + * pipeline port in enable + */ +static void +cmd_pipeline_port_in_enable(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *pipeline_name; + uint32_t port_id; + int status; + + if (n_tokens != 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (strcmp(tokens[3], "in") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); + return; + } + + if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + + if (strcmp(tokens[5], "enable") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); + return; + } + + status = pipeline_port_in_enable(softnic, pipeline_name, port_id); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +/** + * pipeline port in disable + */ +static void +cmd_pipeline_port_in_disable(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *pipeline_name; + uint32_t port_id; + int status; + + if (n_tokens != 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (strcmp(tokens[3], "in") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); + return; + } + + if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + + if (strcmp(tokens[5], "disable") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); + return; + } + + status = pipeline_port_in_disable(softnic, pipeline_name, port_id); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + void cli_process(char *in, char *out, size_t out_size, void *arg) { char *tokens[CMD_MAX_TOKENS]; uint32_t n_tokens = RTE_DIM(tokens); + struct pmd_internals *softnic = arg; int status; - arg = arg; - if (is_comment(in)) return; @@ -58,6 +1612,94 @@ cli_process(char *in, char *out, size_t out_size, void *arg) if (n_tokens == 0) return; + if (strcmp(tokens[0], "mempool") == 0) { + cmd_mempool(softnic, tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "link") == 0) { + cmd_link(softnic, tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "swq") == 0) { + cmd_swq(softnic, tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "tap") == 0) { + cmd_tap(softnic, tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "port") == 0) { + cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "table") == 0) { + cmd_table_action_profile(softnic, tokens, n_tokens, out, out_size); + return; + } + + if (strcmp(tokens[0], "pipeline") == 0) { + if (n_tokens >= 3 && + (strcmp(tokens[2], "period") == 0)) { + cmd_pipeline(softnic, tokens, n_tokens, out, out_size); + return; + } + + if (n_tokens >= 5 && + (strcmp(tokens[2], "port") == 0) && + (strcmp(tokens[3], "in") == 0) && + (strcmp(tokens[4], "bsz") == 0)) { + cmd_pipeline_port_in(softnic, tokens, n_tokens, out, out_size); + return; + } + + if (n_tokens >= 5 && + (strcmp(tokens[2], "port") == 0) && + (strcmp(tokens[3], "out") == 0) && + (strcmp(tokens[4], "bsz") == 0)) { + cmd_pipeline_port_out(softnic, tokens, n_tokens, out, out_size); + return; + } + + if (n_tokens >= 4 && + (strcmp(tokens[2], "table") == 0) && + (strcmp(tokens[3], "match") == 0)) { + cmd_pipeline_table(softnic, tokens, n_tokens, out, out_size); + return; + } + + if (n_tokens >= 6 && + (strcmp(tokens[2], "port") == 0) && + (strcmp(tokens[3], "in") == 0) && + (strcmp(tokens[5], "table") == 0)) { + cmd_pipeline_port_in_table(softnic, tokens, n_tokens, + out, out_size); + return; + } + + if (n_tokens >= 6 && + (strcmp(tokens[2], "port") == 0) && + (strcmp(tokens[3], "in") == 0) && + (strcmp(tokens[5], "enable") == 0)) { + cmd_pipeline_port_in_enable(softnic, tokens, n_tokens, + out, out_size); + return; + } + + if (n_tokens >= 6 && + (strcmp(tokens[2], "port") == 0) && + (strcmp(tokens[3], "in") == 0) && + (strcmp(tokens[5], "disable") == 0)) { + cmd_pipeline_port_in_disable(softnic, tokens, n_tokens, + out, out_size); + return; + } + } + snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); } diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index 155450e..2f9b6a3 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -689,6 +689,91 @@ pipeline_table_create(struct pmd_internals *p, const char *pipeline_name, struct table_params *params); +struct table_rule_match_acl { + int ip_version; + + RTE_STD_C11 + union { + struct { + uint32_t sa; + uint32_t da; + } ipv4; + + struct { + uint8_t sa[16]; + uint8_t da[16]; + } ipv6; + }; + + uint32_t sa_depth; + uint32_t da_depth; + uint16_t sp0; + uint16_t sp1; + uint16_t dp0; + uint16_t dp1; + uint8_t proto; + uint8_t proto_mask; + uint32_t priority; +}; + +struct table_rule_match_array { + uint32_t pos; +}; + +#ifndef TABLE_RULE_MATCH_SIZE_MAX +#define TABLE_RULE_MATCH_SIZE_MAX 256 +#endif + +struct table_rule_match_hash { + uint8_t key[TABLE_RULE_MATCH_SIZE_MAX]; +}; + +struct table_rule_match_lpm { + int ip_version; + + RTE_STD_C11 + union { + uint32_t ipv4; + uint8_t ipv6[16]; + }; + + uint8_t depth; +}; + +struct table_rule_match { + enum table_type match_type; + + union { + struct table_rule_match_acl acl; + struct table_rule_match_array array; + struct table_rule_match_hash hash; + struct table_rule_match_lpm lpm; + } match; +}; + +struct table_rule_action { + uint64_t action_mask; + struct rte_table_action_fwd_params fwd; + struct rte_table_action_lb_params lb; + struct rte_table_action_mtr_params mtr; + struct rte_table_action_tm_params tm; + struct rte_table_action_encap_params encap; + struct rte_table_action_nat_params nat; + struct rte_table_action_ttl_params ttl; + struct rte_table_action_stats_params stats; + struct rte_table_action_time_params time; +}; + +int +pipeline_port_in_enable(struct pmd_internals *p, + const char *pipeline_name, + uint32_t port_id); + +int +pipeline_port_in_disable(struct pmd_internals *p, + const char *pipeline_name, + uint32_t port_id); + /** * Thread */ diff --git a/drivers/net/softnic/rte_eth_softnic_thread.c b/drivers/net/softnic/rte_eth_softnic_thread.c index e8c4916..a59a1a5 100644 --- a/drivers/net/softnic/rte_eth_softnic_thread.c +++ b/drivers/net/softnic/rte_eth_softnic_thread.c @@ -156,11 +156,16 @@ thread_msg_handle(struct thread_data *t) * Master thread & data plane threads: message passing */ enum pipeline_req_type { + /* Port IN */ + PIPELINE_REQ_PORT_IN_ENABLE, + PIPELINE_REQ_PORT_IN_DISABLE, + PIPELINE_REQ_MAX }; struct pipeline_msg_req { enum pipeline_req_type type; + uint32_t id; /* Port IN, port OUT or table ID */ }; struct pipeline_msg_rsp { @@ -168,6 +173,132 @@ struct pipeline_msg_rsp { }; /** + * Master thread + */ +static struct pipeline_msg_req * +pipeline_msg_alloc(void) +{ + size_t size = RTE_MAX(sizeof(struct pipeline_msg_req), + sizeof(struct pipeline_msg_rsp)); + + return calloc(1, size); +} + +static void +pipeline_msg_free(struct pipeline_msg_rsp *rsp) +{ + free(rsp); +} + +static struct pipeline_msg_rsp * +pipeline_msg_send_recv(struct pipeline *p, + struct pipeline_msg_req *req) +{ + struct rte_ring *msgq_req = p->msgq_req; + struct rte_ring *msgq_rsp = p->msgq_rsp; + struct pipeline_msg_rsp *rsp; + int status; + + /* send */ + do { + status = rte_ring_sp_enqueue(msgq_req, req); + } while (status == -ENOBUFS); + + /* recv */ + do { + status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp); + } while (status != 0); + + return rsp; +} + +int +pipeline_port_in_enable(struct pmd_internals *softnic, + const char *pipeline_name, + uint32_t port_id) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if (pipeline_name == NULL) + return -1; + + p = pipeline_find(softnic, pipeline_name); + if (p == NULL || + p->enabled == 0 || + port_id >= p->n_ports_in) + return -1; + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_PORT_IN_ENABLE; + req->id = port_id; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_port_in_disable(struct pmd_internals *softnic, + const char *pipeline_name, + uint32_t port_id) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if (pipeline_name == NULL) + return -1; + + p = pipeline_find(softnic, pipeline_name); + if (p == NULL || + p->enabled == 0 || + port_id >= p->n_ports_in) + return -1; + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_PORT_IN_DISABLE; + req->id = port_id; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +/** * Data plane threads: message handling */ static inline struct pipeline_msg_req * @@ -194,6 +325,32 @@ pipeline_msg_send(struct rte_ring *msgq_rsp, } while (status == -ENOBUFS); } +static struct pipeline_msg_rsp * +pipeline_msg_handle_port_in_enable(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; + uint32_t port_id = req->id; + + rsp->status = rte_pipeline_port_in_enable(p->p, + port_id); + + return rsp; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_port_in_disable(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req; + uint32_t port_id = req->id; + + rsp->status = rte_pipeline_port_in_disable(p->p, + port_id); + + return rsp; +} + static void pipeline_msg_handle(struct pipeline_data *p) { @@ -206,6 +363,14 @@ pipeline_msg_handle(struct pipeline_data *p) break; switch (req->type) { + case PIPELINE_REQ_PORT_IN_ENABLE: + rsp = pipeline_msg_handle_port_in_enable(p, req); + break; + + case PIPELINE_REQ_PORT_IN_DISABLE: + rsp = pipeline_msg_handle_port_in_disable(p, req); + break; + default: rsp = (struct pipeline_msg_rsp *)req; rsp->status = -1; From patchwork Wed Jun 27 16:31:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41710 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 091E51C1DA; Wed, 27 Jun 2018 18:32:13 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id E47E91C19A for ; Wed, 27 Jun 2018 18:31:47 +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:47 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789713" 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:45 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:15 +0100 Message-Id: <20180627163123.135686-16-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 15/23] net/softnic: add cli to enable and disable pipeline 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add cli commands to enable and disable pipelines on specific threads in softnic. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/rte_eth_softnic_cli.c | 103 ++++++++ drivers/net/softnic/rte_eth_softnic_internals.h | 10 + drivers/net/softnic/rte_eth_softnic_thread.c | 325 ++++++++++++++++++++++++ 3 files changed, 438 insertions(+) diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c index a0d715b..2be1f41 100644 --- a/drivers/net/softnic/rte_eth_softnic_cli.c +++ b/drivers/net/softnic/rte_eth_softnic_cli.c @@ -1592,6 +1592,93 @@ cmd_pipeline_port_in_disable(struct pmd_internals *softnic, } } +/** + * thread pipeline enable + */ +static void +cmd_thread_pipeline_enable(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *pipeline_name; + uint32_t thread_id; + int status; + + if (n_tokens != 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); + return; + } + + if (strcmp(tokens[2], "pipeline") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); + return; + } + + pipeline_name = tokens[3]; + + if (strcmp(tokens[4], "enable") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); + return; + } + + status = thread_pipeline_enable(softnic, thread_id, pipeline_name); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable"); + return; + } +} + +/** + * thread pipeline disable + */ +static void +cmd_thread_pipeline_disable(struct pmd_internals *softnic, + char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *pipeline_name; + uint32_t thread_id; + int status; + + if (n_tokens != 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); + return; + } + + if (strcmp(tokens[2], "pipeline") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); + return; + } + + pipeline_name = tokens[3]; + + if (strcmp(tokens[4], "disable") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); + return; + } + + status = thread_pipeline_disable(softnic, thread_id, pipeline_name); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, + "thread pipeline disable"); + return; + } +} + void cli_process(char *in, char *out, size_t out_size, void *arg) { @@ -1700,6 +1787,22 @@ cli_process(char *in, char *out, size_t out_size, void *arg) } } + if (strcmp(tokens[0], "thread") == 0) { + if ((n_tokens >= 5) && + (strcmp(tokens[4], "enable") == 0)) { + cmd_thread_pipeline_enable(softnic, tokens, n_tokens, + out, out_size); + return; + } + + if ((n_tokens >= 5) && + (strcmp(tokens[4], "disable") == 0)) { + cmd_thread_pipeline_disable(softnic, tokens, n_tokens, + out, out_size); + return; + } + } + snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); } diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h index 2f9b6a3..922eda3 100644 --- a/drivers/net/softnic/rte_eth_softnic_internals.h +++ b/drivers/net/softnic/rte_eth_softnic_internals.h @@ -783,6 +783,16 @@ thread_init(struct pmd_internals *p); void thread_free(struct pmd_internals *p); +int +thread_pipeline_enable(struct pmd_internals *p, + uint32_t thread_id, + const char *pipeline_name); + +int +thread_pipeline_disable(struct pmd_internals *p, + uint32_t thread_id, + const char *pipeline_name); + /** * CLI */ diff --git a/drivers/net/softnic/rte_eth_softnic_thread.c b/drivers/net/softnic/rte_eth_softnic_thread.c index a59a1a5..83f9ab1 100644 --- a/drivers/net/softnic/rte_eth_softnic_thread.c +++ b/drivers/net/softnic/rte_eth_softnic_thread.c @@ -93,11 +93,30 @@ thread_init(struct pmd_internals *softnic) * Master thread & data plane threads: message passing */ enum thread_req_type { + THREAD_REQ_PIPELINE_ENABLE = 0, + THREAD_REQ_PIPELINE_DISABLE, THREAD_REQ_MAX }; struct thread_msg_req { enum thread_req_type type; + + union { + struct { + struct rte_pipeline *p; + struct { + struct rte_table_action *a; + } table[RTE_PIPELINE_TABLE_MAX]; + struct rte_ring *msgq_req; + struct rte_ring *msgq_rsp; + uint32_t timer_period_ms; + uint32_t n_tables; + } pipeline_enable; + + struct { + struct rte_pipeline *p; + } pipeline_disable; + }; }; struct thread_msg_rsp { @@ -105,6 +124,231 @@ struct thread_msg_rsp { }; /** + * Master thread + */ +static struct thread_msg_req * +thread_msg_alloc(void) +{ + size_t size = RTE_MAX(sizeof(struct thread_msg_req), + sizeof(struct thread_msg_rsp)); + + return calloc(1, size); +} + +static void +thread_msg_free(struct thread_msg_rsp *rsp) +{ + free(rsp); +} + +static struct thread_msg_rsp * +thread_msg_send_recv(struct pmd_internals *softnic, + uint32_t thread_id, + struct thread_msg_req *req) +{ + struct thread *t = &softnic->thread[thread_id]; + struct rte_ring *msgq_req = t->msgq_req; + struct rte_ring *msgq_rsp = t->msgq_rsp; + struct thread_msg_rsp *rsp; + int status; + + /* send */ + do { + status = rte_ring_sp_enqueue(msgq_req, req); + } while (status == -ENOBUFS); + + /* recv */ + do { + status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp); + } while (status != 0); + + return rsp; +} + +int +thread_pipeline_enable(struct pmd_internals *softnic, + uint32_t thread_id, + const char *pipeline_name) +{ + struct pipeline *p = pipeline_find(softnic, pipeline_name); + struct thread *t; + struct thread_msg_req *req; + struct thread_msg_rsp *rsp; + enum rte_lcore_state_t thread_state; + uint32_t i; + int status; + + /* Check input params */ + if ((thread_id >= RTE_MAX_LCORE) || + (p == NULL) || + (p->n_ports_in == 0) || + (p->n_ports_out == 0) || + (p->n_tables == 0)) + return -1; + + t = &softnic->thread[thread_id]; + if ((t->enabled == 0) || + p->enabled) + return -1; + + thread_state = rte_eal_get_lcore_state(thread_id); + if (thread_state != RUNNING) { + struct thread_data *td = &softnic->thread_data[thread_id]; + struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines]; + + if (td->n_pipelines >= THREAD_PIPELINES_MAX) + return -1; + + /* Data plane thread */ + td->p[td->n_pipelines] = p->p; + + tdp->p = p->p; + for (i = 0; i < p->n_tables; i++) + tdp->table_data[i].a = + p->table[i].a; + tdp->n_tables = p->n_tables; + + tdp->msgq_req = p->msgq_req; + tdp->msgq_rsp = p->msgq_rsp; + tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000; + tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period; + + td->n_pipelines++; + + /* Pipeline */ + p->thread_id = thread_id; + p->enabled = 1; + + return 0; + } + + /* Allocate request */ + req = thread_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = THREAD_REQ_PIPELINE_ENABLE; + req->pipeline_enable.p = p->p; + for (i = 0; i < p->n_tables; i++) + req->pipeline_enable.table[i].a = + p->table[i].a; + req->pipeline_enable.msgq_req = p->msgq_req; + req->pipeline_enable.msgq_rsp = p->msgq_rsp; + req->pipeline_enable.timer_period_ms = p->timer_period_ms; + req->pipeline_enable.n_tables = p->n_tables; + + /* Send request and wait for response */ + rsp = thread_msg_send_recv(softnic, thread_id, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + + /* Free response */ + thread_msg_free(rsp); + + /* Request completion */ + if (status) + return status; + + p->thread_id = thread_id; + p->enabled = 1; + + return 0; +} + +int +thread_pipeline_disable(struct pmd_internals *softnic, + uint32_t thread_id, + const char *pipeline_name) +{ + struct pipeline *p = pipeline_find(softnic, pipeline_name); + struct thread *t; + struct thread_msg_req *req; + struct thread_msg_rsp *rsp; + enum rte_lcore_state_t thread_state; + int status; + + /* Check input params */ + if ((thread_id >= RTE_MAX_LCORE) || + (p == NULL)) + return -1; + + t = &softnic->thread[thread_id]; + if (t->enabled == 0) + return -1; + + if (p->enabled == 0) + return 0; + + if (p->thread_id != thread_id) + return -1; + + thread_state = rte_eal_get_lcore_state(thread_id); + if (thread_state != RUNNING) { + struct thread_data *td = &softnic->thread_data[thread_id]; + uint32_t i; + + for (i = 0; i < td->n_pipelines; i++) { + struct pipeline_data *tdp = &td->pipeline_data[i]; + + if (tdp->p != p->p) + continue; + + /* Data plane thread */ + if (i < td->n_pipelines - 1) { + struct rte_pipeline *pipeline_last = + td->p[td->n_pipelines - 1]; + struct pipeline_data *tdp_last = + &td->pipeline_data[td->n_pipelines - 1]; + + td->p[i] = pipeline_last; + memcpy(tdp, tdp_last, sizeof(*tdp)); + } + + td->n_pipelines--; + + /* Pipeline */ + p->enabled = 0; + + break; + } + + return 0; + } + + /* Allocate request */ + req = thread_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = THREAD_REQ_PIPELINE_DISABLE; + req->pipeline_disable.p = p->p; + + /* Send request and wait for response */ + rsp = thread_msg_send_recv(softnic, thread_id, req); + if (rsp == NULL) + return -1; + + /* Read response */ + status = rsp->status; + + /* Free response */ + thread_msg_free(rsp); + + /* Request completion */ + if (status) + return status; + + p->enabled = 0; + + return 0; +} + +/** * Data plane threads: message handling */ static inline struct thread_msg_req * @@ -131,6 +375,79 @@ thread_msg_send(struct rte_ring *msgq_rsp, } while (status == -ENOBUFS); } +static struct thread_msg_rsp * +thread_msg_handle_pipeline_enable(struct thread_data *t, + struct thread_msg_req *req) +{ + struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req; + struct pipeline_data *p = &t->pipeline_data[t->n_pipelines]; + uint32_t i; + + /* Request */ + if (t->n_pipelines >= THREAD_PIPELINES_MAX) { + rsp->status = -1; + return rsp; + } + + t->p[t->n_pipelines] = req->pipeline_enable.p; + + p->p = req->pipeline_enable.p; + for (i = 0; i < req->pipeline_enable.n_tables; i++) + p->table_data[i].a = + req->pipeline_enable.table[i].a; + + p->n_tables = req->pipeline_enable.n_tables; + + p->msgq_req = req->pipeline_enable.msgq_req; + p->msgq_rsp = req->pipeline_enable.msgq_rsp; + p->timer_period = + (rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000; + p->time_next = rte_get_tsc_cycles() + p->timer_period; + + t->n_pipelines++; + + /* Response */ + rsp->status = 0; + return rsp; +} + +static struct thread_msg_rsp * +thread_msg_handle_pipeline_disable(struct thread_data *t, + struct thread_msg_req *req) +{ + struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req; + uint32_t n_pipelines = t->n_pipelines; + struct rte_pipeline *pipeline = req->pipeline_disable.p; + uint32_t i; + + /* find pipeline */ + for (i = 0; i < n_pipelines; i++) { + struct pipeline_data *p = &t->pipeline_data[i]; + + if (p->p != pipeline) + continue; + + if (i < n_pipelines - 1) { + struct rte_pipeline *pipeline_last = + t->p[n_pipelines - 1]; + struct pipeline_data *p_last = + &t->pipeline_data[n_pipelines - 1]; + + t->p[i] = pipeline_last; + memcpy(p, p_last, sizeof(*p)); + } + + t->n_pipelines--; + + rsp->status = 0; + return rsp; + } + + /* should not get here */ + rsp->status = 0; + return rsp; +} + static void thread_msg_handle(struct thread_data *t) { @@ -143,6 +460,14 @@ thread_msg_handle(struct thread_data *t) break; switch (req->type) { + case THREAD_REQ_PIPELINE_ENABLE: + rsp = thread_msg_handle_pipeline_enable(t, req); + break; + + case THREAD_REQ_PIPELINE_DISABLE: + rsp = thread_msg_handle_pipeline_disable(t, req); + break; + default: rsp = (struct thread_msg_rsp *)req; rsp->status = -1; From patchwork Wed Jun 27 16:31:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jasvinder Singh X-Patchwork-Id: 41711 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id CC05B1C197; Wed, 27 Jun 2018 18:32:14 +0200 (CEST) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 38E431C199 for ; Wed, 27 Jun 2018 18:31:51 +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 orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 Jun 2018 09:31:49 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,279,1526367600"; d="scan'208";a="240789725" 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:46 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com Date: Wed, 27 Jun 2018 17:31:16 +0100 Message-Id: <20180627163123.135686-17-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 16/23] net/softnic: add cli for pipeline table entries 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add cli commands for table entries in softnic pipeline objects. Signed-off-by: Cristian Dumitrescu Signed-off-by: Jasvinder Singh --- drivers/net/softnic/rte_eth_softnic_cli.c | 2187 ++++++++++++++++++++--- drivers/net/softnic/rte_eth_softnic_internals.h | 35 + drivers/net/softnic/rte_eth_softnic_thread.c | 1205 +++++++++++++ 3 files changed, 3208 insertions(+), 219 deletions(-) diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c index 2be1f41..c90e997 100644 --- a/drivers/net/softnic/rte_eth_softnic_cli.c +++ b/drivers/net/softnic/rte_eth_softnic_cli.c @@ -7,6 +7,9 @@ #include #include +#include +#include + #include "rte_eth_softnic_internals.h" #include "parser.h" @@ -1593,272 +1596,2018 @@ cmd_pipeline_port_in_disable(struct pmd_internals *softnic, } /** - * thread pipeline enable + * ::= + * + * match + * acl + * priority + * ipv4 | ipv6 + * + * | array + * | hash + * raw + * | ipv4_5tuple + * | ipv6_5tuple + * | ipv4_addr + * | ipv6_addr + * | qinq + * | lpm + * ipv4 | ipv6 */ -static void -cmd_thread_pipeline_enable(struct pmd_internals *softnic, - char **tokens, +struct pkt_key_qinq { + uint16_t ethertype_svlan; + uint16_t svlan; + uint16_t ethertype_cvlan; + uint16_t cvlan; +} __attribute__((__packed__)); + +struct pkt_key_ipv4_5tuple { + uint8_t time_to_live; + uint8_t proto; + uint16_t hdr_checksum; + uint32_t sa; + uint32_t da; + uint16_t sp; + uint16_t dp; +} __attribute__((__packed__)); + +struct pkt_key_ipv6_5tuple { + uint16_t payload_length; + uint8_t proto; + uint8_t hop_limit; + uint8_t sa[16]; + uint8_t da[16]; + uint16_t sp; + uint16_t dp; +} __attribute__((__packed__)); + +struct pkt_key_ipv4_addr { + uint32_t addr; +} __attribute__((__packed__)); + +struct pkt_key_ipv6_addr { + uint8_t addr[16]; +} __attribute__((__packed__)); + +static uint32_t +parse_match(char **tokens, uint32_t n_tokens, char *out, - size_t out_size) + size_t out_size, + struct table_rule_match *m) { - char *pipeline_name; - uint32_t thread_id; - int status; - - if (n_tokens != 5) { - snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); - return; - } + memset(m, 0, sizeof(*m)); - if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); - return; - } + if (n_tokens < 2) + return 0; - if (strcmp(tokens[2], "pipeline") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); - return; + if (strcmp(tokens[0], "match") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); + return 0; } - pipeline_name = tokens[3]; + if (strcmp(tokens[1], "acl") == 0) { + if (n_tokens < 14) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return 0; + } - if (strcmp(tokens[4], "enable") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); - return; - } + m->match_type = TABLE_ACL; - status = thread_pipeline_enable(softnic, thread_id, pipeline_name); - if (status) { - snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable"); - return; - } -} + if (strcmp(tokens[2], "priority") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority"); + return 0; + } -/** - * thread pipeline disable - */ -static void -cmd_thread_pipeline_disable(struct pmd_internals *softnic, - char **tokens, - uint32_t n_tokens, - char *out, - size_t out_size) -{ - char *pipeline_name; - uint32_t thread_id; - int status; + if (softnic_parser_read_uint32(&m->match.acl.priority, + tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "priority"); + return 0; + } - if (n_tokens != 5) { - snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); - return; - } + if (strcmp(tokens[4], "ipv4") == 0) { + struct in_addr saddr, daddr; - if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); - return; - } + m->match.acl.ip_version = 1; - if (strcmp(tokens[2], "pipeline") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); - return; - } + if (softnic_parse_ipv4_addr(tokens[5], &saddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sa"); + return 0; + } + m->match.acl.ipv4.sa = rte_be_to_cpu_32(saddr.s_addr); - pipeline_name = tokens[3]; + if (softnic_parse_ipv4_addr(tokens[7], &daddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "da"); + return 0; + } + m->match.acl.ipv4.da = rte_be_to_cpu_32(daddr.s_addr); + } else if (strcmp(tokens[4], "ipv6") == 0) { + struct in6_addr saddr, daddr; - if (strcmp(tokens[4], "disable") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); - return; - } + m->match.acl.ip_version = 0; - status = thread_pipeline_disable(softnic, thread_id, pipeline_name); - if (status) { - snprintf(out, out_size, MSG_CMD_FAIL, - "thread pipeline disable"); - return; - } -} + if (softnic_parse_ipv6_addr(tokens[5], &saddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sa"); + return 0; + } + memcpy(m->match.acl.ipv6.sa, saddr.s6_addr, 16); -void -cli_process(char *in, char *out, size_t out_size, void *arg) -{ - char *tokens[CMD_MAX_TOKENS]; - uint32_t n_tokens = RTE_DIM(tokens); - struct pmd_internals *softnic = arg; - int status; + if (softnic_parse_ipv6_addr(tokens[7], &daddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "da"); + return 0; + } + memcpy(m->match.acl.ipv6.da, daddr.s6_addr, 16); + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "ipv4 or ipv6"); + return 0; + } - if (is_comment(in)) - return; + if (softnic_parser_read_uint32(&m->match.acl.sa_depth, + tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sa_depth"); + return 0; + } - status = softnic_parse_tokenize_string(in, tokens, &n_tokens); - if (status) { - snprintf(out, out_size, MSG_ARG_TOO_MANY, ""); - return; - } + if (softnic_parser_read_uint32(&m->match.acl.da_depth, + tokens[8]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "da_depth"); + return 0; + } - if (n_tokens == 0) - return; + if (softnic_parser_read_uint16(&m->match.acl.sp0, tokens[9]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sp0"); + return 0; + } - if (strcmp(tokens[0], "mempool") == 0) { - cmd_mempool(softnic, tokens, n_tokens, out, out_size); - return; - } + if (softnic_parser_read_uint16(&m->match.acl.sp1, tokens[10]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sp1"); + return 0; + } - if (strcmp(tokens[0], "link") == 0) { - cmd_link(softnic, tokens, n_tokens, out, out_size); - return; - } + if (softnic_parser_read_uint16(&m->match.acl.dp0, tokens[11]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "dp0"); + return 0; + } - if (strcmp(tokens[0], "swq") == 0) { - cmd_swq(softnic, tokens, n_tokens, out, out_size); - return; - } + if (softnic_parser_read_uint16(&m->match.acl.dp1, tokens[12]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "dp1"); + return 0; + } - if (strcmp(tokens[0], "tap") == 0) { - cmd_tap(softnic, tokens, n_tokens, out, out_size); - return; - } + if (softnic_parser_read_uint8(&m->match.acl.proto, tokens[13]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "proto"); + return 0; + } - if (strcmp(tokens[0], "port") == 0) { - cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size); - return; - } + m->match.acl.proto_mask = 0xff; - if (strcmp(tokens[0], "table") == 0) { - cmd_table_action_profile(softnic, tokens, n_tokens, out, out_size); - return; - } + return 14; + } /* acl */ - if (strcmp(tokens[0], "pipeline") == 0) { - if (n_tokens >= 3 && - (strcmp(tokens[2], "period") == 0)) { - cmd_pipeline(softnic, tokens, n_tokens, out, out_size); - return; + if (strcmp(tokens[1], "array") == 0) { + if (n_tokens < 3) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return 0; } - if (n_tokens >= 5 && - (strcmp(tokens[2], "port") == 0) && - (strcmp(tokens[3], "in") == 0) && - (strcmp(tokens[4], "bsz") == 0)) { - cmd_pipeline_port_in(softnic, tokens, n_tokens, out, out_size); - return; - } + m->match_type = TABLE_ARRAY; - if (n_tokens >= 5 && - (strcmp(tokens[2], "port") == 0) && - (strcmp(tokens[3], "out") == 0) && - (strcmp(tokens[4], "bsz") == 0)) { - cmd_pipeline_port_out(softnic, tokens, n_tokens, out, out_size); - return; + if (softnic_parser_read_uint32(&m->match.array.pos, tokens[2]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "pos"); + return 0; } - if (n_tokens >= 4 && - (strcmp(tokens[2], "table") == 0) && - (strcmp(tokens[3], "match") == 0)) { - cmd_pipeline_table(softnic, tokens, n_tokens, out, out_size); - return; - } + return 3; + } /* array */ - if (n_tokens >= 6 && - (strcmp(tokens[2], "port") == 0) && - (strcmp(tokens[3], "in") == 0) && - (strcmp(tokens[5], "table") == 0)) { - cmd_pipeline_port_in_table(softnic, tokens, n_tokens, - out, out_size); - return; + if (strcmp(tokens[1], "hash") == 0) { + if (n_tokens < 3) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return 0; } - if (n_tokens >= 6 && - (strcmp(tokens[2], "port") == 0) && - (strcmp(tokens[3], "in") == 0) && - (strcmp(tokens[5], "enable") == 0)) { - cmd_pipeline_port_in_enable(softnic, tokens, n_tokens, - out, out_size); - return; - } + m->match_type = TABLE_HASH; - if (n_tokens >= 6 && - (strcmp(tokens[2], "port") == 0) && - (strcmp(tokens[3], "in") == 0) && - (strcmp(tokens[5], "disable") == 0)) { - cmd_pipeline_port_in_disable(softnic, tokens, n_tokens, - out, out_size); - return; - } - } + if (strcmp(tokens[2], "raw") == 0) { + uint32_t key_size = TABLE_RULE_MATCH_SIZE_MAX; - if (strcmp(tokens[0], "thread") == 0) { - if ((n_tokens >= 5) && - (strcmp(tokens[4], "enable") == 0)) { - cmd_thread_pipeline_enable(softnic, tokens, n_tokens, - out, out_size); - return; - } + if (n_tokens < 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + tokens[0]); + return 0; + } - if ((n_tokens >= 5) && - (strcmp(tokens[4], "disable") == 0)) { - cmd_thread_pipeline_disable(softnic, tokens, n_tokens, - out, out_size); - return; - } - } + if (softnic_parse_hex_string(tokens[3], + m->match.hash.key, &key_size) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key"); + return 0; + } - snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); -} + return 4; + } /* hash raw */ -int -cli_script_process(struct pmd_internals *softnic, - const char *file_name, - size_t msg_in_len_max, - size_t msg_out_len_max) -{ - char *msg_in = NULL, *msg_out = NULL; - FILE *f = NULL; + if (strcmp(tokens[2], "ipv4_5tuple") == 0) { + struct pkt_key_ipv4_5tuple *ipv4 = + (struct pkt_key_ipv4_5tuple *)m->match.hash.key; + struct in_addr saddr, daddr; + uint16_t sp, dp; + uint8_t proto; - /* Check input arguments */ - if (file_name == NULL || - strlen(file_name) == 0 || - msg_in_len_max == 0 || - msg_out_len_max == 0) - return -EINVAL; + if (n_tokens < 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + tokens[0]); + return 0; + } - msg_in = malloc(msg_in_len_max + 1); - msg_out = malloc(msg_out_len_max + 1); - if (msg_in == NULL || - msg_out == NULL) { - free(msg_out); - free(msg_in); - return -ENOMEM; - } + if (softnic_parse_ipv4_addr(tokens[3], &saddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sa"); + return 0; + } - /* Open input file */ - f = fopen(file_name, "r"); - if (f == NULL) { - free(msg_out); - free(msg_in); - return -EIO; - } + if (softnic_parse_ipv4_addr(tokens[4], &daddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "da"); + return 0; + } - /* Read file */ - for ( ; ; ) { - if (fgets(msg_in, msg_in_len_max + 1, f) == NULL) - break; + if (softnic_parser_read_uint16(&sp, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sp"); + return 0; + } - printf("%s", msg_in); - msg_out[0] = 0; + if (softnic_parser_read_uint16(&dp, tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "dp"); + return 0; + } - cli_process(msg_in, - msg_out, - msg_out_len_max, - softnic); + if (softnic_parser_read_uint8(&proto, tokens[7]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "proto"); + return 0; + } - if (strlen(msg_out)) - printf("%s", msg_out); - } + ipv4->sa = saddr.s_addr; + ipv4->da = daddr.s_addr; + ipv4->sp = rte_cpu_to_be_16(sp); + ipv4->dp = rte_cpu_to_be_16(dp); + ipv4->proto = proto; + + return 8; + } /* hash ipv4_5tuple */ + + if (strcmp(tokens[2], "ipv6_5tuple") == 0) { + struct pkt_key_ipv6_5tuple *ipv6 = + (struct pkt_key_ipv6_5tuple *)m->match.hash.key; + struct in6_addr saddr, daddr; + uint16_t sp, dp; + uint8_t proto; + + if (n_tokens < 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + tokens[0]); + return 0; + } - /* Close file */ - fclose(f); - free(msg_out); - free(msg_in); - return 0; + if (softnic_parse_ipv6_addr(tokens[3], &saddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sa"); + return 0; + } + + if (softnic_parse_ipv6_addr(tokens[4], &daddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "da"); + return 0; + } + + if (softnic_parser_read_uint16(&sp, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sp"); + return 0; + } + + if (softnic_parser_read_uint16(&dp, tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "dp"); + return 0; + } + + if (softnic_parser_read_uint8(&proto, tokens[7]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "proto"); + return 0; + } + + memcpy(ipv6->sa, saddr.s6_addr, 16); + memcpy(ipv6->da, daddr.s6_addr, 16); + ipv6->sp = rte_cpu_to_be_16(sp); + ipv6->dp = rte_cpu_to_be_16(dp); + ipv6->proto = proto; + + return 8; + } /* hash ipv6_5tuple */ + + if (strcmp(tokens[2], "ipv4_addr") == 0) { + struct pkt_key_ipv4_addr *ipv4_addr = + (struct pkt_key_ipv4_addr *)m->match.hash.key; + struct in_addr addr; + + if (n_tokens < 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + tokens[0]); + return 0; + } + + if (softnic_parse_ipv4_addr(tokens[3], &addr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "addr"); + return 0; + } + + ipv4_addr->addr = addr.s_addr; + + return 4; + } /* hash ipv4_addr */ + + if (strcmp(tokens[2], "ipv6_addr") == 0) { + struct pkt_key_ipv6_addr *ipv6_addr = + (struct pkt_key_ipv6_addr *)m->match.hash.key; + struct in6_addr addr; + + if (n_tokens < 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + tokens[0]); + return 0; + } + + if (softnic_parse_ipv6_addr(tokens[3], &addr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "addr"); + return 0; + } + + memcpy(ipv6_addr->addr, addr.s6_addr, 16); + + return 4; + } /* hash ipv6_5tuple */ + + if (strcmp(tokens[2], "qinq") == 0) { + struct pkt_key_qinq *qinq = + (struct pkt_key_qinq *)m->match.hash.key; + uint16_t svlan, cvlan; + + if (n_tokens < 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + tokens[0]); + return 0; + } + + if ((softnic_parser_read_uint16(&svlan, tokens[3]) != 0) || + svlan > 0xFFF) { + snprintf(out, out_size, MSG_ARG_INVALID, + "svlan"); + return 0; + } + + if ((softnic_parser_read_uint16(&cvlan, tokens[4]) != 0) || + cvlan > 0xFFF) { + snprintf(out, out_size, MSG_ARG_INVALID, + "cvlan"); + return 0; + } + + qinq->svlan = rte_cpu_to_be_16(svlan); + qinq->cvlan = rte_cpu_to_be_16(cvlan); + + return 5; + } /* hash qinq */ + + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return 0; + } /* hash */ + + if (strcmp(tokens[1], "lpm") == 0) { + if (n_tokens < 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return 0; + } + + m->match_type = TABLE_LPM; + + if (strcmp(tokens[2], "ipv4") == 0) { + struct in_addr addr; + + m->match.lpm.ip_version = 1; + + if (softnic_parse_ipv4_addr(tokens[3], &addr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "addr"); + return 0; + } + + m->match.lpm.ipv4 = rte_be_to_cpu_32(addr.s_addr); + } else if (strcmp(tokens[2], "ipv6") == 0) { + struct in6_addr addr; + + m->match.lpm.ip_version = 0; + + if (softnic_parse_ipv6_addr(tokens[3], &addr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "addr"); + return 0; + } + + memcpy(m->match.lpm.ipv6, addr.s6_addr, 16); + } else { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "ipv4 or ipv6"); + return 0; + } + + if (softnic_parser_read_uint8(&m->match.lpm.depth, tokens[4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "depth"); + return 0; + } + + return 5; + } /* lpm */ + + snprintf(out, out_size, MSG_ARG_MISMATCH, + "acl or array or hash or lpm"); + return 0; +} + +/** + * table_action ::= + * + * action + * fwd + * drop + * | port + * | meta + * | table + * [balance ... ] + * [meter + * tc0 meter policer g y r + * [tc1 meter policer g y r + * tc2 meter policer g y r + * tc3 meter policer g y r ]] + * [tm subport pipe ] + * [encap + * ether + * | vlan + * | qinq + * | mpls unicast | multicast + * + * label0