From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail01.napatech.com (mail01.napatech.com [188.120.77.121]) by dpdk.org (Postfix) with ESMTP id 0F6132B9C for ; Sat, 10 Sep 2016 09:58:52 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2FAAgCvu9NX/1QB8ApeGgEBAQECAQEBAYMtAQEBAQF1fAeNLKMbh32BQkEggXNUgzYCgXoUAQIBAQEBAQEBA4ECglUBOTsBAQEBAQEBIwINIjwBAQEBAw4MAQwTKxQMBAIBCA4DBAEBAR4JBzIUCQgCBA4FCAwHiD3AagEBAQEBAQEBAQEBAQEBAQEBAQEBARyGMIRPhAgKCgcBhXgFiCoHhXuBOol9hiWDAoJ/gx+BdRc3hBKDNoVejFWDex6DJwEbgU5wAYU6D4EgfwEBAQ X-IPAS-Result: A2FAAgCvu9NX/1QB8ApeGgEBAQECAQEBAYMtAQEBAQF1fAeNLKMbh32BQkEggXNUgzYCgXoUAQIBAQEBAQEBA4ECglUBOTsBAQEBAQEBIwINIjwBAQEBAw4MAQwTKxQMBAIBCA4DBAEBAR4JBzIUCQgCBA4FCAwHiD3AagEBAQEBAQEBAQEBAQEBAQEBAQEBARyGMIRPhAgKCgcBhXgFiCoHhXuBOol9hiWDAoJ/gx+BdRc3hBKDNoVejFWDex6DJwEbgU5wAYU6D4EgfwEBAQ Received: from cph-gen-exch02.napatech.com (10.240.1.84) by cph-gen-exch02.napatech.com (10.240.1.84) with Microsoft SMTP Server (TLS) id 15.1.396.30; Sat, 10 Sep 2016 09:58:38 +0200 Received: from cph-gen-exch02.napatech.com ([fe80::581:51a1:ac3f:84e]) by cph-gen-exch02.napatech.com ([fe80::581:51a1:ac3f:84e%12]) with mapi id 15.01.0396.030; Sat, 10 Sep 2016 09:58:38 +0200 From: Finn Christensen To: Neil Horman CC: "dev@dpdk.org" , "thomas.monjalon@6wind.com" , "stephen@networkplumber.org" Thread-Topic: [PATCH v3] ntnic: add PMD driver Thread-Index: AQHSCpjTzYbwHLfWUk6/dlutQqK7kqBxC7UAgAFDdiA= Date: Sat, 10 Sep 2016 07:58:38 +0000 Message-ID: References: <20160908111424.14127-1-fc@napatech.com> <20160909124838.13123-1-fc@napatech.com> <20160909135108.GA15908@hmsreliant.think-freely.org> In-Reply-To: <20160909135108.GA15908@hmsreliant.think-freely.org> Accept-Language: da-DK, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.240.10.146] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [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: Sat, 10 Sep 2016 07:58:52 -0000 > -----Original Message----- > From: Neil Horman [mailto:nhorman@tuxdriver.com] > Sent: 9. september 2016 15:51 > To: Finn Christensen > Cc: dev@dpdk.org; thomas.monjalon@6wind.com; > stephen@networkplumber.org > Subject: Re: [PATCH v3] ntnic: add PMD driver > > On Fri, Sep 09, 2016 at 12:48:38PM +0000, Finn Christensen wrote: > > 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 > So, this is a step in the right direction, but I think its solving the wr= ong > problem. If you have a dependency on an external library, thats ok, and > accessing it via dlopen makes it possible to build the library without ha= ving > that library present, but it not really in keeping with the spirit of wha= t I > meant. This driver is still effectively dependent on a binary blob that = we > have > no visibility into. The better solution is releasing the source for the = ntnic > and ntos libraries. The license file in the referenced git tree indicate= s its > BSD licensed, so I don't think there should be a problem in doing that. > > Neil > No, unfortunately the ntapi is not BSD licensed, only the header files that you can freely download are. We are building this NT NIC by using parts or our technology from our capture adapters and that is using closed source software. We are new to opensource and we want to go that way, but we haven't yet a complete stand-alone driver ready that we can put into the DPDK PMD to have a complete self contained and open sourced DPDK PMD, that only needs the actual HW NIC plugged in to run. Therefore this version is implemented as a virtual device, exactly like the PCAP PMD driver is, and it runs on top of a driver that follows the NIC its= elf. In regards to the DPDK functionality we do not see that anything is missing= . I cannot either see where we should add source code, because it is not part of the DPDK package and it should not be either. One of the things I really liked about the DPDK open source project is that= it uses BSD licensing not GPL. Therefore, I must admit, we completely failed to see that the "spirit" of the DPDK community is not really BSD. Our view of this community was that the main driving force of it was to be able to make DPDK run on everything anywhere effectively, in a global contributing community, without any legally constrains prohibiting us to do so. However, this is our standing, and I don't know what else to do. Please advise or NAK this PMD. Finn > > --- > > 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 copyrigh= t > > + 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 > support > > +for **Napatech NIC** 40/50 Gbps adapters. > > +This PMD is implemented as a pure software virtual device and must be > created > > +by using the EAL --vdev=3Dparameter (parameters are explained i detail > later). > > +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 > includes > > +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 agains= t. > > + > > +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 i= s > > + /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 enable > > +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 > vdev > > + will be load balanced to this amount of queues and each queue can be > handled > > + by its own lcore. > > + Note: The ntservice.ini HostBuffersRx must be configured to the sum = of > all > > + 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 > multiple > > + 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 used > > + by a lcore and each queue is independent for other queues. > > + Note: The ntservice.ini HostBuffersTx must be configured to the sum = of > all > > + 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 fil= e 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 thunderx > > 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 copyri= ght > > +# notice, this list of conditions and the following disclaimer i= n > > +# 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 derive= d > > +# 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 withou= t > > + * modification, are permitted provided that the following condition= s > > + * are met: > > + * > > + * * Redistributions of source code must retain the above copyrigh= t > > + * notice, this list of conditions and the following disclaimer. > > + * * Redistributions in binary form must reproduce the above copyr= ight > > + * 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 deriv= ed > > + * 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 q= ueue */ > > +}; > > + > > +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 q= ueue */ > > + 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 bondin= g */ > > + unsigned int nb_rx_queues; /* Number of Rx queues config= ured > */ > > + unsigned int nb_tx_queues; /* Number of Tx queues config= ured > */ > > + 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_idx], > > + 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- > >pkt)) > > + - 4; > > + if (data_len <=3D rx_q->buf_size) { > > + /* Packet will fit in the mbuf, go ahead and co= py */ > > + 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->p= kt)), > > + 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->p= kt)), > > + 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= _pkts =3D=3D 0)) > > + return 0; > > + > > + > > + do { > > + old =3D 0; > > + new_flag =3D 1; > > + retval =3D rte_atomic16_cmpset(tx_q->plock, old, new_fl= ag); > > + } 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[id= x]); > > + else > > + sprintf(val, "%i", > > + rx_q[queue].astreamids.value[id= x]); > > + strcat(str, val); > > + } > > + > > + for (idx =3D 0; idx < rx_q[queue].astreamids.co= unt; > > + idx++) { > > + status =3D > > + (*_NT_NetRxOpen)(&rx_q[queue].net_rx[id= x], > > + "DPDK", > > + NT_NET_INTERFACE_SEGMENT, > > + rx_q[queue].astreamids.value[id= x], -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= , "DPDK", > > + 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 han= dler */ > > + 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_queues; > > + 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_queues; > > + 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 pc= i driver > > + * 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 9506 || > > + 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.produ= ct !=3D > > + 9507 && > > + info_port.u.port_v7.data.adapterInfo.fpgaid.s.p= roduct !=3D > > + 9510) { > > + RTE_LOG(ERR, PMD, > > + "ERROR: NTNIC PMD does not support the NT adapt= er" > > + "- 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->cou= nt; > > + > > + 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.macAddress, > > + 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.errBuf= fer[0]); > > + fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuf= fer[1]); > > + fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuf= fer[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",= path); > > + 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", p= ath); > > + 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_NetTxRingbufferIn= it"); > > + 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_NetTxRingbufferTransmitPac= ket\"" > > + " 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_AR= G, > > + &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_A= RG, > > + &ascii_to_u32, &rxqueue= s); > > + } > > + /* 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_A= RG, > > + &ascii_to_u32, &txqueue= s); > > + } > > + > > + /* 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_A= RG, > > + &ascii_to_u32_array, &astreamid= s); > > + } > > + > > + /* 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 m= ore" > > + " 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 other= wise, > > + * port defaults to Tx port only > > + */ > > + if (rte_pmd_init_internals(name, rxqueues, txqueues, > numa_node, > > + &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_node, > > + &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, porte= nd); > > + > > + } 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/ntnic/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)/build -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 > confidential information intended for the addressee(s) only. The informat= ion > is not to be surrendered or copied to unauthorized persons. If you have > received this communication in error, please notify the sender immediatel= y > and delete this e-mail from your system. > > 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.