examples/ethtool: add user-space ethtool sample application

Further enhancements to the userspace ethtool implementation that was
submitted in 2.1 and packaged as a self-contained sample application.
Implements an rte_ethtool shim layer based on rte_ethdev API, along
with a command prompt driven demonstration application.

Signed-off-by: Remy Horton <remy.horton@intel.com>
This commit is contained in:
Remy Horton 2015-12-07 13:48:59 +00:00 committed by Thomas Monjalon
parent 341a1e0664
commit bda68ab9d1
13 changed files with 2379 additions and 0 deletions

View file

@ -521,6 +521,10 @@ M: Pablo de Lara <pablo.de.lara.guarch@intel.com>
F: examples/dpdk_qat/
F: doc/guides/sample_app_ug/intel_quickassist.rst
M: Remy Horton <remy.horton@intel.com>
F: examples/ethtool/
F: doc/guides/sample_app_ug/ethtool.rst
F: examples/exception_path/
F: doc/guides/sample_app_ug/exception_path.rst

View file

@ -125,6 +125,8 @@ New Features
* **Added port hotplug support to xenvirt.**
* **Added ethtool shim and sample application.**
Resolved Issues
---------------

View file

@ -0,0 +1,160 @@
.. BSD LICENSE
Copyright(c) 2015 Intel Corporation. All rights reserved.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Ethtool Sample Application
==========================
The Ethtool sample application shows an implementation of an
ethtool-like API and provides a console environment that allows
its use to query and change Ethernet card parameters. The sample
is based upon a simple L2 frame reflector.
Compiling the Application
-------------------------
To compile the application:
#. Go to the sample application directory:
.. code-block:: console
export RTE_SDK=/path/to/rte_sdk
cd ${RTE_SD}/examples/ethtool
#. Set the target (a default target is used if not specified). For example:
.. code-block:: console
export RTE_TARGET=x86_64-native-linuxapp-gcc
See the *DPDK Getting Started Guide* for possible RTE_TARGET values.
#. Build the application:
.. code-block:: console
make
Running the Application
-----------------------
The application requires an available core for each port, plus one.
The only available options are the standard ones for the EAL:
.. code-block:: console
./ethtool-app/ethtool-app/${RTE_TARGET}/ethtool [EAL options]
Refer to the *DPDK Getting Started Guide* for general information on
running applications and the Environment Abstraction Layer (EAL)
options.
Using the application
---------------------
The application is console-driven using the cmdline DPDK interface:
.. code-block:: console
EthApp>
From this interface the available commands and descriptions of what
they do as as follows:
* ``drvinfo``: Print driver info
* ``eeprom``: Dump EEPROM to file
* ``link``: Print port link states
* ``macaddr``: Gets/sets MAC address
* ``mtu``: Set NIC MTU
* ``open``: Open port
* ``pause``: Get/set port pause state
* ``portstats``: Print port statistics
* ``regs``: Dump port register(s) to file
* ``ringparam``: Get/set ring parameters
* ``rxmode``: Toggle port Rx mode
* ``stop``: Stop port
* ``validate``: Check that given MAC address is valid unicast address
* ``vlan``: Add/remove VLAN id
* ``quit``: Exit program
Explanation
-----------
The sample program has two parts: A background `packet reflector`_
that runs on a slave core, and a foreground `Ethtool Shell`_ that
runs on the master core. These are described below.
Packet Reflector
~~~~~~~~~~~~~~~~
The background packet reflector is intended to demonstrate basic
packet processing on NIC ports controlled by the Ethtool shim.
Each incoming MAC frame is rewritten so that it is returned to
the sender, using the port in question's own MAC address as the
source address, and is then sent out on the same port.
Ethtool Shell
~~~~~~~~~~~~~
The foreground part of the Ethtool sample is a console-based
interface that accepts commands as described in `using the
application`_. Individual call-back functions handle the detail
associated with each command, which make use of the functions
defined in the `Ethtool interface`_ to the DPDK functions.
Ethtool interface
-----------------
The Ethtool interface is built as a separate library, and implements
the following functions:
- ``rte_ethtool_get_drvinfo()``
- ``rte_ethtool_get_regs_len()``
- ``rte_ethtool_get_regs()``
- ``rte_ethtool_get_link()``
- ``rte_ethtool_get_eeprom_len()``
- ``rte_ethtool_get_eeprom()``
- ``rte_ethtool_set_eeprom()``
- ``rte_ethtool_get_pauseparam()``
- ``rte_ethtool_set_pauseparam()``
- ``rte_ethtool_net_open()``
- ``rte_ethtool_net_stop()``
- ``rte_ethtool_net_get_mac_addr()``
- ``rte_ethtool_net_set_mac_addr()``
- ``rte_ethtool_net_validate_addr()``
- ``rte_ethtool_net_change_mtu()``
- ``rte_ethtool_net_get_stats64()``
- ``rte_ethtool_net_vlan_rx_add_vid()``
- ``rte_ethtool_net_vlan_rx_kill_vid()``
- ``rte_ethtool_net_set_rx_mode()``
- ``rte_ethtool_get_ringparam()``
- ``rte_ethtool_set_ringparam()``

View file

@ -41,6 +41,7 @@ Sample Applications User Guide
intro
cmd_line
ethtool
exception_path
hello_world
skeleton

View file

@ -43,6 +43,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += distributor
ifneq ($(ICP_ROOT),)
DIRS-y += dpdk_qat
endif
DIRS-y += ethtool
DIRS-y += exception_path
DIRS-y += helloworld
DIRS-y += ip_pipeline

48
examples/ethtool/Makefile Normal file
View file

@ -0,0 +1,48 @@
# BSD LICENSE
#
# Copyright(c) 2015 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ifeq ($(RTE_SDK),)
$(error "Please define RTE_SDK environment variable")
endif
# Default target, can be overwritten by command line or environment
RTE_TARGET ?= x86_64-native-linuxapp-gcc
include $(RTE_SDK)/mk/rte.vars.mk
ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp")
$(error This application can only operate in a linuxapp environment, \
please change the definition of the RTE_TARGET environment variable)
endif
DIRS-y += lib ethtool-app
include $(RTE_SDK)/mk/rte.extsubdir.mk

View file

@ -0,0 +1,54 @@
# BSD LICENSE
#
# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ifeq ($(RTE_SDK),)
$(error "Please define RTE_SDK environment variable")
endif
# Default target, can be overridden by command line or environment
RTE_TARGET ?= x86_64-native-linuxapp-gcc
include $(RTE_SDK)/mk/rte.vars.mk
# binary name
APP = ethtool
# all source are stored in SRCS-y
SRCS-y := main.c ethapp.c
CFLAGS += -O3 -D_GNU_SOURCE -pthread -I$(SRCDIR)/../lib
CFLAGS += $(WERROR_FLAGS)
LDLIBS += -L$(subst ethtool-app,lib,$(RTE_OUTPUT))/lib
LDLIBS += -lrte_ethtool
include $(RTE_SDK)/mk/rte.extapp.mk

View file

