net/mrvl: add net PMD skeleton
Add mrvl net pmd driver skeleton providing base for the further development. Besides the basic functionality QoS configuration is introduced as well. Signed-off-by: Jacek Siuda <jck@semihalf.com> Signed-off-by: Tomasz Duszynski <tdu@semihalf.com>
This commit is contained in:
parent
f98d403bc1
commit
0ddc9b815b
@ -401,6 +401,14 @@ F: drivers/net/mlx5/
|
||||
F: doc/guides/nics/mlx5.rst
|
||||
F: doc/guides/nics/features/mlx5.ini
|
||||
|
||||
Marvell mrvl
|
||||
M: Jacek Siuda <jck@semihalf.com>
|
||||
M: Tomasz Duszynski <tdu@semihalf.com>
|
||||
M: Dmitri Epshtein <dima@marvell.com>
|
||||
M: Natalie Samsonov <nsamsono@marvell.com>
|
||||
M: Jianbo Liu <jianbo.liu@arm.com>
|
||||
F: drivers/net/mrvl/
|
||||
|
||||
Netcope szedata2
|
||||
M: Matej Vido <vido@cesnet.cz>
|
||||
F: drivers/net/szedata2/
|
||||
|
@ -260,6 +260,13 @@ CONFIG_RTE_LIBRTE_ENIC_DEBUG_FLOW=n
|
||||
CONFIG_RTE_LIBRTE_NFP_PMD=n
|
||||
CONFIG_RTE_LIBRTE_NFP_DEBUG=n
|
||||
|
||||
#
|
||||
# Compile Marvell PMD driver
|
||||
#
|
||||
CONFIG_RTE_LIBRTE_MRVL_PMD=n
|
||||
CONFIG_RTE_LIBRTE_MRVL_DEBUG=n
|
||||
CONFIG_RTE_MRVL_MUSDK_DMA_MEMSIZE=41943040
|
||||
|
||||
#
|
||||
# Compile burst-oriented Broadcom BNXT PMD driver
|
||||
#
|
||||
|
@ -47,6 +47,12 @@ New Features
|
||||
256 ports in dpdk. All ethdev APIs which have port_id as parameter are changed
|
||||
in the meantime.
|
||||
|
||||
* **Added a new driver for Marvell Armada 7k/8k devices.**
|
||||
|
||||
Added the new mrvl net driver for Marvell Armada 7k/8k devices. See the
|
||||
"Network Interface Controller Drivers" document for more details on this new
|
||||
driver.
|
||||
|
||||
* **nfp: Added PF support.**
|
||||
|
||||
Previously Netronome's NFP PMD had just support for VFs. PF support is
|
||||
|
@ -75,6 +75,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4
|
||||
DEPDIRS-mlx4 = $(core-libs)
|
||||
DIRS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5
|
||||
DEPDIRS-mlx5 = $(core-libs)
|
||||
DIRS-$(CONFIG_RTE_LIBRTE_MRVL_PMD) += mrvl
|
||||
DEPDIRS-mrvl = $(core-libs) librte_cfgfile
|
||||
DIRS-$(CONFIG_RTE_LIBRTE_NFP_PMD) += nfp
|
||||
DEPDIRS-nfp = $(core-libs)
|
||||
DIRS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += bnxt
|
||||
@ -112,4 +114,10 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += vhost
|
||||
endif # $(CONFIG_RTE_LIBRTE_VHOST)
|
||||
DEPDIRS-vhost = $(core-libs) librte_vhost
|
||||
|
||||
ifeq ($(CONFIG_RTE_LIBRTE_MRVL_PMD),y)
|
||||
ifeq ($(CONFIG_RTE_LIBRTE_CFGFILE),n)
|
||||
$(error "RTE_LIBRTE_CFGFILE must be enabled in configuration!")
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(RTE_SDK)/mk/rte.subdir.mk
|
||||
|
63
drivers/net/mrvl/Makefile
Normal file
63
drivers/net/mrvl/Makefile
Normal file
@ -0,0 +1,63 @@
|
||||
# BSD LICENSE
|
||||
#
|
||||
# Copyright(c) 2017 Semihalf. 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 Semihalf 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
|
||||
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(MAKECMDGOALS),config)
|
||||
ifeq ($(LIBMUSDK_PATH),)
|
||||
$(error "Please define LIBMUSDK_PATH environment variable")
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# library name
|
||||
LIB = librte_pmd_mrvl.a
|
||||
|
||||
# library version
|
||||
LIBABIVER := 1
|
||||
|
||||
# versioning export map
|
||||
EXPORT_MAP := rte_pmd_mrvl_version.map
|
||||
|
||||
# external library dependencies
|
||||
CFLAGS += -I$(LIBMUSDK_PATH)/include
|
||||
CFLAGS += -DMVCONF_ARCH_DMA_ADDR_T_64BIT
|
||||
CFLAGS += -DCONF_PP2_BPOOL_COOKIE_SIZE=32
|
||||
CFLAGS += $(WERROR_FLAGS)
|
||||
CFLAGS += -O3
|
||||
LDLIBS += -L$(LIBMUSDK_PATH)/lib
|
||||
LDLIBS += -lmusdk
|
||||
|
||||
# library source files
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_MRVL_PMD) += mrvl_ethdev.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_MRVL_PMD) += mrvl_qos.c
|
||||
|
||||
include $(RTE_SDK)/mk/rte.lib.mk
|
1112
drivers/net/mrvl/mrvl_ethdev.c
Normal file
1112
drivers/net/mrvl/mrvl_ethdev.c
Normal file
File diff suppressed because it is too large
Load Diff
100
drivers/net/mrvl/mrvl_ethdev.h
Normal file
100
drivers/net/mrvl/mrvl_ethdev.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2017 Semihalf. 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 Semihalf nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MRVL_ETHDEV_H_
|
||||
#define _MRVL_ETHDEV_H_
|
||||
|
||||
#include <drivers/mv_pp2_cls.h>
|
||||
#include <drivers/mv_pp2_ppio.h>
|
||||
|
||||
/** Maximum number of rx queues per port */
|
||||
#define MRVL_PP2_RXQ_MAX 32
|
||||
|
||||
/** Maximum number of tx queues per port */
|
||||
#define MRVL_PP2_TXQ_MAX 8
|
||||
|
||||
/** Minimum number of descriptors in tx queue */
|
||||
#define MRVL_PP2_TXD_MIN 16
|
||||
|
||||
/** Maximum number of descriptors in tx queue */
|
||||
#define MRVL_PP2_TXD_MAX 2048
|
||||
|
||||
/** Tx queue descriptors alignment */
|
||||
#define MRVL_PP2_TXD_ALIGN 16
|
||||
|
||||
/** Minimum number of descriptors in rx queue */
|
||||
#define MRVL_PP2_RXD_MIN 16
|
||||
|
||||
/** Maximum number of descriptors in rx queue */
|
||||
#define MRVL_PP2_RXD_MAX 2048
|
||||
|
||||
/** Rx queue descriptors alignment */
|
||||
#define MRVL_PP2_RXD_ALIGN 16
|
||||
|
||||
/** Maximum number of descriptors in tx aggregated queue */
|
||||
#define MRVL_PP2_AGGR_TXQD_MAX 2048
|
||||
|
||||
/** Maximum number of Traffic Classes. */
|
||||
#define MRVL_PP2_TC_MAX 8
|
||||
|
||||
/** Packet offset inside RX buffer. */
|
||||
#define MRVL_PKT_OFFS 64
|
||||
|
||||
struct mrvl_priv {
|
||||
/* Hot fields, used in fast path. */
|
||||
struct pp2_bpool *bpool; /**< BPool pointer */
|
||||
struct pp2_ppio *ppio; /**< Port handler pointer */
|
||||
uint16_t bpool_max_size; /**< BPool maximum size */
|
||||
uint16_t bpool_min_size; /**< BPool minimum size */
|
||||
uint16_t bpool_init_size; /**< Configured BPool size */
|
||||
|
||||
/** Mapping for DPDK rx queue->(TC, MRVL relative inq) */
|
||||
struct {
|
||||
uint8_t tc; /**< Traffic Class */
|
||||
uint8_t inq; /**< Relative in-queue number */
|
||||
} rxq_map[MRVL_PP2_RXQ_MAX] __rte_cache_aligned;
|
||||
|
||||
/* Configuration data, used sporadically. */
|
||||
uint8_t pp_id;
|
||||
uint8_t ppio_id;
|
||||
uint8_t bpool_bit;
|
||||
|
||||
struct pp2_ppio_params ppio_params;
|
||||
struct pp2_cls_qos_tbl_params qos_tbl_params;
|
||||
struct pp2_cls_tbl *qos_tbl;
|
||||
uint16_t nb_rx_queues;
|
||||
};
|
||||
|
||||
/** Number of ports configured. */
|
||||
extern int mrvl_ports_nb;
|
||||
|
||||
#endif /* _MRVL_ETHDEV_H_ */
|
633
drivers/net/mrvl/mrvl_qos.c
Normal file
633
drivers/net/mrvl/mrvl_qos.c
Normal file
@ -0,0 +1,633 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2017 Semihalf. 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 Semihalf 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 <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rte_common.h>
|
||||
#include <rte_cfgfile.h>
|
||||
#include <rte_log.h>
|
||||
#include <rte_lcore.h>
|
||||
#include <rte_malloc.h>
|
||||
#include <rte_string_fns.h>
|
||||
|
||||
/* Unluckily, container_of is defined by both DPDK and MUSDK,
|
||||
* we'll declare only one version.
|
||||
*
|
||||
* Note that it is not used in this PMD anyway.
|
||||
*/
|
||||
#ifdef container_of
|
||||
#undef container_of
|
||||
#endif
|
||||
|
||||
#include "mrvl_qos.h"
|
||||
|
||||
/* Parsing tokens. Defined conveniently, so that any correction is easy. */
|
||||
#define MRVL_TOK_DEFAULT "default"
|
||||
#define MRVL_TOK_DEFAULT_TC "default_tc"
|
||||
#define MRVL_TOK_DSCP "dscp"
|
||||
#define MRVL_TOK_MAPPING_PRIORITY "mapping_priority"
|
||||
#define MRVL_TOK_IP "ip"
|
||||
#define MRVL_TOK_IP_VLAN "ip/vlan"
|
||||
#define MRVL_TOK_PCP "pcp"
|
||||
#define MRVL_TOK_PORT "port"
|
||||
#define MRVL_TOK_RXQ "rxq"
|
||||
#define MRVL_TOK_SP "SP"
|
||||
#define MRVL_TOK_TC "tc"
|
||||
#define MRVL_TOK_TXQ "txq"
|
||||
#define MRVL_TOK_VLAN "vlan"
|
||||
#define MRVL_TOK_VLAN_IP "vlan/ip"
|
||||
#define MRVL_TOK_WEIGHT "weight"
|
||||
|
||||
/** Number of tokens in range a-b = 2. */
|
||||
#define MAX_RNG_TOKENS 2
|
||||
|
||||
/** Maximum possible value of PCP. */
|
||||
#define MAX_PCP 7
|
||||
|
||||
/** Maximum possible value of DSCP. */
|
||||
#define MAX_DSCP 63
|
||||
|
||||
/** Global QoS configuration. */
|
||||
struct mrvl_qos_cfg *mrvl_qos_cfg;
|
||||
|
||||
/**
|
||||
* Convert string to uint32_t with extra checks for result correctness.
|
||||
*
|
||||
* @param string String to convert.
|
||||
* @param val Conversion result.
|
||||
* @returns 0 in case of success, negative value otherwise.
|
||||
*/
|
||||
static int
|
||||
get_val_securely(const char *string, uint32_t *val)
|
||||
{
|
||||
char *endptr;
|
||||
size_t len = strlen(string);
|
||||
|
||||
if (len == 0)
|
||||
return -1;
|
||||
|
||||
*val = strtoul(string, &endptr, 0);
|
||||
if (errno != 0 || RTE_PTR_DIFF(endptr, string) != len)
|
||||
return -2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read out-queue configuration from file.
|
||||
*
|
||||
* @param file Path to the configuration file.
|
||||
* @param port Port number.
|
||||
* @param outq Out queue number.
|
||||
* @param cfg Pointer to the Marvell QoS configuration structure.
|
||||
* @returns 0 in case of success, negative value otherwise.
|
||||
*/
|
||||
static int
|
||||
get_outq_cfg(struct rte_cfgfile *file, int port, int outq,
|
||||
struct mrvl_qos_cfg *cfg)
|
||||
{
|
||||
char sec_name[32];
|
||||
const char *entry;
|
||||
uint32_t val;
|
||||
|
||||
snprintf(sec_name, sizeof(sec_name), "%s %d %s %d",
|
||||
MRVL_TOK_PORT, port, MRVL_TOK_TXQ, outq);
|
||||
|
||||
/* Skip non-existing */
|
||||
if (rte_cfgfile_num_sections(file, sec_name, strlen(sec_name)) <= 0)
|
||||
return 0;
|
||||
|
||||
entry = rte_cfgfile_get_entry(file, sec_name,
|
||||
MRVL_TOK_WEIGHT);
|
||||
if (entry) {
|
||||
if (get_val_securely(entry, &val) < 0)
|
||||
return -1;
|
||||
cfg->port[port].outq[outq].weight = (uint8_t)val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets multiple-entry values and places them in table.
|
||||
*
|
||||
* Entry can be anything, e.g. "1 2-3 5 6 7-9". This needs to be converted to
|
||||
* table entries, respectively: {1, 2, 3, 5, 6, 7, 8, 9}.
|
||||
* As all result table's elements are always 1-byte long, we
|
||||
* won't overcomplicate the function, but we'll keep API generic,
|
||||
* check if someone hasn't changed element size and make it simple
|
||||
* to extend to other sizes.
|
||||
*
|
||||
* This function is purely utilitary, it does not print any error, only returns
|
||||
* different error numbers.
|
||||
*
|
||||
* @param entry[in] Values string to parse.
|
||||
* @param tab[out] Results table.
|
||||
* @param elem_sz[in] Element size (in bytes).
|
||||
* @param max_elems[in] Number of results table elements available.
|
||||
* @param max val[in] Maximum value allowed.
|
||||
* @returns Number of correctly parsed elements in case of success.
|
||||
* @retval -1 Wrong element size.
|
||||
* @retval -2 More tokens than result table allows.
|
||||
* @retval -3 Wrong range syntax.
|
||||
* @retval -4 Wrong range values.
|
||||
* @retval -5 Maximum value exceeded.
|
||||
*/
|
||||
static int
|
||||
get_entry_values(const char *entry, uint8_t *tab,
|
||||
size_t elem_sz, uint8_t max_elems, uint8_t max_val)
|
||||
{
|
||||
/* There should not be more tokens than max elements.
|
||||
* Add 1 for error trap.
|
||||
*/
|
||||
char *tokens[max_elems + 1];
|
||||
|
||||
/* Begin, End + error trap = 3. */
|
||||
char *rng_tokens[MAX_RNG_TOKENS + 1];
|
||||
long beg, end;
|
||||
uint32_t token_val;
|
||||
int nb_tokens, nb_rng_tokens;
|
||||
int i;
|
||||
int values = 0;
|
||||
char val;
|
||||
char entry_cpy[CFG_VALUE_LEN];
|
||||
|
||||
if (elem_sz != 1)
|
||||
return -1;
|
||||
|
||||
/* Copy the entry to safely use rte_strsplit(). */
|
||||
snprintf(entry_cpy, RTE_DIM(entry_cpy), "%s", entry);
|
||||
|
||||
/*
|
||||
* If there are more tokens than array size, rte_strsplit will
|
||||
* not return error, just array size.
|
||||
*/
|
||||
nb_tokens = rte_strsplit(entry_cpy, strlen(entry_cpy),
|
||||
tokens, max_elems + 1, ' ');
|
||||
|
||||
/* Quick check, will be refined later. */
|
||||
if (nb_tokens > max_elems)
|
||||
return -2;
|
||||
|
||||
for (i = 0; i < nb_tokens; ++i) {
|
||||
if (strchr(tokens[i], '-') != NULL) {
|
||||
/*
|
||||
* Split to begin and end tokens.
|
||||
* We want to catch error cases too, thus we leave
|
||||
* option for number of tokens to be more than 2.
|
||||
*/
|
||||
nb_rng_tokens = rte_strsplit(tokens[i],
|
||||
strlen(tokens[i]), rng_tokens,
|
||||
RTE_DIM(rng_tokens), '-');
|
||||
if (nb_rng_tokens != 2)
|
||||
return -3;
|
||||
|
||||
/* Range and sanity checks. */
|
||||
if (get_val_securely(rng_tokens[0], &token_val) < 0)
|
||||
return -4;
|
||||
beg = (char)token_val;
|
||||
if (get_val_securely(rng_tokens[1], &token_val) < 0)
|
||||
return -4;
|
||||
end = (char)token_val;
|
||||
if (beg < 0 || beg > UCHAR_MAX ||
|
||||
end < 0 || end > UCHAR_MAX || end < beg)
|
||||
return -4;
|
||||
|
||||
for (val = beg; val <= end; ++val) {
|
||||
if (val > max_val)
|
||||
return -5;
|
||||
|
||||
*tab = val;
|
||||
tab = RTE_PTR_ADD(tab, elem_sz);
|
||||
++values;
|
||||
if (values >= max_elems)
|
||||
return -2;
|
||||
}
|
||||
} else {
|
||||
/* Single values. */
|
||||
if (get_val_securely(tokens[i], &token_val) < 0)
|
||||
return -5;
|
||||
val = (char)token_val;
|
||||
if (val > max_val)
|
||||
return -5;
|
||||
|
||||
*tab = val;
|
||||
tab = RTE_PTR_ADD(tab, elem_sz);
|
||||
++values;
|
||||
if (values >= max_elems)
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Traffic Class'es mapping configuration.
|
||||
*
|
||||
* @param file Config file handle.
|
||||
* @param port Which port to look for.
|
||||
* @param tc Which Traffic Class to look for.
|
||||
* @param cfg[out] Parsing results.
|
||||
* @returns 0 in case of success, negative value otherwise.
|
||||
*/
|
||||
static int
|
||||
parse_tc_cfg(struct rte_cfgfile *file, int port, int tc,
|
||||
struct mrvl_qos_cfg *cfg)
|
||||
{
|
||||
char sec_name[32];
|
||||
const char *entry;
|
||||
int n;
|
||||
|
||||
snprintf(sec_name, sizeof(sec_name), "%s %d %s %d",
|
||||
MRVL_TOK_PORT, port, MRVL_TOK_TC, tc);
|
||||
|
||||
/* Skip non-existing */
|
||||
if (rte_cfgfile_num_sections(file, sec_name, strlen(sec_name)) <= 0)
|
||||
return 0;
|
||||
|
||||
entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_RXQ);
|
||||
if (entry) {
|
||||
n = get_entry_values(entry,
|
||||
cfg->port[port].tc[tc].inq,
|
||||
sizeof(cfg->port[port].tc[tc].inq[0]),
|
||||
RTE_DIM(cfg->port[port].tc[tc].inq),
|
||||
MRVL_PP2_RXQ_MAX);
|
||||
if (n < 0) {
|
||||
RTE_LOG(ERR, PMD, "Error %d while parsing: %s\n",
|
||||
n, entry);
|
||||
return n;
|
||||
}
|
||||
cfg->port[port].tc[tc].inqs = n;
|
||||
}
|
||||
|
||||
entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PCP);
|
||||
if (entry) {
|
||||
n = get_entry_values(entry,
|
||||
cfg->port[port].tc[tc].pcp,
|
||||
sizeof(cfg->port[port].tc[tc].pcp[0]),
|
||||
RTE_DIM(cfg->port[port].tc[tc].pcp),
|
||||
MAX_PCP);
|
||||
if (n < 0) {
|
||||
RTE_LOG(ERR, PMD, "Error %d while parsing: %s\n",
|
||||
n, entry);
|
||||
return n;
|
||||
}
|
||||
cfg->port[port].tc[tc].pcps = n;
|
||||
}
|
||||
|
||||
entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_DSCP);
|
||||
if (entry) {
|
||||
n = get_entry_values(entry,
|
||||
cfg->port[port].tc[tc].dscp,
|
||||
sizeof(cfg->port[port].tc[tc].dscp[0]),
|
||||
RTE_DIM(cfg->port[port].tc[tc].dscp),
|
||||
MAX_DSCP);
|
||||
if (n < 0) {
|
||||
RTE_LOG(ERR, PMD, "Error %d while parsing: %s\n",
|
||||
n, entry);
|
||||
return n;
|
||||
}
|
||||
cfg->port[port].tc[tc].dscps = n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse QoS configuration - rte_kvargs_process handler.
|
||||
*
|
||||
* Opens configuration file and parses its content.
|
||||
*
|
||||
* @param key Unused.
|
||||
* @param path Path to config file.
|
||||
* @param extra_args Pointer to configuration structure.
|
||||
* @returns 0 in case of success, exits otherwise.
|
||||
*/
|
||||
int
|
||||
mrvl_get_qoscfg(const char *key __rte_unused, const char *path,
|
||||
void *extra_args)
|
||||
{
|
||||
struct mrvl_qos_cfg **cfg = extra_args;
|
||||
struct rte_cfgfile *file = rte_cfgfile_load(path, 0);
|
||||
uint32_t val;
|
||||
int n, i, ret;
|
||||
const char *entry;
|
||||
char sec_name[32];
|
||||
|
||||
if (file == NULL)
|
||||
rte_exit(EXIT_FAILURE, "Cannot load configuration %s\n", path);
|
||||
|
||||
/* Create configuration. This is never accessed on the fast path,
|
||||
* so we can ignore socket.
|
||||
*/
|
||||
*cfg = rte_zmalloc("mrvl_qos_cfg", sizeof(struct mrvl_qos_cfg), 0);
|
||||
if (*cfg == NULL)
|
||||
rte_exit(EXIT_FAILURE, "Cannot allocate configuration %s\n",
|
||||
path);
|
||||
|
||||
n = rte_cfgfile_num_sections(file, MRVL_TOK_PORT,
|
||||
sizeof(MRVL_TOK_PORT) - 1);
|
||||
|
||||
if (n == 0) {
|
||||
/* This is weird, but not bad. */
|
||||
RTE_LOG(WARNING, PMD, "Empty configuration file?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use the number of ports given as vdev parameters. */
|
||||
for (n = 0; n < mrvl_ports_nb; ++n) {
|
||||
snprintf(sec_name, sizeof(sec_name), "%s %d %s",
|
||||
MRVL_TOK_PORT, n, MRVL_TOK_DEFAULT);
|
||||
|
||||
/* Skip ports non-existing in configuration. */
|
||||
if (rte_cfgfile_num_sections(file, sec_name,
|
||||
strlen(sec_name)) <= 0) {
|
||||
(*cfg)->port[n].use_global_defaults = 1;
|
||||
(*cfg)->port[n].mapping_priority =
|
||||
PP2_CLS_QOS_TBL_VLAN_IP_PRI;
|
||||
continue;
|
||||
}
|
||||
|
||||
entry = rte_cfgfile_get_entry(file, sec_name,
|
||||
MRVL_TOK_DEFAULT_TC);
|
||||
if (entry) {
|
||||
if (get_val_securely(entry, &val) < 0 ||
|
||||
val > USHRT_MAX)
|
||||
return -1;
|
||||
(*cfg)->port[n].default_tc = (uint8_t)val;
|
||||
} else {
|
||||
RTE_LOG(ERR, PMD,
|
||||
"Default Traffic Class required in custom configuration!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
entry = rte_cfgfile_get_entry(file, sec_name,
|
||||
MRVL_TOK_MAPPING_PRIORITY);
|
||||
if (entry) {
|
||||
if (!strncmp(entry, MRVL_TOK_VLAN_IP,
|
||||
sizeof(MRVL_TOK_VLAN_IP)))
|
||||
(*cfg)->port[n].mapping_priority =
|
||||
PP2_CLS_QOS_TBL_VLAN_IP_PRI;
|
||||
else if (!strncmp(entry, MRVL_TOK_IP_VLAN,
|
||||
sizeof(MRVL_TOK_IP_VLAN)))
|
||||
(*cfg)->port[n].mapping_priority =
|
||||
PP2_CLS_QOS_TBL_IP_VLAN_PRI;
|
||||
else if (!strncmp(entry, MRVL_TOK_IP,
|
||||
sizeof(MRVL_TOK_IP)))
|
||||
(*cfg)->port[n].mapping_priority =
|
||||
PP2_CLS_QOS_TBL_IP_PRI;
|
||||
else if (!strncmp(entry, MRVL_TOK_VLAN,
|
||||
sizeof(MRVL_TOK_VLAN)))
|
||||
(*cfg)->port[n].mapping_priority =
|
||||
PP2_CLS_QOS_TBL_VLAN_PRI;
|
||||
else
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Error in parsing %s value (%s)!\n",
|
||||
MRVL_TOK_MAPPING_PRIORITY, entry);
|
||||
} else {
|
||||
(*cfg)->port[n].mapping_priority =
|
||||
PP2_CLS_QOS_TBL_VLAN_IP_PRI;
|
||||
}
|
||||
|
||||
for (i = 0; i < MRVL_PP2_RXQ_MAX; ++i) {
|
||||
ret = get_outq_cfg(file, n, i, *cfg);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Error %d parsing port %d outq %d!\n",
|
||||
ret, n, i);
|
||||
}
|
||||
|
||||
for (i = 0; i < MRVL_PP2_TC_MAX; ++i) {
|
||||
ret = parse_tc_cfg(file, n, i, *cfg);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Error %d parsing port %d tc %d!\n",
|
||||
ret, n, i);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Traffic Class.
|
||||
*
|
||||
* Fill in TC parameters in single MUSDK TC config entry.
|
||||
* @param param TC parameters entry.
|
||||
* @param inqs Number of MUSDK in-queues in this TC.
|
||||
* @param bpool Bpool for this TC.
|
||||
* @returns 0 in case of success, exits otherwise.
|
||||
*/
|
||||
static int
|
||||
setup_tc(struct pp2_ppio_tc_params *param, uint8_t inqs,
|
||||
struct pp2_bpool *bpool)
|
||||
{
|
||||
struct pp2_ppio_inq_params *inq_params;
|
||||
|
||||
param->pkt_offset = MRVL_PKT_OFFS;
|
||||
param->pools[0] = bpool;
|
||||
|
||||
inq_params = rte_zmalloc_socket("inq_params",
|
||||
inqs * sizeof(*inq_params),
|
||||
0, rte_socket_id());
|
||||
if (!inq_params)
|
||||
return -ENOMEM;
|
||||
|
||||
param->num_in_qs = inqs;
|
||||
|
||||
/* Release old config if necessary. */
|
||||
if (param->inqs_params)
|
||||
rte_free(param->inqs_params);
|
||||
|
||||
param->inqs_params = inq_params;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure RX Queues in a given port.
|
||||
*
|
||||
* Sets up RX queues, their Traffic Classes and DPDK rxq->(TC,inq) mapping.
|
||||
*
|
||||
* @param priv Port's private data
|
||||
* @param portid DPDK port ID
|
||||
* @param max_queues Maximum number of queues to configure.
|
||||
* @returns 0 in case of success, negative value otherwise.
|
||||
*/
|
||||
int
|
||||
mrvl_configure_rxqs(struct mrvl_priv *priv, uint8_t portid,
|
||||
uint16_t max_queues)
|
||||
{
|
||||
size_t i, tc;
|
||||
|
||||
if (mrvl_qos_cfg == NULL ||
|
||||
mrvl_qos_cfg->port[portid].use_global_defaults) {
|
||||
/* No port configuration, use default: 1 TC, no QoS. */
|
||||
priv->ppio_params.inqs_params.num_tcs = 1;
|
||||
setup_tc(&priv->ppio_params.inqs_params.tcs_params[0],
|
||||
max_queues, priv->bpool);
|
||||
|
||||
/* Direct mapping of queues i.e. 0->0, 1->1 etc. */
|
||||
for (i = 0; i < max_queues; ++i) {
|
||||
priv->rxq_map[i].tc = 0;
|
||||
priv->rxq_map[i].inq = i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We need only a subset of configuration. */
|
||||
struct port_cfg *port_cfg = &mrvl_qos_cfg->port[portid];
|
||||
|
||||
priv->qos_tbl_params.type = port_cfg->mapping_priority;
|
||||
|
||||
/*
|
||||
* We need to reverse mapping, from tc->pcp (better from usability
|
||||
* point of view) to pcp->tc (configurable in MUSDK).
|
||||
* First, set all map elements to "default".
|
||||
*/
|
||||
for (i = 0; i < RTE_DIM(priv->qos_tbl_params.pcp_cos_map); ++i)
|
||||
priv->qos_tbl_params.pcp_cos_map[i].tc = port_cfg->default_tc;
|
||||
|
||||
/* Then, fill in all known values. */
|
||||
for (tc = 0; tc < RTE_DIM(port_cfg->tc); ++tc) {
|
||||
if (port_cfg->tc[tc].pcps > RTE_DIM(port_cfg->tc[0].pcp)) {
|
||||
/* Better safe than sorry. */
|
||||
RTE_LOG(ERR, PMD,
|
||||
"Too many PCPs configured in TC %zu!\n", tc);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < port_cfg->tc[tc].pcps; ++i) {
|
||||
priv->qos_tbl_params.pcp_cos_map[
|
||||
port_cfg->tc[tc].pcp[i]].tc = tc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The same logic goes with DSCP.
|
||||
* First, set all map elements to "default".
|
||||
*/
|
||||
for (i = 0; i < RTE_DIM(priv->qos_tbl_params.dscp_cos_map); ++i)
|
||||
priv->qos_tbl_params.dscp_cos_map[i].tc =
|
||||
port_cfg->default_tc;
|
||||
|
||||
/* Fill in all known values. */
|
||||
for (tc = 0; tc < RTE_DIM(port_cfg->tc); ++tc) {
|
||||
if (port_cfg->tc[tc].dscps > RTE_DIM(port_cfg->tc[0].dscp)) {
|
||||
/* Better safe than sorry. */
|
||||
RTE_LOG(ERR, PMD,
|
||||
"Too many DSCPs configured in TC %zu!\n", tc);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < port_cfg->tc[tc].dscps; ++i) {
|
||||
priv->qos_tbl_params.dscp_cos_map[
|
||||
port_cfg->tc[tc].dscp[i]].tc = tc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Surprisingly, similar logic goes with queue mapping.
|
||||
* We need only to store qid->tc mapping,
|
||||
* to know TC when queue is read.
|
||||
*/
|
||||
for (i = 0; i < RTE_DIM(priv->rxq_map); ++i)
|
||||
priv->rxq_map[i].tc = MRVL_UNKNOWN_TC;
|
||||
|
||||
/* Set up DPDKq->(TC,inq) mapping. */
|
||||
for (tc = 0; tc < RTE_DIM(port_cfg->tc); ++tc) {
|
||||
if (port_cfg->tc[tc].inqs > RTE_DIM(port_cfg->tc[0].inq)) {
|
||||
/* Overflow. */
|
||||
RTE_LOG(ERR, PMD,
|
||||
"Too many RX queues configured per TC %zu!\n",
|
||||
tc);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < port_cfg->tc[tc].inqs; ++i) {
|
||||
uint8_t idx = port_cfg->tc[tc].inq[i];
|
||||
|
||||
if (idx > RTE_DIM(priv->rxq_map)) {
|
||||
RTE_LOG(ERR, PMD, "Bad queue index %d!\n", idx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
priv->rxq_map[idx].tc = tc;
|
||||
priv->rxq_map[idx].inq = i;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up TC configuration. TCs need to be sequenced: 0, 1, 2
|
||||
* with no gaps. Empty TC means end of processing.
|
||||
*/
|
||||
for (i = 0; i < MRVL_PP2_TC_MAX; ++i) {
|
||||
if (port_cfg->tc[i].inqs == 0)
|
||||
break;
|
||||
setup_tc(&priv->ppio_params.inqs_params.tcs_params[i],
|
||||
port_cfg->tc[i].inqs,
|
||||
priv->bpool);
|
||||
}
|
||||
|
||||
priv->ppio_params.inqs_params.num_tcs = i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start QoS mapping.
|
||||
*
|
||||
* Finalize QoS table configuration and initialize it in SDK. It can be done
|
||||
* only after port is started, so we have a valid ppio reference.
|
||||
*
|
||||
* @param priv Port's private (configuration) data.
|
||||
* @returns 0 in case of success, exits otherwise.
|
||||
*/
|
||||
int
|
||||
mrvl_start_qos_mapping(struct mrvl_priv *priv)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (priv->ppio == NULL) {
|
||||
RTE_LOG(ERR, PMD, "ppio must not be NULL here!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < RTE_DIM(priv->qos_tbl_params.pcp_cos_map); ++i)
|
||||
priv->qos_tbl_params.pcp_cos_map[i].ppio = priv->ppio;
|
||||
|
||||
for (i = 0; i < RTE_DIM(priv->qos_tbl_params.dscp_cos_map); ++i)
|
||||
priv->qos_tbl_params.dscp_cos_map[i].ppio = priv->ppio;
|
||||
|
||||
/* Initialize Classifier QoS table. */
|
||||
|
||||
return pp2_cls_qos_tbl_init(&priv->qos_tbl_params, &priv->qos_tbl);
|
||||
}
|
112
drivers/net/mrvl/mrvl_qos.h
Normal file
112
drivers/net/mrvl/mrvl_qos.h
Normal file
@ -0,0 +1,112 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2017 Semihalf. 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 Semihalf nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MRVL_QOS_H_
|
||||
#define _MRVL_QOS_H_
|
||||
|
||||
#include <rte_common.h>
|
||||
#include <rte_config.h>
|
||||
|
||||
#include "mrvl_ethdev.h"
|
||||
|
||||
/** Code Points per Traffic Class. Equals max(DSCP, PCP). */
|
||||
#define MRVL_CP_PER_TC (64)
|
||||
|
||||
/** Value used as "unknown". */
|
||||
#define MRVL_UNKNOWN_TC (0xFF)
|
||||
|
||||
/* QoS config. */
|
||||
struct mrvl_qos_cfg {
|
||||
struct port_cfg {
|
||||
struct {
|
||||
uint8_t inq[MRVL_PP2_RXQ_MAX];
|
||||
uint8_t dscp[MRVL_CP_PER_TC];
|
||||
uint8_t pcp[MRVL_CP_PER_TC];
|
||||
uint8_t inqs;
|
||||
uint8_t dscps;
|
||||
uint8_t pcps;
|
||||
} tc[MRVL_PP2_TC_MAX];
|
||||
struct {
|
||||
uint8_t weight;
|
||||
} outq[MRVL_PP2_RXQ_MAX];
|
||||
enum pp2_cls_qos_tbl_type mapping_priority;
|
||||
uint16_t inqs;
|
||||
uint16_t outqs;
|
||||
uint8_t default_tc;
|
||||
uint8_t use_global_defaults;
|
||||
} port[RTE_MAX_ETHPORTS];
|
||||
};
|
||||
|
||||
/** Global QoS configuration. */
|
||||
extern struct mrvl_qos_cfg *mrvl_qos_cfg;
|
||||
|
||||
/**
|
||||
* Parse QoS configuration - rte_kvargs_process handler.
|
||||
*
|
||||
* Opens configuration file and parses its content.
|
||||
*
|
||||
* @param key Unused.
|
||||
* @param path Path to config file.
|
||||
* @param extra_args Pointer to configuration structure.
|
||||
* @returns 0 in case of success, exits otherwise.
|
||||
*/
|
||||
int
|
||||
mrvl_get_qoscfg(const char *key __rte_unused, const char *path,
|
||||
void *extra_args);
|
||||
|
||||
/**
|
||||
* Configure RX Queues in a given port.
|
||||
*
|
||||
* Sets up RX queues, their Traffic Classes and DPDK rxq->(TC,inq) mapping.
|
||||
*
|
||||
* @param priv Port's private data
|
||||
* @param portid DPDK port ID
|
||||
* @param max_queues Maximum number of queues to configure.
|
||||
* @returns 0 in case of success, negative value otherwise.
|
||||
*/
|
||||
int
|
||||
mrvl_configure_rxqs(struct mrvl_priv *priv, uint8_t portid,
|
||||
uint16_t max_queues);
|
||||
|
||||
/**
|
||||
* Start QoS mapping.
|
||||
*
|
||||
* Finalize QoS table configuration and initialize it in SDK. It can be done
|
||||
* only after port is started, so we have a valid ppio reference.
|
||||
*
|
||||
* @param priv Port's private (configuration) data.
|
||||
* @returns 0 in case of success, exits otherwise.
|
||||
*/
|
||||
int
|
||||
mrvl_start_qos_mapping(struct mrvl_priv *priv);
|
||||
|
||||
#endif /* _MRVL_QOS_H_ */
|
3
drivers/net/mrvl/rte_pmd_mrvl_version.map
Normal file
3
drivers/net/mrvl/rte_pmd_mrvl_version.map
Normal file
@ -0,0 +1,3 @@
|
||||
DPDK_17.11 {
|
||||
local: *;
|
||||
};
|
@ -137,6 +137,7 @@ endif
|
||||
_LDLIBS-$(CONFIG_RTE_LIBRTE_LIO_PMD) += -lrte_pmd_lio
|
||||
_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -lrte_pmd_mlx4 -libverbs
|
||||
_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += -lrte_pmd_mlx5 -libverbs -lmlx5
|
||||
_LDLIBS-$(CONFIG_RTE_LIBRTE_MRVL_PMD) += -lrte_pmd_mrvl -L$(LIBMUSDK_PATH)/lib -lmusdk
|
||||
_LDLIBS-$(CONFIG_RTE_LIBRTE_NFP_PMD) += -lrte_pmd_nfp
|
||||
_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += -lrte_pmd_null
|
||||
_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += -lrte_pmd_pcap -lpcap
|
||||
|
Loading…
x
Reference in New Issue
Block a user