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