aboutsummaryrefslogtreecommitdiffstats
path: root/tests/vpp/perf/ip4/2n1l-10ge2p1x710-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr.robot
blob: 20442756510b7b993b85ea2b654e88f6b4572abc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# Copyright (c) 2019 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

*** Settings ***
| Resource | resources/libraries/robot/shared/default.robot
| ...
| Force Tags | 2_NODE_SINGLE_LINK_TOPO | PERFTEST | HW_ENV | NDRPDR
| ... | NIC_Intel-X710 | ETH | IP4FWD | FEATURE | ACL | ACL_STATELESS
| ... | IACL | ACL1 | 10K_FLOWS | DRV_VFIO_PCI
| ...
| Suite Setup | Setup suite single link | performance
| Suite Teardown | Tear down suite | performance
| Test Setup | Setup test
| Test Teardown | Tear down test | performance | acl
| ...
| Test Template | Local Template
| ...
| Documentation | *RFC2544: Packet throughput IPv4 test cases with ACL*
| ...
| ... | *[Top] Network Topologies:* TG-DUT1-TG 2-node circular topology\
| ... | with single links between nodes.
| ... | *[Enc] Packet Encapsulations:* Eth-IPv4-UDP for IPv4 routing.
| ... | *[Cfg] DUT configuration:* DUT1 is configured with IPv4 routing.\
| ... | Required ACL rules are applied to input paths of both DUT1 intefaces.\
| ... | DUT1 is tested with ${nic_name}.\
| ... | *[Ver] TG verification:* TG finds and reports throughput NDR (Non Drop\
| ... | Rate) with zero packet loss tolerance and throughput PDR (Partial Drop\
| ... | Rate) with non-zero packet loss tolerance (LT) expressed in percentage\
| ... | of packets transmitted. NDR and PDR are discovered for different\
| ... | Ethernet L2 frame sizes using MLRsearch library.\
| ... | Test packets are generated by TG on links to DUT1. TG traffic profile\
| ... | contains two L3 flow-groups (flow-group per direction, ${flows_per_dir}\
| ... | flows per flow-group) with all packets containing Ethernet header, IPv4\
| ... | header with IP protocol=61 and static payload. MAC addresses are\
| ... | matching MAC addresses of the TG node interfaces.
| ... | *[Ref] Applicable standard specifications:* RFC2544.

*** Variables ***
| @{plugins_to_enable}= | dpdk_plugin.so | acl_plugin.so
| ${crypto_type}= | ${None}
| ${nic_name}= | Intel-X710
| ${nic_driver}= | vfio-pci
| ${osi_layer}= | L3
| ${overhead}= | ${0}
# ACL test setup
| ${acl_action}= | permit
| ${acl_apply_type}= | input
| ${no_hit_aces_number}= | 1
| ${flows_per_dir}= | 10k
| ${ip_nr}= | ${10}
# starting points for non-hitting ACLs
| ${src_ip_start}= | 30.30.30.1
| ${dst_ip_start}= | 40.40.40.1
| ${ip_step}= | ${1}
| ${sport_start}= | ${1000}
| ${dport_start}= | ${1000}
| ${port_step}= | ${1}
| ${trex_stream1_subnet}= | 10.10.10.0/24
| ${trex_stream2_subnet}= | 20.20.20.0/24
# Traffic profile:
| ${traffic_profile}= | trex-sl-2n-ethip4udp-10u1000p-conc

*** Keywords ***
| Local Template
| | ...
| | [Documentation]
| | ... | [Cfg] DUT runs IPv4 routing config.
| | ... | Each DUT uses ${phy_cores} physical core(s) for worker threads.
| | ... | [Ver] Measure NDR and PDR values using MLRsearch algorithm.\
| | ...
| | ... | *Arguments:*
| | ... | - frame_size - Framesize in Bytes in integer or string (IMIX_v4_1).
| | ... | Type: integer, string
| | ... | - phy_cores - Number of physical cores. Type: integer
| | ... | - rxq - Number of RX queues, default value: ${None}. Type: integer
| | ...
| | [Arguments] | ${frame_size} | ${phy_cores} | ${rxq}=${None}
| | ...
| | Set Test Variable | \${frame_size}
| | ...
| | Given Set Max Rate And Jumbo
| | And Add worker threads to all DUTs | ${phy_cores} | ${rxq}
| | And Pre-initialize layer driver | ${nic_driver}
| | And Apply startup configuration on all VPP DUTs
| | When Initialize layer driver | ${nic_driver}
| | And Initialize layer interface
| | And Initialize IPv4 routing with IPv4 ACLs on DUT1 in circular topology
| | ... | ${ip_nr}
| | Then Find NDR and PDR intervals using optimized search

