X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=app%2Ftest-pmd%2Fconfig.c;h=1668ae3238ed60a2b9641749178dde254906adc2;hb=4a91344b5e06081f8e2254266bb469489f6633d8;hp=b6eb2a57a935bcf6674f27129b5f5d22fd5ddc0c;hpb=ba5509a6a80f25088d092c4320fd8ed12b73cfd7;p=dpdk.git diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index b6eb2a57a9..1668ae3238 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -39,16 +39,17 @@ #include #include #include -#ifdef RTE_LIBRTE_IXGBE_PMD +#ifdef RTE_NET_IXGBE #include #endif -#ifdef RTE_LIBRTE_I40E_PMD +#ifdef RTE_NET_I40E #include #endif -#ifdef RTE_LIBRTE_BNXT_PMD +#ifdef RTE_NET_BNXT #include #endif #include +#include #include "testpmd.h" @@ -138,6 +139,28 @@ const struct rss_type_info rss_type_table[] = { { NULL, 0 }, }; +static const struct { + enum rte_eth_fec_mode mode; + const char *name; +} fec_mode_name[] = { + { + .mode = RTE_ETH_FEC_NOFEC, + .name = "off", + }, + { + .mode = RTE_ETH_FEC_AUTO, + .name = "auto", + }, + { + .mode = RTE_ETH_FEC_BASER, + .name = "baser", + }, + { + .mode = RTE_ETH_FEC_RS, + .name = "rs", + }, +}; + static void print_ethaddr(const char *name, struct rte_ether_addr *eth_addr) { @@ -452,6 +475,8 @@ rx_queue_infos_display(portid_t port_id, uint16_t queue_id) (qinfo.conf.rx_deferred_start != 0) ? "on" : "off"); printf("\nRX scattered packets: %s", (qinfo.scattered_rx != 0) ? "on" : "off"); + if (qinfo.rx_buf_size != 0) + printf("\nRX buffer size: %hu", qinfo.rx_buf_size); printf("\nNumber of RXDs: %hu", qinfo.nb_desc); if (rte_eth_rx_burst_mode_get(port_id, queue_id, &mode) == 0) @@ -507,6 +532,46 @@ static int bus_match_all(const struct rte_bus *bus, const void *data) return 0; } +static void +device_infos_display_speeds(uint32_t speed_capa) +{ + printf("\n\tDevice speed capability:"); + if (speed_capa == ETH_LINK_SPEED_AUTONEG) + printf(" Autonegotiate (all speeds)"); + if (speed_capa & ETH_LINK_SPEED_FIXED) + printf(" Disable autonegotiate (fixed speed) "); + if (speed_capa & ETH_LINK_SPEED_10M_HD) + printf(" 10 Mbps half-duplex "); + if (speed_capa & ETH_LINK_SPEED_10M) + printf(" 10 Mbps full-duplex "); + if (speed_capa & ETH_LINK_SPEED_100M_HD) + printf(" 100 Mbps half-duplex "); + if (speed_capa & ETH_LINK_SPEED_100M) + printf(" 100 Mbps full-duplex "); + if (speed_capa & ETH_LINK_SPEED_1G) + printf(" 1 Gbps "); + if (speed_capa & ETH_LINK_SPEED_2_5G) + printf(" 2.5 Gbps "); + if (speed_capa & ETH_LINK_SPEED_5G) + printf(" 5 Gbps "); + if (speed_capa & ETH_LINK_SPEED_10G) + printf(" 10 Gbps "); + if (speed_capa & ETH_LINK_SPEED_20G) + printf(" 20 Gbps "); + if (speed_capa & ETH_LINK_SPEED_25G) + printf(" 25 Gbps "); + if (speed_capa & ETH_LINK_SPEED_40G) + printf(" 40 Gbps "); + if (speed_capa & ETH_LINK_SPEED_50G) + printf(" 50 Gbps "); + if (speed_capa & ETH_LINK_SPEED_56G) + printf(" 56 Gbps "); + if (speed_capa & ETH_LINK_SPEED_100G) + printf(" 100 Gbps "); + if (speed_capa & ETH_LINK_SPEED_200G) + printf(" 200 Gbps "); +} + void device_infos_display(const char *identifier) { @@ -518,6 +583,7 @@ device_infos_display(const char *identifier) struct rte_device *dev; struct rte_devargs da; portid_t port_id; + struct rte_eth_dev_info dev_info; char devstr[128]; memset(&da, 0, sizeof(da)); @@ -569,6 +635,8 @@ skip_parse: &mac_addr); rte_eth_dev_get_name_by_port(port_id, name); printf("\n\tDevice name: %s", name); + if (rte_eth_dev_info_get(port_id, &dev_info) == 0) + device_infos_display_speeds(dev_info.speed_capa); printf("\n"); } } @@ -622,7 +690,7 @@ port_infos_display(portid_t port_id) printf("\nConnect to socket: %u", port->socket_id); if (port_numa[port_id] != NUMA_NO_CONFIG) { - mp = mbuf_pool_find(port_numa[port_id]); + mp = mbuf_pool_find(port_numa[port_id], 0); if (mp) printf("\nmemory allocation on the socket: %d", port_numa[port_id]); @@ -783,6 +851,122 @@ port_summary_display(portid_t port_id) rte_eth_link_speed_to_str(link.link_speed)); } +void +port_eeprom_display(portid_t port_id) +{ + struct rte_dev_eeprom_info einfo; + int ret; + if (port_id_is_invalid(port_id, ENABLED_WARN)) { + print_valid_ports(); + return; + } + + int len_eeprom = rte_eth_dev_get_eeprom_length(port_id); + if (len_eeprom < 0) { + switch (len_eeprom) { + case -ENODEV: + printf("port index %d invalid\n", port_id); + break; + case -ENOTSUP: + printf("operation not supported by device\n"); + break; + case -EIO: + printf("device is removed\n"); + break; + default: + printf("Unable to get EEPROM: %d\n", len_eeprom); + break; + } + return; + } + + char buf[len_eeprom]; + einfo.offset = 0; + einfo.length = len_eeprom; + einfo.data = buf; + + ret = rte_eth_dev_get_eeprom(port_id, &einfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + printf("port index %d invalid\n", port_id); + break; + case -ENOTSUP: + printf("operation not supported by device\n"); + break; + case -EIO: + printf("device is removed\n"); + break; + default: + printf("Unable to get EEPROM: %d\n", ret); + break; + } + return; + } + rte_hexdump(stdout, "hexdump", einfo.data, einfo.length); + printf("Finish -- Port: %d EEPROM length: %d bytes\n", port_id, len_eeprom); +} + +void +port_module_eeprom_display(portid_t port_id) +{ + struct rte_eth_dev_module_info minfo; + struct rte_dev_eeprom_info einfo; + int ret; + + if (port_id_is_invalid(port_id, ENABLED_WARN)) { + print_valid_ports(); + return; + } + + + ret = rte_eth_dev_get_module_info(port_id, &minfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + printf("port index %d invalid\n", port_id); + break; + case -ENOTSUP: + printf("operation not supported by device\n"); + break; + case -EIO: + printf("device is removed\n"); + break; + default: + printf("Unable to get module EEPROM: %d\n", ret); + break; + } + return; + } + + char buf[minfo.eeprom_len]; + einfo.offset = 0; + einfo.length = minfo.eeprom_len; + einfo.data = buf; + + ret = rte_eth_dev_get_module_eeprom(port_id, &einfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + printf("port index %d invalid\n", port_id); + break; + case -ENOTSUP: + printf("operation not supported by device\n"); + break; + case -EIO: + printf("device is removed\n"); + break; + default: + printf("Unable to get module EEPROM: %d\n", ret); + break; + } + return; + } + + rte_hexdump(stdout, "hexdump", einfo.data, einfo.length); + printf("Finish -- Port: %d MODULE EEPROM length: %d bytes\n", port_id, einfo.length); +} + void port_offload_cap_display(portid_t port_id) { @@ -908,6 +1092,15 @@ port_offload_cap_display(portid_t port_id) printf("off\n"); } + if (dev_info.rx_offload_capa & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT) { + printf("RX offload buffer split: "); + if (ports[port_id].dev_conf.rxmode.offloads & + RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT) + printf("on\n"); + else + printf("off\n"); + } + if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT) { printf("VLAN insert: "); if (ports[port_id].dev_conf.txmode.offloads & @@ -1337,6 +1530,115 @@ port_mtu_set(portid_t port_id, uint16_t mtu) /* Generic flow management functions. */ +static struct port_flow_tunnel * +port_flow_locate_tunnel_id(struct rte_port *port, uint32_t port_tunnel_id) +{ + struct port_flow_tunnel *flow_tunnel; + + LIST_FOREACH(flow_tunnel, &port->flow_tunnel_list, chain) { + if (flow_tunnel->id == port_tunnel_id) + goto out; + } + flow_tunnel = NULL; + +out: + return flow_tunnel; +} + +const char * +port_flow_tunnel_type(struct rte_flow_tunnel *tunnel) +{ + const char *type; + switch (tunnel->type) { + default: + type = "unknown"; + break; + case RTE_FLOW_ITEM_TYPE_VXLAN: + type = "vxlan"; + break; + } + + return type; +} + +struct port_flow_tunnel * +port_flow_locate_tunnel(uint16_t port_id, struct rte_flow_tunnel *tun) +{ + struct rte_port *port = &ports[port_id]; + struct port_flow_tunnel *flow_tunnel; + + LIST_FOREACH(flow_tunnel, &port->flow_tunnel_list, chain) { + if (!memcmp(&flow_tunnel->tunnel, tun, sizeof(*tun))) + goto out; + } + flow_tunnel = NULL; + +out: + return flow_tunnel; +} + +void port_flow_tunnel_list(portid_t port_id) +{ + struct rte_port *port = &ports[port_id]; + struct port_flow_tunnel *flt; + + LIST_FOREACH(flt, &port->flow_tunnel_list, chain) { + printf("port %u tunnel #%u type=%s", + port_id, flt->id, port_flow_tunnel_type(&flt->tunnel)); + if (flt->tunnel.tun_id) + printf(" id=%" PRIu64, flt->tunnel.tun_id); + printf("\n"); + } +} + +void port_flow_tunnel_destroy(portid_t port_id, uint32_t tunnel_id) +{ + struct rte_port *port = &ports[port_id]; + struct port_flow_tunnel *flt; + + LIST_FOREACH(flt, &port->flow_tunnel_list, chain) { + if (flt->id == tunnel_id) + break; + } + if (flt) { + LIST_REMOVE(flt, chain); + free(flt); + printf("port %u: flow tunnel #%u destroyed\n", + port_id, tunnel_id); + } +} + +void port_flow_tunnel_create(portid_t port_id, const struct tunnel_ops *ops) +{ + struct rte_port *port = &ports[port_id]; + enum rte_flow_item_type type; + struct port_flow_tunnel *flt; + + if (!strcmp(ops->type, "vxlan")) + type = RTE_FLOW_ITEM_TYPE_VXLAN; + else { + printf("cannot offload \"%s\" tunnel type\n", ops->type); + return; + } + LIST_FOREACH(flt, &port->flow_tunnel_list, chain) { + if (flt->tunnel.type == type) + break; + } + if (!flt) { + flt = calloc(1, sizeof(*flt)); + if (!flt) { + printf("failed to allocate port flt object\n"); + return; + } + flt->tunnel.type = type; + flt->id = LIST_EMPTY(&port->flow_tunnel_list) ? 1 : + LIST_FIRST(&port->flow_tunnel_list)->id + 1; + LIST_INSERT_HEAD(&port->flow_tunnel_list, flt, chain); + } + printf("port %d: flow tunnel #%u type %s\n", + port_id, flt->id, ops->type); +} + /** Generate a port_flow entry from attributes/pattern/actions. */ static struct port_flow * port_flow_new(const struct rte_flow_attr *attr, @@ -1461,19 +1763,352 @@ rss_config_display(struct rte_flow_action_rss *rss_conf) } } +static struct port_shared_action * +action_get_by_id(portid_t port_id, uint32_t id) +{ + struct rte_port *port; + struct port_shared_action **ppsa; + struct port_shared_action *psa = NULL; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return NULL; + port = &ports[port_id]; + ppsa = &port->actions_list; + while (*ppsa) { + if ((*ppsa)->id == id) { + psa = *ppsa; + break; + } + ppsa = &(*ppsa)->next; + } + if (!psa) + printf("Failed to find shared action #%u on port %u\n", + id, port_id); + return psa; +} + +static int +action_alloc(portid_t port_id, uint32_t id, + struct port_shared_action **action) +{ + struct rte_port *port; + struct port_shared_action **ppsa; + struct port_shared_action *psa = NULL; + + *action = NULL; + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + if (id == UINT32_MAX) { + /* taking first available ID */ + if (port->actions_list) { + if (port->actions_list->id == UINT32_MAX - 1) { + printf("Highest shared action ID is already" + " assigned, delete it first\n"); + return -ENOMEM; + } + id = port->actions_list->id + 1; + } else { + id = 0; + } + } + psa = calloc(1, sizeof(*psa)); + if (!psa) { + printf("Allocation of port %u shared action failed\n", + port_id); + return -ENOMEM; + } + ppsa = &port->actions_list; + while (*ppsa && (*ppsa)->id > id) + ppsa = &(*ppsa)->next; + if (*ppsa && (*ppsa)->id == id) { + printf("Shared action #%u is already assigned," + " delete it first\n", id); + free(psa); + return -EINVAL; + } + psa->next = *ppsa; + psa->id = id; + *ppsa = psa; + *action = psa; + return 0; +} + +/** Create shared action */ +int +port_shared_action_create(portid_t port_id, uint32_t id, + const struct rte_flow_shared_action_conf *conf, + const struct rte_flow_action *action) +{ + struct port_shared_action *psa; + int ret; + struct rte_flow_error error; + + ret = action_alloc(port_id, id, &psa); + if (ret) + return ret; + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x22, sizeof(error)); + psa->action = rte_flow_shared_action_create(port_id, conf, action, + &error); + if (!psa->action) { + uint32_t destroy_id = psa->id; + port_shared_action_destroy(port_id, 1, &destroy_id); + return port_flow_complain(&error); + } + psa->type = action->type; + printf("Shared action #%u created\n", psa->id); + return 0; +} + +/** Destroy shared action */ +int +port_shared_action_destroy(portid_t port_id, + uint32_t n, + const uint32_t *actions) +{ + struct rte_port *port; + struct port_shared_action **tmp; + uint32_t c = 0; + int ret = 0; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + tmp = &port->actions_list; + while (*tmp) { + uint32_t i; + + for (i = 0; i != n; ++i) { + struct rte_flow_error error; + struct port_shared_action *psa = *tmp; + + if (actions[i] != psa->id) + continue; + /* + * Poisoning to make sure PMDs update it in case + * of error. + */ + memset(&error, 0x33, sizeof(error)); + + if (psa->action && rte_flow_shared_action_destroy( + port_id, psa->action, &error)) { + ret = port_flow_complain(&error); + continue; + } + *tmp = psa->next; + free(psa); + printf("Shared action #%u destroyed\n", psa->id); + break; + } + if (i == n) + tmp = &(*tmp)->next; + ++c; + } + return ret; +} + + +/** Get shared action by port + id */ +struct rte_flow_shared_action * +port_shared_action_get_by_id(portid_t port_id, uint32_t id) +{ + + struct port_shared_action *psa = action_get_by_id(port_id, id); + + return (psa) ? psa->action : NULL; +} + +/** Update shared action */ +int +port_shared_action_update(portid_t port_id, uint32_t id, + const struct rte_flow_action *action) +{ + struct rte_flow_error error; + struct rte_flow_shared_action *shared_action; + + shared_action = port_shared_action_get_by_id(port_id, id); + if (!shared_action) + return -EINVAL; + if (rte_flow_shared_action_update(port_id, shared_action, action, + &error)) { + return port_flow_complain(&error); + } + printf("Shared action #%u updated\n", id); + return 0; +} + +int +port_shared_action_query(portid_t port_id, uint32_t id) +{ + struct rte_flow_error error; + struct port_shared_action *psa; + uint64_t default_data; + void *data = NULL; + int ret = 0; + + psa = action_get_by_id(port_id, id); + if (!psa) + return -EINVAL; + switch (psa->type) { + case RTE_FLOW_ACTION_TYPE_RSS: + data = &default_data; + break; + default: + printf("Shared action %u (type: %d) on port %u doesn't support" + " query\n", id, psa->type, port_id); + return -1; + } + if (rte_flow_shared_action_query(port_id, psa->action, data, &error)) + ret = port_flow_complain(&error); + switch (psa->type) { + case RTE_FLOW_ACTION_TYPE_RSS: + if (!ret) + printf("Shared RSS action:\n\trefs:%u\n", + *((uint32_t *)data)); + data = NULL; + break; + default: + printf("Shared action %u (type: %d) on port %u doesn't support" + " query\n", id, psa->type, port_id); + ret = -1; + } + return ret; +} +static struct port_flow_tunnel * +port_flow_tunnel_offload_cmd_prep(portid_t port_id, + const struct rte_flow_item *pattern, + const struct rte_flow_action *actions, + const struct tunnel_ops *tunnel_ops) +{ + int ret; + struct rte_port *port; + struct port_flow_tunnel *pft; + struct rte_flow_error error; + + port = &ports[port_id]; + pft = port_flow_locate_tunnel_id(port, tunnel_ops->id); + if (!pft) { + printf("failed to locate port flow tunnel #%u\n", + tunnel_ops->id); + return NULL; + } + if (tunnel_ops->actions) { + uint32_t num_actions; + const struct rte_flow_action *aptr; + + ret = rte_flow_tunnel_decap_set(port_id, &pft->tunnel, + &pft->pmd_actions, + &pft->num_pmd_actions, + &error); + if (ret) { + port_flow_complain(&error); + return NULL; + } + for (aptr = actions, num_actions = 1; + aptr->type != RTE_FLOW_ACTION_TYPE_END; + aptr++, num_actions++); + pft->actions = malloc( + (num_actions + pft->num_pmd_actions) * + sizeof(actions[0])); + if (!pft->actions) { + rte_flow_tunnel_action_decap_release( + port_id, pft->actions, + pft->num_pmd_actions, &error); + return NULL; + } + rte_memcpy(pft->actions, pft->pmd_actions, + pft->num_pmd_actions * sizeof(actions[0])); + rte_memcpy(pft->actions + pft->num_pmd_actions, actions, + num_actions * sizeof(actions[0])); + } + if (tunnel_ops->items) { + uint32_t num_items; + const struct rte_flow_item *iptr; + + ret = rte_flow_tunnel_match(port_id, &pft->tunnel, + &pft->pmd_items, + &pft->num_pmd_items, + &error); + if (ret) { + port_flow_complain(&error); + return NULL; + } + for (iptr = pattern, num_items = 1; + iptr->type != RTE_FLOW_ITEM_TYPE_END; + iptr++, num_items++); + pft->items = malloc((num_items + pft->num_pmd_items) * + sizeof(pattern[0])); + if (!pft->items) { + rte_flow_tunnel_item_release( + port_id, pft->pmd_items, + pft->num_pmd_items, &error); + return NULL; + } + rte_memcpy(pft->items, pft->pmd_items, + pft->num_pmd_items * sizeof(pattern[0])); + rte_memcpy(pft->items + pft->num_pmd_items, pattern, + num_items * sizeof(pattern[0])); + } + + return pft; +} + +static void +port_flow_tunnel_offload_cmd_release(portid_t port_id, + const struct tunnel_ops *tunnel_ops, + struct port_flow_tunnel *pft) +{ + struct rte_flow_error error; + + if (tunnel_ops->actions) { + free(pft->actions); + rte_flow_tunnel_action_decap_release( + port_id, pft->pmd_actions, + pft->num_pmd_actions, &error); + pft->actions = NULL; + pft->pmd_actions = NULL; + } + if (tunnel_ops->items) { + free(pft->items); + rte_flow_tunnel_item_release(port_id, pft->pmd_items, + pft->num_pmd_items, + &error); + pft->items = NULL; + pft->pmd_items = NULL; + } +} + /** Validate flow rule. */ int port_flow_validate(portid_t port_id, const struct rte_flow_attr *attr, const struct rte_flow_item *pattern, - const struct rte_flow_action *actions) + const struct rte_flow_action *actions, + const struct tunnel_ops *tunnel_ops) { struct rte_flow_error error; + struct port_flow_tunnel *pft = NULL; /* Poisoning to make sure PMDs update it in case of error. */ memset(&error, 0x11, sizeof(error)); + if (tunnel_ops->enabled) { + pft = port_flow_tunnel_offload_cmd_prep(port_id, pattern, + actions, tunnel_ops); + if (!pft) + return -ENOENT; + if (pft->items) + pattern = pft->items; + if (pft->actions) + actions = pft->actions; + } if (rte_flow_validate(port_id, attr, pattern, actions, &error)) return port_flow_complain(&error); + if (tunnel_ops->enabled) + port_flow_tunnel_offload_cmd_release(port_id, tunnel_ops, pft); printf("Flow rule validated\n"); return 0; } @@ -1503,13 +2138,15 @@ int port_flow_create(portid_t port_id, const struct rte_flow_attr *attr, const struct rte_flow_item *pattern, - const struct rte_flow_action *actions) + const struct rte_flow_action *actions, + const struct tunnel_ops *tunnel_ops) { struct rte_flow *flow; struct rte_port *port; struct port_flow *pf; uint32_t id = 0; struct rte_flow_error error; + struct port_flow_tunnel *pft = NULL; port = &ports[port_id]; if (port->flow_list) { @@ -1520,6 +2157,16 @@ port_flow_create(portid_t port_id, } id = port->flow_list->id + 1; } + if (tunnel_ops->enabled) { + pft = port_flow_tunnel_offload_cmd_prep(port_id, pattern, + actions, tunnel_ops); + if (!pft) + return -ENOENT; + if (pft->items) + pattern = pft->items; + if (pft->actions) + actions = pft->actions; + } pf = port_flow_new(attr, pattern, actions, &error); if (!pf) return port_flow_complain(&error); @@ -1535,6 +2182,8 @@ port_flow_create(portid_t port_id, pf->id = id; pf->flow = flow; port->flow_list = pf; + if (tunnel_ops->enabled) + port_flow_tunnel_offload_cmd_release(port_id, tunnel_ops, pft); printf("Flow rule #%u created\n", pf->id); return 0; } @@ -1591,15 +2240,21 @@ port_flow_flush(portid_t port_id) struct rte_port *port; int ret = 0; + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + + port = &ports[port_id]; + + if (port->flow_list == NULL) + return ret; + /* Poisoning to make sure PMDs update it in case of error. */ memset(&error, 0x44, sizeof(error)); if (rte_flow_flush(port_id, &error)) { - ret = port_flow_complain(&error); - if (port_id_is_invalid(port_id, DISABLED_WARN) || - port_id == (portid_t)RTE_PORT_ALL) - return ret; + port_flow_complain(&error); } - port = &ports[port_id]; + while (port->flow_list) { struct port_flow *pf = port->flow_list->next; @@ -1648,6 +2303,7 @@ port_flow_query(portid_t port_id, uint32_t rule, union { struct rte_flow_query_count count; struct rte_flow_action_rss rss_conf; + struct rte_flow_query_age age; } query; int ret; @@ -1670,6 +2326,7 @@ port_flow_query(portid_t port_id, uint32_t rule, switch (action->type) { case RTE_FLOW_ACTION_TYPE_COUNT: case RTE_FLOW_ACTION_TYPE_RSS: + case RTE_FLOW_ACTION_TYPE_AGE: break; default: printf("Cannot query action type %d (%s)\n", @@ -1697,6 +2354,16 @@ port_flow_query(portid_t port_id, uint32_t rule, case RTE_FLOW_ACTION_TYPE_RSS: rss_config_display(&query.rss_conf); break; + case RTE_FLOW_ACTION_TYPE_AGE: + printf("%s:\n" + " aged: %u\n" + " sec_since_last_hit_valid: %u\n" + " sec_since_last_hit: %" PRIu32 "\n", + name, + query.age.aged, + query.age.sec_since_last_hit_valid, + query.age.sec_since_last_hit); + break; default: printf("Cannot display result for action type %d (%s)\n", action->type, name); @@ -1774,7 +2441,7 @@ port_flow_aged(portid_t port_id, uint8_t destroy) /** List flow rules. */ void -port_flow_list(portid_t port_id, uint32_t n, const uint32_t group[n]) +port_flow_list(portid_t port_id, uint32_t n, const uint32_t *group) { struct rte_port *port; struct port_flow *pf; @@ -1829,7 +2496,9 @@ port_flow_list(portid_t port_id, uint32_t n, const uint32_t group[n]) pf->rule.attr->egress ? 'e' : '-', pf->rule.attr->transfer ? 't' : '-'); while (item->type != RTE_FLOW_ITEM_TYPE_END) { - if (rte_flow_conv(RTE_FLOW_CONV_OP_ITEM_NAME_PTR, + if ((uint32_t)item->type > INT_MAX) + name = "PMD_INTERNAL"; + else if (rte_flow_conv(RTE_FLOW_CONV_OP_ITEM_NAME_PTR, &name, sizeof(name), (void *)(uintptr_t)item->type, NULL) <= 0) @@ -1840,7 +2509,9 @@ port_flow_list(portid_t port_id, uint32_t n, const uint32_t group[n]) } printf("=>"); while (action->type != RTE_FLOW_ACTION_TYPE_END) { - if (rte_flow_conv(RTE_FLOW_CONV_OP_ACTION_NAME_PTR, + if ((uint32_t)action->type > INT_MAX) + name = "PMD_INTERNAL"; + else if (rte_flow_conv(RTE_FLOW_CONV_OP_ACTION_NAME_PTR, &name, sizeof(name), (void *)(uintptr_t)action->type, NULL) <= 0) @@ -1891,22 +2562,102 @@ tx_queue_id_is_invalid(queueid_t txq_id) } static int -rx_desc_id_is_invalid(uint16_t rxdesc_id) +get_rx_ring_size(portid_t port_id, queueid_t rxq_id, uint16_t *ring_size) { - if (rxdesc_id < nb_rxd) + struct rte_port *port = &ports[port_id]; + struct rte_eth_rxq_info rx_qinfo; + int ret; + + ret = rte_eth_rx_queue_info_get(port_id, rxq_id, &rx_qinfo); + if (ret == 0) { + *ring_size = rx_qinfo.nb_desc; + return ret; + } + + if (ret != -ENOTSUP) + return ret; + /* + * If the rte_eth_rx_queue_info_get is not support for this PMD, + * ring_size stored in testpmd will be used for validity verification. + * When configure the rxq by rte_eth_rx_queue_setup with nb_rx_desc + * being 0, it will use a default value provided by PMDs to setup this + * rxq. If the default value is 0, it will use the + * RTE_ETH_DEV_FALLBACK_RX_RINGSIZE to setup this rxq. + */ + if (port->nb_rx_desc[rxq_id]) + *ring_size = port->nb_rx_desc[rxq_id]; + else if (port->dev_info.default_rxportconf.ring_size) + *ring_size = port->dev_info.default_rxportconf.ring_size; + else + *ring_size = RTE_ETH_DEV_FALLBACK_RX_RINGSIZE; + return 0; +} + +static int +get_tx_ring_size(portid_t port_id, queueid_t txq_id, uint16_t *ring_size) +{ + struct rte_port *port = &ports[port_id]; + struct rte_eth_txq_info tx_qinfo; + int ret; + + ret = rte_eth_tx_queue_info_get(port_id, txq_id, &tx_qinfo); + if (ret == 0) { + *ring_size = tx_qinfo.nb_desc; + return ret; + } + + if (ret != -ENOTSUP) + return ret; + /* + * If the rte_eth_tx_queue_info_get is not support for this PMD, + * ring_size stored in testpmd will be used for validity verification. + * When configure the txq by rte_eth_tx_queue_setup with nb_tx_desc + * being 0, it will use a default value provided by PMDs to setup this + * txq. If the default value is 0, it will use the + * RTE_ETH_DEV_FALLBACK_TX_RINGSIZE to setup this txq. + */ + if (port->nb_tx_desc[txq_id]) + *ring_size = port->nb_tx_desc[txq_id]; + else if (port->dev_info.default_txportconf.ring_size) + *ring_size = port->dev_info.default_txportconf.ring_size; + else + *ring_size = RTE_ETH_DEV_FALLBACK_TX_RINGSIZE; + return 0; +} + +static int +rx_desc_id_is_invalid(portid_t port_id, queueid_t rxq_id, uint16_t rxdesc_id) +{ + uint16_t ring_size; + int ret; + + ret = get_rx_ring_size(port_id, rxq_id, &ring_size); + if (ret) + return 1; + + if (rxdesc_id < ring_size) return 0; - printf("Invalid RX descriptor %d (must be < nb_rxd=%d)\n", - rxdesc_id, nb_rxd); + + printf("Invalid RX descriptor %u (must be < ring_size=%u)\n", + rxdesc_id, ring_size); return 1; } static int -tx_desc_id_is_invalid(uint16_t txdesc_id) +tx_desc_id_is_invalid(portid_t port_id, queueid_t txq_id, uint16_t txdesc_id) { - if (txdesc_id < nb_txd) + uint16_t ring_size; + int ret; + + ret = get_tx_ring_size(port_id, txq_id, &ring_size); + if (ret) + return 1; + + if (txdesc_id < ring_size) return 0; - printf("Invalid TX descriptor %d (must be < nb_txd=%d)\n", - txdesc_id, nb_txd); + + printf("Invalid TX descriptor %u (must be < ring_size=%u)\n", + txdesc_id, ring_size); return 1; } @@ -2027,11 +2778,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, ENABLED_WARN)) - return; - if (rx_queue_id_is_invalid(rxq_id)) - return; - if (rx_desc_id_is_invalid(rxd_id)) + if (rx_desc_id_is_invalid(port_id, rxq_id, rxd_id)) return; rx_mz = ring_dma_zone_lookup("rx_ring", port_id, rxq_id); if (rx_mz == NULL) @@ -2044,11 +2791,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, ENABLED_WARN)) - return; - if (tx_queue_id_is_invalid(txq_id)) - return; - if (tx_desc_id_is_invalid(txd_id)) + if (tx_desc_id_is_invalid(port_id, txq_id, txd_id)) return; tx_mz = ring_dma_zone_lookup("tx_ring", port_id, txq_id); if (tx_mz == NULL) @@ -2089,10 +2832,17 @@ rxtx_config_display(void) struct rte_eth_txconf *tx_conf = &ports[pid].tx_conf[0]; uint16_t *nb_rx_desc = &ports[pid].nb_rx_desc[0]; uint16_t *nb_tx_desc = &ports[pid].nb_tx_desc[0]; - uint16_t nb_rx_desc_tmp; - uint16_t nb_tx_desc_tmp; struct rte_eth_rxq_info rx_qinfo; struct rte_eth_txq_info tx_qinfo; + uint16_t rx_free_thresh_tmp; + uint16_t tx_free_thresh_tmp; + uint16_t tx_rs_thresh_tmp; + uint16_t nb_rx_desc_tmp; + uint16_t nb_tx_desc_tmp; + uint64_t offloads_tmp; + uint8_t pthresh_tmp; + uint8_t hthresh_tmp; + uint8_t wthresh_tmp; int32_t rc; /* per port config */ @@ -2106,41 +2856,64 @@ rxtx_config_display(void) /* per rx queue config only for first queue to be less verbose */ for (qid = 0; qid < 1; qid++) { rc = rte_eth_rx_queue_info_get(pid, qid, &rx_qinfo); - if (rc) + if (rc) { nb_rx_desc_tmp = nb_rx_desc[qid]; - else + rx_free_thresh_tmp = + rx_conf[qid].rx_free_thresh; + pthresh_tmp = rx_conf[qid].rx_thresh.pthresh; + hthresh_tmp = rx_conf[qid].rx_thresh.hthresh; + wthresh_tmp = rx_conf[qid].rx_thresh.wthresh; + offloads_tmp = rx_conf[qid].offloads; + } else { nb_rx_desc_tmp = rx_qinfo.nb_desc; + rx_free_thresh_tmp = + rx_qinfo.conf.rx_free_thresh; + pthresh_tmp = rx_qinfo.conf.rx_thresh.pthresh; + hthresh_tmp = rx_qinfo.conf.rx_thresh.hthresh; + wthresh_tmp = rx_qinfo.conf.rx_thresh.wthresh; + offloads_tmp = rx_qinfo.conf.offloads; + } printf(" RX queue: %d\n", qid); printf(" RX desc=%d - RX free threshold=%d\n", - nb_rx_desc_tmp, rx_conf[qid].rx_free_thresh); + nb_rx_desc_tmp, rx_free_thresh_tmp); printf(" RX threshold registers: pthresh=%d hthresh=%d " " wthresh=%d\n", - rx_conf[qid].rx_thresh.pthresh, - rx_conf[qid].rx_thresh.hthresh, - rx_conf[qid].rx_thresh.wthresh); - printf(" RX Offloads=0x%"PRIx64"\n", - rx_conf[qid].offloads); + pthresh_tmp, hthresh_tmp, wthresh_tmp); + printf(" RX Offloads=0x%"PRIx64"\n", offloads_tmp); } /* per tx queue config only for first queue to be less verbose */ for (qid = 0; qid < 1; qid++) { rc = rte_eth_tx_queue_info_get(pid, qid, &tx_qinfo); - if (rc) + if (rc) { nb_tx_desc_tmp = nb_tx_desc[qid]; - else + tx_free_thresh_tmp = + tx_conf[qid].tx_free_thresh; + pthresh_tmp = tx_conf[qid].tx_thresh.pthresh; + hthresh_tmp = tx_conf[qid].tx_thresh.hthresh; + wthresh_tmp = tx_conf[qid].tx_thresh.wthresh; + offloads_tmp = tx_conf[qid].offloads; + tx_rs_thresh_tmp = tx_conf[qid].tx_rs_thresh; + } else { nb_tx_desc_tmp = tx_qinfo.nb_desc; + tx_free_thresh_tmp = + tx_qinfo.conf.tx_free_thresh; + pthresh_tmp = tx_qinfo.conf.tx_thresh.pthresh; + hthresh_tmp = tx_qinfo.conf.tx_thresh.hthresh; + wthresh_tmp = tx_qinfo.conf.tx_thresh.wthresh; + offloads_tmp = tx_qinfo.conf.offloads; + tx_rs_thresh_tmp = tx_qinfo.conf.tx_rs_thresh; + } printf(" TX queue: %d\n", qid); printf(" TX desc=%d - TX free threshold=%d\n", - nb_tx_desc_tmp, tx_conf[qid].tx_free_thresh); + nb_tx_desc_tmp, tx_free_thresh_tmp); printf(" TX threshold registers: pthresh=%d hthresh=%d " " wthresh=%d\n", - tx_conf[qid].tx_thresh.pthresh, - tx_conf[qid].tx_thresh.hthresh, - tx_conf[qid].tx_thresh.wthresh); + pthresh_tmp, hthresh_tmp, wthresh_tmp); printf(" TX offloads=0x%"PRIx64" - TX RS bit threshold=%d\n", - tx_conf[qid].offloads, tx_conf->tx_rs_thresh); + offloads_tmp, tx_rs_thresh_tmp); } } } @@ -2683,9 +3456,9 @@ set_fwd_lcores_list(unsigned int *lcorelist, unsigned int nb_lc) printf("lcore %u not enabled\n", lcore_cpuid); return -1; } - if (lcore_cpuid == rte_get_master_lcore()) { + if (lcore_cpuid == rte_get_main_lcore()) { printf("lcore %u cannot be masked on for running " - "packet forwarding, which is the master lcore " + "packet forwarding, which is the main lcore " "and reserved for command line parsing only\n", lcore_cpuid); return -1; @@ -2967,6 +3740,128 @@ set_tx_pkt_split(const char *name) printf("unknown value: \"%s\"\n", name); } +int +parse_fec_mode(const char *name, uint32_t *mode) +{ + uint8_t i; + + for (i = 0; i < RTE_DIM(fec_mode_name); i++) { + if (strcmp(fec_mode_name[i].name, name) == 0) { + *mode = RTE_ETH_FEC_MODE_TO_CAPA(fec_mode_name[i].mode); + return 0; + } + } + return -1; +} + +void +show_fec_capability(unsigned int num, struct rte_eth_fec_capa *speed_fec_capa) +{ + unsigned int i, j; + + printf("FEC capabilities:\n"); + + for (i = 0; i < num; i++) { + printf("%s : ", + rte_eth_link_speed_to_str(speed_fec_capa[i].speed)); + + for (j = RTE_ETH_FEC_AUTO; j < RTE_DIM(fec_mode_name); j++) { + if (RTE_ETH_FEC_MODE_TO_CAPA(j) & + speed_fec_capa[i].capa) + printf("%s ", fec_mode_name[j].name); + } + printf("\n"); + } +} + +void +show_rx_pkt_offsets(void) +{ + uint32_t i, n; + + n = rx_pkt_nb_offs; + printf("Number of offsets: %u\n", n); + if (n) { + printf("Segment offsets: "); + for (i = 0; i != n - 1; i++) + printf("%hu,", rx_pkt_seg_offsets[i]); + printf("%hu\n", rx_pkt_seg_lengths[i]); + } +} + +void +set_rx_pkt_offsets(unsigned int *seg_offsets, unsigned int nb_offs) +{ + unsigned int i; + + if (nb_offs >= MAX_SEGS_BUFFER_SPLIT) { + printf("nb segments per RX packets=%u >= " + "MAX_SEGS_BUFFER_SPLIT - ignored\n", nb_offs); + return; + } + + /* + * No extra check here, the segment length will be checked by PMD + * in the extended queue setup. + */ + for (i = 0; i < nb_offs; i++) { + if (seg_offsets[i] >= UINT16_MAX) { + printf("offset[%u]=%u > UINT16_MAX - give up\n", + i, seg_offsets[i]); + return; + } + } + + for (i = 0; i < nb_offs; i++) + rx_pkt_seg_offsets[i] = (uint16_t) seg_offsets[i]; + + rx_pkt_nb_offs = (uint8_t) nb_offs; +} + +void +show_rx_pkt_segments(void) +{ + uint32_t i, n; + + n = rx_pkt_nb_segs; + printf("Number of segments: %u\n", n); + if (n) { + printf("Segment sizes: "); + for (i = 0; i != n - 1; i++) + printf("%hu,", rx_pkt_seg_lengths[i]); + printf("%hu\n", rx_pkt_seg_lengths[i]); + } +} + +void +set_rx_pkt_segments(unsigned int *seg_lengths, unsigned int nb_segs) +{ + unsigned int i; + + if (nb_segs >= MAX_SEGS_BUFFER_SPLIT) { + printf("nb segments per RX packets=%u >= " + "MAX_SEGS_BUFFER_SPLIT - ignored\n", nb_segs); + return; + } + + /* + * No extra check here, the segment length will be checked by PMD + * in the extended queue setup. + */ + for (i = 0; i < nb_segs; i++) { + if (seg_lengths[i] >= UINT16_MAX) { + printf("length[%u]=%u > UINT16_MAX - give up\n", + i, seg_lengths[i]); + return; + } + } + + for (i = 0; i < nb_segs; i++) + rx_pkt_seg_lengths[i] = (uint16_t) seg_lengths[i]; + + rx_pkt_nb_segs = (uint8_t) nb_segs; +} + void show_tx_pkt_segments(void) { @@ -2984,17 +3879,41 @@ show_tx_pkt_segments(void) printf("Split packet: %s\n", split); } +static bool +nb_segs_is_invalid(unsigned int nb_segs) +{ + uint16_t ring_size; + uint16_t queue_id; + uint16_t port_id; + int ret; + + RTE_ETH_FOREACH_DEV(port_id) { + for (queue_id = 0; queue_id < nb_txq; queue_id++) { + ret = get_tx_ring_size(port_id, queue_id, &ring_size); + + if (ret) + return true; + + if (ring_size < nb_segs) { + printf("nb segments per TX packets=%u >= " + "TX queue(%u) ring_size=%u - ignored\n", + nb_segs, queue_id, ring_size); + return true; + } + } + } + + return false; +} + void -set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs) +set_tx_pkt_segments(unsigned int *seg_lengths, unsigned int nb_segs) { uint16_t tx_pkt_len; - unsigned i; + unsigned int i; - if (nb_segs >= (unsigned) nb_txd) { - printf("nb segments per TX packets=%u >= nb_txd=%u - ignored\n", - nb_segs, (unsigned int) nb_txd); + if (nb_segs_is_invalid(nb_segs)) return; - } /* * Check that each segment length is greater or equal than @@ -3005,9 +3924,9 @@ set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs) */ tx_pkt_len = 0; for (i = 0; i < nb_segs; i++) { - if (seg_lengths[i] > (unsigned) mbuf_data_size) { + if (seg_lengths[i] > mbuf_data_size[0]) { printf("length[%u]=%u > mbuf_data_size=%u - give up\n", - i, seg_lengths[i], (unsigned) mbuf_data_size); + i, seg_lengths[i], mbuf_data_size[0]); return; } tx_pkt_len = (uint16_t)(tx_pkt_len + seg_lengths[i]); @@ -3390,9 +4309,11 @@ vlan_extend_set(portid_t port_id, int on) } diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); - if (diag < 0) + if (diag < 0) { printf("rx_vlan_extend_set(port_pi=%d, on=%d) failed " "diag=%d\n", port_id, on, diag); + return; + } ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads; } @@ -3417,9 +4338,11 @@ rx_vlan_strip_set(portid_t port_id, int on) } diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); - if (diag < 0) + if (diag < 0) { printf("rx_vlan_strip_set(port_pi=%d, on=%d) failed " "diag=%d\n", port_id, on, diag); + return; + } ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads; } @@ -3458,9 +4381,11 @@ rx_vlan_filter_set(portid_t port_id, int on) } diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); - if (diag < 0) + if (diag < 0) { printf("rx_vlan_filter_set(port_pi=%d, on=%d) failed " "diag=%d\n", port_id, on, diag); + return; + } ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads; } @@ -3485,9 +4410,11 @@ rx_vlan_qinq_strip_set(portid_t port_id, int on) } diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); - if (diag < 0) + if (diag < 0) { printf("%s(port_pi=%d, on=%d) failed " "diag=%d\n", __func__, port_id, on, diag); + return; + } ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads; } @@ -3545,8 +4472,6 @@ tx_vlan_set(portid_t port_id, uint16_t vlan_id) struct rte_eth_dev_info dev_info; int ret; - if (port_id_is_invalid(port_id, ENABLED_WARN)) - return; if (vlan_id_is_invalid(vlan_id)) return; @@ -3577,8 +4502,6 @@ tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer) struct rte_eth_dev_info dev_info; int ret; - if (port_id_is_invalid(port_id, ENABLED_WARN)) - return; if (vlan_id_is_invalid(vlan_id)) return; if (vlan_id_is_invalid(vlan_id_outer)) @@ -3604,8 +4527,6 @@ tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer) void tx_vlan_reset(portid_t port_id) { - if (port_id_is_invalid(port_id, ENABLED_WARN)) - return; ports[port_id].dev_conf.txmode.offloads &= ~(DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_QINQ_INSERT); @@ -3840,14 +4761,14 @@ get_fdir_info(portid_t port_id, struct rte_eth_fdir_info *fdir_info, return 0; } -#ifdef RTE_LIBRTE_I40E_PMD +#ifdef RTE_NET_I40E if (ret == -ENOTSUP) { ret = rte_pmd_i40e_get_fdir_info(port_id, fdir_info); if (!ret) ret = rte_pmd_i40e_get_fdir_stats(port_id, fdir_stat); } #endif -#ifdef RTE_LIBRTE_IXGBE_PMD +#ifdef RTE_NET_IXGBE if (ret == -ENOTSUP) { ret = rte_pmd_ixgbe_get_fdir_info(port_id, fdir_info); if (!ret) @@ -4000,7 +4921,7 @@ fdir_set_flex_payload(portid_t port_id, struct rte_eth_flex_payload_cfg *cfg) void set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on) { -#ifdef RTE_LIBRTE_IXGBE_PMD +#ifdef RTE_NET_IXGBE int diag; if (is_rx) @@ -4055,12 +4976,12 @@ set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk) RTE_SET_USED(rate); RTE_SET_USED(q_msk); -#ifdef RTE_LIBRTE_IXGBE_PMD +#ifdef RTE_NET_IXGBE if (diag == -ENOTSUP) diag = rte_pmd_ixgbe_set_vf_rate_limit(port_id, vf, rate, q_msk); #endif -#ifdef RTE_LIBRTE_BNXT_PMD +#ifdef RTE_NET_BNXT if (diag == -ENOTSUP) diag = rte_pmd_bnxt_set_vf_rate_limit(port_id, vf, rate, q_msk); #endif @@ -4356,7 +5277,7 @@ close_file(uint8_t *buf) void port_queue_region_info_display(portid_t port_id, void *buf) { -#ifdef RTE_LIBRTE_I40E_PMD +#ifdef RTE_NET_I40E uint16_t i, j; struct rte_pmd_i40e_queue_regions *info = (struct rte_pmd_i40e_queue_regions *)buf;