@ -0,0 +1,873 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2015 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cmdline_parse.h>
#include <cmdline_parse_num.h>
#include <cmdline_parse_string.h>
#include <cmdline_parse_etheraddr.h>
#include <cmdline_socket.h>
#include <cmdline.h>
#include "rte_ethtool.h"
#include "ethapp.h"
#define EEPROM_DUMP_CHUNKSIZE 1024
struct pcmd_get_params {
cmdline_fixed_string_t cmd;
};
struct pcmd_int_params {
cmdline_fixed_string_t cmd;
uint16_t port;
};
struct pcmd_intstr_params {
cmdline_fixed_string_t cmd;
uint16_t port;
cmdline_fixed_string_t opt;
};
struct pcmd_intmac_params {
cmdline_fixed_string_t cmd;
uint16_t port;
struct ether_addr mac;
};
struct pcmd_str_params {
cmdline_fixed_string_t cmd;
cmdline_fixed_string_t opt;
};
struct pcmd_vlan_params {
cmdline_fixed_string_t cmd;
uint16_t port;
cmdline_fixed_string_t mode;
uint16_t vid;
};
struct pcmd_intintint_params {
cmdline_fixed_string_t cmd;
uint16_t port;
uint16_t tx;
uint16_t rx;
};
/* Parameter-less commands */
cmdline_parse_token_string_t pcmd_quit_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_get_params, cmd, "quit");
cmdline_parse_token_string_t pcmd_stats_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_get_params, cmd, "stats");
cmdline_parse_token_string_t pcmd_drvinfo_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_get_params, cmd, "drvinfo");
cmdline_parse_token_string_t pcmd_link_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_get_params, cmd, "link");
/* Commands taking just port id */
cmdline_parse_token_string_t pcmd_open_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "open");
cmdline_parse_token_string_t pcmd_stop_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "stop");
cmdline_parse_token_string_t pcmd_rxmode_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "rxmode");
cmdline_parse_token_string_t pcmd_portstats_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "portstats");
cmdline_parse_token_num_t pcmd_int_token_port =
TOKEN_NUM_INITIALIZER(struct pcmd_int_params, port, UINT16);
/* Commands taking port id and string */
cmdline_parse_token_string_t pcmd_eeprom_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "eeprom");
cmdline_parse_token_string_t pcmd_mtu_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "mtu");
cmdline_parse_token_string_t pcmd_regs_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "regs");
cmdline_parse_token_num_t pcmd_intstr_token_port =
TOKEN_NUM_INITIALIZER(struct pcmd_intstr_params, port, UINT16);
cmdline_parse_token_string_t pcmd_intstr_token_opt =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, opt, NULL);
/* Commands taking port id and a MAC address string */
cmdline_parse_token_string_t pcmd_macaddr_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intmac_params, cmd, "macaddr");
cmdline_parse_token_num_t pcmd_intmac_token_port =
TOKEN_NUM_INITIALIZER(struct pcmd_intmac_params, port, UINT16);
cmdline_parse_token_etheraddr_t pcmd_intmac_token_mac =
TOKEN_ETHERADDR_INITIALIZER(struct pcmd_intmac_params, mac);
/* Command taking just a MAC address */
cmdline_parse_token_string_t pcmd_validate_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intmac_params, cmd, "validate");
/* Commands taking port id and two integers */
cmdline_parse_token_string_t pcmd_ringparam_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intintint_params, cmd,
"ringparam");
cmdline_parse_token_num_t pcmd_intintint_token_port =
TOKEN_NUM_INITIALIZER(struct pcmd_intintint_params, port, UINT16);
cmdline_parse_token_num_t pcmd_intintint_token_tx =
TOKEN_NUM_INITIALIZER(struct pcmd_intintint_params, tx, UINT16);
cmdline_parse_token_num_t pcmd_intintint_token_rx =
TOKEN_NUM_INITIALIZER(struct pcmd_intintint_params, rx, UINT16);
/* Pause commands */
cmdline_parse_token_string_t pcmd_pause_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "pause");
cmdline_parse_token_num_t pcmd_pause_token_port =
TOKEN_NUM_INITIALIZER(struct pcmd_intstr_params, port, UINT16);
cmdline_parse_token_string_t pcmd_pause_token_opt =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params,
opt, "all#tx#rx#none");
/* VLAN commands */
cmdline_parse_token_string_t pcmd_vlan_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_vlan_params, cmd, "vlan");
cmdline_parse_token_num_t pcmd_vlan_token_port =
TOKEN_NUM_INITIALIZER(struct pcmd_vlan_params, port, UINT16);
cmdline_parse_token_string_t pcmd_vlan_token_mode =
TOKEN_STRING_INITIALIZER(struct pcmd_vlan_params, mode, "add#del");
cmdline_parse_token_num_t pcmd_vlan_token_vid =
TOKEN_NUM_INITIALIZER(struct pcmd_vlan_params, vid, UINT16);
static void
pcmd_quit_callback(__rte_unused void *ptr_params,
struct cmdline *ctx,
__rte_unused void *ptr_data)
{
cmdline_quit(ctx);
}
static void
pcmd_drvinfo_callback(__rte_unused void *ptr_params,
__rte_unused struct cmdline *ctx,
__rte_unused void *ptr_data)
{
struct ethtool_drvinfo info;
int id_port;
for (id_port = 0; id_port < rte_eth_dev_count(); id_port++) {
if (rte_ethtool_get_drvinfo(id_port, &info)) {
printf("Error getting info for port %i\n", id_port);
return;
}
printf("Port %i driver: %s (ver: %s)\n",
id_port, info.driver, info.version
);
}
}
static void
pcmd_link_callback(__rte_unused void *ptr_params,
__rte_unused struct cmdline *ctx,
__rte_unused void *ptr_data)
{
int num_ports = rte_eth_dev_count();
int id_port, stat_port;
for (id_port = 0; id_port < num_ports; id_port++) {
if (!rte_eth_dev_is_valid_port(id_port))
continue;
stat_port = rte_ethtool_get_link(id_port);
switch (stat_port) {
case 0:
printf("Port %i: Down\n", id_port);
break;
case 1:
printf("Port %i: Up\n", id_port);
break;
default:
printf("Port %i: Error getting link status\n",
id_port
);
break;
}
}
printf("\n");
}
static void
pcmd_regs_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
__rte_unused void *ptr_data)
{
struct pcmd_intstr_params *params = ptr_params;
int len_regs;
struct ethtool_regs regs;
unsigned char *buf_data;
FILE *fp_regs;
if (!rte_eth_dev_is_valid_port(params->port)) {
printf("Error: Invalid port number %i\n", params->port);
return;
}
len_regs = rte_ethtool_get_regs_len(params->port);
if (len_regs > 0) {
printf("Port %i: %i bytes\n", params->port, len_regs);
buf_data = malloc(len_regs);
if (buf_data == NULL) {
printf("Error allocating %i bytes for buffer\n",
len_regs);
return;
}
if (!rte_ethtool_get_regs(params->port, &regs, buf_data)) {
fp_regs = fopen(params->opt, "wb");
if (fp_regs == NULL) {
printf("Error opening '%s' for writing\n",
params->opt);
} else {
if ((int)fwrite(buf_data,
1, len_regs,
fp_regs) != len_regs)
printf("Error writing '%s'\n",
params->opt);
fclose(fp_regs);
}
}
free(buf_data);
} else if (len_regs == -ENOTSUP)
printf("Port %i: Operation not supported\n", params->port);
else
printf("Port %i: Error getting registers\n", params->port);
}
static void
pcmd_eeprom_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
__rte_unused void *ptr_data)
{
struct pcmd_intstr_params *params = ptr_params;
struct ethtool_eeprom info_eeprom;
int len_eeprom;
int pos_eeprom;
int stat;
unsigned char bytes_eeprom[EEPROM_DUMP_CHUNKSIZE];
FILE *fp_eeprom;
if (!rte_eth_dev_is_valid_port(params->port)) {
printf("Error: Invalid port number %i\n", params->port);
return;
}
len_eeprom = rte_ethtool_get_eeprom_len(params->port);
if (len_eeprom > 0) {
fp_eeprom = fopen(params->opt, "wb");
if (fp_eeprom == NULL) {
printf("Error opening '%s' for writing\n",
params->opt);
return;
}
printf("Total EEPROM length: %i bytes\n", len_eeprom);
info_eeprom.len = EEPROM_DUMP_CHUNKSIZE;
for (pos_eeprom = 0;
pos_eeprom < len_eeprom;
pos_eeprom += EEPROM_DUMP_CHUNKSIZE) {
info_eeprom.offset = pos_eeprom;
if (pos_eeprom + EEPROM_DUMP_CHUNKSIZE > len_eeprom)
info_eeprom.len = len_eeprom - pos_eeprom;
else
info_eeprom.len = EEPROM_DUMP_CHUNKSIZE;
stat = rte_ethtool_get_eeprom(
params->port, &info_eeprom, bytes_eeprom
);
if (stat != 0) {
printf("EEPROM read error %i\n", stat);
break;
}
if (fwrite(bytes_eeprom,
1, info_eeprom.len,
fp_eeprom) != info_eeprom.len) {
printf("Error writing '%s'\n", params->opt);
break;
}
}
fclose(fp_eeprom);
} else if (len_eeprom == 0)
printf("Port %i: Device does not have EEPROM\n", params->port);
else if (len_eeprom == -ENOTSUP)
printf("Port %i: Operation not supported\n", params->port);
else
printf("Port %i: Error getting EEPROM\n", params->port);
}
static void
pcmd_pause_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
void *ptr_data)
{
struct pcmd_intstr_params *params = ptr_params;
struct ethtool_pauseparam info;
int stat;
if (!rte_eth_dev_is_valid_port(params->port)) {
printf("Error: Invalid port number %i\n", params->port);
return;
}
if (ptr_data != NULL) {
stat = rte_ethtool_get_pauseparam(params->port, &info);
} else {
if (strcasecmp("all", params->opt) == 0) {
info.tx_pause = 1;
info.rx_pause = 1;
} else if (strcasecmp("tx", params->opt) == 0) {
info.tx_pause = 1;
info.rx_pause = 0;
} else if (strcasecmp("rx", params->opt) == 0) {
info.tx_pause = 0;
info.rx_pause = 1;
} else {
info.tx_pause = 0;
info.rx_pause = 0;
}
stat = rte_ethtool_set_pauseparam(params->port, &info);
}
if (stat == 0) {
if (info.rx_pause && info.tx_pause)
printf("Port %i: Tx & Rx Paused\n", params->port);
else if (info.rx_pause)
printf("Port %i: Rx Paused\n", params->port);
else if (info.tx_pause)
printf("Port %i: Tx Paused\n", params->port);
else
printf("Port %i: Tx & Rx not paused\n", params->port);
} else if (stat == -ENOTSUP)
printf("Port %i: Operation not supported\n", params->port);
else
printf("Port %i: Error %i\n", params->port, stat);
}
static void
pcmd_open_callback(__rte_unused void *ptr_params,
__rte_unused struct cmdline *ctx,
__rte_unused void *ptr_data)
{
struct pcmd_int_params *params = ptr_params;
int stat;
if (!rte_eth_dev_is_valid_port(params->port)) {
printf("Error: Invalid port number %i\n", params->port);
return;
}
lock_port(params->port);
stat = rte_ethtool_net_open(params->port);
mark_port_active(params->port);
unlock_port(params->port);
if (stat == 0)
return;
else if (stat == -ENOTSUP)
printf("Port %i: Operation not supported\n", params->port);
else
printf("Port %i: Error opening device\n", params->port);
}
static void
pcmd_stop_callback(__rte_unused void *ptr_params,
__rte_unused struct cmdline *ctx,
__rte_unused void *ptr_data)
{
struct pcmd_int_params *params = ptr_params;
int stat;
if (!rte_eth_dev_is_valid_port(params->port)) {
printf("Error: Invalid port number %i\n", params->port);
return;
}
lock_port(params->port);
stat = rte_ethtool_net_stop(params->port);
mark_port_inactive(params->port);
unlock_port(params->port);
if (stat == 0)
return;
else if (stat == -ENOTSUP)
printf("Port %i: Operation not supported\n", params->port);
else
printf("Port %i: Error stopping device\n", params->port);
}
static void
pcmd_rxmode_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
__rte_unused void *ptr_data)
{
struct pcmd_intstr_params *params = ptr_params;
int stat;
if (!rte_eth_dev_is_valid_port(params->port)) {
printf("Error: Invalid port number %i\n", params->port);
return;
}
stat = rte_ethtool_net_set_rx_mode(params->port);
if (stat == 0)
return;
else if (stat == -ENOTSUP)
printf("Port %i: Operation not supported\n", params->port);
else
printf("Port %i: Error setting rx mode\n", params->port);
}
static void
pcmd_macaddr_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
void *ptr_data)
{
struct pcmd_intmac_params *params = ptr_params;
struct ether_addr mac_addr;
int stat;
stat = 0;
if (!rte_eth_dev_is_valid_port(params->port)) {
printf("Error: Invalid port number %i\n", params->port);
return;
}
if (ptr_data != NULL) {
lock_port(params->port);
stat = rte_ethtool_net_set_mac_addr(params->port,
&params->mac);
mark_port_newmac(params->port);
unlock_port(params->port);
if (stat == 0) {
printf("MAC address changed\n");
return;
}
} else {
stat = rte_ethtool_net_get_mac_addr(params->port, &mac_addr);
if (stat == 0) {
printf(
"Port %i MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
params->port,
mac_addr.addr_bytes[0],
mac_addr.addr_bytes[1],
mac_addr.addr_bytes[2],
mac_addr.addr_bytes[3],
mac_addr.addr_bytes[4],
mac_addr.addr_bytes[5]);
return;
}
}
if (stat == 0)
return;
else if (stat == -ENOTSUP)
printf("Port %i: Operation not supported\n", params->port);
else
printf("Port %i: Error %i\n", params->port, stat);
}
static void
pcmd_mtu_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
__rte_unused void *ptr_data)
{
struct pcmd_intstr_params *params = ptr_params;
int stat;
int new_mtu;
char *ptr_parse_end;
if (!rte_eth_dev_is_valid_port(params->port)) {
printf("Error: Invalid port number %i\n", params->port);
return;
}
new_mtu = atoi(params->opt);
new_mtu = strtoul(params->opt, &ptr_parse_end, 10);
if (*ptr_parse_end != '\0' ||
new_mtu < ETHER_MIN_MTU ||
new_mtu > ETHER_MAX_JUMBO_FRAME_LEN) {
printf("Port %i: Invalid MTU value\n", params->port);
return;
}
stat = rte_ethtool_net_change_mtu(params->port, new_mtu);
if (stat == 0)
printf("Port %i: MTU set to %i\n", params->port, new_mtu);
else if (stat == -ENOTSUP)
printf("Port %i: Operation not supported\n", params->port);
else
printf("Port %i: Error setting MTU\n", params->port);
}
static void pcmd_portstats_callback(__rte_unused void *ptr_params,
__rte_unused struct cmdline *ctx,
__rte_unused void *ptr_data)
{
struct pcmd_int_params *params = ptr_params;
struct rte_eth_stats stat_info;
int stat;
if (!rte_eth_dev_is_valid_port(params->port)) {
printf("Error: Invalid port number %i\n", params->port);
return;
}
stat = rte_ethtool_net_get_stats64(params->port, &stat_info);
if (stat == 0) {
/* Most of rte_eth_stats is deprecated.. */
printf("Port %i stats\n", params->port);
printf(" In: %" PRIu64 " (%" PRIu64 " bytes)\n"
" Out: %"PRIu64" (%"PRIu64 " bytes)\n"
" Err: %"PRIu64"\n",
stat_info.ipackets,
stat_info.ibytes,
stat_info.opackets,
stat_info.obytes,
stat_info.ierrors+stat_info.oerrors
);
} else if (stat == -ENOTSUP)
printf("Port %i: Operation not supported\n", params->port);
else
printf("Port %i: Error fetching statistics\n", params->port);
}
static void pcmd_ringparam_callback(__rte_unused void *ptr_params,
__rte_unused struct cmdline *ctx,
void *ptr_data)
{
struct pcmd_intintint_params *params = ptr_params;
struct ethtool_ringparam ring_data;
struct ethtool_ringparam ring_params;
int stat;
if (!rte_eth_dev_is_valid_port(params->port)) {
printf("Error: Invalid port number %i\n", params->port);
return;
}
if (ptr_data == NULL) {
stat = rte_ethtool_get_ringparam(params->port, &ring_data);
if (stat == 0) {
printf("Port %i ring parameters\n"
" Rx Pending: %i (%i max)\n"
" Tx Pending: %i (%i max)\n",
params->port,
ring_data.rx_pending,
ring_data.rx_max_pending,
ring_data.tx_pending,
ring_data.tx_max_pending);
}
} else {
if (params->tx < 1 || params->rx < 1) {
printf("Error: Invalid parameters\n");
return;
}
memset(&ring_params, 0, sizeof(struct ethtool_ringparam));
ring_params.tx_pending = params->tx;
ring_params.rx_pending = params->rx;
lock_port(params->port);
stat = rte_ethtool_set_ringparam(params->port, &ring_params);
unlock_port(params->port);
}
if (stat == 0)
return;
else if (stat == -ENOTSUP)
printf("Port %i: Operation not supported\n", params->port);
else
printf("Port %i: Error fetching statistics\n", params->port);
}
static void pcmd_validate_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
__rte_unused void *ptr_data)
{
struct pcmd_intmac_params *params = ptr_params;
if (rte_ethtool_net_validate_addr(0, &params->mac))
printf("Address is unicast\n");
else
printf("Address is not unicast\n");
}
static void pcmd_vlan_callback(__rte_unused void *ptr_params,
__rte_unused struct cmdline *ctx,
__rte_unused void *ptr_data)
{
struct pcmd_vlan_params *params = ptr_params;
int stat;
if (!rte_eth_dev_is_valid_port(params->port)) {
printf("Error: Invalid port number %i\n", params->port);
return;
}
stat = 0;
if (strcasecmp("add", params->mode) == 0) {
stat = rte_ethtool_net_vlan_rx_add_vid(
params->port, params->vid
);
if (stat == 0)
printf("VLAN vid %i added\n", params->vid);
} else if (strcasecmp("del", params->mode) == 0) {
stat = rte_ethtool_net_vlan_rx_kill_vid(
params->port, params->vid
);
if (stat == 0)
printf("VLAN vid %i removed\n", params->vid);
} else {
/* Should not happen! */
printf("Error: Bad mode %s\n", params->mode);
}
if (stat == -ENOTSUP)
printf("Port %i: Operation not supported\n", params->port);
else if (stat == -ENOSYS)
printf("Port %i: VLAN filtering disabled\n", params->port);
else if (stat != 0)
printf("Port %i: Error changing VLAN setup (code %i)\n",
params->port, -stat);
}
cmdline_parse_inst_t pcmd_quit = {
.f = pcmd_quit_callback,
.data = NULL,
.help_str = "quit\n Exit program",
.tokens = {(void *)&pcmd_quit_token_cmd, NULL},
};
cmdline_parse_inst_t pcmd_drvinfo = {
.f = pcmd_drvinfo_callback,
.data = NULL,
.help_str = "drvinfo\n Print driver info",
.tokens = {(void *)&pcmd_drvinfo_token_cmd, NULL},
};
cmdline_parse_inst_t pcmd_link = {
.f = pcmd_link_callback,
.data = NULL,
.help_str = "link\n Print port link states",
.tokens = {(void *)&pcmd_link_token_cmd, NULL},
};
cmdline_parse_inst_t pcmd_regs = {
.f = pcmd_regs_callback,
.data = NULL,
.help_str = "regs <port_id> <filename>\n"
" Dump port register(s) to file",
.tokens = {
(void *)&pcmd_regs_token_cmd,
(void *)&pcmd_intstr_token_port,
(void *)&pcmd_intstr_token_opt,
NULL
},
};
cmdline_parse_inst_t pcmd_eeprom = {
.f = pcmd_eeprom_callback,
.data = NULL,
.help_str = "eeprom <port_id> <filename>\n Dump EEPROM to file",
.tokens = {
(void *)&pcmd_eeprom_token_cmd,
(void *)&pcmd_intstr_token_port,
(void *)&pcmd_intstr_token_opt,
NULL
},
};
cmdline_parse_inst_t pcmd_pause_noopt = {
.f = pcmd_pause_callback,
.data = (void *)0x01,
.help_str = "pause <port_id>\n Print port pause state",
.tokens = {
(void *)&pcmd_pause_token_cmd,
(void *)&pcmd_pause_token_port,
NULL
},
};
cmdline_parse_inst_t pcmd_pause = {
.f = pcmd_pause_callback,
.data = NULL,
.help_str =
"pause <port_id> <all|tx|rx|none>\n Pause/unpause port",
.tokens = {
(void *)&pcmd_pause_token_cmd,
(void *)&pcmd_pause_token_port,
(void *)&pcmd_pause_token_opt,
NULL
},
};
cmdline_parse_inst_t pcmd_open = {
.f = pcmd_open_callback,
.data = NULL,
.help_str = "open <port_id>\n Open port",
.tokens = {
(void *)&pcmd_open_token_cmd,
(void *)&pcmd_int_token_port,
NULL
},
};
cmdline_parse_inst_t pcmd_stop = {
.f = pcmd_stop_callback,
.data = NULL,
.help_str = "stop <port_id>\n Stop port",
.tokens = {
(void *)&pcmd_stop_token_cmd,
(void *)&pcmd_int_token_port,
NULL
},
};
cmdline_parse_inst_t pcmd_rxmode = {
.f = pcmd_rxmode_callback,
.data = NULL,
.help_str = "rxmode <port_id>\n Toggle port Rx mode",
.tokens = {
(void *)&pcmd_rxmode_token_cmd,
(void *)&pcmd_int_token_port,
NULL
},
};
cmdline_parse_inst_t pcmd_macaddr_get = {
.f = pcmd_macaddr_callback,
.data = NULL,
.help_str = "macaddr <port_id>\n"
" Get MAC address",
.tokens = {
(void *)&pcmd_macaddr_token_cmd,
(void *)&pcmd_intstr_token_port,
NULL
},
};
cmdline_parse_inst_t pcmd_macaddr = {
.f = pcmd_macaddr_callback,
.data = (void *)0x01,
.help_str =
"macaddr <port_id> <mac_addr>\n"
" Set MAC address",
.tokens = {
(void *)&pcmd_macaddr_token_cmd,
(void *)&pcmd_intmac_token_port,
(void *)&pcmd_intmac_token_mac,
NULL
},
};
cmdline_parse_inst_t pcmd_mtu = {
.f = pcmd_mtu_callback,
.data = NULL,
.help_str = "mtu <port_id> <mtu_value>\n"
" Change MTU",
.tokens = {
(void *)&pcmd_mtu_token_cmd,
(void *)&pcmd_intstr_token_port,
(void *)&pcmd_intstr_token_opt,
NULL
},
};
cmdline_parse_inst_t pcmd_portstats = {
.f = pcmd_portstats_callback,
.data = NULL,
.help_str = "portstats <port_id>\n"
" Print port eth statistics",
.tokens = {
(void *)&pcmd_portstats_token_cmd,
(void *)&pcmd_int_token_port,
NULL
},
};
cmdline_parse_inst_t pcmd_ringparam = {
.f = pcmd_ringparam_callback,
.data = NULL,
.help_str = "ringparam <port_id>\n"
" Print ring parameters",
.tokens = {
(void *)&pcmd_ringparam_token_cmd,
(void *)&pcmd_intintint_token_port,
NULL
},
};
cmdline_parse_inst_t pcmd_ringparam_set = {
.f = pcmd_ringparam_callback,
.data = (void *)1,
.help_str = "ringparam <port_id> <tx_param> <rx_param>\n"
" Set ring parameters",
.tokens = {
(void *)&pcmd_ringparam_token_cmd,
(void *)&pcmd_intintint_token_port,
(void *)&pcmd_intintint_token_tx,
(void *)&pcmd_intintint_token_rx,
NULL
},
};
cmdline_parse_inst_t pcmd_validate = {
.f = pcmd_validate_callback,
.data = NULL,
.help_str = "validate <mac_addr>\n"
" Check that MAC address is valid unicast address",
.tokens = {
(void *)&pcmd_validate_token_cmd,
(void *)&pcmd_intmac_token_mac,
NULL
},
};
cmdline_parse_inst_t pcmd_vlan = {
.f = pcmd_vlan_callback,
.data = NULL,
.help_str = "vlan <port_id> <add|del> <vlan_id>\n"
" Add/remove VLAN id",
.tokens = {
(void *)&pcmd_vlan_token_cmd,
(void *)&pcmd_vlan_token_port,
(void *)&pcmd_vlan_token_mode,
(void *)&pcmd_vlan_token_vid,
NULL
},
};
cmdline_parse_ctx_t list_prompt_commands[] = {
(cmdline_parse_inst_t *)&pcmd_drvinfo,
(cmdline_parse_inst_t *)&pcmd_eeprom,
(cmdline_parse_inst_t *)&pcmd_link,
(cmdline_parse_inst_t *)&pcmd_macaddr_get,
(cmdline_parse_inst_t *)&pcmd_macaddr,
(cmdline_parse_inst_t *)&pcmd_mtu,
(cmdline_parse_inst_t *)&pcmd_open,
(cmdline_parse_inst_t *)&pcmd_pause_noopt,
(cmdline_parse_inst_t *)&pcmd_pause,
(cmdline_parse_inst_t *)&pcmd_portstats,
(cmdline_parse_inst_t *)&pcmd_regs,
(cmdline_parse_inst_t *)&pcmd_ringparam,
(cmdline_parse_inst_t *)&pcmd_ringparam_set,
(cmdline_parse_inst_t *)&pcmd_rxmode,
(cmdline_parse_inst_t *)&pcmd_stop,
(cmdline_parse_inst_t *)&pcmd_validate,
(cmdline_parse_inst_t *)&pcmd_vlan,
(cmdline_parse_inst_t *)&pcmd_quit,
NULL
};
void ethapp_main(void)
{
struct cmdline *ctx_cmdline;
ctx_cmdline = cmdline_stdin_new(list_prompt_commands, "EthApp> ");
cmdline_interact(ctx_cmdline);
cmdline_stdin_exit(ctx_cmdline);
}

