LCOV - code coverage report
Current view: top level - app/test-pmd - icmpecho.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 121 0.0 %
Date: 2025-03-01 20:23:48 Functions: 0 4 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2013 6WIND S.A.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdarg.h>
       6                 :            : #include <string.h>
       7                 :            : #include <stdio.h>
       8                 :            : #include <errno.h>
       9                 :            : #include <stdint.h>
      10                 :            : #include <unistd.h>
      11                 :            : #include <inttypes.h>
      12                 :            : 
      13                 :            : #include <sys/queue.h>
      14                 :            : #include <sys/stat.h>
      15                 :            : 
      16                 :            : #include <rte_common.h>
      17                 :            : #include <rte_byteorder.h>
      18                 :            : #include <rte_log.h>
      19                 :            : #include <rte_debug.h>
      20                 :            : #include <rte_cycles.h>
      21                 :            : #include <rte_per_lcore.h>
      22                 :            : #include <rte_lcore.h>
      23                 :            : #include <rte_branch_prediction.h>
      24                 :            : #include <rte_memory.h>
      25                 :            : #include <rte_mempool.h>
      26                 :            : #include <rte_mbuf.h>
      27                 :            : #include <rte_ether.h>
      28                 :            : #include <rte_ethdev.h>
      29                 :            : #include <rte_arp.h>
      30                 :            : #include <rte_ip.h>
      31                 :            : #include <rte_icmp.h>
      32                 :            : #include <rte_string_fns.h>
      33                 :            : #include <rte_flow.h>
      34                 :            : 
      35                 :            : #include "testpmd.h"
      36                 :            : 
      37                 :            : static const char *
      38                 :            : arp_op_name(uint16_t arp_op)
      39                 :            : {
      40                 :          0 :         switch (arp_op) {
      41                 :            :         case RTE_ARP_OP_REQUEST:
      42                 :            :                 return "ARP Request";
      43                 :          0 :         case RTE_ARP_OP_REPLY:
      44                 :          0 :                 return "ARP Reply";
      45                 :          0 :         case RTE_ARP_OP_REVREQUEST:
      46                 :          0 :                 return "Reverse ARP Request";
      47                 :          0 :         case RTE_ARP_OP_REVREPLY:
      48                 :          0 :                 return "Reverse ARP Reply";
      49                 :          0 :         case RTE_ARP_OP_INVREQUEST:
      50                 :          0 :                 return "Peer Identify Request";
      51                 :          0 :         case RTE_ARP_OP_INVREPLY:
      52                 :          0 :                 return "Peer Identify Reply";
      53                 :            :         default:
      54                 :            :                 break;
      55                 :            :         }
      56                 :          0 :         return "Unknown ARP op";
      57                 :            : }
      58                 :            : 
      59                 :            : static const char *
      60                 :            : ip_proto_name(uint16_t ip_proto)
      61                 :            : {
      62                 :            :         static const char * ip_proto_names[] = {
      63                 :            :                 "IP6HOPOPTS", /**< IP6 hop-by-hop options */
      64                 :            :                 "ICMP",       /**< control message protocol */
      65                 :            :                 "IGMP",       /**< group mgmt protocol */
      66                 :            :                 "GGP",        /**< gateway^2 (deprecated) */
      67                 :            :                 "IPv4",       /**< IPv4 encapsulation */
      68                 :            : 
      69                 :            :                 "UNASSIGNED",
      70                 :            :                 "TCP",        /**< transport control protocol */
      71                 :            :                 "ST",         /**< Stream protocol II */
      72                 :            :                 "EGP",        /**< exterior gateway protocol */
      73                 :            :                 "PIGP",       /**< private interior gateway */
      74                 :            : 
      75                 :            :                 "RCC_MON",    /**< BBN RCC Monitoring */
      76                 :            :                 "NVPII",      /**< network voice protocol*/
      77                 :            :                 "PUP",        /**< pup */
      78                 :            :                 "ARGUS",      /**< Argus */
      79                 :            :                 "EMCON",      /**< EMCON */
      80                 :            : 
      81                 :            :                 "XNET",       /**< Cross Net Debugger */
      82                 :            :                 "CHAOS",      /**< Chaos*/
      83                 :            :                 "UDP",        /**< user datagram protocol */
      84                 :            :                 "MUX",        /**< Multiplexing */
      85                 :            :                 "DCN_MEAS",   /**< DCN Measurement Subsystems */
      86                 :            : 
      87                 :            :                 "HMP",        /**< Host Monitoring */
      88                 :            :                 "PRM",        /**< Packet Radio Measurement */
      89                 :            :                 "XNS_IDP",    /**< xns idp */
      90                 :            :                 "TRUNK1",     /**< Trunk-1 */
      91                 :            :                 "TRUNK2",     /**< Trunk-2 */
      92                 :            : 
      93                 :            :                 "LEAF1",      /**< Leaf-1 */
      94                 :            :                 "LEAF2",      /**< Leaf-2 */
      95                 :            :                 "RDP",        /**< Reliable Data */
      96                 :            :                 "IRTP",       /**< Reliable Transaction */
      97                 :            :                 "TP4",        /**< tp-4 w/ class negotiation */
      98                 :            : 
      99                 :            :                 "BLT",        /**< Bulk Data Transfer */
     100                 :            :                 "NSP",        /**< Network Services */
     101                 :            :                 "INP",        /**< Merit Internodal */
     102                 :            :                 "SEP",        /**< Sequential Exchange */
     103                 :            :                 "3PC",        /**< Third Party Connect */
     104                 :            : 
     105                 :            :                 "IDPR",       /**< InterDomain Policy Routing */
     106                 :            :                 "XTP",        /**< XTP */
     107                 :            :                 "DDP",        /**< Datagram Delivery */
     108                 :            :                 "CMTP",       /**< Control Message Transport */
     109                 :            :                 "TPXX",       /**< TP++ Transport */
     110                 :            : 
     111                 :            :                 "ILTP",       /**< IL transport protocol */
     112                 :            :                 "IPv6_HDR",   /**< IP6 header */
     113                 :            :                 "SDRP",       /**< Source Demand Routing */
     114                 :            :                 "IPv6_RTG",   /**< IP6 routing header */
     115                 :            :                 "IPv6_FRAG",  /**< IP6 fragmentation header */
     116                 :            : 
     117                 :            :                 "IDRP",       /**< InterDomain Routing*/
     118                 :            :                 "RSVP",       /**< resource reservation */
     119                 :            :                 "GRE",        /**< General Routing Encap. */
     120                 :            :                 "MHRP",       /**< Mobile Host Routing */
     121                 :            :                 "BHA",        /**< BHA */
     122                 :            : 
     123                 :            :                 "ESP",        /**< IP6 Encap Sec. Payload */
     124                 :            :                 "AH",         /**< IP6 Auth Header */
     125                 :            :                 "INLSP",      /**< Integ. Net Layer Security */
     126                 :            :                 "SWIPE",      /**< IP with encryption */
     127                 :            :                 "NHRP",       /**< Next Hop Resolution */
     128                 :            : 
     129                 :            :                 "UNASSIGNED",
     130                 :            :                 "UNASSIGNED",
     131                 :            :                 "UNASSIGNED",
     132                 :            :                 "ICMPv6",     /**< ICMP6 */
     133                 :            :                 "IPv6NONEXT", /**< IP6 no next header */
     134                 :            : 
     135                 :            :                 "Ipv6DSTOPTS",/**< IP6 destination option */
     136                 :            :                 "AHIP",       /**< any host internal protocol */
     137                 :            :                 "CFTP",       /**< CFTP */
     138                 :            :                 "HELLO",      /**< "hello" routing protocol */
     139                 :            :                 "SATEXPAK",   /**< SATNET/Backroom EXPAK */
     140                 :            : 
     141                 :            :                 "KRYPTOLAN",  /**< Kryptolan */
     142                 :            :                 "RVD",        /**< Remote Virtual Disk */
     143                 :            :                 "IPPC",       /**< Pluribus Packet Core */
     144                 :            :                 "ADFS",       /**< Any distributed FS */
     145                 :            :                 "SATMON",     /**< Satnet Monitoring */
     146                 :            : 
     147                 :            :                 "VISA",       /**< VISA Protocol */
     148                 :            :                 "IPCV",       /**< Packet Core Utility */
     149                 :            :                 "CPNX",       /**< Comp. Prot. Net. Executive */
     150                 :            :                 "CPHB",       /**< Comp. Prot. HeartBeat */
     151                 :            :                 "WSN",        /**< Wang Span Network */
     152                 :            : 
     153                 :            :                 "PVP",        /**< Packet Video Protocol */
     154                 :            :                 "BRSATMON",   /**< BackRoom SATNET Monitoring */
     155                 :            :                 "ND",         /**< Sun net disk proto (temp.) */
     156                 :            :                 "WBMON",      /**< WIDEBAND Monitoring */
     157                 :            :                 "WBEXPAK",    /**< WIDEBAND EXPAK */
     158                 :            : 
     159                 :            :                 "EON",        /**< ISO cnlp */
     160                 :            :                 "VMTP",       /**< VMTP */
     161                 :            :                 "SVMTP",      /**< Secure VMTP */
     162                 :            :                 "VINES",      /**< Banyon VINES */
     163                 :            :                 "TTP",        /**< TTP */
     164                 :            : 
     165                 :            :                 "IGP",        /**< NSFNET-IGP */
     166                 :            :                 "DGP",        /**< dissimilar gateway prot. */
     167                 :            :                 "TCF",        /**< TCF */
     168                 :            :                 "IGRP",       /**< Cisco/GXS IGRP */
     169                 :            :                 "OSPFIGP",    /**< OSPFIGP */
     170                 :            : 
     171                 :            :                 "SRPC",       /**< Strite RPC protocol */
     172                 :            :                 "LARP",       /**< Locus Address Resolution */
     173                 :            :                 "MTP",        /**< Multicast Transport */
     174                 :            :                 "AX25",       /**< AX.25 Frames */
     175                 :            :                 "4IN4",       /**< IP encapsulated in IP */
     176                 :            : 
     177                 :            :                 "MICP",       /**< Mobile Int.ing control */
     178                 :            :                 "SCCSP",      /**< Semaphore Comm. security */
     179                 :            :                 "ETHERIP",    /**< Ethernet IP encapsulation */
     180                 :            :                 "ENCAP",      /**< encapsulation header */
     181                 :            :                 "AES",        /**< any private encr. scheme */
     182                 :            : 
     183                 :            :                 "GMTP",       /**< GMTP */
     184                 :            :                 "IPCOMP",     /**< payload compression (IPComp) */
     185                 :            :                 "UNASSIGNED",
     186                 :            :                 "UNASSIGNED",
     187                 :            :                 "PIM",        /**< Protocol Independent Mcast */
     188                 :            :         };
     189                 :            : 
     190                 :          0 :         if (ip_proto < RTE_DIM(ip_proto_names))
     191                 :          0 :                 return ip_proto_names[ip_proto];
     192                 :          0 :         switch (ip_proto) {
     193                 :            : #ifdef IPPROTO_PGM
     194                 :            :         case IPPROTO_PGM:  /**< PGM */
     195                 :            :                 return "PGM";
     196                 :            : #endif
     197                 :            :         case IPPROTO_SCTP:  /**< Stream Control Transport Protocol */
     198                 :            :                 return "SCTP";
     199                 :            : #ifdef IPPROTO_DIVERT
     200                 :            :         case IPPROTO_DIVERT: /**< divert pseudo-protocol */
     201                 :            :                 return "DIVERT";
     202                 :            : #endif
     203                 :          0 :         case IPPROTO_RAW: /**< raw IP packet */
     204                 :          0 :                 return "RAW";
     205                 :            :         default:
     206                 :            :                 break;
     207                 :            :         }
     208                 :          0 :         return "UNASSIGNED";
     209                 :            : }
     210                 :            : 
     211                 :            : static void
     212                 :          0 : ipv4_addr_to_dot(uint32_t be_ipv4_addr, char *buf)
     213                 :            : {
     214                 :            :         uint32_t ipv4_addr;
     215                 :            : 
     216                 :          0 :         ipv4_addr = rte_be_to_cpu_32(be_ipv4_addr);
     217                 :          0 :         sprintf(buf, "%d.%d.%d.%d", (ipv4_addr >> 24) & 0xFF,
     218                 :          0 :                 (ipv4_addr >> 16) & 0xFF, (ipv4_addr >> 8) & 0xFF,
     219                 :            :                 ipv4_addr & 0xFF);
     220                 :          0 : }
     221                 :            : 
     222                 :            : static void
     223                 :          0 : ether_addr_dump(const char *what, const struct rte_ether_addr *ea)
     224                 :            : {
     225                 :            :         char buf[RTE_ETHER_ADDR_FMT_SIZE];
     226                 :            : 
     227                 :          0 :         rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, ea);
     228                 :          0 :         if (what)
     229                 :            :                 printf("%s", what);
     230                 :            :         printf("%s", buf);
     231                 :          0 : }
     232                 :            : 
     233                 :            : static void
     234                 :          0 : ipv4_addr_dump(const char *what, uint32_t be_ipv4_addr)
     235                 :            : {
     236                 :            :         char buf[16];
     237                 :            : 
     238                 :          0 :         ipv4_addr_to_dot(be_ipv4_addr, buf);
     239                 :          0 :         if (what)
     240                 :            :                 printf("%s", what);
     241                 :            :         printf("%s", buf);
     242                 :          0 : }
     243                 :            : 
     244                 :            : #define is_multicast_ipv4_addr(ipv4_addr) \
     245                 :            :         (((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)
     246                 :            : 
     247                 :            : /*
     248                 :            :  * Receive a burst of packets, lookup for ICMP echo requests, and, if any,
     249                 :            :  * send back ICMP echo replies.
     250                 :            :  */
     251                 :            : static bool
     252                 :          0 : reply_to_icmp_echo_rqsts(struct fwd_stream *fs)
     253                 :            : {
     254                 :            :         struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
     255                 :            :         struct rte_mbuf *pkt;
     256                 :            :         struct rte_ether_hdr *eth_h;
     257                 :            :         struct rte_vlan_hdr *vlan_h;
     258                 :            :         struct rte_arp_hdr  *arp_h;
     259                 :            :         struct rte_ipv4_hdr *ip_h;
     260                 :            :         struct rte_icmp_hdr *icmp_h;
     261                 :            :         struct rte_ether_addr eth_addr;
     262                 :            :         uint32_t ip_addr;
     263                 :            :         uint16_t nb_rx;
     264                 :            :         uint16_t nb_replies;
     265                 :            :         uint16_t eth_type;
     266                 :            :         uint16_t vlan_id;
     267                 :            :         uint16_t arp_op;
     268                 :            :         uint16_t arp_pro;
     269                 :            :         uint32_t cksum;
     270                 :            :         uint8_t  i;
     271                 :            :         int l2_len;
     272                 :            : 
     273                 :            :         /*
     274                 :            :          * First, receive a burst of packets.
     275                 :            :          */
     276                 :          0 :         nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
     277                 :          0 :         if (unlikely(nb_rx == 0))
     278                 :            :                 return false;
     279                 :            : 
     280                 :            :         nb_replies = 0;
     281                 :          0 :         for (i = 0; i < nb_rx; i++) {
     282                 :          0 :                 if (likely(i < nb_rx - 1))
     283                 :          0 :                         rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
     284                 :            :                                                        void *));
     285                 :          0 :                 pkt = pkts_burst[i];
     286                 :          0 :                 eth_h = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
     287                 :          0 :                 eth_type = RTE_BE_TO_CPU_16(eth_h->ether_type);
     288                 :            :                 l2_len = sizeof(struct rte_ether_hdr);
     289                 :          0 :                 if (verbose_level > 0) {
     290                 :          0 :                         printf("\nPort %d pkt-len=%u nb-segs=%u\n",
     291                 :          0 :                                fs->rx_port, pkt->pkt_len, pkt->nb_segs);
     292                 :          0 :                         ether_addr_dump("  ETH:  src=", &eth_h->src_addr);
     293                 :          0 :                         ether_addr_dump(" dst=", &eth_h->dst_addr);
     294                 :            :                 }
     295                 :          0 :                 if (eth_type == RTE_ETHER_TYPE_VLAN) {
     296                 :            :                         vlan_h = (struct rte_vlan_hdr *)
     297                 :            :                                 ((char *)eth_h + sizeof(struct rte_ether_hdr));
     298                 :            :                         l2_len  += sizeof(struct rte_vlan_hdr);
     299                 :          0 :                         eth_type = rte_be_to_cpu_16(vlan_h->eth_proto);
     300                 :          0 :                         if (verbose_level > 0) {
     301                 :          0 :                                 vlan_id = rte_be_to_cpu_16(vlan_h->vlan_tci)
     302                 :            :                                         & 0xFFF;
     303                 :          0 :                                 printf(" [vlan id=%u]", vlan_id);
     304                 :            :                         }
     305                 :            :                 }
     306                 :          0 :                 if (verbose_level > 0) {
     307                 :          0 :                         printf(" type=0x%04x\n", eth_type);
     308                 :            :                 }
     309                 :            : 
     310                 :            :                 /* Reply to ARP requests */
     311                 :          0 :                 if (eth_type == RTE_ETHER_TYPE_ARP) {
     312                 :          0 :                         arp_h = (struct rte_arp_hdr *) ((char *)eth_h + l2_len);
     313                 :          0 :                         arp_op = RTE_BE_TO_CPU_16(arp_h->arp_opcode);
     314                 :          0 :                         arp_pro = RTE_BE_TO_CPU_16(arp_h->arp_protocol);
     315                 :          0 :                         if (verbose_level > 0) {
     316                 :          0 :                                 printf("  ARP:  hrd=%d proto=0x%04x hln=%d "
     317                 :            :                                        "pln=%d op=%u (%s)\n",
     318                 :          0 :                                        RTE_BE_TO_CPU_16(arp_h->arp_hardware),
     319                 :          0 :                                        arp_pro, arp_h->arp_hlen,
     320                 :          0 :                                        arp_h->arp_plen, arp_op,
     321                 :            :                                        arp_op_name(arp_op));
     322                 :            :                         }
     323                 :          0 :                         if ((RTE_BE_TO_CPU_16(arp_h->arp_hardware) !=
     324                 :          0 :                              RTE_ARP_HRD_ETHER) ||
     325                 :            :                             (arp_pro != RTE_ETHER_TYPE_IPV4) ||
     326                 :          0 :                             (arp_h->arp_hlen != 6) ||
     327                 :            :                             (arp_h->arp_plen != 4)
     328                 :            :                             ) {
     329                 :          0 :                                 rte_pktmbuf_free(pkt);
     330                 :          0 :                                 if (verbose_level > 0)
     331                 :            :                                         printf("\n");
     332                 :          0 :                                 continue;
     333                 :            :                         }
     334                 :          0 :                         if (verbose_level > 0) {
     335                 :            :                                 rte_ether_addr_copy(&arp_h->arp_data.arp_sha,
     336                 :            :                                                 &eth_addr);
     337                 :          0 :                                 ether_addr_dump("        sha=", &eth_addr);
     338                 :          0 :                                 ip_addr = arp_h->arp_data.arp_sip;
     339                 :          0 :                                 ipv4_addr_dump(" sip=", ip_addr);
     340                 :            :                                 printf("\n");
     341                 :            :                                 rte_ether_addr_copy(&arp_h->arp_data.arp_tha,
     342                 :            :                                                 &eth_addr);
     343                 :          0 :                                 ether_addr_dump("        tha=", &eth_addr);
     344                 :          0 :                                 ip_addr = arp_h->arp_data.arp_tip;
     345                 :          0 :                                 ipv4_addr_dump(" tip=", ip_addr);
     346                 :            :                                 printf("\n");
     347                 :            :                         }
     348                 :          0 :                         if (arp_op != RTE_ARP_OP_REQUEST) {
     349                 :          0 :                                 rte_pktmbuf_free(pkt);
     350                 :          0 :                                 continue;
     351                 :            :                         }
     352                 :            : 
     353                 :            :                         /*
     354                 :            :                          * Build ARP reply.
     355                 :            :                          */
     356                 :            : 
     357                 :            :                         /* Use source MAC address as destination MAC address. */
     358                 :            :                         rte_ether_addr_copy(&eth_h->src_addr, &eth_h->dst_addr);
     359                 :            :                         /* Set source MAC address with MAC address of TX port */
     360                 :          0 :                         rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
     361                 :            :                                         &eth_h->src_addr);
     362                 :            : 
     363                 :          0 :                         arp_h->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REPLY);
     364                 :            :                         rte_ether_addr_copy(&arp_h->arp_data.arp_tha,
     365                 :            :                                         &eth_addr);
     366                 :            :                         rte_ether_addr_copy(&arp_h->arp_data.arp_sha,
     367                 :            :                                         &arp_h->arp_data.arp_tha);
     368                 :            :                         rte_ether_addr_copy(&eth_h->src_addr,
     369                 :            :                                         &arp_h->arp_data.arp_sha);
     370                 :            : 
     371                 :            :                         /* Swap IP addresses in ARP payload */
     372                 :          0 :                         ip_addr = arp_h->arp_data.arp_sip;
     373                 :          0 :                         arp_h->arp_data.arp_sip = arp_h->arp_data.arp_tip;
     374                 :          0 :                         arp_h->arp_data.arp_tip = ip_addr;
     375                 :          0 :                         pkts_burst[nb_replies++] = pkt;
     376                 :          0 :                         continue;
     377                 :            :                 }
     378                 :            : 
     379                 :          0 :                 if (eth_type != RTE_ETHER_TYPE_IPV4) {
     380                 :          0 :                         rte_pktmbuf_free(pkt);
     381                 :          0 :                         continue;
     382                 :            :                 }
     383                 :          0 :                 ip_h = (struct rte_ipv4_hdr *) ((char *)eth_h + l2_len);
     384                 :          0 :                 if (verbose_level > 0) {
     385                 :          0 :                         ipv4_addr_dump("  IPV4: src=", ip_h->src_addr);
     386                 :          0 :                         ipv4_addr_dump(" dst=", ip_h->dst_addr);
     387                 :          0 :                         printf(" proto=%d (%s)\n",
     388                 :            :                                ip_h->next_proto_id,
     389                 :          0 :                                ip_proto_name(ip_h->next_proto_id));
     390                 :            :                 }
     391                 :            : 
     392                 :            :                 /*
     393                 :            :                  * Check if packet is a ICMP echo request.
     394                 :            :                  */
     395                 :            :                 icmp_h = (struct rte_icmp_hdr *) ((char *)ip_h +
     396                 :            :                                               sizeof(struct rte_ipv4_hdr));
     397                 :          0 :                 if (! ((ip_h->next_proto_id == IPPROTO_ICMP) &&
     398                 :          0 :                        (icmp_h->icmp_type == RTE_ICMP_TYPE_ECHO_REQUEST) &&
     399                 :          0 :                        (icmp_h->icmp_code == 0))) {
     400                 :          0 :                         rte_pktmbuf_free(pkt);
     401                 :          0 :                         continue;
     402                 :            :                 }
     403                 :            : 
     404                 :          0 :                 if (verbose_level > 0)
     405                 :          0 :                         printf("  ICMP: echo request seq id=%d\n",
     406                 :          0 :                                rte_be_to_cpu_16(icmp_h->icmp_seq_nb));
     407                 :            : 
     408                 :            :                 /*
     409                 :            :                  * Prepare ICMP echo reply to be sent back.
     410                 :            :                  * - switch ethernet source and destinations addresses,
     411                 :            :                  * - use the request IP source address as the reply IP
     412                 :            :                  *    destination address,
     413                 :            :                  * - if the request IP destination address is a multicast
     414                 :            :                  *   address:
     415                 :            :                  *     - choose a reply IP source address different from the
     416                 :            :                  *       request IP source address,
     417                 :            :                  *     - re-compute the IP header checksum.
     418                 :            :                  *   Otherwise:
     419                 :            :                  *     - switch the request IP source and destination
     420                 :            :                  *       addresses in the reply IP header,
     421                 :            :                  *     - keep the IP header checksum unchanged.
     422                 :            :                  * - set RTE_ICMP_TYPE_ECHO_REPLY in ICMP header.
     423                 :            :                  * ICMP checksum is computed by assuming it is valid in the
     424                 :            :                  * echo request and not verified.
     425                 :            :                  */
     426                 :            :                 rte_ether_addr_copy(&eth_h->src_addr, &eth_addr);
     427                 :            :                 rte_ether_addr_copy(&eth_h->dst_addr, &eth_h->src_addr);
     428                 :            :                 rte_ether_addr_copy(&eth_addr, &eth_h->dst_addr);
     429                 :          0 :                 ip_addr = ip_h->src_addr;
     430                 :          0 :                 if (is_multicast_ipv4_addr(ip_h->dst_addr)) {
     431                 :            :                         uint32_t ip_src;
     432                 :            : 
     433                 :          0 :                         ip_src = rte_be_to_cpu_32(ip_addr);
     434                 :          0 :                         if ((ip_src & 0x00000003) == 1)
     435                 :          0 :                                 ip_src = (ip_src & 0xFFFFFFFC) | 0x00000002;
     436                 :            :                         else
     437                 :          0 :                                 ip_src = (ip_src & 0xFFFFFFFC) | 0x00000001;
     438                 :          0 :                         ip_h->src_addr = rte_cpu_to_be_32(ip_src);
     439                 :          0 :                         ip_h->dst_addr = ip_addr;
     440                 :          0 :                         ip_h->hdr_checksum = rte_ipv4_cksum_simple(ip_h);
     441                 :            :                 } else {
     442                 :          0 :                         ip_h->src_addr = ip_h->dst_addr;
     443                 :          0 :                         ip_h->dst_addr = ip_addr;
     444                 :            :                 }
     445                 :          0 :                 icmp_h->icmp_type = RTE_ICMP_TYPE_ECHO_REPLY;
     446                 :          0 :                 cksum = ~icmp_h->icmp_cksum & 0xffff;
     447                 :          0 :                 cksum += ~RTE_BE16(RTE_ICMP_TYPE_ECHO_REQUEST << 8) & 0xffff;
     448                 :            :                 cksum += RTE_BE16(RTE_ICMP_TYPE_ECHO_REPLY << 8);
     449                 :          0 :                 cksum = (cksum & 0xffff) + (cksum >> 16);
     450                 :          0 :                 cksum = (cksum & 0xffff) + (cksum >> 16);
     451                 :          0 :                 icmp_h->icmp_cksum = ~cksum;
     452                 :          0 :                 pkts_burst[nb_replies++] = pkt;
     453                 :            :         }
     454                 :            : 
     455                 :            :         /* Send back ICMP echo replies, if any. */
     456                 :          0 :         if (nb_replies > 0)
     457                 :          0 :                 common_fwd_stream_transmit(fs, pkts_burst, nb_replies);
     458                 :            : 
     459                 :            :         return true;
     460                 :            : }
     461                 :            : 
     462                 :            : struct fwd_engine icmp_echo_engine = {
     463                 :            :         .fwd_mode_name  = "icmpecho",
     464                 :            :         .stream_init    = common_fwd_stream_init,
     465                 :            :         .packet_fwd     = reply_to_icmp_echo_rqsts,
     466                 :            : };

Generated by: LCOV version 1.14