1d862c45bSRaslan Darawsheh /* SPDX-License-Identifier: BSD-3-Clause 2d862c45bSRaslan Darawsheh * Copyright(c) 2010-2014 Intel Corporation 3d862c45bSRaslan Darawsheh * Copyright(c) 2018 Mellanox Technology 4d862c45bSRaslan Darawsheh */ 5d862c45bSRaslan Darawsheh 6d862c45bSRaslan Darawsheh #include <stdio.h> 7d862c45bSRaslan Darawsheh 8d862c45bSRaslan Darawsheh #include <rte_net.h> 9d862c45bSRaslan Darawsheh #include <rte_mbuf.h> 10d862c45bSRaslan Darawsheh #include <rte_ether.h> 11512d873fSFlavia Musatescu #include <rte_vxlan.h> 12d862c45bSRaslan Darawsheh #include <rte_ethdev.h> 13d862c45bSRaslan Darawsheh #include <rte_flow.h> 14d862c45bSRaslan Darawsheh 15d862c45bSRaslan Darawsheh #include "testpmd.h" 16d862c45bSRaslan Darawsheh 17d862c45bSRaslan Darawsheh static inline void 183e6b0d5fSDavid Marchand print_ether_addr(const char *what, const struct rte_ether_addr *eth_addr) 19d862c45bSRaslan Darawsheh { 2035b2d13fSOlivier Matz char buf[RTE_ETHER_ADDR_FMT_SIZE]; 2135b2d13fSOlivier Matz rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); 22d862c45bSRaslan Darawsheh printf("%s%s", what, buf); 23d862c45bSRaslan Darawsheh } 24d862c45bSRaslan Darawsheh 25c77ad9deSRaslan Darawsheh static inline void 26d862c45bSRaslan Darawsheh dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], 27d862c45bSRaslan Darawsheh uint16_t nb_pkts, int is_rx) 28d862c45bSRaslan Darawsheh { 29d862c45bSRaslan Darawsheh struct rte_mbuf *mb; 303e6b0d5fSDavid Marchand const struct rte_ether_hdr *eth_hdr; 313e6b0d5fSDavid Marchand struct rte_ether_hdr _eth_hdr; 32d862c45bSRaslan Darawsheh uint16_t eth_type; 33d862c45bSRaslan Darawsheh uint64_t ol_flags; 34d862c45bSRaslan Darawsheh uint16_t i, packet_type; 35d862c45bSRaslan Darawsheh uint16_t is_encapsulation; 36d862c45bSRaslan Darawsheh char buf[256]; 37d862c45bSRaslan Darawsheh struct rte_net_hdr_lens hdr_lens; 38d862c45bSRaslan Darawsheh uint32_t sw_packet_type; 39d862c45bSRaslan Darawsheh uint16_t udp_port; 40d862c45bSRaslan Darawsheh uint32_t vx_vni; 41b6ec9ce9SDavid Marchand const char *reason; 42d862c45bSRaslan Darawsheh 43d862c45bSRaslan Darawsheh if (!nb_pkts) 44d862c45bSRaslan Darawsheh return; 45d862c45bSRaslan Darawsheh printf("port %u/queue %u: %s %u packets\n", 46d862c45bSRaslan Darawsheh port_id, queue, 47d862c45bSRaslan Darawsheh is_rx ? "received" : "sent", 48d862c45bSRaslan Darawsheh (unsigned int) nb_pkts); 49d862c45bSRaslan Darawsheh for (i = 0; i < nb_pkts; i++) { 50d862c45bSRaslan Darawsheh mb = pkts[i]; 513e6b0d5fSDavid Marchand eth_hdr = rte_pktmbuf_read(mb, 0, sizeof(_eth_hdr), &_eth_hdr); 52d862c45bSRaslan Darawsheh eth_type = RTE_BE_TO_CPU_16(eth_hdr->ether_type); 53d862c45bSRaslan Darawsheh ol_flags = mb->ol_flags; 54d862c45bSRaslan Darawsheh packet_type = mb->packet_type; 55d862c45bSRaslan Darawsheh is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type); 56d862c45bSRaslan Darawsheh 57d862c45bSRaslan Darawsheh print_ether_addr(" src=", ð_hdr->s_addr); 58d862c45bSRaslan Darawsheh print_ether_addr(" - dst=", ð_hdr->d_addr); 59d862c45bSRaslan Darawsheh printf(" - type=0x%04x - length=%u - nb_segs=%d", 60d862c45bSRaslan Darawsheh eth_type, (unsigned int) mb->pkt_len, 61d862c45bSRaslan Darawsheh (int)mb->nb_segs); 62d862c45bSRaslan Darawsheh if (ol_flags & PKT_RX_RSS_HASH) { 63d862c45bSRaslan Darawsheh printf(" - RSS hash=0x%x", (unsigned int) mb->hash.rss); 64d862c45bSRaslan Darawsheh printf(" - RSS queue=0x%x", (unsigned int) queue); 65d862c45bSRaslan Darawsheh } 66d862c45bSRaslan Darawsheh if (ol_flags & PKT_RX_FDIR) { 67d862c45bSRaslan Darawsheh printf(" - FDIR matched "); 68d862c45bSRaslan Darawsheh if (ol_flags & PKT_RX_FDIR_ID) 69d862c45bSRaslan Darawsheh printf("ID=0x%x", 70d862c45bSRaslan Darawsheh mb->hash.fdir.hi); 71d862c45bSRaslan Darawsheh else if (ol_flags & PKT_RX_FDIR_FLX) 72d862c45bSRaslan Darawsheh printf("flex bytes=0x%08x %08x", 73d862c45bSRaslan Darawsheh mb->hash.fdir.hi, mb->hash.fdir.lo); 74d862c45bSRaslan Darawsheh else 75d862c45bSRaslan Darawsheh printf("hash=0x%x ID=0x%x ", 76d862c45bSRaslan Darawsheh mb->hash.fdir.hash, mb->hash.fdir.id); 77d862c45bSRaslan Darawsheh } 78d862c45bSRaslan Darawsheh if (ol_flags & PKT_RX_TIMESTAMP) 79d862c45bSRaslan Darawsheh printf(" - timestamp %"PRIu64" ", mb->timestamp); 80d862c45bSRaslan Darawsheh if (ol_flags & PKT_RX_QINQ) 81d862c45bSRaslan Darawsheh printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x", 82d862c45bSRaslan Darawsheh mb->vlan_tci, mb->vlan_tci_outer); 83d862c45bSRaslan Darawsheh else if (ol_flags & PKT_RX_VLAN) 84d862c45bSRaslan Darawsheh printf(" - VLAN tci=0x%x", mb->vlan_tci); 85*d56ec3dcSDekel Peled if (!is_rx && (ol_flags & PKT_TX_DYNF_METADATA)) 869bf26e13SViacheslav Ovsiienko printf(" - Tx metadata: 0x%x", 879bf26e13SViacheslav Ovsiienko *RTE_FLOW_DYNF_METADATA(mb)); 88*d56ec3dcSDekel Peled if (is_rx && (ol_flags & PKT_RX_DYNF_METADATA)) 89e02ecc13SViacheslav Ovsiienko printf(" - Rx metadata: 0x%x", 90e02ecc13SViacheslav Ovsiienko *RTE_FLOW_DYNF_METADATA(mb)); 91d862c45bSRaslan Darawsheh if (mb->packet_type) { 92d862c45bSRaslan Darawsheh rte_get_ptype_name(mb->packet_type, buf, sizeof(buf)); 93d862c45bSRaslan Darawsheh printf(" - hw ptype: %s", buf); 94d862c45bSRaslan Darawsheh } 95d862c45bSRaslan Darawsheh sw_packet_type = rte_net_get_ptype(mb, &hdr_lens, 96d862c45bSRaslan Darawsheh RTE_PTYPE_ALL_MASK); 97d862c45bSRaslan Darawsheh rte_get_ptype_name(sw_packet_type, buf, sizeof(buf)); 98d862c45bSRaslan Darawsheh printf(" - sw ptype: %s", buf); 99d862c45bSRaslan Darawsheh if (sw_packet_type & RTE_PTYPE_L2_MASK) 100d862c45bSRaslan Darawsheh printf(" - l2_len=%d", hdr_lens.l2_len); 101d862c45bSRaslan Darawsheh if (sw_packet_type & RTE_PTYPE_L3_MASK) 102d862c45bSRaslan Darawsheh printf(" - l3_len=%d", hdr_lens.l3_len); 103d862c45bSRaslan Darawsheh if (sw_packet_type & RTE_PTYPE_L4_MASK) 104d862c45bSRaslan Darawsheh printf(" - l4_len=%d", hdr_lens.l4_len); 105d862c45bSRaslan Darawsheh if (sw_packet_type & RTE_PTYPE_TUNNEL_MASK) 106d862c45bSRaslan Darawsheh printf(" - tunnel_len=%d", hdr_lens.tunnel_len); 107d862c45bSRaslan Darawsheh if (sw_packet_type & RTE_PTYPE_INNER_L2_MASK) 108d862c45bSRaslan Darawsheh printf(" - inner_l2_len=%d", hdr_lens.inner_l2_len); 109d862c45bSRaslan Darawsheh if (sw_packet_type & RTE_PTYPE_INNER_L3_MASK) 110d862c45bSRaslan Darawsheh printf(" - inner_l3_len=%d", hdr_lens.inner_l3_len); 111d862c45bSRaslan Darawsheh if (sw_packet_type & RTE_PTYPE_INNER_L4_MASK) 112d862c45bSRaslan Darawsheh printf(" - inner_l4_len=%d", hdr_lens.inner_l4_len); 113d862c45bSRaslan Darawsheh if (is_encapsulation) { 114a7c528e5SOlivier Matz struct rte_ipv4_hdr *ipv4_hdr; 115a7c528e5SOlivier Matz struct rte_ipv6_hdr *ipv6_hdr; 116e73e3547SOlivier Matz struct rte_udp_hdr *udp_hdr; 117d862c45bSRaslan Darawsheh uint8_t l2_len; 118d862c45bSRaslan Darawsheh uint8_t l3_len; 119d862c45bSRaslan Darawsheh uint8_t l4_len; 120d862c45bSRaslan Darawsheh uint8_t l4_proto; 1216d13ea8eSOlivier Matz struct rte_vxlan_hdr *vxlan_hdr; 122d862c45bSRaslan Darawsheh 1236d13ea8eSOlivier Matz l2_len = sizeof(struct rte_ether_hdr); 124d862c45bSRaslan Darawsheh 125d862c45bSRaslan Darawsheh /* Do not support ipv4 option field */ 126d862c45bSRaslan Darawsheh if (RTE_ETH_IS_IPV4_HDR(packet_type)) { 127a7c528e5SOlivier Matz l3_len = sizeof(struct rte_ipv4_hdr); 128d862c45bSRaslan Darawsheh ipv4_hdr = rte_pktmbuf_mtod_offset(mb, 129a7c528e5SOlivier Matz struct rte_ipv4_hdr *, 130d862c45bSRaslan Darawsheh l2_len); 131d862c45bSRaslan Darawsheh l4_proto = ipv4_hdr->next_proto_id; 132d862c45bSRaslan Darawsheh } else { 133a7c528e5SOlivier Matz l3_len = sizeof(struct rte_ipv6_hdr); 134d862c45bSRaslan Darawsheh ipv6_hdr = rte_pktmbuf_mtod_offset(mb, 135a7c528e5SOlivier Matz struct rte_ipv6_hdr *, 136d862c45bSRaslan Darawsheh l2_len); 137d862c45bSRaslan Darawsheh l4_proto = ipv6_hdr->proto; 138d862c45bSRaslan Darawsheh } 139d862c45bSRaslan Darawsheh if (l4_proto == IPPROTO_UDP) { 140d862c45bSRaslan Darawsheh udp_hdr = rte_pktmbuf_mtod_offset(mb, 141e73e3547SOlivier Matz struct rte_udp_hdr *, 142d862c45bSRaslan Darawsheh l2_len + l3_len); 143e73e3547SOlivier Matz l4_len = sizeof(struct rte_udp_hdr); 144d862c45bSRaslan Darawsheh vxlan_hdr = rte_pktmbuf_mtod_offset(mb, 1456d13ea8eSOlivier Matz struct rte_vxlan_hdr *, 146d862c45bSRaslan Darawsheh l2_len + l3_len + l4_len); 147d862c45bSRaslan Darawsheh udp_port = RTE_BE_TO_CPU_16(udp_hdr->dst_port); 148d862c45bSRaslan Darawsheh vx_vni = rte_be_to_cpu_32(vxlan_hdr->vx_vni); 149d862c45bSRaslan Darawsheh printf(" - VXLAN packet: packet type =%d, " 150d862c45bSRaslan Darawsheh "Destination UDP port =%d, VNI = %d", 151d862c45bSRaslan Darawsheh packet_type, udp_port, vx_vni >> 8); 152d862c45bSRaslan Darawsheh } 153d862c45bSRaslan Darawsheh } 154d862c45bSRaslan Darawsheh printf(" - %s queue=0x%x", is_rx ? "Receive" : "Send", 155d862c45bSRaslan Darawsheh (unsigned int) queue); 156d862c45bSRaslan Darawsheh printf("\n"); 157d862c45bSRaslan Darawsheh rte_get_rx_ol_flag_list(mb->ol_flags, buf, sizeof(buf)); 158d862c45bSRaslan Darawsheh printf(" ol_flags: %s\n", buf); 159b6ec9ce9SDavid Marchand if (rte_mbuf_check(mb, 1, &reason) < 0) 160b6ec9ce9SDavid Marchand printf("INVALID mbuf: %s\n", reason); 161d862c45bSRaslan Darawsheh } 162d862c45bSRaslan Darawsheh } 163c77ad9deSRaslan Darawsheh 164c77ad9deSRaslan Darawsheh uint16_t 165c77ad9deSRaslan Darawsheh dump_rx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], 166c77ad9deSRaslan Darawsheh uint16_t nb_pkts, __rte_unused uint16_t max_pkts, 167c77ad9deSRaslan Darawsheh __rte_unused void *user_param) 168c77ad9deSRaslan Darawsheh { 169c77ad9deSRaslan Darawsheh dump_pkt_burst(port_id, queue, pkts, nb_pkts, 1); 170c77ad9deSRaslan Darawsheh return nb_pkts; 171c77ad9deSRaslan Darawsheh } 172c77ad9deSRaslan Darawsheh 173c77ad9deSRaslan Darawsheh uint16_t 174c77ad9deSRaslan Darawsheh dump_tx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], 175c77ad9deSRaslan Darawsheh uint16_t nb_pkts, __rte_unused void *user_param) 176c77ad9deSRaslan Darawsheh { 177c77ad9deSRaslan Darawsheh dump_pkt_burst(port_id, queue, pkts, nb_pkts, 0); 178c77ad9deSRaslan Darawsheh return nb_pkts; 179c77ad9deSRaslan Darawsheh } 1801e45c908SDekel Peled 1811e45c908SDekel Peled uint16_t 1821e45c908SDekel Peled tx_pkt_set_md(uint16_t port_id, __rte_unused uint16_t queue, 1831e45c908SDekel Peled struct rte_mbuf *pkts[], uint16_t nb_pkts, 1841e45c908SDekel Peled __rte_unused void *user_param) 1851e45c908SDekel Peled { 1861e45c908SDekel Peled uint16_t i = 0; 1871e45c908SDekel Peled 1881e45c908SDekel Peled /* 1891e45c908SDekel Peled * Add metadata value to every Tx packet, 1901e45c908SDekel Peled * and set ol_flags accordingly. 1911e45c908SDekel Peled */ 1929bf26e13SViacheslav Ovsiienko if (rte_flow_dynf_metadata_avail()) 1931e45c908SDekel Peled for (i = 0; i < nb_pkts; i++) { 1949bf26e13SViacheslav Ovsiienko *RTE_FLOW_DYNF_METADATA(pkts[i]) = 1959bf26e13SViacheslav Ovsiienko ports[port_id].tx_metadata; 1969bf26e13SViacheslav Ovsiienko pkts[i]->ol_flags |= PKT_TX_DYNF_METADATA; 1971e45c908SDekel Peled } 1981e45c908SDekel Peled return nb_pkts; 1991e45c908SDekel Peled } 2001e45c908SDekel Peled 2011e45c908SDekel Peled void 2021e45c908SDekel Peled add_tx_md_callback(portid_t portid) 2031e45c908SDekel Peled { 2041e45c908SDekel Peled struct rte_eth_dev_info dev_info; 2051e45c908SDekel Peled uint16_t queue; 2066f51deb9SIvan Ilchenko int ret; 2071e45c908SDekel Peled 2081e45c908SDekel Peled if (port_id_is_invalid(portid, ENABLED_WARN)) 2091e45c908SDekel Peled return; 2106f51deb9SIvan Ilchenko 2116f51deb9SIvan Ilchenko ret = eth_dev_info_get_print_err(portid, &dev_info); 2126f51deb9SIvan Ilchenko if (ret != 0) 2136f51deb9SIvan Ilchenko return; 2146f51deb9SIvan Ilchenko 2151e45c908SDekel Peled for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 2161e45c908SDekel Peled if (!ports[portid].tx_set_md_cb[queue]) 2171e45c908SDekel Peled ports[portid].tx_set_md_cb[queue] = 2181e45c908SDekel Peled rte_eth_add_tx_callback(portid, queue, 2191e45c908SDekel Peled tx_pkt_set_md, NULL); 2201e45c908SDekel Peled } 2211e45c908SDekel Peled 2221e45c908SDekel Peled void 2231e45c908SDekel Peled remove_tx_md_callback(portid_t portid) 2241e45c908SDekel Peled { 2251e45c908SDekel Peled struct rte_eth_dev_info dev_info; 2261e45c908SDekel Peled uint16_t queue; 2276f51deb9SIvan Ilchenko int ret; 2281e45c908SDekel Peled 2291e45c908SDekel Peled if (port_id_is_invalid(portid, ENABLED_WARN)) 2301e45c908SDekel Peled return; 2316f51deb9SIvan Ilchenko 2326f51deb9SIvan Ilchenko ret = eth_dev_info_get_print_err(portid, &dev_info); 2336f51deb9SIvan Ilchenko if (ret != 0) 2346f51deb9SIvan Ilchenko return; 2356f51deb9SIvan Ilchenko 2361e45c908SDekel Peled for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 2371e45c908SDekel Peled if (ports[portid].tx_set_md_cb[queue]) { 2381e45c908SDekel Peled rte_eth_remove_tx_callback(portid, queue, 2391e45c908SDekel Peled ports[portid].tx_set_md_cb[queue]); 2401e45c908SDekel Peled ports[portid].tx_set_md_cb[queue] = NULL; 2411e45c908SDekel Peled } 2421e45c908SDekel Peled } 2436f51deb9SIvan Ilchenko 2446f51deb9SIvan Ilchenko int 2456f51deb9SIvan Ilchenko eth_dev_info_get_print_err(uint16_t port_id, 2466f51deb9SIvan Ilchenko struct rte_eth_dev_info *dev_info) 2476f51deb9SIvan Ilchenko { 2486f51deb9SIvan Ilchenko int ret; 2496f51deb9SIvan Ilchenko 2506f51deb9SIvan Ilchenko ret = rte_eth_dev_info_get(port_id, dev_info); 2516f51deb9SIvan Ilchenko if (ret != 0) 2526f51deb9SIvan Ilchenko printf("Error during getting device (port %u) info: %s\n", 2536f51deb9SIvan Ilchenko port_id, strerror(-ret)); 2546f51deb9SIvan Ilchenko 2556f51deb9SIvan Ilchenko return ret; 2566f51deb9SIvan Ilchenko } 25734fc1051SIvan Ilchenko 25834fc1051SIvan Ilchenko void 25934fc1051SIvan Ilchenko eth_set_promisc_mode(uint16_t port, int enable) 26034fc1051SIvan Ilchenko { 26134fc1051SIvan Ilchenko int ret; 26234fc1051SIvan Ilchenko 26334fc1051SIvan Ilchenko if (enable) 26434fc1051SIvan Ilchenko ret = rte_eth_promiscuous_enable(port); 26534fc1051SIvan Ilchenko else 26634fc1051SIvan Ilchenko ret = rte_eth_promiscuous_disable(port); 26734fc1051SIvan Ilchenko 26834fc1051SIvan Ilchenko if (ret != 0) 26934fc1051SIvan Ilchenko printf("Error during %s promiscuous mode for port %u: %s\n", 27034fc1051SIvan Ilchenko enable ? "enabling" : "disabling", 27134fc1051SIvan Ilchenko port, rte_strerror(-ret)); 27234fc1051SIvan Ilchenko } 273e661a08bSIgor Romanov 2748835806dSIvan Ilchenko void 2758835806dSIvan Ilchenko eth_set_allmulticast_mode(uint16_t port, int enable) 2768835806dSIvan Ilchenko { 2778835806dSIvan Ilchenko int ret; 2788835806dSIvan Ilchenko 2798835806dSIvan Ilchenko if (enable) 2808835806dSIvan Ilchenko ret = rte_eth_allmulticast_enable(port); 2818835806dSIvan Ilchenko else 2828835806dSIvan Ilchenko ret = rte_eth_allmulticast_disable(port); 2838835806dSIvan Ilchenko 2848835806dSIvan Ilchenko if (ret != 0) 2858835806dSIvan Ilchenko printf("Error during %s all-multicast mode for port %u: %s\n", 2868835806dSIvan Ilchenko enable ? "enabling" : "disabling", 2878835806dSIvan Ilchenko port, rte_strerror(-ret)); 2888835806dSIvan Ilchenko } 2898835806dSIvan Ilchenko 290e661a08bSIgor Romanov int 291e661a08bSIgor Romanov eth_link_get_nowait_print_err(uint16_t port_id, struct rte_eth_link *link) 292e661a08bSIgor Romanov { 293e661a08bSIgor Romanov int ret; 294e661a08bSIgor Romanov 295e661a08bSIgor Romanov ret = rte_eth_link_get_nowait(port_id, link); 296e661a08bSIgor Romanov if (ret < 0) 297e661a08bSIgor Romanov printf("Device (port %u) link get (without wait) failed: %s\n", 298e661a08bSIgor Romanov port_id, rte_strerror(-ret)); 299e661a08bSIgor Romanov 300e661a08bSIgor Romanov return ret; 301e661a08bSIgor Romanov } 302a5279d25SIgor Romanov 303a5279d25SIgor Romanov int 304a5279d25SIgor Romanov eth_macaddr_get_print_err(uint16_t port_id, struct rte_ether_addr *mac_addr) 305a5279d25SIgor Romanov { 306a5279d25SIgor Romanov int ret; 307a5279d25SIgor Romanov 308a5279d25SIgor Romanov ret = rte_eth_macaddr_get(port_id, mac_addr); 309a5279d25SIgor Romanov if (ret != 0) 310a5279d25SIgor Romanov printf("Error getting device (port %u) mac address: %s\n", 311a5279d25SIgor Romanov port_id, rte_strerror(-ret)); 312a5279d25SIgor Romanov 313a5279d25SIgor Romanov return ret; 314a5279d25SIgor Romanov } 315