View file

@ -0,0 +1,41 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2015 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
void ethapp_main(void);
void print_stats(void);
void lock_port(int idx_port);
void unlock_port(int idx_port);
void mark_port_inactive(int idx_port);
void mark_port_active(int idx_port);
void mark_port_newmac(int idx_port);

View file

@ -0,0 +1,305 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2015 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <rte_common.h>
#include <rte_rwlock.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_ether.h>
#include <rte_ip.h>
#include <rte_memory.h>
#include <rte_mempool.h>
#include <rte_mbuf.h>
#include "ethapp.h"
#define MAX_PORTS RTE_MAX_ETHPORTS
#define MAX_BURST_LENGTH 32
#define PORT_RX_QUEUE_SIZE 128
#define PORT_TX_QUEUE_SIZE 256
#define PKTPOOL_EXTRA_SIZE 512
#define PKTPOOL_CACHE 32
struct txq_port {
uint16_t cnt_unsent;
struct rte_mbuf *buf_frames[MAX_BURST_LENGTH];
};
struct app_port {
struct ether_addr mac_addr;
struct txq_port txq;
rte_spinlock_t lock;
int port_active;
int port_dirty;
int idx_port;
struct rte_mempool *pkt_pool;
};
struct app_config {
struct app_port ports[MAX_PORTS];
int cnt_ports;
int exit_now;
};
struct app_config app_cfg;
void lock_port(int idx_port)
{
struct app_port *ptr_port = &app_cfg.ports[idx_port];
rte_spinlock_lock(&ptr_port->lock);
}
void unlock_port(int idx_port)
{
struct app_port *ptr_port = &app_cfg.ports[idx_port];
rte_spinlock_unlock(&ptr_port->lock);
}
void mark_port_active(int idx_port)
{
struct app_port *ptr_port = &app_cfg.ports[idx_port];
ptr_port->port_active = 1;
}
void mark_port_inactive(int idx_port)
{
struct app_port *ptr_port = &app_cfg.ports[idx_port];
ptr_port->port_active = 0;
}
void mark_port_newmac(int idx_port)
{
struct app_port *ptr_port = &app_cfg.ports[idx_port];
ptr_port->port_dirty = 1;
}
static void setup_ports(struct app_config *app_cfg, int cnt_ports)
{
int idx_port;
int size_pktpool;
struct rte_eth_conf cfg_port;
struct rte_eth_dev_info dev_info;
char str_name[16];
memset(&cfg_port, 0, sizeof(cfg_port));
cfg_port.txmode.mq_mode = ETH_MQ_TX_NONE;
for (idx_port = 0; idx_port < cnt_ports; idx_port++) {
struct app_port *ptr_port = &app_cfg->ports[idx_port];
rte_eth_dev_info_get(idx_port, &dev_info);
size_pktpool = dev_info.rx_desc_lim.nb_max +
dev_info.tx_desc_lim.nb_max + PKTPOOL_EXTRA_SIZE;
snprintf(str_name, 16, "pkt_pool%i", idx_port);
ptr_port->pkt_pool = rte_pktmbuf_pool_create(
str_name,
size_pktpool, PKTPOOL_CACHE,
0,
RTE_MBUF_DEFAULT_BUF_SIZE,
rte_socket_id()
);
if (ptr_port->pkt_pool == NULL)
rte_exit(EXIT_FAILURE,
"rte_pktmbuf_pool_create failed"
);
printf("Init port %i..\n", idx_port);
ptr_port->port_active = 1;
ptr_port->port_dirty = 0;
ptr_port->idx_port = idx_port;
if (rte_eth_dev_configure(idx_port, 1, 1, &cfg_port) < 0)
rte_exit(EXIT_FAILURE,
"rte_eth_dev_configure failed");
if (rte_eth_rx_queue_setup(
idx_port, 0, PORT_RX_QUEUE_SIZE,
rte_eth_dev_socket_id(idx_port), NULL,
ptr_port->pkt_pool) < 0)
rte_exit(EXIT_FAILURE,
"rte_eth_rx_queue_setup failed"
);
if (rte_eth_tx_queue_setup(
idx_port, 0, PORT_TX_QUEUE_SIZE,
rte_eth_dev_socket_id(idx_port), NULL) < 0)
rte_exit(EXIT_FAILURE,
"rte_eth_tx_queue_setup failed"
);
if (rte_eth_dev_start(idx_port) < 0)
rte_exit(EXIT_FAILURE,
"%s:%i: rte_eth_dev_start failed",
__FILE__, __LINE__
);
rte_eth_promiscuous_enable(idx_port);
rte_eth_macaddr_get(idx_port, &ptr_port->mac_addr);
rte_spinlock_init(&ptr_port->lock);
}
}
static void process_frame(struct app_port *ptr_port,
struct rte_mbuf *ptr_frame)
{
struct ether_hdr *ptr_mac_hdr;
ptr_mac_hdr = rte_pktmbuf_mtod(ptr_frame, struct ether_hdr *);
ether_addr_copy(&ptr_mac_hdr->s_addr, &ptr_mac_hdr->d_addr);
ether_addr_copy(&ptr_port->mac_addr, &ptr_mac_hdr->s_addr);
}
static int slave_main(__attribute__((unused)) void *ptr_data)
{
struct app_port *ptr_port;
struct rte_mbuf *ptr_frame;
struct txq_port *txq;
uint16_t cnt_recv_frames;
uint16_t idx_frame;
uint16_t cnt_sent;
uint16_t idx_port;
uint16_t lock_result;
while (app_cfg.exit_now == 0) {
for (idx_port = 0; idx_port < app_cfg.cnt_ports; idx_port++) {
/* Check that port is active and unlocked */
ptr_port = &app_cfg.ports[idx_port];
lock_result = rte_spinlock_trylock(&ptr_port->lock);
if (lock_result == 0)
continue;
if (ptr_port->port_active == 0) {
rte_spinlock_unlock(&ptr_port->lock);
continue;
}
txq = &ptr_port->txq;
/* MAC address was updated */
if (ptr_port->port_dirty == 1) {
rte_eth_macaddr_get(ptr_port->idx_port,
&ptr_port->mac_addr);
ptr_port->port_dirty = 0;
}
/* Incoming frames */
cnt_recv_frames = rte_eth_rx_burst(
ptr_port->idx_port, 0,
&txq->buf_frames[txq->cnt_unsent],
RTE_DIM(txq->buf_frames) - txq->cnt_unsent
);
if (cnt_recv_frames > 0) {
for (idx_frame = 0;
idx_frame < cnt_recv_frames;
idx_frame++) {
ptr_frame = txq->buf_frames[
idx_frame + txq->cnt_unsent];
process_frame(ptr_port, ptr_frame);
}
txq->cnt_unsent += cnt_recv_frames;
}
/* Outgoing frames */
if (txq->cnt_unsent > 0) {
cnt_sent = rte_eth_tx_burst(
ptr_port->idx_port, 0,
txq->buf_frames,
txq->cnt_unsent
);
/* Shuffle up unsent frame pointers */
for (idx_frame = cnt_sent;
idx_frame < txq->cnt_unsent;
idx_frame++)
txq->buf_frames[idx_frame - cnt_sent] =
txq->buf_frames[idx_frame];
txq->cnt_unsent -= cnt_sent;
}
rte_spinlock_unlock(&ptr_port->lock);
} /* end for( idx_port ) */
} /* end for(;;) */
return 0;
}
int main(int argc, char **argv)
{
int cnt_args_parsed;
uint32_t id_core;
uint32_t cnt_ports;
/* Init runtime enviornment */
cnt_args_parsed = rte_eal_init(argc, argv);
if (cnt_args_parsed < 0)
rte_exit(EXIT_FAILURE, "rte_eal_init(): Failed");
cnt_ports = rte_eth_dev_count();
printf("Number of NICs: %i\n", cnt_ports);
if (cnt_ports == 0)
rte_exit(EXIT_FAILURE, "No available NIC ports!\n");
if (cnt_ports > MAX_PORTS) {
printf("Info: Using only %i of %i ports\n",
cnt_ports, MAX_PORTS
);
cnt_ports = MAX_PORTS;
}
setup_ports(&app_cfg, cnt_ports);
app_cfg.exit_now = 0;
app_cfg.cnt_ports = cnt_ports;
if (rte_lcore_count() < 2)
rte_exit(EXIT_FAILURE, "No available slave core!\n");
/* Assume there is an available slave.. */
id_core = rte_lcore_id();
id_core = rte_get_next_lcore(id_core, 1, 1);
rte_eal_remote_launch(slave_main, NULL, id_core);
ethapp_main();
app_cfg.exit_now = 1;
RTE_LCORE_FOREACH_SLAVE(id_core) {
if (rte_eal_wait_lcore(id_core) < 0)
return -1;
}
return 0;
}