*** Test Cases ***
| tc01-64B-1c-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr
| | [Tags] | 64B | 1C
| | frame_size=${64} | phy_cores=${1}

| tc02-64B-2c-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr
| | [Tags] | 64B | 2C
| | frame_size=${64} | phy_cores=${2}

| tc03-64B-4c-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr
| | [Tags] | 64B | 4C
| | frame_size=${64} | phy_cores=${4}

| tc04-1518B-1c-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr
| | [Tags] | 1518B | 1C
| | frame_size=${1518} | phy_cores=${1}

| tc05-1518B-2c-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr
| | [Tags] | 1518B | 2C
| | frame_size=${1518} | phy_cores=${2}

| tc06-1518B-4c-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr
| | [Tags] | 1518B | 4C
| | frame_size=${1518} | phy_cores=${4}

| tc07-9000B-1c-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr
| | [Tags] | 9000B | 1C
| | frame_size=${9000} | phy_cores=${1}

| tc08-9000B-2c-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr
| | [Tags] | 9000B | 2C
| | frame_size=${9000} | phy_cores=${2}

| tc09-9000B-4c-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr
| | [Tags] | 9000B | 4C
| | frame_size=${9000} | phy_cores=${4}

| tc10-IMIX-1c-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr
| | [Tags] | IMIX | 1C
| | frame_size=IMIX_v4_1 | phy_cores=${1}

| tc11-IMIX-2c-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr
| | [Tags] | IMIX | 2C
| | frame_size=IMIX_v4_1 | phy_cores=${2}

