app/testpmd: support port hotplug

The patch introduces following commands.
- port attach [ident]
- port detach [port_id]
 - attach: attaching a port
 - detach: detaching a port
 - ident: pci address of physical device.
          Or device name and parameters of virtual device.
         (ex. 0000:02:00.0, eth_pcap0,iface=eth0)
 - port_id: port identifier

Signed-off-by: Tetsuya Mukawa <mukawa@igel.co.jp>
Acked-by: Bernard Iremonger <bernard.iremonger@intel.com>
This commit is contained in:
Tetsuya Mukawa 2015-02-26 04:32:29 +09:00 committed by Thomas Monjalon
parent c956caa6ea
commit edab33b1c0
6 changed files with 409 additions and 126 deletions

View File

@ -513,6 +513,12 @@ static void cmd_help_long_parsed(void *parsed_result,
"port close (port_id|all)\n"
" Close all ports or port_id.\n\n"
"port attach (ident)\n"
" Attach physical or virtual dev by pci address or virtual device name\n\n"
"port detach (port_id)\n"
" Detach physical or virtual dev by port_id\n\n"
"port config (port_id|all)"
" speed (10|100|1000|10000|40000|auto)"
" duplex (half|full|auto)\n"
@ -793,6 +799,89 @@ cmdline_parse_inst_t cmd_operate_specific_port = {
},
};
/* *** attach a specified port *** */
struct cmd_operate_attach_port_result {
cmdline_fixed_string_t port;
cmdline_fixed_string_t keyword;
cmdline_fixed_string_t identifier;
};
static void cmd_operate_attach_port_parsed(void *parsed_result,
__attribute__((unused)) struct cmdline *cl,
__attribute__((unused)) void *data)
{
struct cmd_operate_attach_port_result *res = parsed_result;
if (!strcmp(res->keyword, "attach"))
attach_port(res->identifier);
else
printf("Unknown parameter\n");
}
cmdline_parse_token_string_t cmd_operate_attach_port_port =
TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result,
port, "port");
cmdline_parse_token_string_t cmd_operate_attach_port_keyword =
TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result,
keyword, "attach");
cmdline_parse_token_string_t cmd_operate_attach_port_identifier =
TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result,
identifier, NULL);
cmdline_parse_inst_t cmd_operate_attach_port = {
.f = cmd_operate_attach_port_parsed,
.data = NULL,
.help_str = "port attach identifier, "
"identifier: pci address or virtual dev name",
.tokens = {
(void *)&cmd_operate_attach_port_port,
(void *)&cmd_operate_attach_port_keyword,
(void *)&cmd_operate_attach_port_identifier,
NULL,
},
};
/* *** detach a specified port *** */
struct cmd_operate_detach_port_result {
cmdline_fixed_string_t port;
cmdline_fixed_string_t keyword;
uint8_t port_id;
};
static void cmd_operate_detach_port_parsed(void *parsed_result,
__attribute__((unused)) struct cmdline *cl,
__attribute__((unused)) void *data)
{
struct cmd_operate_detach_port_result *res = parsed_result;
if (!strcmp(res->keyword, "detach"))
detach_port(res->port_id);
else
printf("Unknown parameter\n");
}
cmdline_parse_token_string_t cmd_operate_detach_port_port =
TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result,
port, "port");
cmdline_parse_token_string_t cmd_operate_detach_port_keyword =
TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result,
keyword, "detach");
cmdline_parse_token_num_t cmd_operate_detach_port_port_id =
TOKEN_NUM_INITIALIZER(struct cmd_operate_detach_port_result,
port_id, UINT8);
cmdline_parse_inst_t cmd_operate_detach_port = {
.f = cmd_operate_detach_port_parsed,
.data = NULL,
.help_str = "port detach port_id",
.tokens = {
(void *)&cmd_operate_detach_port_port,
(void *)&cmd_operate_detach_port_keyword,
(void *)&cmd_operate_detach_port_port_id,
NULL,
},
};
/* *** configure speed for all ports *** */
struct cmd_config_speed_all {
cmdline_fixed_string_t port;
@ -847,7 +936,7 @@ cmd_config_speed_all_parsed(void *parsed_result,
return;
}
for (pid = 0; pid < nb_ports; pid++) {
FOREACH_PORT(pid, ports) {
ports[pid].dev_conf.link_speed = link_speed;
ports[pid].dev_conf.link_duplex = link_duplex;
}
@ -915,10 +1004,8 @@ cmd_config_speed_specific_parsed(void *parsed_result,
return;
}
if (res->id >= nb_ports) {
printf("Port id %d must be less than %d\n", res->id, nb_ports);
if (port_id_is_invalid(res->id, ENABLED_WARN))
return;
}
if (!strcmp(res->value1, "10"))
link_speed = ETH_LINK_SPEED_10;
@ -1489,7 +1576,7 @@ cmd_config_rxtx_queue_parsed(void *parsed_result,
return;
}
if (port_id_is_invalid(res->portid))
if (port_id_is_invalid(res->portid, ENABLED_WARN))
return;
if (port_is_started(res->portid) != 1) {
@ -2889,7 +2976,7 @@ cmd_csum_parsed(void *parsed_result,
int hw = 0;
uint16_t mask = 0;
if (port_id_is_invalid(res->port_id)) {
if (port_id_is_invalid(res->port_id, ENABLED_WARN)) {
printf("invalid port %d\n", res->port_id);
return;
}
@ -2981,10 +3068,8 @@ cmd_csum_tunnel_parsed(void *parsed_result,
{
struct cmd_csum_tunnel_result *res = parsed_result;
if (port_id_is_invalid(res->port_id)) {
printf("invalid port %d\n", res->port_id);
if (port_id_is_invalid(res->port_id, ENABLED_WARN))
return;
}
if (!strcmp(res->onoff, "on"))
ports[res->port_id].tx_ol_flags |=
@ -3039,7 +3124,7 @@ cmd_tso_set_parsed(void *parsed_result,
struct cmd_tso_set_result *res = parsed_result;
struct rte_eth_dev_info dev_info;
if (port_id_is_invalid(res->port_id))
if (port_id_is_invalid(res->port_id, ENABLED_WARN))
return;
if (!strcmp(res->mode, "set"))
@ -4015,10 +4100,8 @@ static void cmd_set_bond_mac_addr_parsed(void *parsed_result,
struct cmd_set_bond_mac_addr_result *res = parsed_result;
int ret;
if (res->port_num >= nb_ports) {
printf("Port id %d must be less than %d\n", res->port_num, nb_ports);
if (port_id_is_invalid(res->port_num, ENABLED_WARN))
return;
}
ret = rte_eth_bond_mac_address_set(res->port_num, &res->address);
@ -4255,7 +4338,7 @@ static void cmd_set_promisc_mode_parsed(void *parsed_result,
/* all ports */
if (allports) {
for (i = 0; i < nb_ports; i++) {
FOREACH_PORT(i, ports) {
if (enable)
rte_eth_promiscuous_enable(i);
else
@ -4335,7 +4418,7 @@ static void cmd_set_allmulti_mode_parsed(void *parsed_result,
/* all ports */
if (allports) {
for (i = 0; i < nb_ports; i++) {
FOREACH_PORT(i, ports) {
if (enable)
rte_eth_allmulticast_enable(i);
else
@ -5023,25 +5106,25 @@ static void cmd_showportall_parsed(void *parsed_result,
struct cmd_showportall_result *res = parsed_result;
if (!strcmp(res->show, "clear")) {
if (!strcmp(res->what, "stats"))
for (i = 0; i < nb_ports; i++)
FOREACH_PORT(i, ports)
nic_stats_clear(i);
else if (!strcmp(res->what, "xstats"))
for (i = 0; i < nb_ports; i++)
FOREACH_PORT(i, ports)
nic_xstats_clear(i);
} else if (!strcmp(res->what, "info"))
for (i = 0; i < nb_ports; i++)
FOREACH_PORT(i, ports)
port_infos_display(i);
else if (!strcmp(res->what, "stats"))
for (i = 0; i < nb_ports; i++)
FOREACH_PORT(i, ports)
nic_stats_display(i);
else if (!strcmp(res->what, "xstats"))
for (i = 0; i < nb_ports; i++)
FOREACH_PORT(i, ports)
nic_xstats_display(i);
else if (!strcmp(res->what, "fdir"))
for (i = 0; i < nb_ports; i++)
FOREACH_PORT(i, ports)
fdir_get_infos(i);
else if (!strcmp(res->what, "stat_qmap"))
for (i = 0; i < nb_ports; i++)
FOREACH_PORT(i, ports)
nic_stats_mapping_display(i);
}
@ -8687,6 +8770,8 @@ cmdline_parse_ctx_t main_ctx[] = {
(cmdline_parse_inst_t *)&cmd_set_qmap,
(cmdline_parse_inst_t *)&cmd_operate_port,
(cmdline_parse_inst_t *)&cmd_operate_specific_port,
(cmdline_parse_inst_t *)&cmd_operate_attach_port,
(cmdline_parse_inst_t *)&cmd_operate_detach_port,
(cmdline_parse_inst_t *)&cmd_config_speed_all,
(cmdline_parse_inst_t *)&cmd_config_speed_specific,
(cmdline_parse_inst_t *)&cmd_config_rx_tx,
@ -8758,7 +8843,7 @@ prompt(void)
static void
cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue)
{
if (id < nb_ports) {
if (!port_id_is_invalid(id, DISABLED_WARN)) {
/* check if need_reconfig has been set to 1 */
if (ports[id].need_reconfig == 0)
ports[id].need_reconfig = dev;
@ -8768,7 +8853,7 @@ cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue)
} else {
portid_t pid;
for (pid = 0; pid < nb_ports; pid++) {
FOREACH_PORT(pid, ports) {
/* check if need_reconfig has been set to 1 */
if (ports[pid].need_reconfig == 0)
ports[pid].need_reconfig = dev;
@ -8786,10 +8871,8 @@ bypass_is_supported(portid_t port_id)
struct rte_port *port;
struct rte_pci_id *pci_id;
if (port_id >= nb_ports) {
printf("\tPort id must be less than %d.\n", nb_ports);
if (port_id_is_invalid(port_id, ENABLED_WARN))
return 0;
}
/* Get the device id. */
port = &ports[port_id];

View File

@ -112,11 +112,15 @@ nic_stats_display(portid_t port_id)
struct rte_eth_stats stats;
struct rte_port *port = &ports[port_id];
uint8_t i;
portid_t pid;
static const char *nic_stats_border = "########################";
if (port_id >= nb_ports) {
printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
if (port_id_is_invalid(port_id, ENABLED_WARN)) {
printf("Valid port range is [0");
FOREACH_PORT(pid, ports)
printf(", %d", pid);
printf("]\n");
return;
}
rte_eth_stats_get(port_id, &stats);
@ -189,8 +193,13 @@ nic_stats_display(portid_t port_id)
void
nic_stats_clear(portid_t port_id)
{
if (port_id >= nb_ports) {
printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
portid_t pid;
if (port_id_is_invalid(port_id, ENABLED_WARN)) {
printf("Valid port range is [0");
FOREACH_PORT(pid, ports)
printf(", %d", pid);
printf("]\n");
return;
}
rte_eth_stats_reset(port_id);
@ -237,11 +246,15 @@ nic_stats_mapping_display(portid_t port_id)
{
struct rte_port *port = &ports[port_id];
uint16_t i;
portid_t pid;
static const char *nic_stats_mapping_border = "########################";
if (port_id >= nb_ports) {
printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
if (port_id_is_invalid(port_id, ENABLED_WARN)) {
printf("Valid port range is [0");
FOREACH_PORT(pid, ports)
printf(", %d", pid);
printf("]\n");
return;
}
@ -290,9 +303,13 @@ port_infos_display(portid_t port_id)
int vlan_offload;
struct rte_mempool * mp;
static const char *info_border = "*********************";
portid_t pid;
if (port_id >= nb_ports) {
printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
if (port_id_is_invalid(port_id, ENABLED_WARN)) {
printf("Valid port range is [0");
FOREACH_PORT(pid, ports)
printf(", %d", pid);
printf("]\n");
return;
}
port = &ports[port_id];
@ -365,11 +382,14 @@ port_infos_display(portid_t port_id)
}
int
port_id_is_invalid(portid_t port_id)
port_id_is_invalid(portid_t port_id, enum print_warning warning)
{
if (port_id < nb_ports)
if (ports[port_id].enabled)
return 0;
printf("Invalid port %d (must be < nb_ports=%d)\n", port_id, nb_ports);
if (warning == ENABLED_WARN)
printf("Invalid port %d\n", port_id);
return 1;
}
@ -428,7 +448,7 @@ port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_x)
uint32_t reg_v;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (port_reg_off_is_invalid(port_id, reg_off))
return;
@ -447,7 +467,7 @@ port_reg_bit_field_display(portid_t port_id, uint32_t reg_off,
uint8_t l_bit;
uint8_t h_bit;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (port_reg_off_is_invalid(port_id, reg_off))
return;
@ -474,7 +494,7 @@ port_reg_display(portid_t port_id, uint32_t reg_off)
{
uint32_t reg_v;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (port_reg_off_is_invalid(port_id, reg_off))
return;
@ -488,7 +508,7 @@ port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos,
{
uint32_t reg_v;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (port_reg_off_is_invalid(port_id, reg_off))
return;
@ -516,7 +536,7 @@ port_reg_bit_field_set(portid_t port_id, uint32_t reg_off,
uint8_t l_bit;
uint8_t h_bit;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (port_reg_off_is_invalid(port_id, reg_off))
return;
@ -550,7 +570,7 @@ port_reg_bit_field_set(portid_t port_id, uint32_t reg_off,
void
port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t reg_v)
{
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (port_reg_off_is_invalid(port_id, reg_off))
return;
@ -563,7 +583,7 @@ port_mtu_set(portid_t port_id, uint16_t mtu)
{
int diag;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
diag = rte_eth_dev_set_mtu(port_id, mtu);
if (diag == 0)
@ -726,7 +746,7 @@ rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id)
{
const struct rte_memzone *rx_mz;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (rx_queue_id_is_invalid(rxq_id))
return;
@ -743,7 +763,7 @@ tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id)
{
const struct rte_memzone *tx_mz;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (tx_queue_id_is_invalid(txq_id))
return;
@ -804,7 +824,7 @@ port_rss_reta_info(portid_t port_id,
uint16_t i, idx, shift;
int ret;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
ret = rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries);
@ -859,7 +879,7 @@ port_rss_hash_conf_show(portid_t port_id, int show_rss_key)
uint8_t i;
int diag;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
/* Get RSS hash key if asked to display it */
rss_conf.rss_key = (show_rss_key) ? rss_key : NULL;
@ -1423,12 +1443,8 @@ set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt)
again:
for (i = 0; i < nb_pt; i++) {
port_id = (portid_t) portlist[i];
if (port_id >= nb_ports) {
printf("Invalid port id %u >= %u\n",
(unsigned int) port_id,
(unsigned int) nb_ports);
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
}
if (record_now)
fwd_ports_ids[i] = port_id;
}
@ -1586,7 +1602,7 @@ vlan_extend_set(portid_t port_id, int on)
int diag;
int vlan_offload;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
@ -1608,7 +1624,7 @@ rx_vlan_strip_set(portid_t port_id, int on)
int diag;
int vlan_offload;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
@ -1629,7 +1645,7 @@ rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on)
{
int diag;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
diag = rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on);
@ -1644,7 +1660,7 @@ rx_vlan_filter_set(portid_t port_id, int on)
int diag;
int vlan_offload;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
@ -1665,7 +1681,7 @@ rx_vft_set(portid_t port_id, uint16_t vlan_id, int on)
{
int diag;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (vlan_id_is_invalid(vlan_id))
return;
@ -1682,7 +1698,7 @@ rx_vlan_all_filter_set(portid_t port_id, int on)
{
uint16_t vlan_id;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
for (vlan_id = 0; vlan_id < 4096; vlan_id++)
rx_vft_set(port_id, vlan_id, on);
@ -1692,7 +1708,7 @@ void
vlan_tpid_set(portid_t port_id, uint16_t tp_id)
{
int diag;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
diag = rte_eth_dev_set_vlan_ether_type(port_id, tp_id);
@ -1707,7 +1723,7 @@ vlan_tpid_set(portid_t port_id, uint16_t tp_id)
void
tx_vlan_set(portid_t port_id, uint16_t vlan_id)
{
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (vlan_id_is_invalid(vlan_id))
return;
@ -1718,7 +1734,7 @@ tx_vlan_set(portid_t port_id, uint16_t vlan_id)
void
tx_vlan_reset(portid_t port_id)
{
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
ports[port_id].tx_ol_flags &= ~TESTPMD_TX_OFFLOAD_INSERT_VLAN;
}
@ -1726,7 +1742,7 @@ tx_vlan_reset(portid_t port_id)
void
tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on)
{
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
rte_eth_dev_set_vlan_pvid(port_id, vlan_id, on);
@ -1738,7 +1754,7 @@ set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value)
uint16_t i;
uint8_t existing_mapping_found = 0;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_invalid(queue_id)))
@ -1904,7 +1920,7 @@ fdir_get_infos(portid_t port_id)
static const char *fdir_stats_border = "########################";
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR);
if (ret < 0) {
@ -2030,7 +2046,7 @@ set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on)
{
int diag;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (is_rx)
diag = rte_eth_dev_set_vf_rx(port_id,vf,on);
@ -2052,7 +2068,7 @@ set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on)
{
int diag;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (vlan_id_is_invalid(vlan_id))
return;
@ -2069,7 +2085,7 @@ set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate)
int diag;
struct rte_eth_link link;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return 1;
rte_eth_link_get_nowait(port_id, &link);
if (rate > link.link_speed) {
@ -2094,7 +2110,7 @@ set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk)
if (q_msk == 0)
return 0;
if (port_id_is_invalid(port_id))
if (port_id_is_invalid(port_id, ENABLED_WARN))
return 1;
rte_eth_link_get_nowait(port_id, &link);
if (rate > link.link_speed) {

View File

@ -366,6 +366,7 @@ parse_portnuma_config(const char *q_arg)
};
unsigned long int_fld[_NUM_FLD];
char *str_fld[_NUM_FLD];
portid_t pid;
/* reset from value set at definition */
while ((p = strchr(p0,'(')) != NULL) {
@ -387,8 +388,11 @@ parse_portnuma_config(const char *q_arg)
return -1;
}
port_id = (uint8_t)int_fld[FLD_PORT];
if (port_id >= nb_ports) {
printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
if (port_id_is_invalid(port_id, ENABLED_WARN)) {
printf("Valid port range is [0");
FOREACH_PORT(pid, ports)
printf(", %d", pid);
printf("]\n");
return -1;
}
socket_id = (uint8_t)int_fld[FLD_SOCKET];
@ -419,6 +423,7 @@ parse_ringnuma_config(const char *q_arg)
};
unsigned long int_fld[_NUM_FLD];
char *str_fld[_NUM_FLD];
portid_t pid;
#define RX_RING_ONLY 0x1
#define TX_RING_ONLY 0x2
#define RXTX_RING 0x3
@ -443,8 +448,11 @@ parse_ringnuma_config(const char *q_arg)
return -1;
}
port_id = (uint8_t)int_fld[FLD_PORT];
if (port_id >= nb_ports) {
printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
if (port_id_is_invalid(port_id, ENABLED_WARN)) {
printf("Valid port range is [0");
FOREACH_PORT(pid, ports)
printf(", %d", pid);
printf("]\n");
return -1;
}
socket_id = (uint8_t)int_fld[FLD_SOCKET];
@ -615,12 +623,12 @@ launch_args_parse(int argc, char** argv)
#endif
if (!strcmp(lgopts[opt_idx].name, "nb-ports")) {
n = atoi(optarg);
if (n > 0 && n <= nb_ports)
if (n > 0 &&
!port_id_is_invalid(n, DISABLED_WARN))
nb_fwd_ports = (uint8_t) n;
else
rte_exit(EXIT_FAILURE,
"nb-ports should be > 0 and <= %d\n",
nb_ports);
"Invalid port %d\n", n);
}
if (!strcmp(lgopts[opt_idx].name, "nb-cores")) {
n = atoi(optarg);

View File

@ -71,6 +71,7 @@
#include <rte_pci.h>
#include <rte_ether.h>
#include <rte_ethdev.h>
#include <rte_dev.h>
#include <rte_string_fns.h>
#ifdef RTE_LIBRTE_PMD_XENVIRT
#include <rte_eth_xenvirt.h>
@ -315,7 +316,7 @@ uint16_t nb_rx_queue_stats_mappings = 0;
/* Forward function declarations */
static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask);
static void check_all_ports_link_status(uint32_t port_mask);
/*
* Check if all the ports are started.
@ -323,6 +324,20 @@ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask);
*/
static int all_ports_started(void);
/*
* Find next enabled port
*/
portid_t
find_next_port(portid_t p, struct rte_port *ports, int size)
{
if (ports == NULL)
rte_exit(-EINVAL, "failed to find a next port id\n");
while ((ports[p].enabled == 0) && (p < size))
p++;
return p;
}
/*
* Setup default configuration.
*/
@ -552,7 +567,8 @@ init_config(void)
+ RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST;
if (!numa_support)
nb_mbuf_per_pool = (nb_mbuf_per_pool * nb_ports);
nb_mbuf_per_pool =
(nb_mbuf_per_pool * RTE_MAX_ETHPORTS);
}
if (!numa_support) {
@ -565,14 +581,19 @@ init_config(void)
/* Configuration of Ethernet ports. */
ports = rte_zmalloc("testpmd: ports",
sizeof(struct rte_port) * nb_ports,
sizeof(struct rte_port) * RTE_MAX_ETHPORTS,
RTE_CACHE_LINE_SIZE);
if (ports == NULL) {
rte_exit(EXIT_FAILURE, "rte_zmalloc(%d struct rte_port) "
"failed\n", nb_ports);
rte_exit(EXIT_FAILURE,
"rte_zmalloc(%d struct rte_port) failed\n",
RTE_MAX_ETHPORTS);
}
for (pid = 0; pid < nb_ports; pid++) {
/* enabled allocated ports */
for (pid = 0; pid < nb_ports; pid++)
ports[pid].enabled = 1;
FOREACH_PORT(pid, ports) {
port = &ports[pid];
rte_eth_dev_info_get(pid, &port->dev_info);
@ -602,8 +623,7 @@ init_config(void)
nb_mbuf_per_pool = nb_mbuf_per_pool/nb_ports;
for (i = 0; i < MAX_SOCKET; i++) {
nb_mbuf = (nb_mbuf_per_pool *
port_per_socket[i]);
nb_mbuf = (nb_mbuf_per_pool * RTE_MAX_ETHPORTS);
if (nb_mbuf)
mbuf_pool_create(mbuf_data_size,
nb_mbuf,i);
@ -635,14 +655,6 @@ reconfig(portid_t new_port_id, unsigned socket_id)
struct rte_port *port;
/* Reconfiguration of Ethernet ports. */
ports = rte_realloc(ports,
sizeof(struct rte_port) * nb_ports,
RTE_CACHE_LINE_SIZE);
if (ports == NULL) {
rte_exit(EXIT_FAILURE, "rte_realloc(%d struct rte_port) failed\n",
nb_ports);
}
port = &ports[new_port_id];
rte_eth_dev_info_get(new_port_id, &port->dev_info);
@ -663,7 +675,7 @@ init_fwd_streams(void)
streamid_t sm_id, nb_fwd_streams_new;
/* set socket id according to numa or not */
for (pid = 0; pid < nb_ports; pid++) {
FOREACH_PORT(pid, ports) {
port = &ports[pid];
if (nb_rxq > port->dev_info.max_rx_queues) {
printf("Fail: nb_rxq(%d) is greater than "
@ -1264,7 +1276,7 @@ all_ports_started(void)
portid_t pi;
struct rte_port *port;
for (pi = 0; pi < nb_ports; pi++) {
FOREACH_PORT(pi, ports) {
port = &ports[pi];
/* Check if there is a port which is not started */
if (port->port_status != RTE_PORT_STARTED)
@ -1275,6 +1287,45 @@ all_ports_started(void)
return 1;
}
int
all_ports_stopped(void)
{
portid_t pi;
struct rte_port *port;
FOREACH_PORT(pi, ports) {
port = &ports[pi];
if (port->port_status != RTE_PORT_STOPPED)
return 0;
}
return 1;
}
int
port_is_started(portid_t port_id)
{
if (port_id_is_invalid(port_id, ENABLED_WARN))
return 0;
if (ports[port_id].port_status != RTE_PORT_STARTED)
return 0;
return 1;
}
static int
port_is_closed(portid_t port_id)
{
if (port_id_is_invalid(port_id, ENABLED_WARN))
return 0;
if (ports[port_id].port_status != RTE_PORT_CLOSED)
return 0;
return 1;
}
int
start_port(portid_t pid)
{
@ -1296,8 +1347,8 @@ start_port(portid_t pid)
if(dcb_config)
dcb_test = 1;
for (pi = 0; pi < nb_ports; pi++) {
if (pid < nb_ports && pid != pi)
FOREACH_PORT(pi, ports) {
if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
continue;
port = &ports[pi];
@ -1421,7 +1472,7 @@ start_port(portid_t pid)
}
if (need_check_link_status && !no_link_check)
check_all_ports_link_status(nb_ports, RTE_PORT_ALL);
check_all_ports_link_status(RTE_PORT_ALL);
else
printf("Please stop the ports first\n");
@ -1446,8 +1497,8 @@ stop_port(portid_t pid)
}
printf("Stopping ports...\n");
for (pi = 0; pi < nb_ports; pi++) {
if (pid < nb_ports && pid != pi)
FOREACH_PORT(pi, ports) {
if (!port_id_is_invalid(pid, DISABLED_WARN) && pid != pi)
continue;
port = &ports[pi];
@ -1463,7 +1514,7 @@ stop_port(portid_t pid)
need_check_link_status = 1;
}
if (need_check_link_status && !no_link_check)
check_all_ports_link_status(nb_ports, RTE_PORT_ALL);
check_all_ports_link_status(RTE_PORT_ALL);
printf("Done\n");
}
@ -1481,8 +1532,8 @@ close_port(portid_t pid)
printf("Closing ports...\n");
for (pi = 0; pi < nb_ports; pi++) {
if (pid < nb_ports && pid != pi)
FOREACH_PORT(pi, ports) {
if (!port_id_is_invalid(pid, DISABLED_WARN) && pid != pi)
continue;
port = &ports[pi];
@ -1502,31 +1553,83 @@ close_port(portid_t pid)
printf("Done\n");
}
int
all_ports_stopped(void)
void
attach_port(char *identifier)
{
portid_t pi;
struct rte_port *port;
portid_t i, j, pi = 0;
for (pi = 0; pi < nb_ports; pi++) {
port = &ports[pi];
if (port->port_status != RTE_PORT_STOPPED)
return 0;
printf("Attaching a new port...\n");
if (identifier == NULL) {
printf("Invalid parameters are specified\n");
return;
}
return 1;
if (test_done == 0) {
printf("Please stop forwarding first\n");
return;
}
if (rte_eth_dev_attach(identifier, &pi))
return;
ports[pi].enabled = 1;
reconfig(pi, rte_eth_dev_socket_id(pi));
rte_eth_promiscuous_enable(pi);
nb_ports = rte_eth_dev_count();
/* set_default_fwd_ports_config(); */
bzero(fwd_ports_ids, sizeof(fwd_ports_ids));
i = 0;
FOREACH_PORT(j, ports) {
fwd_ports_ids[i] = j;
i++;
}
nb_cfg_ports = nb_ports;
nb_fwd_ports++;
ports[pi].port_status = RTE_PORT_STOPPED;
printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports);
printf("Done\n");
}
int
port_is_started(portid_t port_id)
void
detach_port(uint8_t port_id)
{
if (port_id_is_invalid(port_id))
return -1;
portid_t i, pi = 0;
char name[RTE_ETH_NAME_MAX_LEN];
if (ports[port_id].port_status != RTE_PORT_STARTED)
return 0;
printf("Detaching a port...\n");
return 1;
if (!port_is_closed(port_id)) {
printf("Please close port first\n");
return;
}
rte_eth_promiscuous_disable(port_id);
if (rte_eth_dev_detach(port_id, name))
return;
ports[port_id].enabled = 0;
nb_ports = rte_eth_dev_count();
/* set_default_fwd_ports_config(); */
bzero(fwd_ports_ids, sizeof(fwd_ports_ids));
i = 0;
FOREACH_PORT(pi, ports) {
fwd_ports_ids[i] = pi;
i++;
}
nb_cfg_ports = nb_ports;
nb_fwd_ports--;
printf("Port '%s' is detached. Now total ports is %d\n",
name, nb_ports);
printf("Done\n");
return;
}
void
@ -1534,7 +1637,7 @@ pmd_test_exit(void)
{
portid_t pt_id;
for (pt_id = 0; pt_id < nb_ports; pt_id++) {
FOREACH_PORT(pt_id, ports) {
printf("Stopping port %d...", pt_id);
fflush(stdout);
rte_eth_dev_close(pt_id);
@ -1553,7 +1656,7 @@ struct pmd_test_command {
/* Check the link status of all ports in up to 9s, and print them finally */
static void
check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
check_all_ports_link_status(uint32_t port_mask)
{
#define CHECK_INTERVAL 100 /* 100ms */
#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
@ -1564,7 +1667,7 @@ check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
fflush(stdout);
for (count = 0; count <= MAX_CHECK_TIME; count++) {
all_ports_up = 1;
for (portid = 0; portid < port_num; portid++) {
FOREACH_PORT(portid, ports) {
if ((port_mask & (1 << portid)) == 0)
continue;
memset(&link, 0, sizeof(link));
@ -1729,7 +1832,7 @@ init_port_config(void)
portid_t pid;
struct rte_port *port;
for (pid = 0; pid < nb_ports; pid++) {
FOREACH_PORT(pid, ports) {
port = &ports[pid];
port->dev_conf.rxmode = rx_mode;
port->dev_conf.fdir_conf = fdir_conf;
@ -1908,7 +2011,7 @@ main(int argc, char** argv)
nb_ports = (portid_t) rte_eth_dev_count();
if (nb_ports == 0)
rte_exit(EXIT_FAILURE, "No probed ethernet device\n");
RTE_LOG(WARNING, EAL, "No probed ethernet devices\n");
set_def_fwd_config();
if (nb_lcores == 0)
@ -1930,7 +2033,7 @@ main(int argc, char** argv)
rte_exit(EXIT_FAILURE, "Start ports failed\n");
/* set all ports to promiscuous mode by default */
for (port_id = 0; port_id < nb_ports; port_id++)
FOREACH_PORT(port_id, ports)
rte_eth_promiscuous_enable(port_id);
#ifdef RTE_LIBRTE_CMDLINE

View File

@ -137,6 +137,7 @@ struct fwd_stream {
* The data structure associated with each port.
*/
struct rte_port {
uint8_t enabled; /**< Port enabled or not */
struct rte_eth_dev_info dev_info; /**< PCI info + driver name */
struct rte_eth_conf dev_conf; /**< Port configuration. */
struct ether_addr eth_addr; /**< Port ethernet address */
@ -162,6 +163,14 @@ struct rte_port {
struct rte_eth_txconf tx_conf; /**< tx configuration */
};
extern portid_t __rte_unused
find_next_port(portid_t p, struct rte_port *ports, int size);
#define FOREACH_PORT(p, ports) \
for (p = find_next_port(0, ports, RTE_MAX_ETHPORTS); \
p < RTE_MAX_ETHPORTS; \
p = find_next_port(p + 1, ports, RTE_MAX_ETHPORTS))
/**
* The data structure associated with each forwarding logical core.
* The logical cores are internally numbered by a core index from 0 to
@ -522,6 +531,8 @@ int init_port_dcb_config(portid_t pid,struct dcb_config *dcb_conf);
int start_port(portid_t pid);
void stop_port(portid_t pid);
void close_port(portid_t pid);
void attach_port(char *identifier);
void detach_port(uint8_t port_id);
int all_ports_stopped(void);
int port_is_started(portid_t port_id);
void pmd_test_exit(void);
@ -548,10 +559,15 @@ void get_syn_filter(uint8_t port_id);
void get_ethertype_filter(uint8_t port_id, uint16_t index);
void get_2tuple_filter(uint8_t port_id, uint16_t index);
void get_5tuple_filter(uint8_t port_id, uint16_t index);
int port_id_is_invalid(portid_t port_id);
int rx_queue_id_is_invalid(queueid_t rxq_id);
int tx_queue_id_is_invalid(queueid_t txq_id);
enum print_warning {
ENABLED_WARN = 0,
DISABLED_WARN
};
int port_id_is_invalid(portid_t port_id, enum print_warning warning);
/*
* Work-around of a compilation error with ICC on invocations of the
* rte_be_to_cpu_16() function.

View File

@ -807,6 +807,63 @@ The following sections show functions for configuring ports.
Port configuration changes only become active when forwarding is started/restarted.
port attach
~~~~~~~~~~~
Attach a port specified by pci address or virtual device args.
To attach a new pci device, the device should be recognized by kernel first.
Then it should be moved under DPDK management.
Finally the port can be attached to testpmd.
On the other hand, to attach a port created by virtual device, above steps are not needed.
port attach (identifier)
For example, to attach a port whose pci address is 0000:02:00.0.
.. code-block:: console
testpmd> port attach 0000:02:00.0
Attaching a new port...
... snip ...
Port 0 is attached. Now total ports is 1
Done
For example, to attach a port created by pcap PMD.
.. code-block:: console
testpmd> port attach eth_pcap0,iface=eth0
Attaching a new port...
... snip ...
Port 0 is attached. Now total ports is 1
Done
In this case, identifier is "eth_pcap0,iface=eth0".
This identifier format is the same as "--vdev" format of DPDK applications.
port detach
~~~~~~~~~~~
Detach a specific port.
Before detaching a port, the port should be closed.
Also to remove a pci device completely from the system, first detach the port from testpmd.
Then the device should be moved under kernel management.
Finally the device can be removed using kernel pci hotplug functionality.
On the other hand, to remove a port created by a virtual device, above steps are not needed.
port detach (port_id)
For example, to detach a port 0.
.. code-block:: console
testpmd> port detach 0
Detaching a port...
... snip ...
Done
port start
~~~~~~~~~~