View file

@ -0,0 +1,57 @@
# BSD LICENSE
#
# Copyright(c) 2015 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ifeq ($(RTE_SDK),)
$(error "Please define RTE_SDK environment variable")
endif
# Default target, can be overwritten by command line or environment
RTE_TARGET ?= x86_64-native-linuxapp-gcc
include $(RTE_SDK)/mk/rte.vars.mk
ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp")
$(error This application can only operate in a linuxapp environment, \
please change the definition of the RTE_TARGET environment variable)
endif
# library name
LIB = librte_ethtool.a
LIBABIVER := 1
# all source are stored in SRC-Y
SRCS-y := rte_ethtool.c
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
include $(RTE_SDK)/mk/rte.extlib.mk

View file

@ -0,0 +1,423 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <rte_version.h>
#include <rte_ethdev.h>
#include <rte_ether.h>
#include "rte_ethtool.h"
#define PKTPOOL_SIZE 512
#define PKTPOOL_CACHE 32
int
rte_ethtool_get_drvinfo(uint8_t port_id, struct ethtool_drvinfo *drvinfo)
{
struct rte_eth_dev_info dev_info;
int n;
if (drvinfo == NULL)
return -EINVAL;
if (!rte_eth_dev_is_valid_port(port_id))
return -ENODEV;
memset(&dev_info, 0, sizeof(dev_info));
rte_eth_dev_info_get(port_id, &dev_info);
snprintf(drvinfo->driver, sizeof(drvinfo->driver), "%s",
dev_info.driver_name);
snprintf(drvinfo->version, sizeof(drvinfo->version), "%s",
rte_version());
snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info),
"%04x:%02x:%02x.%x",
dev_info.pci_dev->addr.domain, dev_info.pci_dev->addr.bus,
dev_info.pci_dev->addr.devid, dev_info.pci_dev->addr.function);
n = rte_eth_dev_get_reg_length(port_id);
if (n > 0)
drvinfo->regdump_len = n;
else
drvinfo->regdump_len = 0;
n = rte_eth_dev_get_eeprom_length(port_id);
if (n > 0)
drvinfo->eedump_len = n;
else
drvinfo->eedump_len = 0;
drvinfo->n_stats = sizeof(struct rte_eth_stats) / sizeof(uint64_t);
drvinfo->testinfo_len = 0;
return 0;
}
int
rte_ethtool_get_regs_len(uint8_t port_id)
{
int count_regs;
count_regs = rte_eth_dev_get_reg_length(port_id);
if (count_regs > 0)
return count_regs * sizeof(uint32_t);
return count_regs;
}
int
rte_ethtool_get_regs(uint8_t port_id, struct ethtool_regs *regs, void *data)
{
struct rte_dev_reg_info reg_info;
int status;
if (regs == NULL || data == NULL)
return -EINVAL;
reg_info.data = data;
reg_info.length = 0;
status = rte_eth_dev_get_reg_info(port_id, &reg_info);
if (status)
return status;
regs->version = reg_info.version;
return 0;
}
int
rte_ethtool_get_link(uint8_t port_id)
{
struct rte_eth_link link;
if (!rte_eth_dev_is_valid_port(port_id))
return -ENODEV;
rte_eth_link_get(port_id, &link);
return link.link_status;
}
int
rte_ethtool_get_eeprom_len(uint8_t port_id)
{
return rte_eth_dev_get_eeprom_length(port_id);
}
int
rte_ethtool_get_eeprom(uint8_t port_id, struct ethtool_eeprom *eeprom,
void *words)
{
struct rte_dev_eeprom_info eeprom_info;
int status;
if (eeprom == NULL || words == NULL)
return -EINVAL;
eeprom_info.offset = eeprom->offset;
eeprom_info.length = eeprom->len;
eeprom_info.data = words;
status = rte_eth_dev_get_eeprom(port_id, &eeprom_info);
if (status)
return status;
eeprom->magic = eeprom_info.magic;
return 0;
}
int
rte_ethtool_set_eeprom(uint8_t port_id, struct ethtool_eeprom *eeprom,
void *words)
{
struct rte_dev_eeprom_info eeprom_info;
int status;
if (eeprom == NULL || words == NULL || eeprom->offset >= eeprom->len)
return -EINVAL;
eeprom_info.offset = eeprom->offset;
eeprom_info.length = eeprom->len;
eeprom_info.data = words;
status = rte_eth_dev_set_eeprom(port_id, &eeprom_info);
if (status)
return status;
eeprom->magic = eeprom_info.magic;
return 0;
}
int
rte_ethtool_get_pauseparam(uint8_t port_id,
struct ethtool_pauseparam *pause_param)
{
struct rte_eth_fc_conf fc_conf;
int status;
if (pause_param == NULL)
return -EINVAL;
status = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf);
if (status)
return status;
pause_param->tx_pause = 0;
pause_param->rx_pause = 0;
switch (fc_conf.mode) {
case RTE_FC_RX_PAUSE:
pause_param->rx_pause = 1;
break;
case RTE_FC_TX_PAUSE:
pause_param->tx_pause = 1;
break;
case RTE_FC_FULL:
pause_param->rx_pause = 1;
pause_param->tx_pause = 1;
default:
/* dummy block to avoid compiler warning */
break;
}
pause_param->autoneg = (uint32_t)fc_conf.autoneg;
return 0;
}
int
rte_ethtool_set_pauseparam(uint8_t port_id,
struct ethtool_pauseparam *pause_param)
{
struct rte_eth_fc_conf fc_conf;
int status;
if (pause_param == NULL)
return -EINVAL;
/*
* Read device flow control parameter first since
* ethtool set_pauseparam op doesn't have all the information.
* as defined in struct rte_eth_fc_conf.
* This API requires the device to support both
* rte_eth_dev_flow_ctrl_get and rte_eth_dev_flow_ctrl_set, otherwise
* return -ENOTSUP
*/
status = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf);
if (status)
return status;
fc_conf.autoneg = (uint8_t)pause_param->autoneg;
if (pause_param->tx_pause) {
if (pause_param->rx_pause)
fc_conf.mode = RTE_FC_FULL;
else
fc_conf.mode = RTE_FC_TX_PAUSE;
} else {
if (pause_param->rx_pause)
fc_conf.mode = RTE_FC_RX_PAUSE;
else
fc_conf.mode = RTE_FC_NONE;
}
status = rte_eth_dev_flow_ctrl_set(port_id, &fc_conf);
if (status)
return status;
return 0;
}
int
rte_ethtool_net_open(uint8_t port_id)
{
rte_eth_dev_stop(port_id);
return rte_eth_dev_start(port_id);
}
int
rte_ethtool_net_stop(uint8_t port_id)
{
if (!rte_eth_dev_is_valid_port(port_id))
return -ENODEV;
rte_eth_dev_stop(port_id);
return 0;
}
int
rte_ethtool_net_get_mac_addr(uint8_t port_id, struct ether_addr *addr)
{
if (!rte_eth_dev_is_valid_port(port_id))
return -ENODEV;
if (addr == NULL)
return -EINVAL;
rte_eth_macaddr_get(port_id, addr);
return 0;
}
int
rte_ethtool_net_set_mac_addr(uint8_t port_id, struct ether_addr *addr)
{
if (addr == NULL)
return -EINVAL;
return rte_eth_dev_default_mac_addr_set(port_id, addr);
}
int
rte_ethtool_net_validate_addr(uint8_t port_id __rte_unused,
struct ether_addr *addr)
{
if (addr == NULL)
return -EINVAL;
return is_valid_assigned_ether_addr(addr);
}
int
rte_ethtool_net_change_mtu(uint8_t port_id, int mtu)
{
if (mtu < 0 || mtu > UINT16_MAX)
return -EINVAL;
return rte_eth_dev_set_mtu(port_id, (uint16_t)mtu);
}
int
rte_ethtool_net_get_stats64(uint8_t port_id, struct rte_eth_stats *stats)
{
if (stats == NULL)
return -EINVAL;
return rte_eth_stats_get(port_id, stats);
}
int
rte_ethtool_net_vlan_rx_add_vid(uint8_t port_id, uint16_t vid)
{
return rte_eth_dev_vlan_filter(port_id, vid, 1);
}
int
rte_ethtool_net_vlan_rx_kill_vid(uint8_t port_id, uint16_t vid)
{
return rte_eth_dev_vlan_filter(port_id, vid, 0);
}
/*
* The set_rx_mode provides driver-specific rx mode setting.
* This implementation implements rx mode setting based upon
* ixgbe/igb drivers. Further improvement is to provide a
* callback op field over struct rte_eth_dev::dev_ops so each
* driver can register device-specific implementation
*/
int
rte_ethtool_net_set_rx_mode(uint8_t port_id)
{
uint16_t num_vfs;
struct rte_eth_dev_info dev_info;
uint16_t vf;
memset(&dev_info, 0, sizeof(dev_info));
rte_eth_dev_info_get(port_id, &dev_info);
num_vfs = dev_info.max_vfs;
/* Set VF vf_rx_mode, VF unsupport status is discard */
for (vf = 0; vf < num_vfs; vf++)
rte_eth_dev_set_vf_rxmode(port_id, vf,
ETH_VMDQ_ACCEPT_UNTAG, 0);
/* Enable Rx vlan filter, VF unspport status is discard */
rte_eth_dev_set_vlan_offload(port_id, ETH_VLAN_FILTER_MASK);
return 0;
}
int
rte_ethtool_get_ringparam(uint8_t port_id,
struct ethtool_ringparam *ring_param)
{
struct rte_eth_dev_info dev_info;
struct rte_eth_rxq_info rx_qinfo;
struct rte_eth_txq_info tx_qinfo;
int stat;
if (ring_param == NULL)
return -EINVAL;
rte_eth_dev_info_get(port_id, &dev_info);
stat = rte_eth_rx_queue_info_get(port_id, 0, &rx_qinfo);
if (stat != 0)
return stat;
stat = rte_eth_tx_queue_info_get(port_id, 0, &tx_qinfo);
if (stat != 0)
return stat;
memset(ring_param, 0, sizeof(*ring_param));
ring_param->rx_pending = rx_qinfo.nb_desc;
ring_param->rx_max_pending = dev_info.rx_desc_lim.nb_max;
ring_param->tx_pending = tx_qinfo.nb_desc;
ring_param->tx_max_pending = dev_info.tx_desc_lim.nb_max;
return 0;
}
int
rte_ethtool_set_ringparam(uint8_t port_id,
struct ethtool_ringparam *ring_param)
{
struct rte_eth_rxq_info rx_qinfo;
int stat;
if (ring_param == NULL)
return -EINVAL;
stat = rte_eth_rx_queue_info_get(port_id, 0, &rx_qinfo);
if (stat != 0)
return stat;
rte_eth_dev_stop(port_id);
stat = rte_eth_tx_queue_setup(port_id, 0, ring_param->tx_pending,
rte_socket_id(), NULL);
if (stat != 0)
return stat;
stat = rte_eth_rx_queue_setup(port_id, 0, ring_param->rx_pending,
rte_socket_id(), NULL, rx_qinfo.mp);
if (stat != 0)
return stat;
return rte_eth_dev_start(port_id);
}

