1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 * Copyright(c) 2018 Mellanox Technology 4 */ 5 6 #include <stdio.h> 7 8 #include <rte_net.h> 9 #include <rte_mbuf.h> 10 #include <rte_ether.h> 11 #include <rte_ethdev.h> 12 #include <rte_flow.h> 13 14 #include "testpmd.h" 15 16 static inline void 17 print_ether_addr(const char *what, const struct rte_ether_addr *eth_addr) 18 { 19 char buf[RTE_ETHER_ADDR_FMT_SIZE]; 20 rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); 21 printf("%s%s", what, buf); 22 } 23 24 static inline void 25 dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], 26 uint16_t nb_pkts, int is_rx) 27 { 28 struct rte_mbuf *mb; 29 const struct rte_ether_hdr *eth_hdr; 30 struct rte_ether_hdr _eth_hdr; 31 uint16_t eth_type; 32 uint64_t ol_flags; 33 uint16_t i, packet_type; 34 uint16_t is_encapsulation; 35 char buf[256]; 36 struct rte_net_hdr_lens hdr_lens; 37 uint32_t sw_packet_type; 38 uint16_t udp_port; 39 uint32_t vx_vni; 40 const char *reason; 41 42 if (!nb_pkts) 43 return; 44 printf("port %u/queue %u: %s %u packets\n", 45 port_id, queue, 46 is_rx ? "received" : "sent", 47 (unsigned int) nb_pkts); 48 for (i = 0; i < nb_pkts; i++) { 49 mb = pkts[i]; 50 eth_hdr = rte_pktmbuf_read(mb, 0, sizeof(_eth_hdr), &_eth_hdr); 51 eth_type = RTE_BE_TO_CPU_16(eth_hdr->ether_type); 52 ol_flags = mb->ol_flags; 53 packet_type = mb->packet_type; 54 is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type); 55 56 print_ether_addr(" src=", ð_hdr->s_addr); 57 print_ether_addr(" - dst=", ð_hdr->d_addr); 58 printf(" - type=0x%04x - length=%u - nb_segs=%d", 59 eth_type, (unsigned int) mb->pkt_len, 60 (int)mb->nb_segs); 61 if (ol_flags & PKT_RX_RSS_HASH) { 62 printf(" - RSS hash=0x%x", (unsigned int) mb->hash.rss); 63 printf(" - RSS queue=0x%x", (unsigned int) queue); 64 } 65 if (ol_flags & PKT_RX_FDIR) { 66 printf(" - FDIR matched "); 67 if (ol_flags & PKT_RX_FDIR_ID) 68 printf("ID=0x%x", 69 mb->hash.fdir.hi); 70 else if (ol_flags & PKT_RX_FDIR_FLX) 71 printf("flex bytes=0x%08x %08x", 72 mb->hash.fdir.hi, mb->hash.fdir.lo); 73 else 74 printf("hash=0x%x ID=0x%x ", 75 mb->hash.fdir.hash, mb->hash.fdir.id); 76 } 77 if (ol_flags & PKT_RX_TIMESTAMP) 78 printf(" - timestamp %"PRIu64" ", mb->timestamp); 79 if (ol_flags & PKT_RX_QINQ) 80 printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x", 81 mb->vlan_tci, mb->vlan_tci_outer); 82 else if (ol_flags & PKT_RX_VLAN) 83 printf(" - VLAN tci=0x%x", mb->vlan_tci); 84 if (mb->packet_type) { 85 rte_get_ptype_name(mb->packet_type, buf, sizeof(buf)); 86 printf(" - hw ptype: %s", buf); 87 } 88 sw_packet_type = rte_net_get_ptype(mb, &hdr_lens, 89 RTE_PTYPE_ALL_MASK); 90 rte_get_ptype_name(sw_packet_type, buf, sizeof(buf)); 91 printf(" - sw ptype: %s", buf); 92 if (sw_packet_type & RTE_PTYPE_L2_MASK) 93 printf(" - l2_len=%d", hdr_lens.l2_len); 94 if (sw_packet_type & RTE_PTYPE_L3_MASK) 95 printf(" - l3_len=%d", hdr_lens.l3_len); 96 if (sw_packet_type & RTE_PTYPE_L4_MASK) 97 printf(" - l4_len=%d", hdr_lens.l4_len); 98 if (sw_packet_type & RTE_PTYPE_TUNNEL_MASK) 99 printf(" - tunnel_len=%d", hdr_lens.tunnel_len); 100 if (sw_packet_type & RTE_PTYPE_INNER_L2_MASK) 101 printf(" - inner_l2_len=%d", hdr_lens.inner_l2_len); 102 if (sw_packet_type & RTE_PTYPE_INNER_L3_MASK) 103 printf(" - inner_l3_len=%d", hdr_lens.inner_l3_len); 104 if (sw_packet_type & RTE_PTYPE_INNER_L4_MASK) 105 printf(" - inner_l4_len=%d", hdr_lens.inner_l4_len); 106 if (is_encapsulation) { 107 struct rte_ipv4_hdr *ipv4_hdr; 108 struct rte_ipv6_hdr *ipv6_hdr; 109 struct rte_udp_hdr *udp_hdr; 110 uint8_t l2_len; 111 uint8_t l3_len; 112 uint8_t l4_len; 113 uint8_t l4_proto; 114 struct rte_vxlan_hdr *vxlan_hdr; 115 116 l2_len = sizeof(struct rte_ether_hdr); 117 118 /* Do not support ipv4 option field */ 119 if (RTE_ETH_IS_IPV4_HDR(packet_type)) { 120 l3_len = sizeof(struct rte_ipv4_hdr); 121 ipv4_hdr = rte_pktmbuf_mtod_offset(mb, 122 struct rte_ipv4_hdr *, 123 l2_len); 124 l4_proto = ipv4_hdr->next_proto_id; 125 } else { 126 l3_len = sizeof(struct rte_ipv6_hdr); 127 ipv6_hdr = rte_pktmbuf_mtod_offset(mb, 128 struct rte_ipv6_hdr *, 129 l2_len); 130 l4_proto = ipv6_hdr->proto; 131 } 132 if (l4_proto == IPPROTO_UDP) { 133 udp_hdr = rte_pktmbuf_mtod_offset(mb, 134 struct rte_udp_hdr *, 135 l2_len + l3_len); 136 l4_len = sizeof(struct rte_udp_hdr); 137 vxlan_hdr = rte_pktmbuf_mtod_offset(mb, 138 struct rte_vxlan_hdr *, 139 l2_len + l3_len + l4_len); 140 udp_port = RTE_BE_TO_CPU_16(udp_hdr->dst_port); 141 vx_vni = rte_be_to_cpu_32(vxlan_hdr->vx_vni); 142 printf(" - VXLAN packet: packet type =%d, " 143 "Destination UDP port =%d, VNI = %d", 144 packet_type, udp_port, vx_vni >> 8); 145 } 146 } 147 printf(" - %s queue=0x%x", is_rx ? "Receive" : "Send", 148 (unsigned int) queue); 149 printf("\n"); 150 rte_get_rx_ol_flag_list(mb->ol_flags, buf, sizeof(buf)); 151 printf(" ol_flags: %s\n", buf); 152 if (rte_mbuf_check(mb, 1, &reason) < 0) 153 printf("INVALID mbuf: %s\n", reason); 154 } 155 } 156 157 uint16_t 158 dump_rx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], 159 uint16_t nb_pkts, __rte_unused uint16_t max_pkts, 160 __rte_unused void *user_param) 161 { 162 dump_pkt_burst(port_id, queue, pkts, nb_pkts, 1); 163 return nb_pkts; 164 } 165 166 uint16_t 167 dump_tx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], 168 uint16_t nb_pkts, __rte_unused void *user_param) 169 { 170 dump_pkt_burst(port_id, queue, pkts, nb_pkts, 0); 171 return nb_pkts; 172 } 173 174 uint16_t 175 tx_pkt_set_md(uint16_t port_id, __rte_unused uint16_t queue, 176 struct rte_mbuf *pkts[], uint16_t nb_pkts, 177 __rte_unused void *user_param) 178 { 179 uint16_t i = 0; 180 181 /* 182 * Add metadata value to every Tx packet, 183 * and set ol_flags accordingly. 184 */ 185 for (i = 0; i < nb_pkts; i++) { 186 pkts[i]->tx_metadata = ports[port_id].tx_metadata; 187 pkts[i]->ol_flags |= PKT_TX_METADATA; 188 } 189 return nb_pkts; 190 } 191 192 void 193 add_tx_md_callback(portid_t portid) 194 { 195 struct rte_eth_dev_info dev_info; 196 uint16_t queue; 197 int ret; 198 199 if (port_id_is_invalid(portid, ENABLED_WARN)) 200 return; 201 202 ret = eth_dev_info_get_print_err(portid, &dev_info); 203 if (ret != 0) 204 return; 205 206 for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 207 if (!ports[portid].tx_set_md_cb[queue]) 208 ports[portid].tx_set_md_cb[queue] = 209 rte_eth_add_tx_callback(portid, queue, 210 tx_pkt_set_md, NULL); 211 } 212 213 void 214 remove_tx_md_callback(portid_t portid) 215 { 216 struct rte_eth_dev_info dev_info; 217 uint16_t queue; 218 int ret; 219 220 if (port_id_is_invalid(portid, ENABLED_WARN)) 221 return; 222 223 ret = eth_dev_info_get_print_err(portid, &dev_info); 224 if (ret != 0) 225 return; 226 227 for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 228 if (ports[portid].tx_set_md_cb[queue]) { 229 rte_eth_remove_tx_callback(portid, queue, 230 ports[portid].tx_set_md_cb[queue]); 231 ports[portid].tx_set_md_cb[queue] = NULL; 232 } 233 } 234 235 int 236 eth_dev_info_get_print_err(uint16_t port_id, 237 struct rte_eth_dev_info *dev_info) 238 { 239 int ret; 240 241 ret = rte_eth_dev_info_get(port_id, dev_info); 242 if (ret != 0) 243 printf("Error during getting device (port %u) info: %s\n", 244 port_id, strerror(-ret)); 245 246 return ret; 247 } 248 249 void 250 eth_set_promisc_mode(uint16_t port, int enable) 251 { 252 int ret; 253 254 if (enable) 255 ret = rte_eth_promiscuous_enable(port); 256 else 257 ret = rte_eth_promiscuous_disable(port); 258 259 if (ret != 0) 260 printf("Error during %s promiscuous mode for port %u: %s\n", 261 enable ? "enabling" : "disabling", 262 port, rte_strerror(-ret)); 263 } 264 265 void 266 eth_set_allmulticast_mode(uint16_t port, int enable) 267 { 268 int ret; 269 270 if (enable) 271 ret = rte_eth_allmulticast_enable(port); 272 else 273 ret = rte_eth_allmulticast_disable(port); 274 275 if (ret != 0) 276 printf("Error during %s all-multicast mode for port %u: %s\n", 277 enable ? "enabling" : "disabling", 278 port, rte_strerror(-ret)); 279 } 280 281 int 282 eth_link_get_nowait_print_err(uint16_t port_id, struct rte_eth_link *link) 283 { 284 int ret; 285 286 ret = rte_eth_link_get_nowait(port_id, link); 287 if (ret < 0) 288 printf("Device (port %u) link get (without wait) failed: %s\n", 289 port_id, rte_strerror(-ret)); 290 291 return ret; 292 } 293 294 int 295 eth_macaddr_get_print_err(uint16_t port_id, struct rte_ether_addr *mac_addr) 296 { 297 int ret; 298 299 ret = rte_eth_macaddr_get(port_id, mac_addr); 300 if (ret != 0) 301 printf("Error getting device (port %u) mac address: %s\n", 302 port_id, rte_strerror(-ret)); 303 304 return ret; 305 } 306