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 92 if (!nb_pkts) 93 return; 94 MKDUMPSTR(print_buf, buf_size, cur_len, 95 "port %u/queue %u: %s %u packets\n", port_id, queue, 96 is_rx ? "received" : "sent", (unsigned int) nb_pkts); 97 for (i = 0; i < nb_pkts; i++) { 98 int ret; 99 struct rte_flow_error error; 100 struct rte_flow_restore_info info = { 0, }; 101 102 mb = pkts[i]; 103 eth_hdr = rte_pktmbuf_read(mb, 0, sizeof(_eth_hdr), &_eth_hdr); 104 eth_type = RTE_BE_TO_CPU_16(eth_hdr->ether_type); 105 packet_type = mb->packet_type; 106 is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type); 107 ret = rte_flow_get_restore_info(port_id, mb, &info, &error); 108 if (!ret) { 109 MKDUMPSTR(print_buf, buf_size, cur_len, 110 "restore info:"); 111 if (info.flags & RTE_FLOW_RESTORE_INFO_TUNNEL) { 112 struct port_flow_tunnel *port_tunnel; 113 114 port_tunnel = port_flow_locate_tunnel 115 (port_id, &info.tunnel); 116 MKDUMPSTR(print_buf, buf_size, cur_len, 117 " - tunnel"); 118 if (port_tunnel) 119 MKDUMPSTR(print_buf, buf_size, cur_len, 120 " #%u", port_tunnel->id); 121 else 122 MKDUMPSTR(print_buf, buf_size, cur_len, 123 " %s", "-none-"); 124 MKDUMPSTR(print_buf, buf_size, cur_len, 125 " type %s", port_flow_tunnel_type 126 (&info.tunnel)); 127 } else { 128 MKDUMPSTR(print_buf, buf_size, cur_len, 129 " - no tunnel info"); 130 } 131 if (info.flags & RTE_FLOW_RESTORE_INFO_ENCAPSULATED) 132 MKDUMPSTR(print_buf, buf_size, cur_len, 133 " - outer header present"); 134 else 135 MKDUMPSTR(print_buf, buf_size, cur_len, 136 " - no outer header"); 137 if (info.flags & RTE_FLOW_RESTORE_INFO_GROUP_ID) 138 MKDUMPSTR(print_buf, buf_size, cur_len, 139 " - miss group %u", info.group_id); 140 else 141 MKDUMPSTR(print_buf, buf_size, cur_len, 142 " - no miss group"); 143 MKDUMPSTR(print_buf, buf_size, cur_len, "\n"); 144 } 145 print_ether_addr(" src=", ð_hdr->s_addr, 146 print_buf, buf_size, &cur_len); 147 print_ether_addr(" - dst=", ð_hdr->d_addr, 148 print_buf, buf_size, &cur_len); 149 MKDUMPSTR(print_buf, buf_size, cur_len, 150 " - type=0x%04x - length=%u - nb_segs=%d", 151 eth_type, (unsigned int) mb->pkt_len, 152 (int)mb->nb_segs); 153 ol_flags = mb->ol_flags; 154 if (ol_flags & PKT_RX_RSS_HASH) { 155 MKDUMPSTR(print_buf, buf_size, cur_len, 156 " - RSS hash=0x%x", 157 (unsigned int) mb->hash.rss); 158 MKDUMPSTR(print_buf, buf_size, cur_len, 159 " - RSS queue=0x%x", (unsigned int) queue); 160 } 161 if (ol_flags & PKT_RX_FDIR) { 162 MKDUMPSTR(print_buf, buf_size, cur_len, 163 " - FDIR matched "); 164 if (ol_flags & PKT_RX_FDIR_ID) 165 MKDUMPSTR(print_buf, buf_size, cur_len, 166 "ID=0x%x", mb->hash.fdir.hi); 167 else if (ol_flags & PKT_RX_FDIR_FLX) 168 MKDUMPSTR(print_buf, buf_size, cur_len, 169 "flex bytes=0x%08x %08x", 170 mb->hash.fdir.hi, mb->hash.fdir.lo); 171 else 172 MKDUMPSTR(print_buf, buf_size, cur_len, 173 "hash=0x%x ID=0x%x ", 174 mb->hash.fdir.hash, mb->hash.fdir.id); 175 } 176 if (is_timestamp_enabled(mb)) 177 MKDUMPSTR(print_buf, buf_size, cur_len, 178 " - timestamp %"PRIu64" ", get_timestamp(mb)); 179 if (ol_flags & PKT_RX_QINQ) 180 MKDUMPSTR(print_buf, buf_size, cur_len, 181 " - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x", 182 mb->vlan_tci, mb->vlan_tci_outer); 183 else if (ol_flags & PKT_RX_VLAN) 184 MKDUMPSTR(print_buf, buf_size, cur_len, 185 " - VLAN tci=0x%x", mb->vlan_tci); 186 if (!is_rx && (ol_flags & PKT_TX_DYNF_METADATA)) 187 MKDUMPSTR(print_buf, buf_size, cur_len, 188 " - Tx metadata: 0x%x", 189 *RTE_FLOW_DYNF_METADATA(mb)); 190 if (is_rx && (ol_flags & PKT_RX_DYNF_METADATA)) 191 MKDUMPSTR(print_buf, buf_size, cur_len, 192 " - Rx metadata: 0x%x", 193 *RTE_FLOW_DYNF_METADATA(mb)); 194 for (dynf_index = 0; dynf_index < 64; dynf_index++) { 195 if (dynf_names[dynf_index][0] != '\0') 196 MKDUMPSTR(print_buf, buf_size, cur_len, 197 " - dynf %s: %d", 198 dynf_names[dynf_index], 199 !!(ol_flags & (1UL << dynf_index))); 200 } 201 if (mb->packet_type) { 202 rte_get_ptype_name(mb->packet_type, buf, sizeof(buf)); 203 MKDUMPSTR(print_buf, buf_size, cur_len, 204 " - hw ptype: %s", buf); 205 } 206 sw_packet_type = rte_net_get_ptype(mb, &hdr_lens, 207 RTE_PTYPE_ALL_MASK); 208 rte_get_ptype_name(sw_packet_type, buf, sizeof(buf)); 209 MKDUMPSTR(print_buf, buf_size, cur_len, " - sw ptype: %s", buf); 210 if (sw_packet_type & RTE_PTYPE_L2_MASK) 211 MKDUMPSTR(print_buf, buf_size, cur_len, " - l2_len=%d", 212 hdr_lens.l2_len); 213 if (sw_packet_type & RTE_PTYPE_L3_MASK) 214 MKDUMPSTR(print_buf, buf_size, cur_len, " - l3_len=%d", 215 hdr_lens.l3_len); 216 if (sw_packet_type & RTE_PTYPE_L4_MASK) 217 MKDUMPSTR(print_buf, buf_size, cur_len, " - l4_len=%d", 218 hdr_lens.l4_len); 219 if (sw_packet_type & RTE_PTYPE_TUNNEL_MASK) 220 MKDUMPSTR(print_buf, buf_size, cur_len, 221 " - tunnel_len=%d", hdr_lens.tunnel_len); 222 if (sw_packet_type & RTE_PTYPE_INNER_L2_MASK) 223 MKDUMPSTR(print_buf, buf_size, cur_len, 224 " - inner_l2_len=%d", hdr_lens.inner_l2_len); 225 if (sw_packet_type & RTE_PTYPE_INNER_L3_MASK) 226 MKDUMPSTR(print_buf, buf_size, cur_len, 227 " - inner_l3_len=%d", hdr_lens.inner_l3_len); 228 if (sw_packet_type & RTE_PTYPE_INNER_L4_MASK) 229 MKDUMPSTR(print_buf, buf_size, cur_len, 230 " - inner_l4_len=%d", hdr_lens.inner_l4_len); 231 if (is_encapsulation) { 232 struct rte_ipv4_hdr *ipv4_hdr; 233 struct rte_ipv6_hdr *ipv6_hdr; 234 struct rte_udp_hdr *udp_hdr; 235 uint8_t l2_len; 236 uint8_t l3_len; 237 uint8_t l4_len; 238 uint8_t l4_proto; 239 struct rte_vxlan_hdr *vxlan_hdr; 240 241 l2_len = sizeof(struct rte_ether_hdr); 242 243 /* Do not support ipv4 option field */ 244 if (RTE_ETH_IS_IPV4_HDR(packet_type)) { 245 l3_len = sizeof(struct rte_ipv4_hdr); 246 ipv4_hdr = rte_pktmbuf_mtod_offset(mb, 247 struct rte_ipv4_hdr *, 248 l2_len); 249 l4_proto = ipv4_hdr->next_proto_id; 250 } else { 251 l3_len = sizeof(struct rte_ipv6_hdr); 252 ipv6_hdr = rte_pktmbuf_mtod_offset(mb, 253 struct rte_ipv6_hdr *, 254 l2_len); 255 l4_proto = ipv6_hdr->proto; 256 } 257 if (l4_proto == IPPROTO_UDP) { 258 udp_hdr = rte_pktmbuf_mtod_offset(mb, 259 struct rte_udp_hdr *, 260 l2_len + l3_len); 261 l4_len = sizeof(struct rte_udp_hdr); 262 vxlan_hdr = rte_pktmbuf_mtod_offset(mb, 263 struct rte_vxlan_hdr *, 264 l2_len + l3_len + l4_len); 265 udp_port = RTE_BE_TO_CPU_16(udp_hdr->dst_port); 266 vx_vni = rte_be_to_cpu_32(vxlan_hdr->vx_vni); 267 MKDUMPSTR(print_buf, buf_size, cur_len, 268 " - VXLAN packet: packet type =%d, " 269 "Destination UDP port =%d, VNI = %d, " 270 "last_rsvd = %d", packet_type, 271 udp_port, vx_vni >> 8, vx_vni & 0xff); 272 } 273 } 274 MKDUMPSTR(print_buf, buf_size, cur_len, 275 " - %s queue=0x%x", is_rx ? "Receive" : "Send", 276 (unsigned int) queue); 277 MKDUMPSTR(print_buf, buf_size, cur_len, "\n"); 278 rte_get_rx_ol_flag_list(mb->ol_flags, buf, sizeof(buf)); 279 MKDUMPSTR(print_buf, buf_size, cur_len, 280 " ol_flags: %s\n", buf); 281 if (rte_mbuf_check(mb, 1, &reason) < 0) 282 MKDUMPSTR(print_buf, buf_size, cur_len, 283 "INVALID mbuf: %s\n", reason); 284 if (cur_len >= buf_size) 285 printf("%s ...\n", print_buf); 286 else 287 printf("%s", print_buf); 288 cur_len = 0; 289 } 290 } 291 292 uint16_t 293 dump_rx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], 294 uint16_t nb_pkts, __rte_unused uint16_t max_pkts, 295 __rte_unused void *user_param) 296 { 297 dump_pkt_burst(port_id, queue, pkts, nb_pkts, 1); 298 return nb_pkts; 299 } 300 301 uint16_t 302 dump_tx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], 303 uint16_t nb_pkts, __rte_unused void *user_param) 304 { 305 dump_pkt_burst(port_id, queue, pkts, nb_pkts, 0); 306 return nb_pkts; 307 } 308 309 uint16_t 310 tx_pkt_set_md(uint16_t port_id, __rte_unused uint16_t queue, 311 struct rte_mbuf *pkts[], uint16_t nb_pkts, 312 __rte_unused void *user_param) 313 { 314 uint16_t i = 0; 315 316 /* 317 * Add metadata value to every Tx packet, 318 * and set ol_flags accordingly. 319 */ 320 if (rte_flow_dynf_metadata_avail()) 321 for (i = 0; i < nb_pkts; i++) { 322 *RTE_FLOW_DYNF_METADATA(pkts[i]) = 323 ports[port_id].tx_metadata; 324 pkts[i]->ol_flags |= PKT_TX_DYNF_METADATA; 325 } 326 return nb_pkts; 327 } 328 329 void 330 add_tx_md_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_md_cb[queue]) 345 ports[portid].tx_set_md_cb[queue] = 346 rte_eth_add_tx_callback(portid, queue, 347 tx_pkt_set_md, NULL); 348 } 349 350 void 351 remove_tx_md_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_md_cb[queue]) { 366 rte_eth_remove_tx_callback(portid, queue, 367 ports[portid].tx_set_md_cb[queue]); 368 ports[portid].tx_set_md_cb[queue] = NULL; 369 } 370 } 371 372 uint16_t 373 tx_pkt_set_dynf(uint16_t port_id, __rte_unused uint16_t queue, 374 struct rte_mbuf *pkts[], uint16_t nb_pkts, 375 __rte_unused void *user_param) 376 { 377 uint16_t i = 0; 378 379 if (ports[port_id].mbuf_dynf) 380 for (i = 0; i < nb_pkts; i++) 381 pkts[i]->ol_flags |= ports[port_id].mbuf_dynf; 382 return nb_pkts; 383 } 384 385 void 386 add_tx_dynf_callback(portid_t portid) 387 { 388 struct rte_eth_dev_info dev_info; 389 uint16_t queue; 390 int ret; 391 392 if (port_id_is_invalid(portid, ENABLED_WARN)) 393 return; 394 395 ret = eth_dev_info_get_print_err(portid, &dev_info); 396 if (ret != 0) 397 return; 398 399 for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 400 if (!ports[portid].tx_set_dynf_cb[queue]) 401 ports[portid].tx_set_dynf_cb[queue] = 402 rte_eth_add_tx_callback(portid, queue, 403 tx_pkt_set_dynf, NULL); 404 } 405 406 void 407 remove_tx_dynf_callback(portid_t portid) 408 { 409 struct rte_eth_dev_info dev_info; 410 uint16_t queue; 411 int ret; 412 413 if (port_id_is_invalid(portid, ENABLED_WARN)) 414 return; 415 416 ret = eth_dev_info_get_print_err(portid, &dev_info); 417 if (ret != 0) 418 return; 419 420 for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 421 if (ports[portid].tx_set_dynf_cb[queue]) { 422 rte_eth_remove_tx_callback(portid, queue, 423 ports[portid].tx_set_dynf_cb[queue]); 424 ports[portid].tx_set_dynf_cb[queue] = NULL; 425 } 426 } 427 428 int 429 eth_dev_info_get_print_err(uint16_t port_id, 430 struct rte_eth_dev_info *dev_info) 431 { 432 int ret; 433 434 ret = rte_eth_dev_info_get(port_id, dev_info); 435 if (ret != 0) 436 printf("Error during getting device (port %u) info: %s\n", 437 port_id, strerror(-ret)); 438 439 return ret; 440 } 441 442 void 443 eth_set_promisc_mode(uint16_t port, int enable) 444 { 445 int ret; 446 447 if (enable) 448 ret = rte_eth_promiscuous_enable(port); 449 else 450 ret = rte_eth_promiscuous_disable(port); 451 452 if (ret != 0) 453 printf("Error during %s promiscuous mode for port %u: %s\n", 454 enable ? "enabling" : "disabling", 455 port, rte_strerror(-ret)); 456 } 457 458 void 459 eth_set_allmulticast_mode(uint16_t port, int enable) 460 { 461 int ret; 462 463 if (enable) 464 ret = rte_eth_allmulticast_enable(port); 465 else 466 ret = rte_eth_allmulticast_disable(port); 467 468 if (ret != 0) 469 printf("Error during %s all-multicast mode for port %u: %s\n", 470 enable ? "enabling" : "disabling", 471 port, rte_strerror(-ret)); 472 } 473 474 int 475 eth_link_get_nowait_print_err(uint16_t port_id, struct rte_eth_link *link) 476 { 477 int ret; 478 479 ret = rte_eth_link_get_nowait(port_id, link); 480 if (ret < 0) 481 printf("Device (port %u) link get (without wait) failed: %s\n", 482 port_id, rte_strerror(-ret)); 483 484 return ret; 485 } 486 487 int 488 eth_macaddr_get_print_err(uint16_t port_id, struct rte_ether_addr *mac_addr) 489 { 490 int ret; 491 492 ret = rte_eth_macaddr_get(port_id, mac_addr); 493 if (ret != 0) 494 printf("Error getting device (port %u) mac address: %s\n", 495 port_id, rte_strerror(-ret)); 496 497 return ret; 498 } 499