View file

@ -0,0 +1,410 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _RTE_ETHTOOL_H_
#define _RTE_ETHTOOL_H_
/*
* This new interface is designed to provide a user-space shim layer for
* Ethtool and Netdevice op API.
*
* rte_ethtool_get_driver: ethtool_ops::get_driverinfo
* rte_ethtool_get_link: ethtool_ops::get_link
* rte_ethtool_get_regs_len: ethtool_ops::get_regs_len
* rte_ethtool_get_regs: ethtool_ops::get_regs
* rte_ethtool_get_eeprom_len: ethtool_ops::get_eeprom_len
* rte_ethtool_get_eeprom: ethtool_ops::get_eeprom
* rte_ethtool_set_eeprom: ethtool_ops::set_eeprom
* rte_ethtool_get_pauseparam: ethtool_ops::get_pauseparam
* rte_ethtool_set_pauseparam: ethtool_ops::set_pauseparam
*
* rte_ethtool_net_open: net_device_ops::ndo_open
* rte_ethtool_net_stop: net_device_ops::ndo_stop
* rte_ethtool_net_set_mac_addr: net_device_ops::ndo_set_mac_address
* rte_ethtool_net_validate_addr: net_device_ops::ndo_validate_addr
* rte_ethtool_net_change_mtu: net_device_ops::rte_net_change_mtu
* rte_ethtool_net_get_stats64: net_device_ops::ndo_get_stats64
* rte_ethtool_net_vlan_rx_add_vid net_device_ops::ndo_vlan_rx_add_vid
* rte_ethtool_net_vlan_rx_kill_vid net_device_ops::ndo_vlan_rx_kill_vid
* rte_ethtool_net_set_rx_mode net_device_ops::ndo_set_rx_mode
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <rte_ethdev.h>
#include <linux/ethtool.h>
/**
* Retrieve the Ethernet device driver information according to
* attributes described by ethtool data structure, ethtool_drvinfo.
*
* @param port_id
* The port identifier of the Ethernet device.
* @param drvinfo
* A pointer to get driver information
* @return
* - (0) if successful.
* - (-ENODEV) if *port_id* invalid.
*/
int rte_ethtool_get_drvinfo(uint8_t port_id, struct ethtool_drvinfo *drvinfo);
/**
* Retrieve the Ethernet device register length in bytes.
*
* @param port_id
* The port identifier of the Ethernet device.
* @return
* - (> 0) # of device registers (in bytes) available for dump
* - (0) no registers available for dump.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_get_regs_len(uint8_t port_id);
/**
* Retrieve the Ethernet device register information according to
* attributes described by ethtool data structure, ethtool_regs
*
* @param port_id
* The port identifier of the Ethernet device.
* @param reg
* A pointer to ethtool_regs that has register information
* @param data
* A pointer to a buffer that is used to retrieve device register content
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_get_regs(uint8_t port_id, struct ethtool_regs *regs,
void *data);
/**
* Retrieve the Ethernet device link status
*
* @param port_id
* The port identifier of the Ethernet device.
* @return
* - (1) if link up.
* - (0) if link down.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - (-EINVAL) if parameters invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_get_link(uint8_t port_id);
/**
* Retrieve the Ethernet device EEPROM size
*
* @param port_id
* The port identifier of the Ethernet device.
* @return
* - (> 0) device EEPROM size in bytes
* - (0) device has NO EEPROM
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_get_eeprom_len(uint8_t port_id);
/**
* Retrieve EEPROM content based upon eeprom range described in ethtool
* data structure, ethtool_eeprom
*
* @param port_id
* The port identifier of the Ethernet device.
* @param eeprom
* The pointer of ethtool_eeprom that provides eeprom range
* @param words
* A buffer that holds data read from eeprom
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_get_eeprom(uint8_t port_id, struct ethtool_eeprom *eeprom,
void *words);
/**
* Setting EEPROM content based upon eeprom range described in ethtool
* data structure, ethtool_eeprom
*
* @param port_id
* The port identifier of the Ethernet device.
* @param eeprom
* The pointer of ethtool_eeprom that provides eeprom range
* @param words
* A buffer that holds data to be written into eeprom
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - (-EINVAL) if parameters invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_set_eeprom(uint8_t port_id, struct ethtool_eeprom *eeprom,
void *words);
/**
* Retrieve the Ethernet device pause frame configuration according to
* parameter attributes desribed by ethtool data structure,
* ethtool_pauseparam.
*
* @param port_id
* The port identifier of the Ethernet device.
* @param pause_param
* The pointer of ethtool_coalesce that gets pause frame
* configuration parameters
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - (-EINVAL) if parameters invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_get_pauseparam(uint8_t port_id,
struct ethtool_pauseparam *pause_param);
/**
* Setting the Ethernet device pause frame configuration according to
* parameter attributes desribed by ethtool data structure, ethtool_pauseparam.
*
* @param port_id
* The port identifier of the Ethernet device.
* @param pause_param
* The pointer of ethtool_coalesce that gets ring configuration parameters
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - (-EINVAL) if parameters invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_set_pauseparam(uint8_t port_id,
struct ethtool_pauseparam *param);
/**
* Start the Ethernet device.
*
* @param port_id
* The port identifier of the Ethernet device.
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_net_open(uint8_t port_id);
/**
* Stop the Ethernet device.
*
* @param port_id
* The port identifier of the Ethernet device.
* @return
* - (0) if successful.
* - (-ENODEV) if *port_id* invalid.
*/
int rte_ethtool_net_stop(uint8_t port_id);
/**
* Get the Ethernet device MAC address.
*
* @param port_id
* The port identifier of the Ethernet device.
* @param addr
* MAC address of the Ethernet device.
* @return
* - (0) if successful.
* - (-ENODEV) if *port_id* invalid.
*/
int rte_ethtool_net_get_mac_addr(uint8_t port_id, struct ether_addr *addr);
/**
* Setting the Ethernet device MAC address.
*
* @param port_id
* The port identifier of the Ethernet device.
* @param addr
* The new MAC addr.
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - (-EINVAL) if parameters invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_net_set_mac_addr(uint8_t port_id, struct ether_addr *addr);
/**
* Validate if the provided MAC address is valid unicast address
*
* @param port_id
* The port identifier of the Ethernet device.
* @param addr
* A pointer to a buffer (6-byte, 48bit) for the target MAC address
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - (-EINVAL) if parameters invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_net_validate_addr(uint8_t port_id, struct ether_addr *addr);
/**
* Setting the Ethernet device maximum Tx unit.
*
* @param port_id
* The port identifier of the Ethernet device.
* @param mtu
* New MTU
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - (-EINVAL) if parameters invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_net_change_mtu(uint8_t port_id, int mtu);
/**
* Retrieve the Ethernet device traffic statistics
*
* @param port_id
* The port identifier of the Ethernet device.
* @param stats
* A pointer to struct rte_eth_stats for statistics parameters
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - (-EINVAL) if parameters invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_net_get_stats64(uint8_t port_id, struct rte_eth_stats *stats);
/**
* Update the Ethernet device VLAN filter with new vid
*
* @param port_id
* The port identifier of the Ethernet device.
* @param vid
* A new VLAN id
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_net_vlan_rx_add_vid(uint8_t port_id, uint16_t vid);
/**
* Remove VLAN id from Ethernet device.
*
* @param port_id
* The port identifier of the Ethernet device.
* @param vid
* A new VLAN id
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_net_vlan_rx_kill_vid(uint8_t port_id, uint16_t vid);
/**
* Setting the Ethernet device rx mode.
*
* @param port_id
* The port identifier of the Ethernet device.
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - others depends on the specific operations implementation.
*/
int rte_ethtool_net_set_rx_mode(uint8_t port_id);
/**
* Getting ring paramaters for Ethernet device.
*
* @param port_id
* The port identifier of the Ethernet device.
* @param ring_param
* Pointer to struct ethrool_ringparam to receive parameters.
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - others depends on the specific operations implementation.
* @note
* Only the tx_pending and rx_pending fields of struct ethtool_ringparam
* are used, and the function only gets parameters for queue 0.
*/
int rte_ethtool_get_ringparam(uint8_t port_id,
struct ethtool_ringparam *ring_param);
/**
* Setting ring paramaters for Ethernet device.
*
* @param port_id
* The port identifier of the Ethernet device.
* @param ring_param
* Pointer to struct ethrool_ringparam with parameters to set.
* @return
* - (0) if successful.
* - (-ENOTSUP) if hardware doesn't support.
* - (-ENODEV) if *port_id* invalid.
* - others depends on the specific operations implementation.
* @note
* Only the tx_pending and rx_pending fields of struct ethtool_ringparam
* are used, and the function only sets parameters for queue 0.
*/
int rte_ethtool_set_ringparam(uint8_t port_id,
struct ethtool_ringparam *ring_param);
#ifdef __cplusplus
}
#endif
#endif /* _RTE_ETHTOOL_H_ */