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