#endif
#include <rte_gro.h>
#include <cmdline_parse_etheraddr.h>
+#include <rte_config.h>
#include "testpmd.h"
};
const struct rss_type_info rss_type_table[] = {
+ { "all", ETH_RSS_IP | ETH_RSS_TCP |
+ ETH_RSS_UDP | ETH_RSS_SCTP |
+ ETH_RSS_L2_PAYLOAD },
+ { "none", 0 },
{ "ipv4", ETH_RSS_IPV4 },
{ "ipv4-frag", ETH_RSS_FRAG_IPV4 },
{ "ipv4-tcp", ETH_RSS_NONFRAG_IPV4_TCP },
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_is_invalid(port_id, ENABLED_WARN)) {
- printf("Valid port range is [0");
- RTE_ETH_FOREACH_DEV(pid)
- printf(", %d", pid);
- printf("]\n");
+ print_valid_ports();
return;
}
rte_eth_stats_get(port_id, &stats);
void
nic_stats_clear(portid_t port_id)
{
- portid_t pid;
-
if (port_id_is_invalid(port_id, ENABLED_WARN)) {
- printf("Valid port range is [0");
- RTE_ETH_FOREACH_DEV(pid)
- printf(", %d", pid);
- printf("]\n");
+ print_valid_ports();
return;
}
rte_eth_stats_reset(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_is_invalid(port_id, ENABLED_WARN)) {
- printf("Valid port range is [0");
- RTE_ETH_FOREACH_DEV(pid)
- printf(", %d", pid);
- printf("]\n");
+ print_valid_ports();
return;
}
int vlan_offload;
struct rte_mempool * mp;
static const char *info_border = "*********************";
- portid_t pid;
uint16_t mtu;
+ char name[RTE_ETH_NAME_MAX_LEN];
if (port_id_is_invalid(port_id, ENABLED_WARN)) {
- printf("Valid port range is [0");
- RTE_ETH_FOREACH_DEV(pid)
- printf(", %d", pid);
- printf("]\n");
+ print_valid_ports();
return;
}
port = &ports[port_id];
info_border, port_id, info_border);
rte_eth_macaddr_get(port_id, &mac_addr);
print_ethaddr("MAC address: ", &mac_addr);
+ rte_eth_dev_get_name_by_port(port_id, name);
+ printf("\nDevice name: %s", name);
printf("\nDriver name: %s", dev_info.driver_name);
+ if (dev_info.device->devargs && dev_info.device->devargs->args)
+ printf("\nDevargs: %s", dev_info.device->devargs->args);
printf("\nConnect to socket: %u", port->socket_id);
if (port_numa[port_id] != NUMA_NO_CONFIG) {
if (dev_info.reta_size > 0)
printf("Redirection table size: %u\n", dev_info.reta_size);
if (!dev_info.flow_type_rss_offloads)
- printf("No flow type is supported.\n");
+ printf("No RSS offload flow type is supported.\n");
else {
uint16_t i;
char *p;
- printf("Supported flow types:\n");
+ printf("Supported RSS offload flow types:\n");
for (i = RTE_ETH_FLOW_UNKNOWN + 1;
i < sizeof(dev_info.flow_type_rss_offloads) * CHAR_BIT; i++) {
if (!(dev_info.flow_type_rss_offloads & (1ULL << i)))
printf("Min possible number of TXDs per queue: %hu\n",
dev_info.tx_desc_lim.nb_min);
printf("TXDs number alignment: %hu\n", dev_info.tx_desc_lim.nb_align);
+
+ /* Show switch info only if valid switch domain and port id is set */
+ if (dev_info.switch_info.domain_id !=
+ RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) {
+ if (dev_info.switch_info.name)
+ printf("Switch name: %s\n", dev_info.switch_info.name);
+
+ printf("Switch domain Id: %u\n",
+ dev_info.switch_info.domain_id);
+ printf("Switch Port Id: %u\n",
+ dev_info.switch_info.port_id);
+ }
+}
+
+void
+port_summary_header_display(void)
+{
+ uint16_t port_number;
+
+ port_number = rte_eth_dev_count_avail();
+ printf("Number of available ports: %i\n", port_number);
+ printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
+ "Driver", "Status", "Link");
+}
+
+void
+port_summary_display(portid_t port_id)
+{
+ struct ether_addr mac_addr;
+ struct rte_eth_link link;
+ struct rte_eth_dev_info dev_info;
+ char name[RTE_ETH_NAME_MAX_LEN];
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ print_valid_ports();
+ return;
+ }
+
+ rte_eth_link_get_nowait(port_id, &link);
+ rte_eth_dev_info_get(port_id, &dev_info);
+ rte_eth_dev_get_name_by_port(port_id, name);
+ rte_eth_macaddr_get(port_id, &mac_addr);
+
+ printf("%-4d %02X:%02X:%02X:%02X:%02X:%02X %-12s %-14s %-8s %uMbps\n",
+ port_id, 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], name,
+ dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
+ (unsigned int) link.link_speed);
}
void
if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_QINQ_STRIP) {
printf("Double VLANs stripped: ");
if (ports[port_id].dev_conf.rxmode.offloads &
- DEV_RX_OFFLOAD_VLAN_EXTEND)
+ DEV_RX_OFFLOAD_QINQ_STRIP)
printf("on\n");
else
printf("off\n");
printf("off\n");
}
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SCTP_CKSUM) {
+ printf("RX SCTP checksum: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_SCTP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM) {
- printf("RX Outer IPv4 checksum: ");
+ printf("RX Outer IPv4 checksum: ");
if (ports[port_id].dev_conf.rxmode.offloads &
DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM)
printf("on\n");
printf("off\n");
}
- if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) {
- printf("Large receive offload: ");
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_OUTER_UDP_CKSUM) {
+ printf("RX Outer UDP checksum: ");
if (ports[port_id].dev_conf.rxmode.offloads &
- DEV_RX_OFFLOAD_TCP_LRO)
+ DEV_RX_OFFLOAD_OUTER_UDP_CKSUM)
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 &
- DEV_TX_OFFLOAD_VLAN_INSERT)
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) {
+ printf("Large receive offload: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_TCP_LRO)
printf("on\n");
else
printf("off\n");
printf("off\n");
}
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_KEEP_CRC) {
+ printf("Rx Keep CRC: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_KEEP_CRC)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SECURITY) {
+ printf("RX offload security: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_SECURITY)
+ 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 &
+ DEV_TX_OFFLOAD_VLAN_INSERT)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT) {
printf("Double VLANs insert: ");
if (ports[port_id].dev_conf.txmode.offloads &
else
printf("off\n");
}
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) {
+ printf("TX Outer UDP checksum: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_OUTER_UDP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
}
int
return 1;
}
+void print_valid_ports(void)
+{
+ portid_t pid;
+
+ printf("The valid ports array is [");
+ RTE_ETH_FOREACH_DEV(pid) {
+ printf(" %d", pid);
+ }
+ printf(" ]\n");
+}
+
static int
vlan_id_is_invalid(uint16_t vlan_id)
{
port_mtu_set(portid_t port_id, uint16_t mtu)
{
int diag;
+ struct rte_eth_dev_info dev_info;
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
+ rte_eth_dev_info_get(port_id, &dev_info);
+ if (mtu > dev_info.max_mtu || mtu < dev_info.min_mtu) {
+ printf("Set MTU failed. MTU:%u is not in valid range, min:%u - max:%u\n",
+ mtu, dev_info.min_mtu, dev_info.max_mtu);
+ return;
+ }
diag = rte_eth_dev_set_mtu(port_id, mtu);
if (diag == 0)
return;
/* Generic flow management functions. */
-/** Generate flow_item[] entry. */
-#define MK_FLOW_ITEM(t, s) \
- [RTE_FLOW_ITEM_TYPE_ ## t] = { \
- .name = # t, \
- .size = s, \
- }
-
-/** Information about known flow pattern items. */
-static const struct {
- const char *name;
- size_t size;
-} flow_item[] = {
- MK_FLOW_ITEM(END, 0),
- MK_FLOW_ITEM(VOID, 0),
- MK_FLOW_ITEM(INVERT, 0),
- MK_FLOW_ITEM(ANY, sizeof(struct rte_flow_item_any)),
- MK_FLOW_ITEM(PF, 0),
- MK_FLOW_ITEM(VF, sizeof(struct rte_flow_item_vf)),
- MK_FLOW_ITEM(PHY_PORT, sizeof(struct rte_flow_item_phy_port)),
- MK_FLOW_ITEM(PORT_ID, sizeof(struct rte_flow_item_port_id)),
- MK_FLOW_ITEM(RAW, sizeof(struct rte_flow_item_raw)),
- MK_FLOW_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
- MK_FLOW_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
- MK_FLOW_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
- MK_FLOW_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
- MK_FLOW_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
- MK_FLOW_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
- MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
- MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
- MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
- MK_FLOW_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
- MK_FLOW_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
- MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
- MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
- MK_FLOW_ITEM(FUZZY, sizeof(struct rte_flow_item_fuzzy)),
- MK_FLOW_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
- MK_FLOW_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
- MK_FLOW_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
- MK_FLOW_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
- MK_FLOW_ITEM(VXLAN_GPE, sizeof(struct rte_flow_item_vxlan_gpe)),
- MK_FLOW_ITEM(ARP_ETH_IPV4, sizeof(struct rte_flow_item_arp_eth_ipv4)),
- MK_FLOW_ITEM(IPV6_EXT, sizeof(struct rte_flow_item_ipv6_ext)),
- MK_FLOW_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
- MK_FLOW_ITEM(ICMP6_ND_NS, sizeof(struct rte_flow_item_icmp6_nd_ns)),
- MK_FLOW_ITEM(ICMP6_ND_NA, sizeof(struct rte_flow_item_icmp6_nd_na)),
- MK_FLOW_ITEM(ICMP6_ND_OPT, sizeof(struct rte_flow_item_icmp6_nd_opt)),
- MK_FLOW_ITEM(ICMP6_ND_OPT_SLA_ETH,
- sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
- MK_FLOW_ITEM(ICMP6_ND_OPT_TLA_ETH,
- sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
-};
-
-/** Pattern item specification types. */
-enum item_spec_type {
- ITEM_SPEC,
- ITEM_LAST,
- ITEM_MASK,
-};
-
-/** Compute storage space needed by item specification and copy it. */
-static size_t
-flow_item_spec_copy(void *buf, const struct rte_flow_item *item,
- enum item_spec_type type)
-{
- size_t size = 0;
- const void *item_spec =
- type == ITEM_SPEC ? item->spec :
- type == ITEM_LAST ? item->last :
- type == ITEM_MASK ? item->mask :
- NULL;
-
- if (!item_spec)
- goto empty;
- switch (item->type) {
- union {
- const struct rte_flow_item_raw *raw;
- } src;
- union {
- struct rte_flow_item_raw *raw;
- } dst;
- size_t off;
-
- case RTE_FLOW_ITEM_TYPE_RAW:
- src.raw = item_spec;
- dst.raw = buf;
- off = RTE_ALIGN_CEIL(sizeof(struct rte_flow_item_raw),
- sizeof(*src.raw->pattern));
- size = off + src.raw->length * sizeof(*src.raw->pattern);
- if (dst.raw) {
- memcpy(dst.raw, src.raw, sizeof(*src.raw));
- dst.raw->pattern = memcpy((uint8_t *)dst.raw + off,
- src.raw->pattern,
- size - off);
- }
- break;
- default:
- size = flow_item[item->type].size;
- if (buf)
- memcpy(buf, item_spec, size);
- break;
- }
-empty:
- return RTE_ALIGN_CEIL(size, sizeof(double));
-}
-
-/** Generate flow_action[] entry. */
-#define MK_FLOW_ACTION(t, s) \
- [RTE_FLOW_ACTION_TYPE_ ## t] = { \
- .name = # t, \
- .size = s, \
- }
-
-/** Information about known flow actions. */
-static const struct {
- const char *name;
- size_t size;
-} flow_action[] = {
- MK_FLOW_ACTION(END, 0),
- MK_FLOW_ACTION(VOID, 0),
- MK_FLOW_ACTION(PASSTHRU, 0),
- MK_FLOW_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
- MK_FLOW_ACTION(FLAG, 0),
- MK_FLOW_ACTION(QUEUE, sizeof(struct rte_flow_action_queue)),
- MK_FLOW_ACTION(DROP, 0),
- MK_FLOW_ACTION(COUNT, 0),
- MK_FLOW_ACTION(RSS, sizeof(struct rte_flow_action_rss)),
- MK_FLOW_ACTION(PF, 0),
- MK_FLOW_ACTION(VF, sizeof(struct rte_flow_action_vf)),
- MK_FLOW_ACTION(PHY_PORT, sizeof(struct rte_flow_action_phy_port)),
- MK_FLOW_ACTION(PORT_ID, sizeof(struct rte_flow_action_port_id)),
- MK_FLOW_ACTION(METER, sizeof(struct rte_flow_action_meter)),
-};
-
-/** Compute storage space needed by action configuration and copy it. */
-static size_t
-flow_action_conf_copy(void *buf, const struct rte_flow_action *action)
-{
- size_t size = 0;
-
- if (!action->conf)
- goto empty;
- switch (action->type) {
- union {
- const struct rte_flow_action_rss *rss;
- } src;
- union {
- struct rte_flow_action_rss *rss;
- } dst;
- size_t off;
-
- case RTE_FLOW_ACTION_TYPE_RSS:
- src.rss = action->conf;
- dst.rss = buf;
- off = 0;
- if (dst.rss)
- *dst.rss = (struct rte_flow_action_rss){
- .func = src.rss->func,
- .level = src.rss->level,
- .types = src.rss->types,
- .key_len = src.rss->key_len,
- .queue_num = src.rss->queue_num,
- };
- off += sizeof(*src.rss);
- if (src.rss->key_len) {
- off = RTE_ALIGN_CEIL(off, sizeof(double));
- size = sizeof(*src.rss->key) * src.rss->key_len;
- if (dst.rss)
- dst.rss->key = memcpy
- ((void *)((uintptr_t)dst.rss + off),
- src.rss->key, size);
- off += size;
- }
- if (src.rss->queue_num) {
- off = RTE_ALIGN_CEIL(off, sizeof(double));
- size = sizeof(*src.rss->queue) * src.rss->queue_num;
- if (dst.rss)
- dst.rss->queue = memcpy
- ((void *)((uintptr_t)dst.rss + off),
- src.rss->queue, size);
- off += size;
- }
- size = off;
- break;
- default:
- size = flow_action[action->type].size;
- if (buf)
- memcpy(buf, action->conf, size);
- break;
- }
-empty:
- return RTE_ALIGN_CEIL(size, sizeof(double));
-}
-
/** Generate a port_flow entry from attributes/pattern/actions. */
static struct port_flow *
port_flow_new(const struct rte_flow_attr *attr,
const struct rte_flow_item *pattern,
- const struct rte_flow_action *actions)
-{
- const struct rte_flow_item *item;
- const struct rte_flow_action *action;
- struct port_flow *pf = NULL;
- size_t tmp;
- size_t off1 = 0;
- size_t off2 = 0;
- int err = ENOTSUP;
-
-store:
- item = pattern;
- if (pf)
- pf->pattern = (void *)&pf->data[off1];
- do {
- struct rte_flow_item *dst = NULL;
-
- if ((unsigned int)item->type >= RTE_DIM(flow_item) ||
- !flow_item[item->type].name)
- goto notsup;
- if (pf)
- dst = memcpy(pf->data + off1, item, sizeof(*item));
- off1 += sizeof(*item);
- if (item->spec) {
- if (pf)
- dst->spec = pf->data + off2;
- off2 += flow_item_spec_copy
- (pf ? pf->data + off2 : NULL, item, ITEM_SPEC);
- }
- if (item->last) {
- if (pf)
- dst->last = pf->data + off2;
- off2 += flow_item_spec_copy
- (pf ? pf->data + off2 : NULL, item, ITEM_LAST);
- }
- if (item->mask) {
- if (pf)
- dst->mask = pf->data + off2;
- off2 += flow_item_spec_copy
- (pf ? pf->data + off2 : NULL, item, ITEM_MASK);
- }
- off2 = RTE_ALIGN_CEIL(off2, sizeof(double));
- } while ((item++)->type != RTE_FLOW_ITEM_TYPE_END);
- off1 = RTE_ALIGN_CEIL(off1, sizeof(double));
- action = actions;
- if (pf)
- pf->actions = (void *)&pf->data[off1];
- do {
- struct rte_flow_action *dst = NULL;
-
- if ((unsigned int)action->type >= RTE_DIM(flow_action) ||
- !flow_action[action->type].name)
- goto notsup;
- if (pf)
- dst = memcpy(pf->data + off1, action, sizeof(*action));
- off1 += sizeof(*action);
- if (action->conf) {
- if (pf)
- dst->conf = pf->data + off2;
- off2 += flow_action_conf_copy
- (pf ? pf->data + off2 : NULL, action);
- }
- off2 = RTE_ALIGN_CEIL(off2, sizeof(double));
- } while ((action++)->type != RTE_FLOW_ACTION_TYPE_END);
- if (pf != NULL)
+ const struct rte_flow_action *actions,
+ struct rte_flow_error *error)
+{
+ const struct rte_flow_conv_rule rule = {
+ .attr_ro = attr,
+ .pattern_ro = pattern,
+ .actions_ro = actions,
+ };
+ struct port_flow *pf;
+ int ret;
+
+ ret = rte_flow_conv(RTE_FLOW_CONV_OP_RULE, NULL, 0, &rule, error);
+ if (ret < 0)
+ return NULL;
+ pf = calloc(1, offsetof(struct port_flow, rule) + ret);
+ if (!pf) {
+ rte_flow_error_set
+ (error, errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "calloc() failed");
+ return NULL;
+ }
+ if (rte_flow_conv(RTE_FLOW_CONV_OP_RULE, &pf->rule, ret, &rule,
+ error) >= 0)
return pf;
- off1 = RTE_ALIGN_CEIL(off1, sizeof(double));
- tmp = RTE_ALIGN_CEIL(offsetof(struct port_flow, data), sizeof(double));
- pf = calloc(1, tmp + off1 + off2);
- if (pf == NULL)
- err = errno;
- else {
- *pf = (const struct port_flow){
- .size = tmp + off1 + off2,
- .attr = *attr,
- };
- tmp -= offsetof(struct port_flow, data);
- off2 = tmp + off1;
- off1 = tmp;
- goto store;
- }
-notsup:
- rte_errno = err;
+ free(pf);
return NULL;
}
errstr = "unknown type";
else
errstr = errstrlist[error->type];
- printf("Caught error type %d (%s): %s%s\n",
+ printf("Caught error type %d (%s): %s%s: %s\n",
error->type, errstr,
error->cause ? (snprintf(buf, sizeof(buf), "cause: %p, ",
error->cause), buf) : "",
- error->message ? error->message : "(no stated reason)");
+ error->message ? error->message : "(no stated reason)",
+ rte_strerror(err));
return -err;
}
id = port->flow_list->id + 1;
} else
id = 0;
- pf = port_flow_new(attr, pattern, actions);
+ pf = port_flow_new(attr, pattern, actions, &error);
if (!pf) {
- int err = rte_errno;
-
- printf("Cannot allocate flow: %s\n", rte_strerror(err));
rte_flow_destroy(port_id, flow, NULL);
- return -err;
+ return port_flow_complain(&error);
}
pf->next = port->flow_list;
pf->id = id;
/** Query a flow rule. */
int
port_flow_query(portid_t port_id, uint32_t rule,
- enum rte_flow_action_type action)
+ const struct rte_flow_action *action)
{
struct rte_flow_error error;
struct rte_port *port;
union {
struct rte_flow_query_count count;
} query;
+ int ret;
if (port_id_is_invalid(port_id, ENABLED_WARN) ||
port_id == (portid_t)RTE_PORT_ALL)
printf("Flow rule #%u not found\n", rule);
return -ENOENT;
}
- if ((unsigned int)action >= RTE_DIM(flow_action) ||
- !flow_action[action].name)
- name = "unknown";
- else
- name = flow_action[action].name;
- switch (action) {
+ ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTION_NAME_PTR,
+ &name, sizeof(name),
+ (void *)(uintptr_t)action->type, &error);
+ if (ret < 0)
+ return port_flow_complain(&error);
+ switch (action->type) {
case RTE_FLOW_ACTION_TYPE_COUNT:
break;
default:
- printf("Cannot query action type %d (%s)\n", action, name);
+ printf("Cannot query action type %d (%s)\n",
+ action->type, name);
return -ENOTSUP;
}
/* Poisoning to make sure PMDs update it in case of error. */
memset(&query, 0, sizeof(query));
if (rte_flow_query(port_id, pf->flow, action, &query, &error))
return port_flow_complain(&error);
- switch (action) {
+ switch (action->type) {
case RTE_FLOW_ACTION_TYPE_COUNT:
printf("%s:\n"
" hits_set: %u\n"
break;
default:
printf("Cannot display result for action type %d (%s)\n",
- action, name);
+ action->type, name);
break;
}
return 0;
/* Sort flows by group, priority and ID. */
for (pf = port->flow_list; pf != NULL; pf = pf->next) {
struct port_flow **tmp;
+ const struct rte_flow_attr *curr = pf->rule.attr;
if (n) {
/* Filter out unwanted groups. */
for (i = 0; i != n; ++i)
- if (pf->attr.group == group[i])
+ if (curr->group == group[i])
break;
if (i == n)
continue;
}
- tmp = &list;
- while (*tmp &&
- (pf->attr.group > (*tmp)->attr.group ||
- (pf->attr.group == (*tmp)->attr.group &&
- pf->attr.priority > (*tmp)->attr.priority) ||
- (pf->attr.group == (*tmp)->attr.group &&
- pf->attr.priority == (*tmp)->attr.priority &&
- pf->id > (*tmp)->id)))
- tmp = &(*tmp)->tmp;
+ for (tmp = &list; *tmp; tmp = &(*tmp)->tmp) {
+ const struct rte_flow_attr *comp = (*tmp)->rule.attr;
+
+ if (curr->group > comp->group ||
+ (curr->group == comp->group &&
+ curr->priority > comp->priority) ||
+ (curr->group == comp->group &&
+ curr->priority == comp->priority &&
+ pf->id > (*tmp)->id))
+ continue;
+ break;
+ }
pf->tmp = *tmp;
*tmp = pf;
}
printf("ID\tGroup\tPrio\tAttr\tRule\n");
for (pf = list; pf != NULL; pf = pf->tmp) {
- const struct rte_flow_item *item = pf->pattern;
- const struct rte_flow_action *action = pf->actions;
+ const struct rte_flow_item *item = pf->rule.pattern;
+ const struct rte_flow_action *action = pf->rule.actions;
+ const char *name;
printf("%" PRIu32 "\t%" PRIu32 "\t%" PRIu32 "\t%c%c%c\t",
pf->id,
- pf->attr.group,
- pf->attr.priority,
- pf->attr.ingress ? 'i' : '-',
- pf->attr.egress ? 'e' : '-',
- pf->attr.transfer ? 't' : '-');
+ pf->rule.attr->group,
+ pf->rule.attr->priority,
+ pf->rule.attr->ingress ? 'i' : '-',
+ 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,
+ &name, sizeof(name),
+ (void *)(uintptr_t)item->type,
+ NULL) <= 0)
+ name = "[UNKNOWN]";
if (item->type != RTE_FLOW_ITEM_TYPE_VOID)
- printf("%s ", flow_item[item->type].name);
+ printf("%s ", name);
++item;
}
printf("=>");
while (action->type != RTE_FLOW_ACTION_TYPE_END) {
+ if (rte_flow_conv(RTE_FLOW_CONV_OP_ACTION_NAME_PTR,
+ &name, sizeof(name),
+ (void *)(uintptr_t)action->type,
+ NULL) <= 0)
+ name = "[UNKNOWN]";
if (action->type != RTE_FLOW_ACTION_TYPE_VOID)
- printf(" %s", flow_action[action->type].name);
+ printf(" %s", name);
++action;
}
printf("\n");
char mz_name[RTE_MEMZONE_NAMESIZE];
const struct rte_memzone *mz;
- snprintf(mz_name, sizeof(mz_name), "%s_%s_%d_%d",
- ports[port_id].dev_info.driver_name, ring_name, port_id, q_id);
+ snprintf(mz_name, sizeof(mz_name), "eth_p%d_q%d_%s",
+ port_id, q_id, ring_name);
mz = rte_memzone_lookup(mz_name);
if (mz == NULL)
printf("%s ring memory zoneof (port %d, queue %d) not"
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;
+ int32_t rc;
/* per port config */
printf(" port %d: RX queue number: %d Tx queue number: %d\n",
/* 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)
+ nb_rx_desc_tmp = nb_rx_desc[qid];
+ else
+ nb_rx_desc_tmp = rx_qinfo.nb_desc;
+
printf(" RX queue: %d\n", qid);
printf(" RX desc=%d - RX free threshold=%d\n",
- nb_rx_desc[qid], rx_conf[qid].rx_free_thresh);
+ nb_rx_desc_tmp, rx_conf[qid].rx_free_thresh);
printf(" RX threshold registers: pthresh=%d hthresh=%d "
" wthresh=%d\n",
rx_conf[qid].rx_thresh.pthresh,
/* 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)
+ nb_tx_desc_tmp = nb_tx_desc[qid];
+ else
+ nb_tx_desc_tmp = tx_qinfo.nb_desc;
+
printf(" TX queue: %d\n", qid);
printf(" TX desc=%d - TX free threshold=%d\n",
- nb_tx_desc[qid], tx_conf[qid].tx_free_thresh);
+ nb_tx_desc_tmp, tx_conf[qid].tx_free_thresh);
printf(" TX threshold registers: pthresh=%d hthresh=%d "
" wthresh=%d\n",
tx_conf[qid].tx_thresh.pthresh,
* key of the port.
*/
void
-port_rss_hash_conf_show(portid_t port_id, char rss_info[], int show_rss_key)
+port_rss_hash_conf_show(portid_t port_id, int show_rss_key)
{
- struct rte_eth_rss_conf rss_conf;
+ struct rte_eth_rss_conf rss_conf = {0};
uint8_t rss_key[RSS_HASH_KEY_LENGTH];
uint64_t rss_hf;
uint8_t i;
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
- memset(&dev_info, 0, sizeof(dev_info));
rte_eth_dev_info_get(port_id, &dev_info);
if (dev_info.hash_key_size > 0 &&
dev_info.hash_key_size <= sizeof(rss_key))
return;
}
- rss_conf.rss_hf = 0;
- for (i = 0; rss_type_table[i].str; i++) {
- if (!strcmp(rss_info, rss_type_table[i].str))
- rss_conf.rss_hf = rss_type_table[i].rss_type;
- }
-
/* Get RSS hash key if asked to display it */
rss_conf.rss_key = (show_rss_key) ? rss_key : NULL;
rss_conf.rss_key_len = hash_key_size;
fs->tx_queue = rxq;
fs->peer_addr = fs->tx_port;
fs->retry_enabled = retry_enabled;
- rxq = (queueid_t) (rxq + 1);
- if (rxq < nb_q)
- continue;
- /*
- * rxq == nb_q
- * Restart from RX queue 0 on next RX port
- */
- rxq = 0;
rxp++;
+ if (rxp < nb_fwd_ports)
+ continue;
+ rxp = 0;
+ rxq++;
}
}
}
}
+#if defined RTE_LIBRTE_PMD_SOFTNIC
+static void
+softnic_fwd_config_setup(void)
+{
+ struct rte_port *port;
+ portid_t pid, softnic_portid;
+ queueid_t i;
+ uint8_t softnic_enable = 0;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ port = &ports[pid];
+ const char *driver = port->dev_info.driver_name;
+
+ if (strcmp(driver, "net_softnic") == 0) {
+ softnic_portid = pid;
+ softnic_enable = 1;
+ break;
+ }
+ }
+
+ if (softnic_enable == 0) {
+ printf("Softnic mode not configured(%s)!\n", __func__);
+ return;
+ }
+
+ cur_fwd_config.nb_fwd_ports = 1;
+ cur_fwd_config.nb_fwd_streams = (streamid_t) nb_rxq;
+
+ /* Re-initialize forwarding streams */
+ init_fwd_streams();
+
+ /*
+ * In the softnic forwarding test, the number of forwarding cores
+ * is set to one and remaining are used for softnic packet processing.
+ */
+ cur_fwd_config.nb_fwd_lcores = 1;
+ setup_fwd_config_of_each_lcore(&cur_fwd_config);
+
+ for (i = 0; i < cur_fwd_config.nb_fwd_streams; i++) {
+ fwd_streams[i]->rx_port = softnic_portid;
+ fwd_streams[i]->rx_queue = i;
+ fwd_streams[i]->tx_port = softnic_portid;
+ fwd_streams[i]->tx_queue = i;
+ fwd_streams[i]->peer_addr = fwd_streams[i]->tx_port;
+ fwd_streams[i]->retry_enabled = retry_enabled;
+ }
+}
+#endif
+
void
fwd_config_setup(void)
{
icmp_echo_config_setup();
return;
}
+
+#if defined RTE_LIBRTE_PMD_SOFTNIC
+ if (strcmp(cur_fwd_eng->fwd_mode_name, "softnic") == 0) {
+ softnic_fwd_config_setup();
+ return;
+ }
+#endif
+
if ((nb_rxq > 1) && (nb_txq > 1)){
if (dcb_config)
dcb_fwd_config_setup();
simple_fwd_config_setup();
}
+static const char *
+mp_alloc_to_str(uint8_t mode)
+{
+ switch (mode) {
+ case MP_ALLOC_NATIVE:
+ return "native";
+ case MP_ALLOC_ANON:
+ return "anon";
+ case MP_ALLOC_XMEM:
+ return "xmem";
+ case MP_ALLOC_XMEM_HUGE:
+ return "xmemhuge";
+ default:
+ return "invalid";
+ }
+}
+
void
pkt_fwd_config_display(struct fwd_config *cfg)
{
streamid_t sm_id;
printf("%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
- "NUMA support %s, MP over anonymous pages %s\n",
+ "NUMA support %s, MP allocation mode: %s\n",
cfg->fwd_eng->fwd_mode_name,
retry_enabled == 0 ? "" : " with retry",
cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams,
numa_support == 1 ? "enabled" : "disabled",
- mp_anon != 0 ? "enabled" : "disabled");
+ mp_alloc_to_str(mp_alloc_type));
if (retry_enabled)
printf("TX retry num: %u, delay between TX retries: %uus\n",
printf("Invalid %s packet forwarding mode\n", fwd_mode_name);
}
+void
+add_rx_dump_callbacks(portid_t portid)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t queue;
+
+ if (port_id_is_invalid(portid, ENABLED_WARN))
+ return;
+
+ rte_eth_dev_info_get(portid, &dev_info);
+ for (queue = 0; queue < dev_info.nb_rx_queues; queue++)
+ if (!ports[portid].rx_dump_cb[queue])
+ ports[portid].rx_dump_cb[queue] =
+ rte_eth_add_rx_callback(portid, queue,
+ dump_rx_pkts, NULL);
+}
+
+void
+add_tx_dump_callbacks(portid_t portid)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t queue;
+
+ if (port_id_is_invalid(portid, ENABLED_WARN))
+ return;
+ rte_eth_dev_info_get(portid, &dev_info);
+ for (queue = 0; queue < dev_info.nb_tx_queues; queue++)
+ if (!ports[portid].tx_dump_cb[queue])
+ ports[portid].tx_dump_cb[queue] =
+ rte_eth_add_tx_callback(portid, queue,
+ dump_tx_pkts, NULL);
+}
+
+void
+remove_rx_dump_callbacks(portid_t portid)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t queue;
+
+ if (port_id_is_invalid(portid, ENABLED_WARN))
+ return;
+ rte_eth_dev_info_get(portid, &dev_info);
+ for (queue = 0; queue < dev_info.nb_rx_queues; queue++)
+ if (ports[portid].rx_dump_cb[queue]) {
+ rte_eth_remove_rx_callback(portid, queue,
+ ports[portid].rx_dump_cb[queue]);
+ ports[portid].rx_dump_cb[queue] = NULL;
+ }
+}
+
+void
+remove_tx_dump_callbacks(portid_t portid)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t queue;
+
+ if (port_id_is_invalid(portid, ENABLED_WARN))
+ return;
+ rte_eth_dev_info_get(portid, &dev_info);
+ for (queue = 0; queue < dev_info.nb_tx_queues; queue++)
+ if (ports[portid].tx_dump_cb[queue]) {
+ rte_eth_remove_tx_callback(portid, queue,
+ ports[portid].tx_dump_cb[queue]);
+ ports[portid].tx_dump_cb[queue] = NULL;
+ }
+}
+
+void
+configure_rxtx_dump_callbacks(uint16_t verbose)
+{
+ portid_t portid;
+
+#ifndef RTE_ETHDEV_RXTX_CALLBACKS
+ TESTPMD_LOG(ERR, "setting rxtx callbacks is not enabled\n");
+ return;
+#endif
+
+ RTE_ETH_FOREACH_DEV(portid)
+ {
+ if (verbose == 1 || verbose > 2)
+ add_rx_dump_callbacks(portid);
+ else
+ remove_rx_dump_callbacks(portid);
+ if (verbose >= 2)
+ add_tx_dump_callbacks(portid);
+ else
+ remove_tx_dump_callbacks(portid);
+ }
+}
+
void
set_verbose_level(uint16_t vb_level)
{
printf("Change verbose level from %u to %u\n",
(unsigned int) verbose_level, (unsigned int) vb_level);
verbose_level = vb_level;
+ configure_rxtx_dump_callbacks(verbose_level);
}
void
void
tx_vlan_set(portid_t port_id, uint16_t vlan_id)
{
- int vlan_offload;
struct rte_eth_dev_info dev_info;
if (port_id_is_invalid(port_id, ENABLED_WARN))
if (vlan_id_is_invalid(vlan_id))
return;
- vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
- if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD) {
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_QINQ_INSERT) {
printf("Error, as QinQ has been enabled.\n");
return;
}
void
tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer)
{
- int vlan_offload;
struct rte_eth_dev_info dev_info;
if (port_id_is_invalid(port_id, ENABLED_WARN))
if (vlan_id_is_invalid(vlan_id_outer))
return;
- vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
- if (!(vlan_offload & ETH_VLAN_EXTEND_OFFLOAD)) {
- printf("Error, as QinQ hasn't been enabled.\n");
- return;
- }
rte_eth_dev_info_get(port_id, &dev_info);
if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT) == 0) {
printf("Error: qinq insert not supported by port %d\n",
}
tx_vlan_reset(port_id);
- ports[port_id].dev_conf.txmode.offloads |= DEV_TX_OFFLOAD_QINQ_INSERT;
+ ports[port_id].dev_conf.txmode.offloads |= (DEV_TX_OFFLOAD_VLAN_INSERT |
+ DEV_TX_OFFLOAD_QINQ_INSERT);
ports[port_id].tx_vlan_id = vlan_id;
ports[port_id].tx_vlan_id_outer = vlan_id_outer;
}