1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 * Copyright 2018 Mellanox Technologies, Ltd 4 */ 5 6 #include <stdio.h> 7 8 #include <rte_bitops.h> 9 #include <rte_net.h> 10 #include <rte_mbuf.h> 11 #include <rte_ether.h> 12 #include <rte_vxlan.h> 13 #include <rte_ethdev.h> 14 #include <rte_flow.h> 15 16 #include "testpmd.h" 17 18 static inline void 19 print_ether_addr(const char *what, const struct rte_ether_addr *eth_addr) 20 { 21 char buf[RTE_ETHER_ADDR_FMT_SIZE]; 22 rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); 23 printf("%s%s", what, buf); 24 } 25 26 static inline bool 27 is_timestamp_enabled(const struct rte_mbuf *mbuf) 28 { 29 static uint64_t timestamp_rx_dynflag; 30 int timestamp_rx_dynflag_offset; 31 32 if (timestamp_rx_dynflag == 0) { 33 timestamp_rx_dynflag_offset = rte_mbuf_dynflag_lookup( 34 RTE_MBUF_DYNFLAG_RX_TIMESTAMP_NAME, NULL); 35 if (timestamp_rx_dynflag_offset < 0) 36 return false; 37 timestamp_rx_dynflag = RTE_BIT64(timestamp_rx_dynflag_offset); 38 } 39 40 return (mbuf->ol_flags & timestamp_rx_dynflag) != 0; 41 } 42 43 static inline rte_mbuf_timestamp_t 44 get_timestamp(const struct rte_mbuf *mbuf) 45 { 46 static int timestamp_dynfield_offset = -1; 47 48 if (timestamp_dynfield_offset < 0) { 49 timestamp_dynfield_offset = rte_mbuf_dynfield_lookup( 50 RTE_MBUF_DYNFIELD_TIMESTAMP_NAME, NULL); 51 if (timestamp_dynfield_offset < 0) 52 return 0; 53 } 54 55 return *RTE_MBUF_DYNFIELD(mbuf, 56 timestamp_dynfield_offset, rte_mbuf_timestamp_t *); 57 } 58 59 static inline void 60 dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], 61 uint16_t nb_pkts, int is_rx) 62 { 63 struct rte_mbuf *mb; 64 const struct rte_ether_hdr *eth_hdr; 65 struct rte_ether_hdr _eth_hdr; 66 uint16_t eth_type; 67 uint64_t ol_flags; 68 uint16_t i, packet_type; 69 uint16_t is_encapsulation; 70 char buf[256]; 71 struct rte_net_hdr_lens hdr_lens; 72 uint32_t sw_packet_type; 73 uint16_t udp_port; 74 uint32_t vx_vni; 75 const char *reason; 76 int dynf_index; 77 78 if (!nb_pkts) 79 return; 80 printf("port %u/queue %u: %s %u packets\n", 81 port_id, queue, 82 is_rx ? "received" : "sent", 83 (unsigned int) nb_pkts); 84 for (i = 0; i < nb_pkts; i++) { 85 int ret; 86 struct rte_flow_error error; 87 struct rte_flow_restore_info info = { 0, }; 88 89 mb = pkts[i]; 90 eth_hdr = rte_pktmbuf_read(mb, 0, sizeof(_eth_hdr), &_eth_hdr); 91 eth_type = RTE_BE_TO_CPU_16(eth_hdr->ether_type); 92 packet_type = mb->packet_type; 93 is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type); 94 ret = rte_flow_get_restore_info(port_id, mb, &info, &error); 95 if (!ret) { 96 printf("restore info:"); 97 if (info.flags & RTE_FLOW_RESTORE_INFO_TUNNEL) { 98 struct port_flow_tunnel *port_tunnel; 99 100 port_tunnel = port_flow_locate_tunnel 101 (port_id, &info.tunnel); 102 printf(" - tunnel"); 103 if (port_tunnel) 104 printf(" #%u", port_tunnel->id); 105 else 106 printf(" %s", "-none-"); 107 printf(" type %s", 108 port_flow_tunnel_type(&info.tunnel)); 109 } else { 110 printf(" - no tunnel info"); 111 } 112 if (info.flags & RTE_FLOW_RESTORE_INFO_ENCAPSULATED) 113 printf(" - outer header present"); 114 else 115 printf(" - no outer header"); 116 if (info.flags & RTE_FLOW_RESTORE_INFO_GROUP_ID) 117 printf(" - miss group %u", info.group_id); 118 else 119 printf(" - no miss group"); 120 printf("\n"); 121 } 122 print_ether_addr(" src=", ð_hdr->s_addr); 123 print_ether_addr(" - dst=", ð_hdr->d_addr); 124 printf(" - type=0x%04x - length=%u - nb_segs=%d", 125 eth_type, (unsigned int) mb->pkt_len, 126 (int)mb->nb_segs); 127 ol_flags = mb->ol_flags; 128 if (ol_flags & PKT_RX_RSS_HASH) { 129 printf(" - RSS hash=0x%x", (unsigned int) mb->hash.rss); 130 printf(" - RSS queue=0x%x", (unsigned int) queue); 131 } 132 if (ol_flags & PKT_RX_FDIR) { 133 printf(" - FDIR matched "); 134 if (ol_flags & PKT_RX_FDIR_ID) 135 printf("ID=0x%x", 136 mb->hash.fdir.hi); 137 else if (ol_flags & PKT_RX_FDIR_FLX) 138 printf("flex bytes=0x%08x %08x", 139 mb->hash.fdir.hi, mb->hash.fdir.lo); 140 else 141 printf("hash=0x%x ID=0x%x ", 142 mb->hash.fdir.hash, mb->hash.fdir.id); 143 } 144 if (is_timestamp_enabled(mb)) 145 printf(" - timestamp %"PRIu64" ", get_timestamp(mb)); 146 if (ol_flags & PKT_RX_QINQ) 147 printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x", 148 mb->vlan_tci, mb->vlan_tci_outer); 149 else if (ol_flags & PKT_RX_VLAN) 150 printf(" - VLAN tci=0x%x", mb->vlan_tci); 151 if (!is_rx && (ol_flags & PKT_TX_DYNF_METADATA)) 152 printf(" - Tx metadata: 0x%x", 153 *RTE_FLOW_DYNF_METADATA(mb)); 154 if (is_rx && (ol_flags & PKT_RX_DYNF_METADATA)) 155 printf(" - Rx metadata: 0x%x", 156 *RTE_FLOW_DYNF_METADATA(mb)); 157 for (dynf_index = 0; dynf_index < 64; dynf_index++) { 158 if (dynf_names[dynf_index][0] != '\0') 159 printf(" - dynf %s: %d", 160 dynf_names[dynf_index], 161 !!(ol_flags & (1UL << dynf_index))); 162 } 163 if (mb->packet_type) { 164 rte_get_ptype_name(mb->packet_type, buf, sizeof(buf)); 165 printf(" - hw ptype: %s", buf); 166 } 167 sw_packet_type = rte_net_get_ptype(mb, &hdr_lens, 168 RTE_PTYPE_ALL_MASK); 169 rte_get_ptype_name(sw_packet_type, buf, sizeof(buf)); 170 printf(" - sw ptype: %s", buf); 171 if (sw_packet_type & RTE_PTYPE_L2_MASK) 172 printf(" - l2_len=%d", hdr_lens.l2_len); 173 if (sw_packet_type & RTE_PTYPE_L3_MASK) 174 printf(" - l3_len=%d", hdr_lens.l3_len); 175 if (sw_packet_type & RTE_PTYPE_L4_MASK) 176 printf(" - l4_len=%d", hdr_lens.l4_len); 177 if (sw_packet_type & RTE_PTYPE_TUNNEL_MASK) 178 printf(" - tunnel_len=%d", hdr_lens.tunnel_len); 179 if (sw_packet_type & RTE_PTYPE_INNER_L2_MASK) 180 printf(" - inner_l2_len=%d", hdr_lens.inner_l2_len); 181 if (sw_packet_type & RTE_PTYPE_INNER_L3_MASK) 182 printf(" - inner_l3_len=%d", hdr_lens.inner_l3_len); 183 if (sw_packet_type & RTE_PTYPE_INNER_L4_MASK) 184 printf(" - inner_l4_len=%d", hdr_lens.inner_l4_len); 185 if (is_encapsulation) { 186 struct rte_ipv4_hdr *ipv4_hdr; 187 struct rte_ipv6_hdr *ipv6_hdr; 188 struct rte_udp_hdr *udp_hdr; 189 uint8_t l2_len; 190 uint8_t l3_len; 191 uint8_t l4_len; 192 uint8_t l4_proto; 193 struct rte_vxlan_hdr *vxlan_hdr; 194 195 l2_len = sizeof(struct rte_ether_hdr); 196 197 /* Do not support ipv4 option field */ 198 if (RTE_ETH_IS_IPV4_HDR(packet_type)) { 199 l3_len = sizeof(struct rte_ipv4_hdr); 200 ipv4_hdr = rte_pktmbuf_mtod_offset(mb, 201 struct rte_ipv4_hdr *, 202 l2_len); 203 l4_proto = ipv4_hdr->next_proto_id; 204 } else { 205 l3_len = sizeof(struct rte_ipv6_hdr); 206 ipv6_hdr = rte_pktmbuf_mtod_offset(mb, 207 struct rte_ipv6_hdr *, 208 l2_len); 209 l4_proto = ipv6_hdr->proto; 210 } 211 if (l4_proto == IPPROTO_UDP) { 212 udp_hdr = rte_pktmbuf_mtod_offset(mb, 213 struct rte_udp_hdr *, 214 l2_len + l3_len); 215 l4_len = sizeof(struct rte_udp_hdr); 216 vxlan_hdr = rte_pktmbuf_mtod_offset(mb, 217 struct rte_vxlan_hdr *, 218 l2_len + l3_len + l4_len); 219 udp_port = RTE_BE_TO_CPU_16(udp_hdr->dst_port); 220 vx_vni = rte_be_to_cpu_32(vxlan_hdr->vx_vni); 221 printf(" - VXLAN packet: packet type =%d, " 222 "Destination UDP port =%d, VNI = %d", 223 packet_type, udp_port, vx_vni >> 8); 224 } 225 } 226 printf(" - %s queue=0x%x", is_rx ? "Receive" : "Send", 227 (unsigned int) queue); 228 printf("\n"); 229 rte_get_rx_ol_flag_list(mb->ol_flags, buf, sizeof(buf)); 230 printf(" ol_flags: %s\n", buf); 231 if (rte_mbuf_check(mb, 1, &reason) < 0) 232 printf("INVALID mbuf: %s\n", reason); 233 } 234 } 235 236 uint16_t 237 dump_rx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], 238 uint16_t nb_pkts, __rte_unused uint16_t max_pkts, 239 __rte_unused void *user_param) 240 { 241 dump_pkt_burst(port_id, queue, pkts, nb_pkts, 1); 242 return nb_pkts; 243 } 244 245 uint16_t 246 dump_tx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], 247 uint16_t nb_pkts, __rte_unused void *user_param) 248 { 249 dump_pkt_burst(port_id, queue, pkts, nb_pkts, 0); 250 return nb_pkts; 251 } 252 253 uint16_t 254 tx_pkt_set_md(uint16_t port_id, __rte_unused uint16_t queue, 255 struct rte_mbuf *pkts[], uint16_t nb_pkts, 256 __rte_unused void *user_param) 257 { 258 uint16_t i = 0; 259 260 /* 261 * Add metadata value to every Tx packet, 262 * and set ol_flags accordingly. 263 */ 264 if (rte_flow_dynf_metadata_avail()) 265 for (i = 0; i < nb_pkts; i++) { 266 *RTE_FLOW_DYNF_METADATA(pkts[i]) = 267 ports[port_id].tx_metadata; 268 pkts[i]->ol_flags |= PKT_TX_DYNF_METADATA; 269 } 270 return nb_pkts; 271 } 272 273 void 274 add_tx_md_callback(portid_t portid) 275 { 276 struct rte_eth_dev_info dev_info; 277 uint16_t queue; 278 int ret; 279 280 if (port_id_is_invalid(portid, ENABLED_WARN)) 281 return; 282 283 ret = eth_dev_info_get_print_err(portid, &dev_info); 284 if (ret != 0) 285 return; 286 287 for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 288 if (!ports[portid].tx_set_md_cb[queue]) 289 ports[portid].tx_set_md_cb[queue] = 290 rte_eth_add_tx_callback(portid, queue, 291 tx_pkt_set_md, NULL); 292 } 293 294 void 295 remove_tx_md_callback(portid_t portid) 296 { 297 struct rte_eth_dev_info dev_info; 298 uint16_t queue; 299 int ret; 300 301 if (port_id_is_invalid(portid, ENABLED_WARN)) 302 return; 303 304 ret = eth_dev_info_get_print_err(portid, &dev_info); 305 if (ret != 0) 306 return; 307 308 for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 309 if (ports[portid].tx_set_md_cb[queue]) { 310 rte_eth_remove_tx_callback(portid, queue, 311 ports[portid].tx_set_md_cb[queue]); 312 ports[portid].tx_set_md_cb[queue] = NULL; 313 } 314 } 315 316 uint16_t 317 tx_pkt_set_dynf(uint16_t port_id, __rte_unused uint16_t queue, 318 struct rte_mbuf *pkts[], uint16_t nb_pkts, 319 __rte_unused void *user_param) 320 { 321 uint16_t i = 0; 322 323 if (ports[port_id].mbuf_dynf) 324 for (i = 0; i < nb_pkts; i++) 325 pkts[i]->ol_flags |= ports[port_id].mbuf_dynf; 326 return nb_pkts; 327 } 328 329 void 330 add_tx_dynf_callback(portid_t portid) 331 { 332 struct rte_eth_dev_info dev_info; 333 uint16_t queue; 334 int ret; 335 336 if (port_id_is_invalid(portid, ENABLED_WARN)) 337 return; 338 339 ret = eth_dev_info_get_print_err(portid, &dev_info); 340 if (ret != 0) 341 return; 342 343 for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 344 if (!ports[portid].tx_set_dynf_cb[queue]) 345 ports[portid].tx_set_dynf_cb[queue] = 346 rte_eth_add_tx_callback(portid, queue, 347 tx_pkt_set_dynf, NULL); 348 } 349 350 void 351 remove_tx_dynf_callback(portid_t portid) 352 { 353 struct rte_eth_dev_info dev_info; 354 uint16_t queue; 355 int ret; 356 357 if (port_id_is_invalid(portid, ENABLED_WARN)) 358 return; 359 360 ret = eth_dev_info_get_print_err(portid, &dev_info); 361 if (ret != 0) 362 return; 363 364 for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 365 if (ports[portid].tx_set_dynf_cb[queue]) { 366 rte_eth_remove_tx_callback(portid, queue, 367 ports[portid].tx_set_dynf_cb[queue]); 368 ports[portid].tx_set_dynf_cb[queue] = NULL; 369 } 370 } 371 372 int 373 eth_dev_info_get_print_err(uint16_t port_id, 374 struct rte_eth_dev_info *dev_info) 375 { 376 int ret; 377 378 ret = rte_eth_dev_info_get(port_id, dev_info); 379 if (ret != 0) 380 printf("Error during getting device (port %u) info: %s\n", 381 port_id, strerror(-ret)); 382 383 return ret; 384 } 385 386 void 387 eth_set_promisc_mode(uint16_t port, int enable) 388 { 389 int ret; 390 391 if (enable) 392 ret = rte_eth_promiscuous_enable(port); 393 else 394 ret = rte_eth_promiscuous_disable(port); 395 396 if (ret != 0) 397 printf("Error during %s promiscuous mode for port %u: %s\n", 398 enable ? "enabling" : "disabling", 399 port, rte_strerror(-ret)); 400 } 401 402 void 403 eth_set_allmulticast_mode(uint16_t port, int enable) 404 { 405 int ret; 406 407 if (enable) 408 ret = rte_eth_allmulticast_enable(port); 409 else 410 ret = rte_eth_allmulticast_disable(port); 411 412 if (ret != 0) 413 printf("Error during %s all-multicast mode for port %u: %s\n", 414 enable ? "enabling" : "disabling", 415 port, rte_strerror(-ret)); 416 } 417 418 int 419 eth_link_get_nowait_print_err(uint16_t port_id, struct rte_eth_link *link) 420 { 421 int ret; 422 423 ret = rte_eth_link_get_nowait(port_id, link); 424 if (ret < 0) 425 printf("Device (port %u) link get (without wait) failed: %s\n", 426 port_id, rte_strerror(-ret)); 427 428 return ret; 429 } 430 431 int 432 eth_macaddr_get_print_err(uint16_t port_id, struct rte_ether_addr *mac_addr) 433 { 434 int ret; 435 436 ret = rte_eth_macaddr_get(port_id, mac_addr); 437 if (ret != 0) 438 printf("Error getting device (port %u) mac address: %s\n", 439 port_id, rte_strerror(-ret)); 440 441 return ret; 442 } 443