| tc12-IMIX-4c-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr
| | [Tags] | IMIX | 4C
| | frame_size=IMIX_v4_1 | phy_cores=${4}
NDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <vnet/vnet.h> #include <vppinfra/vec.h> #include <vppinfra/format.h> #include <assert.h> #define __USE_GNU #include <dlfcn.h> #include <vnet/ethernet/ethernet.h> #include <vnet/ethernet/sfp.h> #include <dpdk/device/dpdk.h> #include <dpdk/device/dpdk_priv.h> #include <vppinfra/error.h> #define foreach_dpdk_counter \ _ (tx_frames_ok, opackets) \ _ (tx_bytes_ok, obytes) \ _ (tx_errors, oerrors) \ _ (rx_frames_ok, ipackets) \ _ (rx_bytes_ok, ibytes) \ _ (rx_errors, ierrors) \ _ (rx_missed, imissed) \ _ (rx_no_bufs, rx_nombuf) #define foreach_dpdk_q_counter \ _ (rx_frames_ok, q_ipackets) \ _ (tx_frames_ok, q_opackets) \ _ (rx_bytes_ok, q_ibytes) \ _ (tx_bytes_ok, q_obytes) \ _ (rx_errors, q_errors) #define foreach_dpdk_pkt_rx_offload_flag \ _ (PKT_RX_VLAN, "RX packet is a 802.1q VLAN packet") \ _ (PKT_RX_RSS_HASH, "RX packet with RSS hash result") \ _ (PKT_RX_FDIR, "RX packet with FDIR infos") \ _ (PKT_RX_L4_CKSUM_BAD, "L4 cksum of RX pkt. is not OK") \ _ (PKT_RX_IP_CKSUM_BAD, "IP cksum of RX pkt. is not OK") \ _ (PKT_RX_EIP_CKSUM_BAD, "External IP header checksum error") \ _ (PKT_RX_VLAN_STRIPPED, "RX packet VLAN tag stripped") \ _ (PKT_RX_IP_CKSUM_GOOD, "IP cksum of RX pkt. is valid") \ _ (PKT_RX_L4_CKSUM_GOOD, "L4 cksum of RX pkt. is valid") \ _ (PKT_RX_IEEE1588_PTP, "RX IEEE1588 L2 Ethernet PT Packet") \ _ (PKT_RX_IEEE1588_TMST, "RX IEEE1588 L2/L4 timestamped packet") \ _ (PKT_RX_QINQ_STRIPPED, "RX packet QinQ tags stripped") \ _ (PKT_RX_TIMESTAMP, "Timestamp field is valid") #define foreach_dpdk_pkt_type \ _ (L2, ETHER, "Ethernet packet") \ _ (L2, ETHER_TIMESYNC, "Ethernet packet for time sync") \ _ (L2, ETHER_ARP, "ARP packet") \ _ (L2, ETHER_LLDP, "LLDP (Link Layer Discovery Protocol) packet") \ _ (L2, ETHER_NSH, "NSH (Network Service Header) packet") \ _ (L2, ETHER_VLAN, "VLAN packet") \ _ (L2, ETHER_QINQ, "QinQ packet") \ _ (L3, IPV4, "IPv4 packet without extension headers") \ _ (L3, IPV4_EXT, "IPv4 packet with extension headers") \ _ (L3, IPV4_EXT_UNKNOWN, "IPv4 packet with or without extension headers") \ _ (L3, IPV6, "IPv6 packet without extension headers") \ _ (L3, IPV6_EXT, "IPv6 packet with extension headers") \ _ (L3, IPV6_EXT_UNKNOWN, "IPv6 packet with or without extension headers") \ _ (L4, TCP, "TCP packet") \ _ (L4, UDP, "UDP packet") \ _ (L4, FRAG, "Fragmented IP packet") \ _ (L4, SCTP, "SCTP (Stream Control Transmission Protocol) packet") \ _ (L4, ICMP, "ICMP packet") \ _ (L4, NONFRAG, "Non-fragmented IP packet") \ _ (TUNNEL, GRE, "GRE tunneling packet") \ _ (TUNNEL, VXLAN, "VXLAN tunneling packet") \ _ (TUNNEL, NVGRE, "NVGRE Tunneling packet") \ _ (TUNNEL, GENEVE, "GENEVE Tunneling packet") \ _ (TUNNEL, GRENAT, "Teredo, VXLAN or GRE Tunneling packet") \ _ (INNER_L2, ETHER, "Inner Ethernet packet") \ _ (INNER_L2, ETHER_VLAN, "Inner Ethernet packet with VLAN") \ _ (INNER_L3, IPV4, "Inner IPv4 packet without extension headers") \ _ (INNER_L3, IPV4_EXT, "Inner IPv4 packet with extension headers") \ _ (INNER_L3, IPV4_EXT_UNKNOWN, "Inner IPv4 packet with or without extension headers") \ _ (INNER_L3, IPV6, "Inner IPv6 packet without extension headers") \ _ (INNER_L3, IPV6_EXT, "Inner IPv6 packet with extension headers") \ _ (INNER_L3, IPV6_EXT_UNKNOWN, "Inner IPv6 packet with or without extension headers") \ _ (INNER_L4, TCP, "Inner TCP packet") \ _ (INNER_L4, UDP, "Inner UDP packet") \ _ (INNER_L4, FRAG, "Inner fragmented IP packet") \ _ (INNER_L4, SCTP, "Inner SCTP (Stream Control Transmission Protocol) packet") \ _ (INNER_L4, ICMP, "Inner ICMP packet") \ _ (INNER_L4, NONFRAG, "Inner non-fragmented IP packet") #define foreach_dpdk_pkt_tx_offload_flag \ _ (PKT_TX_VLAN_PKT, "TX packet is a 802.1q VLAN packet") \ _ (PKT_TX_IP_CKSUM, "IP cksum of TX pkt. computed by NIC") \ _ (PKT_TX_TCP_CKSUM, "TCP cksum of TX pkt. computed by NIC") \ _ (PKT_TX_SCTP_CKSUM, "SCTP cksum of TX pkt. computed by NIC") \ _ (PKT_TX_IEEE1588_TMST, "TX IEEE1588 packet to timestamp") #define foreach_dpdk_pkt_offload_flag \ foreach_dpdk_pkt_rx_offload_flag \ foreach_dpdk_pkt_tx_offload_flag u8 * format_dpdk_device_name (u8 * s, va_list * args) { dpdk_main_t *dm = &dpdk_main; char *devname_format; char *device_name; u32 i = va_arg (*args, u32); dpdk_device_t *xd = vec_elt_at_index (dm->devices, i); struct rte_eth_dev_info dev_info; struct rte_pci_device *pci_dev; u8 *ret; if (xd->name) return format (s, "%s", xd->name); if (dm->conf->interface_name_format_decimal) devname_format = "%s%d/%d/%d"; else devname_format = "%s%x/%x/%x"; switch (xd->port_type) { case VNET_DPDK_PORT_TYPE_ETH_1G: device_name = "GigabitEthernet"; break; case VNET_DPDK_PORT_TYPE_ETH_2_5G: device_name = "Two_FiveGigabitEthernet"; break; case VNET_DPDK_PORT_TYPE_ETH_5G: device_name = "FiveGigabitEthernet"; break; case VNET_DPDK_PORT_TYPE_ETH_10G: device_name = "TenGigabitEthernet"; break; case VNET_DPDK_PORT_TYPE_ETH_20G: device_name = "TwentyGigabitEthernet"; break; case VNET_DPDK_PORT_TYPE_ETH_25G: device_name = "TwentyFiveGigabitEthernet"; break; case VNET_DPDK_PORT_TYPE_ETH_40G: device_name = "FortyGigabitEthernet"; break; case VNET_DPDK_PORT_TYPE_ETH_50G: device_name = "FiftyGigabitEthernet"; break; case VNET_DPDK_PORT_TYPE_ETH_56G: device_name = "FiftySixGigabitEthernet"; break; case VNET_DPDK_PORT_TYPE_ETH_100G: device_name = "HundredGigabitEthernet"; break; case VNET_DPDK_PORT_TYPE_ETH_SWITCH: device_name = "EthernetSwitch"; break; case VNET_DPDK_PORT_TYPE_ETH_VF: device_name = "VirtualFunctionEthernet"; break; case VNET_DPDK_PORT_TYPE_AF_PACKET: return format (s, "af_packet%d", xd->af_packet_instance_num); case VNET_DPDK_PORT_TYPE_VIRTIO_USER: device_name = "VirtioUser"; break; case VNET_DPDK_PORT_TYPE_VHOST_ETHER: device_name = "VhostEthernet"; break; case VNET_DPDK_PORT_TYPE_FAILSAFE: device_name = "FailsafeEthernet"; break; default: case VNET_DPDK_PORT_TYPE_UNKNOWN: device_name = "UnknownEthernet"; break; } rte_eth_dev_info_get (xd->port_id, &dev_info); pci_dev = dpdk_get_pci_device (&dev_info); if (pci_dev && xd->port_type != VNET_DPDK_PORT_TYPE_FAILSAFE) ret = format (s, devname_format, device_name, pci_dev->addr.bus, pci_dev->addr.devid, pci_dev->addr.function); else ret = format (s, "%s%d", device_name, xd->port_id); if (xd->interface_name_suffix) return format (ret, "/%s", xd->interface_name_suffix); return ret; } u8 * format_dpdk_device_flags (u8 * s, va_list * args) { dpdk_device_t *xd = va_arg (*args, dpdk_device_t *); u8 *t = 0; #define _(a, b, c) if (xd->flags & (1 << a)) \ t = format (t, "%s%s", t ? " ":"", c); foreach_dpdk_device_flags #undef _ s = format (s, "%v", t); vec_free (t); return s; } static u8 * format_dpdk_device_type (u8 * s, va_list * args) { dpdk_main_t *dm = &dpdk_main; char *dev_type; u32 i = va_arg (*args, u32); switch (dm->devices[i].pmd) { case VNET_DPDK_PMD_E1000EM: dev_type = "Intel 82540EM (e1000)"; break; case VNET_DPDK_PMD_IGB: dev_type = "Intel e1000"; break; case VNET_DPDK_PMD_I40E: dev_type = "Intel X710/XL710 Family"; break; case VNET_DPDK_PMD_I40EVF: dev_type = "Intel X710/XL710 Family VF"; break; case VNET_DPDK_PMD_ICE: dev_type = "Intel E810 Family"; break; case VNET_DPDK_PMD_IAVF: dev_type = "Intel iAVF"; break; case VNET_DPDK_PMD_FM10K: dev_type = "Intel FM10000 Family Ethernet Switch"; break; case VNET_DPDK_PMD_IGBVF: dev_type = "Intel e1000 VF"; break; case VNET_DPDK_PMD_VIRTIO: dev_type = "Red Hat Virtio"; break; case VNET_DPDK_PMD_IXGBEVF: dev_type = "Intel 82599 VF"; break; case VNET_DPDK_PMD_IXGBE: dev_type = "Intel 82599"; break; case VNET_DPDK_PMD_ENIC: dev_type = "Cisco VIC"; break; case VNET_DPDK_PMD_CXGBE: dev_type = "Chelsio T4/T5"; break; case VNET_DPDK_PMD_MLX4: dev_type = "Mellanox ConnectX-3 Family"; break; case VNET_DPDK_PMD_MLX5: dev_type = "Mellanox ConnectX-4 Family"; break; case VNET_DPDK_PMD_VMXNET3: dev_type = "VMware VMXNET3"; break; case VNET_DPDK_PMD_AF_PACKET: dev_type = "af_packet"; break; case VNET_DPDK_PMD_DPAA2: dev_type = "NXP DPAA2 Mac"; break; case VNET_DPDK_PMD_VIRTIO_USER: dev_type = "Virtio User"; break; case VNET_DPDK_PMD_THUNDERX: dev_type = "Cavium ThunderX"; break; case VNET_DPDK_PMD_VHOST_ETHER: dev_type = "VhostEthernet"; break; case VNET_DPDK_PMD_ENA: dev_type = "AWS ENA VF"; break; case VNET_DPDK_PMD_FAILSAFE: dev_type = "FailsafeEthernet"; break; case VNET_DPDK_PMD_LIOVF_ETHER: dev_type = "Cavium Lio VF"; break; case VNET_DPDK_PMD_QEDE: dev_type = "Cavium QLogic FastLinQ QL4xxxx"; break; case VNET_DPDK_PMD_NETVSC: dev_type = "Microsoft Hyper-V Netvsc"; break; case VNET_DPDK_PMD_BNXT: dev_type = "Broadcom NetXtreme E/S-Series"; break; default: case VNET_DPDK_PMD_UNKNOWN: dev_type = "### UNKNOWN ###"; break; } return format (s, dev_type); } static u8 * format_dpdk_link_status (u8 * s, va_list * args) { dpdk_device_t *xd = va_arg (*args, dpdk_device_t *); struct rte_eth_link *l = &xd->link; vnet_main_t *vnm = vnet_get_main (); vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, xd->hw_if_index); s = format (s, "%s ", l->link_status ? "up" : "down"); if (l->link_status) { u32 promisc = rte_eth_promiscuous_get (xd->port_id); s = format (s, "%s duplex ", (l->link_duplex == ETH_LINK_FULL_DUPLEX) ? "full" : "half"); s = format (s, "mtu %d %s\n", hi->max_packet_bytes, promisc ? " promisc" : ""); } else s = format (s, "\n"); return s; } #define _(n, v, str) \ if (bitmap & v) { \ if (format_get_indent (s) > 72) \ s = format(s,"\n%U", format_white_space, indent); \ s = format(s, "%s ", str); \ } u8 * format_dpdk_rss_hf_name (u8 * s, va_list * args) { u64 bitmap = va_arg (*args, u64); u32 indent = format_get_indent (s); if (!bitmap) return format (s, "none"); foreach_dpdk_rss_hf return s; } #undef _ /* Convert to all lower case e.g "VLAN_STRIP" -> "vlan-strip" Works for both vector names and null terminated c strings. */ static u8 * format_offload (u8 * s, va_list * va) { u8 *id = va_arg (*va, u8 *); uword i, l; l = ~0; if (clib_mem_is_vec (id)) l = vec_len (id); if (id) for (i = 0; id[i] != 0 && i < l; i++) { u8 c = id[i]; if (c == '_') c = '-'; else c = tolower (c); vec_add1 (s, c); } return s; } #define _(v, func) \ if (bitmap & v) { \ if (format_get_indent (s) > 72) \ s = format(s,"\n%U", format_white_space, indent); \ s = format(s, "%U ", format_offload, func (v)); \ } u8 * format_dpdk_rx_offload_caps (u8 * s, va_list * args) { u64 bitmap = va_arg (*args, u32); u32 indent = format_get_indent (s); uword i; if (!bitmap) return format (s, "none"); for (i = 0; i < 64; i++) { u64 mask = (u64) 1 << i; _(mask, rte_eth_dev_rx_offload_name); } return s; } u8 * format_dpdk_tx_offload_caps (u8 * s, va_list * args) { u64 bitmap = va_arg (*args, u32); u32 indent = format_get_indent (s); uword i; if (!bitmap) return format (s, "none"); for (i = 0; i < 64; i++) { u64 mask = (u64) 1 << i; _(mask, rte_eth_dev_tx_offload_name); } return s; } #undef _ u8 * format_dpdk_device_errors (u8 * s, va_list * args) { dpdk_device_t *xd = va_arg (*args, dpdk_device_t *); clib_error_t *e; u32 indent = format_get_indent (s); vec_foreach (e, xd->errors) { s = format (s, "%U%v\n", format_white_space, indent, e->what); } return s; } static u8 * format_dpdk_device_module_info (u8 * s, va_list * args) { dpdk_device_t *xd = va_arg (*args, dpdk_device_t *); struct rte_eth_dev_module_info mi = { 0 }; struct rte_dev_eeprom_info ei = { 0 }; if (rte_eth_dev_get_module_info (xd->port_id, &mi) != 0) return format (s, "unknown"); ei.length = mi.eeprom_len; ei.data = clib_mem_alloc (mi.eeprom_len); if (rte_eth_dev_get_module_eeprom (xd->port_id, &ei) == 0) { s = format (s, "%U", format_sfp_eeprom, ei.data + (mi.type == RTE_ETH_MODULE_SFF_8436 ? 0x80 : 0)); } else s = format (s, "eeprom read error"); clib_mem_free (ei.data); return s; } static const char * ptr2sname (void *p) { Dl_info info = { 0 }; if (dladdr (p, &info) == 0) return 0; return info.dli_sname; } static u8 * format_switch_info (u8 * s, va_list * args) { struct rte_eth_switch_info *si = va_arg (*args, struct rte_eth_switch_info *); if (si->name) s = format (s, "name %s ", si->name); s = format (s, "domain id %d port id %d", si->domain_id, si->port_id); return s; } u8 * format_dpdk_device (u8 * s, va_list * args) { u32 dev_instance = va_arg (*args, u32); int verbose = va_arg (*args, int); dpdk_main_t *dm = &dpdk_main; dpdk_device_t *xd = vec_elt_at_index (dm->devices, dev_instance); u32 indent = format_get_indent (s); f64 now = vlib_time_now (dm->vlib_main); struct rte_eth_dev_info di; struct rte_eth_burst_mode mode; dpdk_update_counters (xd, now); dpdk_update_link_state (xd, now); rte_eth_dev_info_get (xd->port_id, &di); s = format (s, "%U\n%Ucarrier %U", format_dpdk_device_type, dev_instance, format_white_space, indent + 2, format_dpdk_link_status, xd); s = format (s, "%Uflags: %U\n", format_white_space, indent + 2, format_dpdk_device_flags, xd); if (di.device->devargs && di.device->devargs->args) s = format (s, "%UDevargs: %s\n", format_white_space, indent + 2, di.device->devargs->args); s = format (s, "%Urx: queues %d (max %d), desc %d " "(min %d max %d align %d)\n", format_white_space, indent + 2, xd->rx_q_used, di.max_rx_queues, xd->nb_rx_desc, di.rx_desc_lim.nb_min, di.rx_desc_lim.nb_max, di.rx_desc_lim.nb_align); s = format (s, "%Utx: queues %d (max %d), desc %d " "(min %d max %d align %d)\n", format_white_space, indent + 2, xd->tx_q_used, di.max_tx_queues, xd->nb_tx_desc, di.tx_desc_lim.nb_min, di.tx_desc_lim.nb_max, di.tx_desc_lim.nb_align); if (xd->flags & DPDK_DEVICE_FLAG_PMD) { struct rte_pci_device *pci; struct rte_eth_rss_conf rss_conf; int vlan_off; int retval; rss_conf.rss_key = 0; rss_conf.rss_hf = 0; retval = rte_eth_dev_rss_hash_conf_get (xd->port_id, &rss_conf); if (retval < 0) clib_warning ("rte_eth_dev_rss_hash_conf_get returned %d", retval); pci = dpdk_get_pci_device (&di); if (pci) { u8 *s2; if (xd->cpu_socket > -1) s2 = format (0, "%d", xd->cpu_socket); else s2 = format (0, "unknown"); s = format (s, "%Upci: device %04x:%04x subsystem %04x:%04x " "address %04x:%02x:%02x.%02x numa %v\n", format_white_space, indent + 2, pci->id.vendor_id, pci->id.device_id, pci->id.subsystem_vendor_id, pci->id.subsystem_device_id, pci->addr.domain, pci->addr.bus, pci->addr.devid, pci->addr.function, s2); vec_free (s2); } if (di.switch_info.domain_id != RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) { s = format (s, "%Uswitch info: %U\n", format_white_space, indent + 2, format_switch_info, &di.switch_info); } if (1 < verbose) { s = format (s, "%Umodule: %U\n", format_white_space, indent + 2, format_dpdk_device_module_info, xd); } s = format (s, "%Umax rx packet len: %d\n", format_white_space, indent + 2, di.max_rx_pktlen); s = format (s, "%Upromiscuous: unicast %s all-multicast %s\n", format_white_space, indent + 2, rte_eth_promiscuous_get (xd->port_id) ? "on" : "off", rte_eth_allmulticast_get (xd->port_id) ? "on" : "off"); vlan_off = rte_eth_dev_get_vlan_offload (xd->port_id); s = format (s, "%Uvlan offload: strip %s filter %s qinq %s\n", format_white_space, indent + 2, vlan_off & ETH_VLAN_STRIP_OFFLOAD ? "on" : "off", vlan_off & ETH_VLAN_FILTER_OFFLOAD ? "on" : "off", vlan_off & ETH_VLAN_EXTEND_OFFLOAD ? "on" : "off"); s = format (s, "%Urx offload avail: %U\n", format_white_space, indent + 2, format_dpdk_rx_offload_caps, di.rx_offload_capa); s = format (s, "%Urx offload active: %U\n", format_white_space, indent + 2, format_dpdk_rx_offload_caps, xd->port_conf.rxmode.offloads); s = format (s, "%Utx offload avail: %U\n", format_white_space, indent + 2, format_dpdk_tx_offload_caps, di.tx_offload_capa); s = format (s, "%Utx offload active: %U\n", format_white_space, indent + 2, format_dpdk_tx_offload_caps, xd->port_conf.txmode.offloads); s = format (s, "%Urss avail: %U\n" "%Urss active: %U\n", format_white_space, indent + 2, format_dpdk_rss_hf_name, di.flow_type_rss_offloads, format_white_space, indent + 2, format_dpdk_rss_hf_name, rss_conf.rss_hf); if (rte_eth_tx_burst_mode_get (xd->port_id, 0, &mode) == 0) { s = format (s, "%Utx burst mode: %s%s\n", format_white_space, indent + 2, mode.info, mode.flags & RTE_ETH_BURST_FLAG_PER_QUEUE ? " (per queue)" : ""); } else { s = format (s, "%Utx burst function: %s\n", format_white_space, indent + 2, ptr2sname (rte_eth_devices[xd->port_id].tx_pkt_burst)); } if (rte_eth_rx_burst_mode_get (xd->port_id, 0, &mode) == 0) { s = format (s, "%Urx burst mode: %s%s\n", format_white_space, indent + 2, mode.info, mode.flags & RTE_ETH_BURST_FLAG_PER_QUEUE ? " (per queue)" : ""); } else { s = format (s, "%Urx burst function: %s\n", format_white_space, indent + 2, ptr2sname (rte_eth_devices[xd->port_id].rx_pkt_burst)); } } /* $$$ MIB counters */ { #define _(N, V) \ if (xd->stats.V != 0) { \ s = format (s, "\n%U%-40U%16Lu", \ format_white_space, indent + 2, \ format_c_identifier, #N, \ xd->stats.V); \ } \ foreach_dpdk_counter #undef _ } u8 *xs = 0; u32 i = 0; struct rte_eth_xstat *xstat; struct rte_eth_xstat_name *xstat_names = 0; int len = vec_len (xd->xstats); vec_validate (xstat_names, len - 1); int ret = rte_eth_xstats_get_names (xd->port_id, xstat_names, len); if (ret >= 0 && ret <= len) { /* *INDENT-OFF* */ vec_foreach_index(i, xd->xstats) { xstat = vec_elt_at_index(xd->xstats, i); if (verbose == 2 || (verbose && xstat->value)) { /* format_c_identifier doesn't like c strings inside vector */ u8 * name = format(0,"%s", xstat_names[i].name); xs = format(xs, "\n%U%-38U%16Lu", format_white_space, indent + 4, format_c_identifier, name, xstat->value); vec_free(name); } } /* *INDENT-ON* */ vec_free (xstat_names); } if (xs) { s = format (s, "\n%Uextended stats:%v", format_white_space, indent + 2, xs); vec_free (xs); } if (vec_len (xd->errors)) { s = format (s, "%UErrors:\n %U", format_white_space, indent, format_dpdk_device_errors, xd); } return s; } u8 * format_dpdk_tx_trace (u8 * s, va_list * va) { CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *); CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *); CLIB_UNUSED (vnet_main_t * vnm) = vnet_get_main (); dpdk_tx_trace_t *t = va_arg (*va, dpdk_tx_trace_t *); dpdk_main_t *dm = &dpdk_main; dpdk_device_t *xd = vec_elt_at_index (dm->devices, t->device_index); u32 indent = format_get_indent (s); vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, xd->sw_if_index); s = format (s, "%U tx queue %d", format_vnet_sw_interface_name, vnm, sw, t->queue_index); s = format (s, "\n%Ubuffer 0x%x: %U", format_white_space, indent, t->buffer_index, format_vnet_buffer, &t->buffer); s = format (s, "\n%U%U", format_white_space, indent, format_dpdk_rte_mbuf, &t->mb, &t->data); s = format (s, "\n%U%U", format_white_space, indent, format_ethernet_header_with_length, t->buffer.pre_data, sizeof (t->buffer.pre_data)); return s; } u8 * format_dpdk_rx_trace (u8 * s, va_list * va) { CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *); CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *); CLIB_UNUSED (vnet_main_t * vnm) = vnet_get_main (); dpdk_rx_trace_t *t = va_arg (*va, dpdk_rx_trace_t *); dpdk_main_t *dm = &dpdk_main; dpdk_device_t *xd = vec_elt_at_index (dm->devices, t->device_index); format_function_t *f; u32 indent = format_get_indent (s); vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, xd->sw_if_index); s = format (s, "%U rx queue %d", format_vnet_sw_interface_name, vnm, sw, t->queue_index); s = format (s, "\n%Ubuffer 0x%x: %U", format_white_space, indent, t->buffer_index, format_vnet_buffer, &t->buffer); s = format (s, "\n%U%U", format_white_space, indent, format_dpdk_rte_mbuf, &t->mb, &t->data); if (vm->trace_main.verbose) { s = format (s, "\n%UPacket Dump%s", format_white_space, indent + 2, t->mb.data_len > sizeof (t->data) ? " (truncated)" : ""); s = format (s, "\n%U%U", format_white_space, indent + 4, format_hexdump, &t->data, t->mb.data_len > sizeof (t->data) ? sizeof (t->data) : t->mb.data_len); } f = node->format_buffer; if (!f) f = format_hex_bytes; s = format (s, "\n%U%U", format_white_space, indent, f, t->buffer.pre_data, sizeof (t->buffer.pre_data)); return s; } static inline u8 * format_dpdk_pkt_types (u8 * s, va_list * va) { u32 *pkt_types = va_arg (*va, u32 *); u32 indent __attribute__ ((unused)) = format_get_indent (s) + 2; if (!*pkt_types) return s; s = format (s, "Packet Types"); #define _(L, F, S) \ if ((*pkt_types & RTE_PTYPE_##L##_MASK) == RTE_PTYPE_##L##_##F) \ { \ s = format (s, "\n%U%s (0x%04x) %s", format_white_space, indent, \ "RTE_PTYPE_" #L "_" #F, RTE_PTYPE_##L##_##F, S); \ } foreach_dpdk_pkt_type #undef _ return s; } static inline u8 * format_dpdk_pkt_offload_flags (u8 * s, va_list * va) { u64 *ol_flags = va_arg (*va, u64 *); u32 indent = format_get_indent (s) + 2; if (!*ol_flags) return s; s = format (s, "Packet Offload Flags"); #define _(F, S) \ if (*ol_flags & F) \ { \ s = format (s, "\n%U%s (0x%04x) %s", \ format_white_space, indent, #F, F, S); \ } foreach_dpdk_pkt_offload_flag #undef _ return s; } u8 * format_dpdk_rte_mbuf_vlan (u8 * s, va_list * va) { ethernet_vlan_header_tv_t *vlan_hdr = va_arg (*va, ethernet_vlan_header_tv_t *); if (clib_net_to_host_u16 (vlan_hdr->type) == ETHERNET_TYPE_DOT1AD) { s = format (s, "%U 802.1q vlan ", format_ethernet_vlan_tci, clib_net_to_host_u16 (vlan_hdr->priority_cfi_and_id)); vlan_hdr++; } s = format (s, "%U", format_ethernet_vlan_tci, clib_net_to_host_u16 (vlan_hdr->priority_cfi_and_id)); return s; } u8 * format_dpdk_rte_mbuf (u8 * s, va_list * va) { struct rte_mbuf *mb = va_arg (*va, struct rte_mbuf *); ethernet_header_t *eth_hdr = va_arg (*va, ethernet_header_t *); u32 indent = format_get_indent (s) + 2; s = format (s, "PKT MBUF: port %d, nb_segs %d, pkt_len %d" "\n%Ubuf_len %d, data_len %d, ol_flags 0x%lx, data_off %d, phys_addr 0x%x" "\n%Upacket_type 0x%x l2_len %u l3_len %u outer_l2_len %u outer_l3_len %u" "\n%Urss 0x%x fdir.hi 0x%x fdir.lo 0x%x", mb->port, mb->nb_segs, mb->pkt_len, format_white_space, indent, mb->buf_len, mb->data_len, mb->ol_flags, mb->data_off, mb->buf_physaddr, format_white_space, indent, mb->packet_type, mb->l2_len, mb->l3_len, mb->outer_l2_len, mb->outer_l3_len, format_white_space, indent, mb->hash.rss, mb->hash.fdir.hi, mb->hash.fdir.lo); if (mb->ol_flags) s = format (s, "\n%U%U", format_white_space, indent, format_dpdk_pkt_offload_flags, &mb->ol_flags); if ((mb->ol_flags & PKT_RX_VLAN) && ((mb->ol_flags & (PKT_RX_VLAN_STRIPPED | PKT_RX_QINQ_STRIPPED)) == 0)) { ethernet_vlan_header_tv_t *vlan_hdr = ((ethernet_vlan_header_tv_t *) & (eth_hdr->type)); s = format (s, " %U", format_dpdk_rte_mbuf_vlan, vlan_hdr); } if (mb->packet_type) s = format (s, "\n%U%U", format_white_space, indent, format_dpdk_pkt_types, &mb->packet_type); return s; } clib_error_t * unformat_rss_fn (unformat_input_t * input, uword * rss_fn) { while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (0) ; #undef _ #define _(n, f, s) \ else if (unformat (input, s)) \ *rss_fn |= f; foreach_dpdk_rss_hf #undef _ else { return clib_error_return (0, "unknown input `%U'", format_unformat_error, input); } } return 0; } /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */