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, struct ether_addr *eth_addr) 18 { 19 char buf[ETHER_ADDR_FMT_SIZE]; 20 ether_format_addr(buf, 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 struct ether_hdr *eth_hdr; 30 uint16_t eth_type; 31 uint64_t ol_flags; 32 uint16_t i, packet_type; 33 uint16_t is_encapsulation; 34 char buf[256]; 35 struct rte_net_hdr_lens hdr_lens; 36 uint32_t sw_packet_type; 37 uint16_t udp_port; 38 uint32_t vx_vni; 39 const char *reason; 40 41 if (!nb_pkts) 42 return; 43 printf("port %u/queue %u: %s %u packets\n", 44 port_id, queue, 45 is_rx ? "received" : "sent", 46 (unsigned int) nb_pkts); 47 for (i = 0; i < nb_pkts; i++) { 48 mb = pkts[i]; 49 eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *); 50 eth_type = RTE_BE_TO_CPU_16(eth_hdr->ether_type); 51 ol_flags = mb->ol_flags; 52 packet_type = mb->packet_type; 53 is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type); 54 55 print_ether_addr(" src=", ð_hdr->s_addr); 56 print_ether_addr(" - dst=", ð_hdr->d_addr); 57 printf(" - type=0x%04x - length=%u - nb_segs=%d", 58 eth_type, (unsigned int) mb->pkt_len, 59 (int)mb->nb_segs); 60 if (ol_flags & PKT_RX_RSS_HASH) { 61 printf(" - RSS hash=0x%x", (unsigned int) mb->hash.rss); 62 printf(" - RSS queue=0x%x", (unsigned int) queue); 63 } 64 if (ol_flags & PKT_RX_FDIR) { 65 printf(" - FDIR matched "); 66 if (ol_flags & PKT_RX_FDIR_ID) 67 printf("ID=0x%x", 68 mb->hash.fdir.hi); 69 else if (ol_flags & PKT_RX_FDIR_FLX) 70 printf("flex bytes=0x%08x %08x", 71 mb->hash.fdir.hi, mb->hash.fdir.lo); 72 else 73 printf("hash=0x%x ID=0x%x ", 74 mb->hash.fdir.hash, mb->hash.fdir.id); 75 } 76 if (ol_flags & PKT_RX_TIMESTAMP) 77 printf(" - timestamp %"PRIu64" ", mb->timestamp); 78 if (ol_flags & PKT_RX_QINQ) 79 printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x", 80 mb->vlan_tci, mb->vlan_tci_outer); 81 else if (ol_flags & PKT_RX_VLAN) 82 printf(" - VLAN tci=0x%x", mb->vlan_tci); 83 if (mb->packet_type) { 84 rte_get_ptype_name(mb->packet_type, buf, sizeof(buf)); 85 printf(" - hw ptype: %s", buf); 86 } 87 sw_packet_type = rte_net_get_ptype(mb, &hdr_lens, 88 RTE_PTYPE_ALL_MASK); 89 rte_get_ptype_name(sw_packet_type, buf, sizeof(buf)); 90 printf(" - sw ptype: %s", buf); 91 if (sw_packet_type & RTE_PTYPE_L2_MASK) 92 printf(" - l2_len=%d", hdr_lens.l2_len); 93 if (sw_packet_type & RTE_PTYPE_L3_MASK) 94 printf(" - l3_len=%d", hdr_lens.l3_len); 95 if (sw_packet_type & RTE_PTYPE_L4_MASK) 96 printf(" - l4_len=%d", hdr_lens.l4_len); 97 if (sw_packet_type & RTE_PTYPE_TUNNEL_MASK) 98 printf(" - tunnel_len=%d", hdr_lens.tunnel_len); 99 if (sw_packet_type & RTE_PTYPE_INNER_L2_MASK) 100 printf(" - inner_l2_len=%d", hdr_lens.inner_l2_len); 101 if (sw_packet_type & RTE_PTYPE_INNER_L3_MASK) 102 printf(" - inner_l3_len=%d", hdr_lens.inner_l3_len); 103 if (sw_packet_type & RTE_PTYPE_INNER_L4_MASK) 104 printf(" - inner_l4_len=%d", hdr_lens.inner_l4_len); 105 if (is_encapsulation) { 106 struct ipv4_hdr *ipv4_hdr; 107 struct ipv6_hdr *ipv6_hdr; 108 struct udp_hdr *udp_hdr; 109 uint8_t l2_len; 110 uint8_t l3_len; 111 uint8_t l4_len; 112 uint8_t l4_proto; 113 struct vxlan_hdr *vxlan_hdr; 114 115 l2_len = sizeof(struct ether_hdr); 116 117 /* Do not support ipv4 option field */ 118 if (RTE_ETH_IS_IPV4_HDR(packet_type)) { 119 l3_len = sizeof(struct ipv4_hdr); 120 ipv4_hdr = rte_pktmbuf_mtod_offset(mb, 121 struct ipv4_hdr *, 122 l2_len); 123 l4_proto = ipv4_hdr->next_proto_id; 124 } else { 125 l3_len = sizeof(struct ipv6_hdr); 126 ipv6_hdr = rte_pktmbuf_mtod_offset(mb, 127 struct ipv6_hdr *, 128 l2_len); 129 l4_proto = ipv6_hdr->proto; 130 } 131 if (l4_proto == IPPROTO_UDP) { 132 udp_hdr = rte_pktmbuf_mtod_offset(mb, 133 struct udp_hdr *, 134 l2_len + l3_len); 135 l4_len = sizeof(struct udp_hdr); 136 vxlan_hdr = rte_pktmbuf_mtod_offset(mb, 137 struct vxlan_hdr *, 138 l2_len + l3_len + l4_len); 139 udp_port = RTE_BE_TO_CPU_16(udp_hdr->dst_port); 140 vx_vni = rte_be_to_cpu_32(vxlan_hdr->vx_vni); 141 printf(" - VXLAN packet: packet type =%d, " 142 "Destination UDP port =%d, VNI = %d", 143 packet_type, udp_port, vx_vni >> 8); 144 } 145 } 146 printf(" - %s queue=0x%x", is_rx ? "Receive" : "Send", 147 (unsigned int) queue); 148 printf("\n"); 149 rte_get_rx_ol_flag_list(mb->ol_flags, buf, sizeof(buf)); 150 printf(" ol_flags: %s\n", buf); 151 if (rte_mbuf_check(mb, 1, &reason) < 0) 152 printf("INVALID mbuf: %s\n", reason); 153 } 154 } 155 156 uint16_t 157 dump_rx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], 158 uint16_t nb_pkts, __rte_unused uint16_t max_pkts, 159 __rte_unused void *user_param) 160 { 161 dump_pkt_burst(port_id, queue, pkts, nb_pkts, 1); 162 return nb_pkts; 163 } 164 165 uint16_t 166 dump_tx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], 167 uint16_t nb_pkts, __rte_unused void *user_param) 168 { 169 dump_pkt_burst(port_id, queue, pkts, nb_pkts, 0); 170 return nb_pkts; 171 } 172 173 uint16_t 174 tx_pkt_set_md(uint16_t port_id, __rte_unused uint16_t queue, 175 struct rte_mbuf *pkts[], uint16_t nb_pkts, 176 __rte_unused void *user_param) 177 { 178 uint16_t i = 0; 179 180 /* 181 * Add metadata value to every Tx packet, 182 * and set ol_flags accordingly. 183 */ 184 for (i = 0; i < nb_pkts; i++) { 185 pkts[i]->tx_metadata = ports[port_id].tx_metadata; 186 pkts[i]->ol_flags |= PKT_TX_METADATA; 187 } 188 return nb_pkts; 189 } 190 191 void 192 add_tx_md_callback(portid_t portid) 193 { 194 struct rte_eth_dev_info dev_info; 195 uint16_t queue; 196 197 if (port_id_is_invalid(portid, ENABLED_WARN)) 198 return; 199 rte_eth_dev_info_get(portid, &dev_info); 200 for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 201 if (!ports[portid].tx_set_md_cb[queue]) 202 ports[portid].tx_set_md_cb[queue] = 203 rte_eth_add_tx_callback(portid, queue, 204 tx_pkt_set_md, NULL); 205 } 206 207 void 208 remove_tx_md_callback(portid_t portid) 209 { 210 struct rte_eth_dev_info dev_info; 211 uint16_t queue; 212 213 if (port_id_is_invalid(portid, ENABLED_WARN)) 214 return; 215 rte_eth_dev_info_get(portid, &dev_info); 216 for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 217 if (ports[portid].tx_set_md_cb[queue]) { 218 rte_eth_remove_tx_callback(portid, queue, 219 ports[portid].tx_set_md_cb[queue]); 220 ports[portid].tx_set_md_cb[queue] = NULL; 221 } 222 } 223