From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.napatech.com (mail02.napatech.com [91.102.88.21]) by dpdk.org (Postfix) with ESMTP id A0BAC7EEF for ; Fri, 9 Sep 2016 14:51:36 +0200 (CEST) IronPort-PHdr: 9a23:+UMY1hFL3nfOZ/9vwJvrXJ1GYnF86YWxBRYc798ds5kLTJ75oMmwAkXT6L1XgUPTWs2DsrQf2rOQ7fyrBDBIoc7Y9itTKNoUD15NoP5VtjRoONSCB0z/IayiRA0BN+MGamVY+WqmO1NeAsf0ag6aiHSz6TkPBke3blItdazLE4Lfx/66y/q1s8WKJV4Z3XzjPfgvcF329VyX7ZhOx9M6a+4Y8VjgmjNwYeNYxGdldxq4vi3XwYOOxqNl6DlaoPk79sRNAu3QdqU8SqFEXnx9azhmrJ6jiR6WGQeC+FMQSmkV1B1SDF6BpEX8XpDrtyL8nvZgyCWAPNP7V/Y/XjH0vIlxTxq9piYBMXYS8HvWkdB9irlWplr1qRdXxYfMaZ2YP/o4daTYK4BJDVFdV9pcAnQSSri3aJECWrIM X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2HnAQBdrtJX/1QB8ApdGwEBAQMBAQEJAQEBGAEFAQsBgw4BAQEBAXV8B40soxmHfYFCQSCBclSDNgKCDxQBAQEBAQEBAQEBAQKBAoIyGAsBOTsBAQEBAQEBIwINIj0CBA4MAQw+FBBRVwYBDQWIWL1xAQEBAQEBAQMBAQEBAQEBAQEBARyGMIhgCgcBhXgFiCkHhXuBOol8hiODAoJ9gxiBeBc3hBGDNoVdjFODex6DJgEbgU5wAYR7D4EgfwEBAQ X-IPAS-Result: A2HnAQBdrtJX/1QB8ApdGwEBAQMBAQEJAQEBGAEFAQsBgw4BAQEBAXV8B40soxmHfYFCQSCBclSDNgKCDxQBAQEBAQEBAQEBAQKBAoIyGAsBOTsBAQEBAQEBIwINIj0CBA4MAQw+FBBRVwYBDQWIWL1xAQEBAQEBAQMBAQEBAQEBAQEBARyGMIhgCgcBhXgFiCkHhXuBOol8hiODAoJ9gxiBeBc3hBGDNoVdjFODex6DJgEbgU5wAYR7D4EgfwEBAQ Received: from localhost.localdomain (10.10.11.99) by cph-gen-exch02.napatech.com (10.240.1.84) with Microsoft SMTP Server (TLS) id 15.1.396.30; Fri, 9 Sep 2016 14:51:03 +0200 From: Finn Christensen To: , CC: , , Finn Christensen Date: Fri, 9 Sep 2016 12:48:38 +0000 Message-ID: <20160909124838.13123-1-fc@napatech.com> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20160908111424.14127-1-fc@napatech.com> References: <20160908111424.14127-1-fc@napatech.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.10.11.99] X-ClientProxiedBy: cph-gen-exch02.napatech.com (10.240.1.84) To cph-gen-exch02.napatech.com (10.240.1.84) Content-Transfer-Encoding: quoted-printable Subject: [dpdk-dev] [PATCH v3] ntnic: add PMD driver X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 09 Sep 2016 12:51:37 -0000 This is the Napatech NTNIC Poll Mode Driver (PMD) for DPDK. This patch adds support for Napatech NICs to DPDK. This is the initial implementation. Signed-off-by: Finn Christensen --- v3: * Removed the need for binary libraries on build v2: * Added information how to build the PMD without NIC Board Support Package * Fixed some formatting issues --- MAINTAINERS | 5 + config/common_base | 6 + doc/guides/nics/features/ntnic.ini | 14 + doc/guides/nics/index.rst | 1 + doc/guides/nics/ntnic.rst | 145 ++++ drivers/net/Makefile | 1 + drivers/net/ntnic/Makefile | 66 ++ drivers/net/ntnic/rte_eth_ntnic.c | 1150 +++++++++++++++++++++++= ++++ drivers/net/ntnic/rte_pmd_ntnic_version.map | 4 + mk/rte.app.mk | 3 + 10 files changed, 1395 insertions(+) create mode 100644 doc/guides/nics/features/ntnic.ini create mode 100644 doc/guides/nics/ntnic.rst create mode 100644 drivers/net/ntnic/Makefile create mode 100644 drivers/net/ntnic/rte_eth_ntnic.c create mode 100644 drivers/net/ntnic/rte_pmd_ntnic_version.map diff --git a/MAINTAINERS b/MAINTAINERS index bc9aa02..d3e5f56 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -356,6 +356,11 @@ M: Sony Chacko F: drivers/net/qede/ F: doc/guides/nics/qede.rst +Napatech ntnic +M: Finn Christensen +F: drivers/net/ntnic/ +F: doc/guides/nics/ntnic.rst + RedHat virtio M: Huawei Xie M: Yuanhan Liu diff --git a/config/common_base b/config/common_base index 7830535..4a3b2b8 100644 --- a/config/common_base +++ b/config/common_base @@ -309,6 +309,12 @@ CONFIG_RTE_PMD_RING_MAX_TX_RINGS=3D16 CONFIG_RTE_LIBRTE_PMD_PCAP=3Dn # +# Compile software PMD backed by NTNIC files +# +CONFIG_RTE_LIBRTE_PMD_NTNIC=3Dn + + +# # Compile link bonding PMD library # CONFIG_RTE_LIBRTE_PMD_BOND=3Dy diff --git a/doc/guides/nics/features/ntnic.ini b/doc/guides/nics/features/= ntnic.ini new file mode 100644 index 0000000..4237e6e --- /dev/null +++ b/doc/guides/nics/features/ntnic.ini @@ -0,0 +1,14 @@ +; +; Supported features of the 'ntnic' network poll mode driver. +; +; Refer to default.ini for the full list of available PMD features. +; +[Features] +Link status =3D Y +Queue start/stop =3D Y +Promiscuous mode =3D Y +Jumbo frame =3D Y +Basic stats =3D Y +Multiprocess aware =3D Y +x86-64 =3D Y +Usage doc =3D Y diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst index 92d56a5..5c4205c 100644 --- a/doc/guides/nics/index.rst +++ b/doc/guides/nics/index.rst @@ -52,6 +52,7 @@ Network Interface Controller Drivers qede szedata2 thunderx + ntnic virtio vhost vmxnet3 diff --git a/doc/guides/nics/ntnic.rst b/doc/guides/nics/ntnic.rst new file mode 100644 index 0000000..f9398db --- /dev/null +++ b/doc/guides/nics/ntnic.rst @@ -0,0 +1,145 @@ +.. BSD LICENSE + Copyright (c) 2016 Napatech A/S + 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 Napatech 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. + +NTNIC Poll Mode Driver +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The NTNIC poll mode driver library (**librte_pmd_ntnic**) implements suppo= rt +for **Napatech NIC** 40/50 Gbps adapters. +This PMD is implemented as a pure software virtual device and must be crea= ted +by using the EAL --vdev=3Dparameter (parameters are explained i detail lat= er). +It runs on top of the Napatech NFV NIC Board Support Package that must be +installed and started. +If no Napatech NIC is available, you can download the Napatech NTAPI inclu= des +to build with. + +Supported Features +------------------ + +- RSS (Receive Side Scaling) +- TSS (Transmit Side Scaling) +- Promiscuous mode +- Basic statistics + + +Prerequisites +------------- + +Requires Napatech NIC and Napatech NIC Board Support Package installed and +running in version **0.3.0** or higher. +This includes external libraries and kernel driver for resources +allocations and initialization. +If build only is required, download the Napatech NTAPI to build against. + +Pre-Installation Configuration +------------------------------ + +Environment variables +~~~~~~~~~~~~~~~~~~~~~ + +In order to compile the Napatech NIC PMD, user must: + +* Export the environment variable NAPATECH3_PATH with the path where + the Napatech Board Support Package was installed (default location is + /opt/napatech3). + Or if no Napatech NIC available: + Download the Napatech NTAPI include files from Github: + `Napatech NTAPI `_. + + +Config File Options +~~~~~~~~~~~~~~~~~~~ + +- ``CONFIG_RTE_LIBRTE_PMD_NTNIC`` (default **n**) + +Using the NTNIC PMD from a DPDK application using EAL vdev parameter +-------------------------------------------------------------------- + +Napatech NIC PMD VDEV parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Napatech NIC PMD vdev has the following command line parameters to ena= ble +its features. + +* port + Configures which NT port the vdev should use. + + --vdev eth_ntnic0,port=3D4,rxqs=3D1,txqs=3D1 + + This will create a DPDK port0 using NT port 4 + +* rxqs + Control how many receive queues a vdev should have. The traffic from a v= dev + will be load balanced to this amount of queues and each queue can be han= dled + by its own lcore. + Note: The ntservice.ini HostBuffersRx must be configured to the sum of a= ll + receive queues across all vdevs. + + --vdev eth_ntnic0,port=3D0,rxqs=3D8,txqs=3D1 + + Traffic from NT port 0 will be split across + 8 queues meaning that 8 lcores can be + opened on DPDK port 0 and each will be + their individual traffic. + +* hash + Control which load balancing scheme should be used when running with mul= tiple + receive queues. + The possible values are: + 1 =3D HashRoundRobin + 2 =3D Hash2TupleSorted + 3 =3D Hash5TupleSorted + + --vdev eth_ntnic0,port=3D0,rxqs=3D4,hash=3D3,txqs=3D1 + + Create 4 queues from NT port 0 and + load balance the traffic using the + 5-tuple sorted algorithm. Each of the + 4 queues can be opened via DPDK port 0 + +* txqs + Control how many transmit queues a vdev should have. Each queue can be u= sed + by a lcore and each queue is independent for other queues. + Note: The ntservice.ini HostBuffersTx must be configured to the sum of a= ll + transmit queues across all vdevs. + + --vdev eth_ntnic0,port=3D0,txqs=3D32,rxqs=3D1 + + Enable 32 transmit queues on NT port 0 + + +Changes to Napatech driver configuration file ntservice.ini +----------------------------------------------------------- +Depending on the number of queues that is created, more hostbuffers may be +needed pre-allocated by the Napatech NIC Driver. This is controlled in the +ntservice.ini file (default locations is /opt/napatech3/config). +The Napatech NIC Driver must be re-started when this configuration file is +changed. + diff --git a/drivers/net/Makefile b/drivers/net/Makefile index bc93230..aff29e9 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -55,6 +55,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) +=3D thunder= x DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) +=3D virtio DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) +=3D vmxnet3 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) +=3D xenvirt +DIRS-$(CONFIG_RTE_LIBRTE_PMD_NTNIC) +=3D ntnic ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y) DIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) +=3D vhost diff --git a/drivers/net/ntnic/Makefile b/drivers/net/ntnic/Makefile new file mode 100644 index 0000000..d816c56 --- /dev/null +++ b/drivers/net/ntnic/Makefile @@ -0,0 +1,66 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Napatech A/S. 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 Napatech 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. + +include $(RTE_SDK)/mk/rte.vars.mk + +# +# library name +# +LIB =3D librte_pmd_ntnic.a + +CFLAGS +=3D -O3 -g +CFLAGS +=3D $(WERROR_FLAGS) +CFLAGS +=3D -I$(NAPATECH3_PATH)/include +CFLAGS +=3D -DNAPATECH3_LIB_PATH=3D\"$(NAPATECH3_PATH)/lib\" +LDLIBS +=3D -ldl + +EXPORT_MAP :=3D rte_pmd_ntnic_version.map + +LIBABIVER :=3D 1 + +# +# all source are stored in SRCS-y +# +SRCS-$(CONFIG_RTE_LIBRTE_PMD_NTNIC) +=3D rte_eth_ntnic.c + +# +# Export include files +# +SYMLINK-y-include +=3D + +# this lib depends upon: +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NTNIC) +=3D lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NTNIC) +=3D lib/librte_mbuf +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NTNIC) +=3D lib/librte_mempool +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NTNIC) +=3D lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NTNIC) +=3D lib/librte_kvargs + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/drivers/net/ntnic/rte_eth_ntnic.c b/drivers/net/ntnic/rte_eth_= ntnic.c new file mode 100644 index 0000000..f83e94d --- /dev/null +++ b/drivers/net/ntnic/rte_eth_ntnic.c @@ -0,0 +1,1150 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Napatech A/S. 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 Napatech 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ETH_NTNIC_PORT_ARG "port" +#define ETH_NTNIC_PORTEND_ARG "portend" +#define ETH_NTNIC_RXQUEUES_ARG "rxqs" +#define ETH_NTNIC_TXQUEUES_ARG "txqs" +#define ETH_NTNIC_STREAMID_ARG "streamid" +#define ETH_NTNIC_HASH_ARG "hash" + +#define HW_MAX_PKT_LEN 10000 +#define HW_MTU (HW_MAX_PKT_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) + +#define MAX_RX_QUEUES 64 +#define MAX_TX_QUEUES 64 +#define MAX_NTNIC_PORTS 32 + +static void *_libnt; + +/* NTAPI library functions */ +int (*_NT_Init)(uint32_t); +int (*_NT_NetRxOpen)(NtNetStreamRx_t *, + const char *, enum NtNetInterface_e, uint32_t, int); +int (*_NT_NetRxGet)(NtNetStreamRx_t, NtNetBuf_t *, int); +int (*_NT_NetRxRelease)(NtNetStreamRx_t, NtNetBuf_t); +int (*_NT_NetRxClose)(NtNetStreamRx_t); +char *(*_NT_ExplainError)(int, char *, uint32_t); +int (*_NT_NetTxOpen)(NtNetStreamTx_t *, + const char *, uint64_t, uint32_t, uint32_t); +int (*_NT_NetTxRingbufferInit)(NtNetStreamTx_t, uint32_t); +int (*_NT_NetTxRingbufferTransmitPacket)(NtNetStreamTx_t, + uint8_t *, uint16_t); +int (*_NT_NetTxRingbufferFlush)(NtNetStreamTx_t); +void (*_NT_NetTxRingbufferDone)(NtNetStreamTx_t); +int (*_NT_NetTxClose)(NtNetStreamTx_t); +int (*_NT_InfoOpen)(NtInfoStream_t *, const char *); +int (*_NT_InfoRead)(NtInfoStream_t, NtInfo_t *); +int (*_NT_InfoClose)(NtInfoStream_t); +int (*_NT_ConfigOpen)(NtConfigStream_t *, const char *); +int (*_NT_ConfigClose)(NtConfigStream_t); +int (*_NT_NTPL)(NtConfigStream_t, const char *, + NtNtplInfo_t *, uint32_t); + +static char ebuf[1024]; + +struct array_s { + uint32_t value[MAX_RX_QUEUES]; + int count; +}; + +static volatile uint16_t port_locks[MAX_NTNIC_PORTS]; + +struct ntnic_rx_queue { + NtNetStreamRx_t net_rx[MAX_RX_QUEUES]; /* NT Rx streams */ + int rx_idx; /* Current Rx stream index */ + struct rte_mempool *mb_pool; /* mbuf memory pool */ + uint16_t buf_size; /* Size of data area in mbuf */ + NtNetBuf_t seg; /* The current NT data segment */ + struct NtNetBuf_s pkt; /* The current packet */ + volatile unsigned long rx_pkts; /* Rx packet statistics */ + volatile unsigned long err_pkts; /* Rx error packet statistics */ + struct array_s astreamids; /* NT streams to read from */ + int enabled; /* Enabling/disabling of this queue= */ +}; + +struct ntnic_tx_queue { + NtNetStreamTx_t net_tx; /* NT Tx stream */ + volatile unsigned long tx_pkts; /* Tx packet statistics */ + volatile unsigned long err_pkts; /* Tx error packet stat */ + volatile uint16_t *plock; /* Per port transmit atomic lock */ + uint32_t port; /* Tx port for this queue */ + int enabled; /* Enabling/disabling of this queue= */ + int fcs_add; /* If needs added room for FCS */ +}; + +struct pmd_internals { + struct ntnic_rx_queue rxq[MAX_RX_QUEUES]; /* Array of Rx queues */ + struct ntnic_tx_queue txq[MAX_TX_QUEUES]; /* Array of Tx queues */ + int if_index; /* Itf index always 0 - no bonding */ + unsigned int nb_rx_queues; /* Number of Rx queues configured= */ + unsigned int nb_tx_queues; /* Number of Tx queues configured= */ + int MAC_50G; /* True if 50G ports */ +}; + +static const char *valid_arguments[] =3D { + ETH_NTNIC_PORT_ARG, + ETH_NTNIC_PORTEND_ARG, + ETH_NTNIC_RXQUEUES_ARG, + ETH_NTNIC_TXQUEUES_ARG, + ETH_NTNIC_STREAMID_ARG, + ETH_NTNIC_HASH_ARG, + NULL +}; + +static struct ether_addr eth_addr[MAX_NTNIC_PORTS]; +static const char *drivername =3D "NTNIC PMD"; + +static int +eth_ntnic_rx_jumbo(struct rte_mempool *mb_pool, + struct rte_mbuf *mbuf, + const u_char *data, + uint16_t data_len) +{ + struct rte_mbuf *m =3D mbuf; + + /* Copy the first segment. */ + uint16_t len =3D rte_pktmbuf_tailroom(mbuf); + + rte_memcpy(rte_pktmbuf_append(mbuf, len), data, len); + data_len -=3D len; + data +=3D len; + + while (data_len > 0) { + /* Allocate next mbuf and point to that. */ + m->next =3D rte_pktmbuf_alloc(mb_pool); + + if (unlikely(!m->next)) + return -1; + + m =3D m->next; + + /* Headroom is not needed in chained mbufs. */ + rte_pktmbuf_prepend(m, rte_pktmbuf_headroom(m)); + m->pkt_len =3D 0; + m->data_len =3D 0; + + /* Copy next segment. */ + len =3D RTE_MIN(rte_pktmbuf_tailroom(m), data_len); + rte_memcpy(rte_pktmbuf_append(m, len), data, len); + + mbuf->nb_segs++; + data_len -=3D len; + data +=3D len; + } + + return mbuf->nb_segs; +} + + + +static uint16_t +eth_ntnic_rx(void *queue, + struct rte_mbuf **bufs, + uint16_t nb_pkts) +{ + unsigned int i; + struct rte_mbuf *mbuf; + struct ntnic_rx_queue *rx_q =3D queue; + uint16_t num_rx =3D 0; + uint16_t data_len; + + if (unlikely(rx_q->net_rx[rx_q->rx_idx] =3D=3D NULL || nb_pkts =3D= =3D 0)) + return 0; + + /* Do we have any data segment */ + if (rx_q->seg =3D=3D NULL) { + /* Next stream - if multiple streams are combined */ + rx_q->rx_idx =3D + (rx_q->rx_idx < + (rx_q->astreamids.count - 1)) ? rx_q->rx_idx + 1 + : 0; + + if ((*_NT_NetRxGet)(rx_q->net_rx[rx_q->rx_idx], + &rx_q->seg, 0) !=3D NT_SUCCESS) { + if (rx_q->seg !=3D NULL) { + (*_NT_NetRxRelease)(rx_q->net_rx[rx_q->rx_i= dx], + rx_q->seg); + rx_q->seg =3D NULL; + } + return 0; + } + if (NT_NET_GET_SEGMENT_LENGTH(rx_q->seg)) { + /* Build a packet structure */ + _nt_net_build_pkt_netbuf(rx_q->seg, &rx_q->pkt); + } else { + (*_NT_NetRxRelease)(rx_q->net_rx[rx_q->rx_idx], + rx_q->seg); + rx_q->seg =3D NULL; + return 0; + } + } + + if (rte_mempool_get_bulk(rx_q->mb_pool, (void **)bufs, nb_pkts) != =3D 0) + return 0; + + for (i =3D 0; i < nb_pkts; i++) { + mbuf =3D bufs[i]; + rte_mbuf_refcnt_set(mbuf, 1); + rte_pktmbuf_reset(mbuf); + + /* HW slicing not supported */ + data_len =3D (uint16_t)NT_NET_GET_PKT_WIRE_LENGTH((&rx_q->p= kt)) + - 4; + if (data_len <=3D rx_q->buf_size) { + /* Packet will fit in the mbuf, go ahead and copy *= / + mbuf->pkt_len =3D mbuf->data_len; + data_len =3D mbuf->data_len; + rte_memcpy((u_char *)mbuf->buf_addr + + RTE_PKTMBUF_HEADROOM, + NT_NET_GET_PKT_L2_PTR((&rx_q->pkt))= , + mbuf->data_len); + } else { + /* Try read jumbo frame into multi mbufs. */ + if (unlikely(eth_ntnic_rx_jumbo(rx_q->mb_pool, + mbuf, + NT_NET_GET_PKT_L2_PTR((&rx_q->pkt))= , + data_len) =3D=3D -1)) + break; + } + + mbuf->port =3D NT_NET_GET_PKT_RXPORT((&rx_q->pkt)); + num_rx++; + + /* Get the next packet if any */ + if (_nt_net_get_next_packet(rx_q->seg, + NT_NET_GET_SEGMENT_LENGTH(rx_q->seg), + &rx_q->pkt) =3D=3D 0) { + (*_NT_NetRxRelease)(rx_q->net_rx[rx_q->rx_idx], + rx_q->seg); + rx_q->seg =3D NULL; + break; + } + + rx_q->rx_pkts++; + } + + if (num_rx < nb_pkts) { + rte_mempool_put_bulk(rx_q->mb_pool, + (void * const *)(bufs + num_rx), + nb_pkts - num_rx); + } + return num_rx; +} + + + + + +/* Callback to handle sending packets through a NT NIC. */ +static uint16_t +eth_ntnic_tx_ringbuffer(void *queue, + struct rte_mbuf **bufs, + uint16_t nb_pkts) +{ + unsigned int i; + struct ntnic_tx_queue *tx_q =3D queue; + int retval; + uint16_t old; + uint16_t new_flag =3D 0; + + + if (unlikely(tx_q =3D=3D NULL || tx_q->net_tx =3D=3D NULL || nb_pkt= s =3D=3D 0)) + return 0; + + + do { + old =3D 0; + new_flag =3D 1; + retval =3D rte_atomic16_cmpset(tx_q->plock, old, new_flag); + } while (unlikely(retval =3D=3D 0)); + + for (i =3D 0; i < nb_pkts; i++) { + /* Not allowed to TX less than 64 byte packets */ + if (bufs[i]->pkt_len < 60) + bufs[i]->pkt_len =3D 60; + + /* transmit a single packet */ + (*_NT_NetTxRingbufferTransmitPacket)(tx_q->net_tx, + rte_pktmbuf_mtod(bufs[i], uint8_t *), + bufs[i]->pkt_len + 4 - tx_q->fcs_add); + rte_pktmbuf_free(bufs[i]); + } + tx_q->tx_pkts +=3D nb_pkts; + + *tx_q->plock =3D 0; + return nb_pkts; +} + + + +static int +eth_dev_start(struct rte_eth_dev *dev) +{ + struct pmd_internals *internals =3D dev->data->dev_private; + struct ntnic_rx_queue *rx_q =3D internals->rxq; + struct ntnic_tx_queue *tx_q =3D internals->txq; + uint queue; + int status, idx; + + RTE_LOG(INFO, PMD, "NTNIC: %s\n", __func__); + + if ((internals->nb_tx_queues | internals->nb_rx_queues) =3D=3D 0) + return -1; + + for (queue =3D 0; queue < internals->nb_rx_queues; queue++) { + if (rx_q[queue].enabled) { + char str[128], val[10]; + str[0] =3D 0; + /* build list of streamids to log */ + for (idx =3D 0; idx < + rx_q[queue].astreamids.count; idx++) { + if (idx) + sprintf(val, ",%d", + rx_q[queue].astreamids.value[idx]); + else + sprintf(val, "%i", + rx_q[queue].astreamids.value[idx]); + strcat(str, val); + } + + for (idx =3D 0; idx < rx_q[queue].astreamids.count; + idx++) { + status =3D + (*_NT_NetRxOpen)(&rx_q[queue].net_rx[idx], + "DPDK", + NT_NET_INTERFACE_SEGMENT, + rx_q[queue].astreamids.value[idx], = -1); + if (status !=3D NT_SUCCESS) { + /* try packet interface instead */ + (*_NT_ExplainError)(status, + ebuf, + sizeof(ebuf)); + RTE_LOG(ERR, PMD, + "NT_NetRxOpen() failed: %s\= n", + ebuf); + return -1; + } + } + } + } + + for (queue =3D 0; queue < internals->nb_tx_queues; queue++) { + if (tx_q[queue].enabled) { + RTE_LOG(INFO, PMD, "NTNIC: NT_NetTxOpen(%d)\n", + tx_q[queue].port); + status =3D (*_NT_NetTxOpen)(&tx_q[queue].net_tx, "D= PDK", + 1 << tx_q[queue].port, + dev->pci_dev->numa_node, 0); + if (status !=3D NT_SUCCESS) { + (*_NT_ExplainError)(status, ebuf, + sizeof(ebuf)); + RTE_LOG(INFO, PMD, + "NT_NetTxOpen(0x%X, %d, 0) failed: %s\n", + 1 << tx_q[queue].port, + dev->pci_dev->numa_node, ebuf); + return -1; + } + + /* Init and associate RTD Tx Ring buf to Tx handler= */ + status =3D (*_NT_NetTxRingbufferInit)( + tx_q[queue].net_tx, + tx_q[queue].port); + if (status !=3D NT_SUCCESS) { + (*_NT_ExplainError)(status, ebuf, + sizeof(ebuf)); + RTE_LOG(ERR, PMD, + "NT_NetRxOpen() failed: %s\n", + ebuf); + return -1; + } + } + tx_q[queue].plock =3D &port_locks[tx_q[queue].port]; + tx_q[queue].fcs_add =3D (internals->MAC_50G) ? 4 : 0; + } + + dev->data->dev_link.link_status =3D 1; + return 0; +} + + +static void +eth_dev_stop(struct rte_eth_dev *dev) +{ + struct pmd_internals *internals =3D dev->data->dev_private; + struct ntnic_rx_queue *rx_q =3D internals->rxq; + struct ntnic_tx_queue *tx_q =3D internals->txq; + uint q; + int idx; + RTE_LOG(INFO, PMD, "NTNIC: %s\n", __func__); + + for (q =3D 0; q < internals->nb_rx_queues; q++) { + if (rx_q[q].seg) { + (*_NT_NetRxRelease)(rx_q[q].net_rx[rx_q->rx_idx], + rx_q[q].seg); + rx_q[q].seg =3D NULL; + } + for (idx =3D 0; idx < rx_q[q].astreamids.count; idx++) { + if (rx_q[q].net_rx[idx]) + (void)(*_NT_NetRxClose)(rx_q[q].net_rx[idx]); + } + } + for (q =3D 0; q < internals->nb_tx_queues; q++) { + if (tx_q[q].net_tx) { + (*_NT_NetTxRingbufferDone)(tx_q[q].net_tx); + (void)(*_NT_NetTxClose)(tx_q[q].net_tx); + } + } + dev->data->dev_link.link_status =3D 0; +} + +static int +eth_dev_configure(struct rte_eth_dev *dev __rte_unused) +{ + RTE_LOG(INFO, PMD, "NTNIC: %s\n", __func__); + return 0; +} + +static void +eth_dev_info(struct rte_eth_dev *dev, + struct rte_eth_dev_info *dev_info) +{ + struct pmd_internals *internals =3D dev->data->dev_private; + dev_info->if_index =3D internals->if_index; + dev_info->driver_name =3D drivername; + dev_info->max_mac_addrs =3D 1; + dev_info->max_rx_pktlen =3D HW_MTU; + dev_info->max_rx_queues =3D (uint16_t)internals->nb_rx_queues; + dev_info->max_tx_queues =3D (uint16_t)internals->nb_tx_queues; + dev_info->min_rx_bufsize =3D 0; + dev_info->pci_dev =3D NULL; +} + +static void +eth_stats_get(struct rte_eth_dev *dev, + struct rte_eth_stats *igb_stats) +{ + unsigned int i; + unsigned long rx_total =3D 0; + unsigned long tx_total =3D 0; + unsigned long tx_err_total =3D 0; + const struct pmd_internals *internal =3D dev->data->dev_private; + + memset(igb_stats, 0, sizeof(*igb_stats)); + for (i =3D 0; + i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internal->nb_rx_queu= es; + i++) { + igb_stats->q_ipackets[i] =3D internal->rxq[i].rx_pkts; + rx_total +=3D igb_stats->q_ipackets[i]; + } + for (i =3D 0; + i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internal->nb_tx_queu= es; + i++) { + igb_stats->q_opackets[i] =3D internal->txq[i].tx_pkts; + igb_stats->q_errors[i] =3D internal->txq[i].err_pkts; + tx_total +=3D igb_stats->q_opackets[i]; + tx_err_total +=3D igb_stats->q_errors[i]; + } + + igb_stats->ipackets =3D rx_total; + igb_stats->opackets =3D tx_total; + igb_stats->oerrors =3D tx_err_total; +} + +static void +eth_stats_reset(struct rte_eth_dev *dev) +{ + unsigned int i; + struct pmd_internals *internal =3D dev->data->dev_private; + + for (i =3D 0; i < internal->nb_rx_queues; i++) + internal->rxq[i].rx_pkts =3D 0; + for (i =3D 0; i < internal->nb_tx_queues; i++) { + internal->txq[i].tx_pkts =3D 0; + internal->txq[i].err_pkts =3D 0; + } +} + +static void +eth_dev_close(struct rte_eth_dev *dev __rte_unused) +{ + RTE_LOG(INFO, PMD, "NTNIC: %s\n", __func__); +} + +static void +eth_queue_release(void *q __rte_unused) +{ + RTE_LOG(INFO, PMD, "NTNIC: %s\n", __func__); +} + +static int +eth_link_update(struct rte_eth_dev *dev __rte_unused, + int wait_to_complete __rte_unused) +{ + return 0; +} + +static int +eth_rx_queue_setup(struct rte_eth_dev *dev, + uint16_t rx_queue_id, + uint16_t nb_rx_desc __rte_unused, + unsigned int socket_id __rte_unused, + const struct rte_eth_rxconf *rx_conf __rte_unused, + struct rte_mempool *mb_pool) +{ + struct rte_pktmbuf_pool_private *mbp_priv; + struct pmd_internals *internals =3D dev->data->dev_private; + struct ntnic_rx_queue *rx_q =3D &internals->rxq[rx_queue_id]; + + RTE_LOG(INFO, PMD, "NTNIC RX queue setup\n"); + rx_q->mb_pool =3D mb_pool; + dev->data->rx_queues[rx_queue_id] =3D rx_q; + + mbp_priv =3D rte_mempool_get_priv(rx_q->mb_pool); + rx_q->buf_size =3D (uint16_t)(mbp_priv->mbuf_data_room_size - + RTE_PKTMBUF_HEADROOM); + rx_q->enabled =3D 1; + return 0; +} + +static int +eth_tx_queue_setup(struct rte_eth_dev *dev __rte_unused, + uint16_t tx_queue_id __rte_unused, + uint16_t nb_tx_desc __rte_unused, + unsigned int socket_id __rte_unused, + const struct rte_eth_txconf *tx_conf __rte_unused) +{ + struct pmd_internals *internals =3D dev->data->dev_private; + RTE_LOG(INFO, PMD, "NTNIC TX queue setup\n"); + dev->data->tx_queues[tx_queue_id] =3D &internals->txq[tx_queue_id]; + internals->txq[tx_queue_id].enabled =3D 1; + return 0; +} + +static int _dev_set_mtu(struct rte_eth_dev *dev __rte_unused, uint16_t mtu= ) +{ + if (mtu < 46 || mtu > HW_MTU) + return -EINVAL; + + return 0; +} + +static struct eth_dev_ops ops =3D { + .dev_start =3D eth_dev_start, + .dev_stop =3D eth_dev_stop, + .dev_close =3D eth_dev_close, + .mtu_set =3D _dev_set_mtu, + .dev_configure =3D eth_dev_configure, + .dev_infos_get =3D eth_dev_info, + .rx_queue_setup =3D eth_rx_queue_setup, + .tx_queue_setup =3D eth_tx_queue_setup, + .rx_queue_release =3D eth_queue_release, + .tx_queue_release =3D eth_queue_release, + .link_update =3D eth_link_update, + .stats_get =3D eth_stats_get, + .stats_reset =3D eth_stats_reset, +}; + +static int +rte_pmd_init_internals(const char *name, + const unsigned int nb_rx_queues, + const unsigned int nb_tx_queues, + const unsigned int numa_node, + struct array_s *pastreamids, + const uint32_t port, + struct rte_eth_dev **eth_dev) +{ + struct pmd_internals *internals =3D NULL; + struct rte_eth_dev_data *data =3D NULL; + struct rte_pci_device *pci_dev =3D NULL; + uint i, status; + char err_buf[NT_ERRBUF_SIZE]; + NtInfoStream_t info; + NtInfo_t info_port; + struct rte_eth_link pmd_link; + assert(nb_rx_queues < MAX_RX_QUEUES); + assert(nb_tx_queues < MAX_TX_QUEUES); + assert(port < MAX_NTNIC_PORTS); + + RTE_LOG(INFO, PMD, + "Creating ntnic-backend ethdev on numa socket %u\n"= , + numa_node); + + /* now do all data allocation - for eth_dev structure, dummy pci dr= iver + * and internal (private) data + */ + data =3D rte_zmalloc_socket(name, sizeof(*data), 0, numa_node); + if (data =3D=3D NULL) + goto error; + + pci_dev =3D rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node= ); + if (pci_dev =3D=3D NULL) + goto error; + + internals =3D rte_zmalloc_socket(name, sizeof(*internals), 0, numa_= node); + if (internals =3D=3D NULL) + goto error; + + /* reserve an ethdev entry */ + *eth_dev =3D rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL); + if (*eth_dev =3D=3D NULL) + goto error; + + /* Open the information stream */ + status =3D (*_NT_InfoOpen)(&info, "DPDK Info stream"); + if (status !=3D NT_SUCCESS) { + (*_NT_ExplainError)(status, err_buf, sizeof(err_buf)); + RTE_LOG(ERR, PMD, + ">>> Error: NT_InfoOpen failed. Code 0x%x =3D %s\n"= , + status, err_buf); + return status; + } + + /* Find local port offset */ + info_port.cmd =3D NT_INFO_CMD_READ_PORT_V7; + info_port.u.port_v7.portNo =3D (uint8_t)(port); + status =3D (*_NT_InfoRead)(info, &info_port); + if (status !=3D 0) { + (*_NT_ExplainError)(status, err_buf, sizeof(err_buf)); + RTE_LOG(ERR, PMD, + "ERROR: NT_InfoRead failed. Code 0x%x =3D %s\n", + status, err_buf); + return status; + } + + /* check for 50G MAC */ + if (info_port.u.port_v7.data.adapterInfo.fpgaid.s.product =3D=3D 95= 06 || + info_port.u.port_v7.data.adapterInfo.fpgaid.s.product =3D= =3D 9509) { + internals->MAC_50G =3D 1; + } else { + internals->MAC_50G =3D 0; + /* Check for valid FPGAs (NFV NICs) */ + if (info_port.u.port_v7.data.adapterInfo.fpgaid.s.product != =3D + 9507 && + info_port.u.port_v7.data.adapterInfo.fpgaid.s.produ= ct !=3D + 9510) { + RTE_LOG(ERR, PMD, + "ERROR: NTNIC PMD does not support the NT adapter" + "- port %i\n", + port); + return -1; + } + } + + internals->nb_rx_queues =3D nb_rx_queues; + internals->nb_tx_queues =3D nb_tx_queues; + for (i =3D 0; i < nb_rx_queues; i++) { + int idx; + for (idx =3D 0; idx < pastreamids->count; idx++) { + internals->rxq[i].astreamids.value[idx] =3D + pastreamids->value[idx] + i; + } + + internals->rxq[i].astreamids.count =3D pastreamids->count; + + internals->rxq[i].seg =3D NULL; + internals->rxq[i].enabled =3D 0; + } + + for (i =3D 0; i < nb_tx_queues; i++) { + if (port < info_port.u.port_v7.data.adapterInfo.portOffset) { + RTE_LOG(ERR, PMD, "Error wrong port specified\n"); + return -1; + } + internals->txq[i].port =3D port; + internals->txq[i].enabled =3D 0; + } + + switch (info_port.u.port_v7.data.speed) { + case NT_LINK_SPEED_UNKNOWN: + pmd_link.link_speed =3D ETH_SPEED_NUM_1G; + break; + case NT_LINK_SPEED_10M: + pmd_link.link_speed =3D ETH_SPEED_NUM_10M; + break; + case NT_LINK_SPEED_100M: + pmd_link.link_speed =3D ETH_SPEED_NUM_100M; + break; + case NT_LINK_SPEED_1G: + pmd_link.link_speed =3D ETH_SPEED_NUM_1G; + break; + case NT_LINK_SPEED_10G: + pmd_link.link_speed =3D ETH_SPEED_NUM_10G; + break; + case NT_LINK_SPEED_40G: + pmd_link.link_speed =3D ETH_SPEED_NUM_40G; + break; + case NT_LINK_SPEED_50G: + pmd_link.link_speed =3D ETH_SPEED_NUM_50G; + break; + case NT_LINK_SPEED_100G: + pmd_link.link_speed =3D ETH_SPEED_NUM_100G; + break; + } + + memcpy(ð_addr[port].addr_bytes, &info_port.u.port_v7.data.macAdd= ress, + sizeof(eth_addr[port].addr_bytes)); + status =3D (*_NT_InfoClose)(info); + if (status !=3D NT_SUCCESS) { + (*_NT_ExplainError)(status, err_buf, sizeof(err_buf)); + RTE_LOG(ERR, PMD, + ">>> Error: NT_InfoOpen failed. Code 0x%x =3D %s\n"= , + status, err_buf); + return status; + } + + pmd_link.link_duplex =3D ETH_LINK_FULL_DUPLEX; + pmd_link.link_status =3D 0; + + internals->if_index =3D 0; + + pci_dev->numa_node =3D numa_node; + + data->dev_private =3D internals; + data->port_id =3D (*eth_dev)->data->port_id; + data->nb_rx_queues =3D (uint16_t)nb_rx_queues; + data->nb_tx_queues =3D (uint16_t)nb_tx_queues; + data->dev_link =3D pmd_link; + data->mac_addrs =3D ð_addr[port]; + data->numa_node =3D numa_node; + data->drv_name =3D drivername; + + (*eth_dev)->data =3D data; + (*eth_dev)->dev_ops =3D &ops; + (*eth_dev)->pci_dev =3D pci_dev; + + return 0; + +error: + if (data) + rte_free(data); + if (pci_dev) + rte_free(pci_dev); + if (internals) + rte_free(internals); + return -1; +} + +/* + * convert ascii to int + */ +static inline int +ascii_to_u32(const char *key __rte_unused, + const char *value, void *extra_args __rte_unused) +{ + *(uint32_t *)extra_args =3D atoi(value); + return 0; +} + +static inline int +ascii_to_u32_array(const char *key __rte_unused, + const char *value, void *extra_args) +{ + struct array_s *pastreams =3D (struct array_s *)extra_args; + int sval, eval; + if (sscanf(value, "%d..%d", &sval, &eval) =3D=3D 2) { + int cnt; + for (cnt =3D sval; cnt <=3D eval; cnt++) + pastreams->value[pastreams->count++] =3D cnt; + } else { + pastreams->value[pastreams->count++] =3D atoi(value); + } + return 0; +} + + +static int DoNtpl(const char *ntplStr) +{ + NtConfigStream_t hCfgStream; + NtNtplInfo_t ntplInfo; + int status; + + status =3D (*_NT_ConfigOpen)(&hCfgStream, "capture"); + if (status !=3D NT_SUCCESS) { + /* Get the status code as text */ + (*_NT_ExplainError)(status, ebuf, sizeof(ebuf) - 1); + fprintf(stderr, "NT_ConfigOpen() failed: %s\n", ebuf); + return -1; + } + + RTE_LOG(INFO, PMD, "NTPL : %s\n", ntplStr); + status =3D (*_NT_NTPL)(hCfgStream, ntplStr, &ntplInfo, + NT_NTPL_PARSER_VALIDATE_NORMAL); + if (status !=3D NT_SUCCESS) { + /* Get the status code as text */ + (*_NT_ExplainError)(status, ebuf, sizeof(ebuf) - 1); + fprintf(stderr, "NT_NTPL() failed: %s\n", ebuf); + fprintf(stderr, ">>> NTPL errorcode: %X\n", + ntplInfo.u.errorData.errCode); + fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[= 0]); + fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[= 1]); + fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[= 2]); + (*_NT_ConfigClose)(hCfgStream); + return -1; + } + (*_NT_ConfigClose)(hCfgStream); + return 0; +} + + +static int +_nt_lib_open(void) +{ + char path[128]; + strcpy(path, NAPATECH3_LIB_PATH); + strcat(path, "/libntapi.so"); + + /* Load the library */ + _libnt =3D dlopen(path, RTLD_NOW); + if (_libnt =3D=3D NULL) { + /* Library does not exist. */ + fprintf(stderr, "Failed to find needed library : %s\n", pat= h); + return -1; + } + _NT_Init =3D dlsym(_libnt, "NT_Init"); + if (_NT_Init =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_Init\" in %s\n", path)= ; + return -1; + } + + _NT_ConfigOpen =3D dlsym(_libnt, "NT_ConfigOpen"); + if (_NT_ConfigOpen =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_ConfigOpen\" in %s\n", + path); + return -1; + } + _NT_ConfigClose =3D dlsym(_libnt, "NT_ConfigClose"); + if (_NT_ConfigClose =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_ConfigClose\" in %s\n"= , + path); + return -1; + } + _NT_NTPL =3D dlsym(_libnt, "NT_NTPL"); + if (_NT_NTPL =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_NTPL\" in %s\n", + path); + return -1; + } + + _NT_InfoOpen =3D dlsym(_libnt, "NT_InfoOpen"); + if (_NT_InfoOpen =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_InfoOpen\" in %s\n", + path); + return -1; + } + _NT_InfoRead =3D dlsym(_libnt, "NT_InfoRead"); + if (_NT_InfoRead =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_InfoRead\" in %s\n", + path); + return -1; + } + _NT_InfoClose =3D dlsym(_libnt, "NT_InfoClose"); + if (_NT_InfoClose =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_InfoClose\" in %s\n", + path); + return -1; + } + + _NT_ExplainError =3D dlsym(_libnt, "NT_ExplainError"); + if (_NT_ExplainError =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_ExplainError\" in %s\n= ", + path); + return -1; + } + _NT_NetTxOpen =3D dlsym(_libnt, "NT_NetTxOpen"); + if (_NT_NetTxOpen =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_NetTxOpen\" in %s\n", + path); + return -1; + } + _NT_NetTxRingbufferInit =3D dlsym(_libnt, "NT_NetTxRingbufferInit")= ; + if (_NT_NetTxRingbufferInit =3D=3D NULL) { + fprintf(stderr, + "Failed to find \"NT_NetTxRingbufferInit\" in %s\n"= , + path); + return -1; + } + _NT_NetTxRingbufferFlush =3D dlsym(_libnt, "NT_NetTxRingbufferFlush= "); + if (_NT_NetTxRingbufferFlush =3D=3D NULL) { + fprintf(stderr, + "Failed to find \"NT_NetTxRingbufferFlush\" in %s\n= ", + path); + return -1; + } + _NT_NetTxRingbufferTransmitPacket =3D + dlsym(_libnt, "NT_NetTxRingbufferTransmitPacket"); + if (_NT_NetTxRingbufferTransmitPacket =3D=3D NULL) { + fprintf(stderr, + "Failed to find \"NT_NetTxRingbufferTransmitPacket\= "" + " in %s\n", path); + return -1; + } + _NT_NetTxRingbufferDone =3D dlsym(_libnt, "NT_NetTxRingbufferDone")= ; + if (_NT_NetTxRingbufferDone =3D=3D NULL) { + fprintf(stderr, + "Failed to find \"NT_NetTxRingbufferDone\" in %s\n"= , + path); + return -1; + } + _NT_NetTxClose =3D dlsym(_libnt, "NT_NetTxClose"); + if (_NT_NetTxClose =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_NetTxClose\" in %s\n", + path); + return -1; + } + + _NT_NetRxOpen =3D dlsym(_libnt, "NT_NetRxOpen"); + if (_NT_NetRxOpen =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_NetRxOpen\" in %s\n", + path); + return -1; + } + _NT_NetRxGet =3D dlsym(_libnt, "NT_NetRxGet"); + if (_NT_NetRxGet =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_NetRxGet\" in %s\n", + path); + return -1; + } + _NT_NetRxRelease =3D dlsym(_libnt, "NT_NetRxRelease"); + if (_NT_NetRxRelease =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_NetRxRelease\" in %s\n= ", + path); + return -1; + } + _NT_NetRxClose =3D dlsym(_libnt, "NT_NetRxClose"); + if (_NT_NetRxClose =3D=3D NULL) { + fprintf(stderr, "Failed to find \"NT_NetRxClose\" in %s\n", + path); + return -1; + } + + return 0; +} + + + +static int +rte_pmd_ntnic_devinit(const char *name, const char *params) +{ + unsigned int numa_node; + int ret =3D 0; + struct rte_kvargs *kvlist; + struct rte_eth_dev *eth_dev; + unsigned int i; + uint32_t rxqueues =3D 0; + uint32_t txqueues =3D 0; + uint32_t port =3D 0; + uint32_t portend =3D (uint32_t)-1; + uint32_t hash =3D (uint32_t)-1; + struct array_s astreamids; + + static int first =3D 1; + static int stream_id; + char ntplStr[512]; + + astreamids.count =3D 0; + + RTE_LOG(INFO, PMD, "Initializing pmd_ntnic for %s\n", name); + + numa_node =3D rte_socket_id(); + + kvlist =3D rte_kvargs_parse(params, valid_arguments); + if (kvlist =3D=3D NULL) + return -1; + + /* Get port to use for Rx/Tx */ + i =3D rte_kvargs_count(kvlist, ETH_NTNIC_PORT_ARG); + if (i) { + assert(i =3D=3D 1); + ret =3D rte_kvargs_process(kvlist, ETH_NTNIC_PORT_ARG, + &ascii_to_u32, &port); + } + /* If Rx port merge is need, her the portend is specified */ + i =3D rte_kvargs_count(kvlist, ETH_NTNIC_PORTEND_ARG); + if (i) { + assert(i =3D=3D 1); + ret =3D rte_kvargs_process(kvlist, ETH_NTNIC_PORTEND_ARG, + &ascii_to_u32, &portend); + } + + /* Get # RX queues */ + i =3D rte_kvargs_count(kvlist, ETH_NTNIC_RXQUEUES_ARG); + if (i) { + assert(i =3D=3D 1); + ret =3D rte_kvargs_process(kvlist, ETH_NTNIC_RXQUEUES_ARG, + &ascii_to_u32, &rxqueues); + } + /* Get # TX queues */ + i =3D rte_kvargs_count(kvlist, ETH_NTNIC_TXQUEUES_ARG); + if (i) { + assert(i =3D=3D 1); + ret =3D rte_kvargs_process(kvlist, ETH_NTNIC_TXQUEUES_ARG, + &ascii_to_u32, &txqueues); + } + + /* Get list of streamIds - if used */ + i =3D rte_kvargs_count(kvlist, ETH_NTNIC_STREAMID_ARG); + if (i) { + ret =3D rte_kvargs_process(kvlist, ETH_NTNIC_STREAMID_ARG, + &ascii_to_u32_array, &astreamids); + } + + /* Get an alternative hash algorithm */ + i =3D rte_kvargs_count(kvlist, ETH_NTNIC_HASH_ARG); + if (i) { + assert(i =3D=3D 1); + ret =3D rte_kvargs_process(kvlist, ETH_NTNIC_HASH_ARG, + &ascii_to_u32, &hash); + } + + /* check portend and streamids */ + if (portend !=3D (uint32_t)-1 && astreamids.count) { + RTE_LOG(ERR, PMD, "Cannot specify portend when one or more" + " streamid's are specified\n"); + return -1; + } + rte_kvargs_free(kvlist); + + if (ret < 0) + return -1; + + ret =3D _nt_lib_open(); + if (ret < 0) + return -1; + + if (first) + (*_NT_Init)(NTAPI_VERSION); + + if (astreamids.count) { + first =3D 0; + /* + * if a specific streamid specified then use that otherwise= , + * port defaults to Tx port only + */ + if (rte_pmd_init_internals(name, rxqueues, txqueues, numa_n= ode, + &astreamids, port, ð_dev) < 0) + return -1; + } else { + struct array_s astrids; + if (first) { + /* Delete all NTPL */ + sprintf(ntplStr, "Delete=3DAll"); + if (DoNtpl(ntplStr) !=3D 0) + return -1; + first =3D 0; + } + astrids.count =3D 1; + astrids.value[0] =3D stream_id; + if (rte_pmd_init_internals(name, rxqueues, txqueues, numa_n= ode, + &astrids, port, ð_dev) < 0) + return -1; + + /* Assign the traffic */ + if (portend !=3D (uint32_t)-1) { + sprintf(ntplStr, + "Assign[streamid=3D(%d..%d);Descriptor=3DNT= ]" + "=3Dport=3D=3D(%d..%d)", + stream_id, + (stream_id + rxqueues - 1), port, portend); + + } else { + sprintf(ntplStr, + "Assign[streamid=3D(%d..%d);Descriptor=3DNT= ]" + "=3Dport=3D=3D%d", + stream_id, + (stream_id + rxqueues - 1), port); + } + if (DoNtpl(ntplStr) !=3D 0) + return -1; + + if (hash !=3D (uint32_t)-1) { + switch (hash) { + default: + case 1: + DoNtpl("HashMode=3DHashRoundRobin"); + break; + case 2: + DoNtpl("HashMode=3DHash2TupleSorted"); + break; + case 3: + DoNtpl("HashMode=3DHash5TupleSorted"); + break; + } + } + + stream_id +=3D rxqueues; + } + + eth_dev->rx_pkt_burst =3D eth_ntnic_rx; + eth_dev->tx_pkt_burst =3D eth_ntnic_tx_ringbuffer; + + return 0; +} + +static int +rte_pmd_ntnic_devuninit(const char *name) +{ + (void)name; + if (_libnt !=3D NULL) + dlclose(_libnt); + return 0; +} + + +static struct rte_driver pmd_ntnic_drv =3D { + .type =3D PMD_VDEV, + .init =3D rte_pmd_ntnic_devinit, + .uninit =3D rte_pmd_ntnic_devuninit, +}; + +PMD_REGISTER_DRIVER(pmd_ntnic_drv, eth_ntnic); +DRIVER_REGISTER_PARAM_STRING(eth_ntnic, + "port=3D " + "rxqs=3D" + "txqs=3D" + "hash=3D" + "streamids=3D"); + diff --git a/drivers/net/ntnic/rte_pmd_ntnic_version.map b/drivers/net/ntni= c/rte_pmd_ntnic_version.map new file mode 100644 index 0000000..ef35398 --- /dev/null +++ b/drivers/net/ntnic/rte_pmd_ntnic_version.map @@ -0,0 +1,4 @@ +DPDK_2.0 { + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 1a0095b..9ef357f 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -120,6 +120,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) +=3D -lrte_= pmd_mpipe -lgxio _LDLIBS-$(CONFIG_RTE_LIBRTE_NFP_PMD) +=3D -lrte_pmd_nfp -lm _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NULL) +=3D -lrte_pmd_null _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) +=3D -lrte_pmd_pcap -lpcap + _LDLIBS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) +=3D -lrte_pmd_qede -lz _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_RING) +=3D -lrte_pmd_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) +=3D -lrte_pmd_szedata2 -lsze2 @@ -143,6 +144,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_KASUMI) +=3D -lrte_= pmd_kasumi _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_KASUMI) +=3D -L$(LIBSSO_KASUMI_PATH)/b= uild -lsso_kasumi endif # CONFIG_RTE_LIBRTE_CRYPTODEV +_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NTNIC) +=3D -lrte_pmd_ntnic endif # !CONFIG_RTE_BUILD_SHARED_LIBS _LDLIBS-y +=3D --no-whole-archive @@ -163,6 +165,7 @@ endif _LDLIBS-$(CONFIG_RTE_PORT_PCAP) +=3D -lpcap endif # !CONFIG_RTE_BUILD_SHARED_LIBS + _LDLIBS-y +=3D $(EXECENV_LDLIBS) LDLIBS +=3D $(_LDLIBS-y) $(CPU_LDLIBS) $(EXTRA_LDLIBS) -- 2.9.0 Disclaimer: This email and any files transmitted with it may contain confid= ential information intended for the addressee(s) only. The information is n= ot to be surrendered or copied to unauthorized persons. If you have receive= d this communication in error, please notify the sender immediately and del= ete this e-mail from your system.