Adapt the ICMP echo code to reply to UDP echo requests on port 7. The testpmd
forward engine udpecho is used for that.

Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo at redhat.com>
---
 app/test-pmd/config.c                       |  7 ++-
 app/test-pmd/icmpecho.c                     | 90 ++++++++++++++++++++++-------
 app/test-pmd/testpmd.c                      |  1 +
 app/test-pmd/testpmd.h                      |  1 +
 doc/guides/testpmd_app_ug/run_app.rst       |  2 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  6 +-
 6 files changed, 79 insertions(+), 28 deletions(-)

diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index cf2aa6e..0b5c4e6 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1239,7 +1239,7 @@ dcb_fwd_config_setup(void)
 }

 static void
-icmp_echo_config_setup(void)
+echo_config_setup(void)
 {
        portid_t  rxp;
        queueid_t rxq;
@@ -1297,8 +1297,9 @@ void
 fwd_config_setup(void)
 {
        cur_fwd_config.fwd_eng = cur_fwd_eng;
-       if (strcmp(cur_fwd_eng->fwd_mode_name, "icmpecho") == 0) {
-               icmp_echo_config_setup();
+       if (strcmp(cur_fwd_eng->fwd_mode_name, "icmpecho") == 0 ||
+           strcmp(cur_fwd_eng->fwd_mode_name, "udpecho") == 0) {
+               echo_config_setup();
                return;
        }
        if ((nb_rxq > 1) && (nb_txq > 1)){
diff --git a/app/test-pmd/icmpecho.c b/app/test-pmd/icmpecho.c
index e510f9b..a7f882a 100644
--- a/app/test-pmd/icmpecho.c
+++ b/app/test-pmd/icmpecho.c
@@ -61,6 +61,7 @@
 #include <rte_arp.h>
 #include <rte_ip.h>
 #include <rte_icmp.h>
+#include <rte_udp.h>
 #include <rte_string_fns.h>

 #include "testpmd.h"
@@ -301,7 +302,7 @@ ipv4_hdr_cksum(struct ipv4_hdr *ip_h)
  * send back ICMP echo replies.
  */
 static void
-reply_to_icmp_echo_rqsts(struct fwd_stream *fs)
+reply_to_echo_rqsts(struct fwd_stream *fs, int proto)
 {
        struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
        struct rte_mbuf *pkt;
@@ -310,6 +311,7 @@ reply_to_icmp_echo_rqsts(struct fwd_stream *fs)
        struct arp_hdr  *arp_h;
        struct ipv4_hdr *ip_h;
        struct icmp_hdr *icmp_h;
+       struct udp_hdr *udp_h;
        struct ether_addr eth_addr;
        uint32_t ip_addr;
        uint16_t nb_rx;
@@ -319,6 +321,7 @@ reply_to_icmp_echo_rqsts(struct fwd_stream *fs)
        uint16_t vlan_id;
        uint16_t arp_op;
        uint16_t arp_pro;
+       uint16_t udp_port;
        uint32_t cksum;
        uint8_t  i;
        int l2_len;
@@ -448,24 +451,40 @@ reply_to_icmp_echo_rqsts(struct fwd_stream *fs)
                               ip_proto_name(ip_h->next_proto_id));
                }

-               /*
-                * Check if packet is a ICMP echo request.
-                */
-               icmp_h = (struct icmp_hdr *) ((char *)ip_h +
-                                             sizeof(struct ipv4_hdr));
-               if (! ((ip_h->next_proto_id == IPPROTO_ICMP) &&
-                      (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST) &&
-                      (icmp_h->icmp_code == 0))) {
-                       rte_pktmbuf_free(pkt);
-                       continue;
+               if (proto == IPPROTO_ICMP) {
+                       /*
+                        * Check if packet is a ICMP echo request.
+                        */
+                       icmp_h = (struct icmp_hdr *) ((char *)ip_h +
+                                                     sizeof(struct ipv4_hdr));
+                       if (! ((ip_h->next_proto_id == IPPROTO_ICMP) &&
+                              (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST) &&
+                              (icmp_h->icmp_code == 0))) {
+                               rte_pktmbuf_free(pkt);
+                               continue;
+                       }
+               } else if (proto == IPPROTO_UDP) {
+                       udp_h = (struct udp_hdr *) ((char *)ip_h +
+                                                     sizeof(struct ipv4_hdr));
+                       if ((ip_h->next_proto_id != IPPROTO_UDP) &&
+                           (rte_be_to_cpu_16(udp_h->dst_port) != 7)) {
+                               rte_pktmbuf_free(pkt);
+                               continue;
+                       }
                }

-               if (verbose_level > 0)
-                       printf("  ICMP: echo request seq id=%d\n",
-                              rte_be_to_cpu_16(icmp_h->icmp_seq_nb));
+               if (proto == IPPROTO_ICMP) {
+                       if (verbose_level > 0)
+                               printf("  ICMP: echo request seq id=%d\n",
+                                      rte_be_to_cpu_16(icmp_h->icmp_seq_nb));
+               } else if (proto == IPPROTO_UDP) {
+                       if (verbose_level > 0)
+                               printf("  UDP: echo request from port=%d\n",
+                                      rte_be_to_cpu_16(udp_h->src_port));
+               }

                /*
-                * Prepare ICMP echo reply to be sent back.
+                * Prepare ICMP or UDP echo reply to be sent back.
                 * - switch ethernet source and destinations addresses,
                 * - use the request IP source address as the reply IP
                 *    destination address,
@@ -479,6 +498,8 @@ reply_to_icmp_echo_rqsts(struct fwd_stream *fs)
                 *       addresses in the reply IP header,
                 *     - keep the IP header checksum unchanged.
                 * - set IP_ICMP_ECHO_REPLY in ICMP header.
+                * - switch the UDP source and destination ports in the UDP
+                *   header.
                 * ICMP checksum is computed by assuming it is valid in the
                 * echo request and not verified.
                 */
@@ -501,13 +522,19 @@ reply_to_icmp_echo_rqsts(struct fwd_stream *fs)
                        ip_h->src_addr = ip_h->dst_addr;
                        ip_h->dst_addr = ip_addr;
                }
-               icmp_h->icmp_type = IP_ICMP_ECHO_REPLY;
-               cksum = ~icmp_h->icmp_cksum & 0xffff;
-               cksum += ~htons(IP_ICMP_ECHO_REQUEST << 8) & 0xffff;
-               cksum += htons(IP_ICMP_ECHO_REPLY << 8);
-               cksum = (cksum & 0xffff) + (cksum >> 16);
-               cksum = (cksum & 0xffff) + (cksum >> 16);
-               icmp_h->icmp_cksum = ~cksum;
+               if (proto == IPPROTO_ICMP) {
+                       icmp_h->icmp_type = IP_ICMP_ECHO_REPLY;
+                       cksum = ~icmp_h->icmp_cksum & 0xffff;
+                       cksum += ~htons(IP_ICMP_ECHO_REQUEST << 8) & 0xffff;
+                       cksum += htons(IP_ICMP_ECHO_REPLY << 8);
+                       cksum = (cksum & 0xffff) + (cksum >> 16);
+                       cksum = (cksum & 0xffff) + (cksum >> 16);
+                       icmp_h->icmp_cksum = ~cksum;
+               } else if (proto == IPPROTO_UDP) {
+                       udp_port = udp_h->src_port;
+                       udp_h->src_port = udp_h->dst_port;
+                       udp_h->dst_port = udp_port;
+               }
                pkts_burst[nb_replies++] = pkt;
        }

@@ -534,9 +561,28 @@ reply_to_icmp_echo_rqsts(struct fwd_stream *fs)
 #endif
 }

+static void
+reply_to_icmp_echo_rqsts(struct fwd_stream *fs)
+{
+       reply_to_echo_rqsts(fs, IPPROTO_ICMP);
+}
+
+static void
+reply_to_udp_echo_rqsts(struct fwd_stream *fs)
+{
+       reply_to_echo_rqsts(fs, IPPROTO_UDP);
+}
+
 struct fwd_engine icmp_echo_engine = {
        .fwd_mode_name  = "icmpecho",
        .port_fwd_begin = NULL,
        .port_fwd_end   = NULL,
        .packet_fwd     = reply_to_icmp_echo_rqsts,
 };
+
+struct fwd_engine udp_echo_engine = {
+       .fwd_mode_name  = "udpecho",
+       .port_fwd_begin = NULL,
+       .port_fwd_end   = NULL,
+       .packet_fwd     = reply_to_udp_echo_rqsts,
+};
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 386bf84..b9a0ddb 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -151,6 +151,7 @@ struct fwd_engine * fwd_engines[] = {
        &tx_only_engine,
        &csum_fwd_engine,
        &icmp_echo_engine,
+       &udp_echo_engine,
 #ifdef RTE_LIBRTE_IEEE1588
        &ieee1588_fwd_engine,
 #endif
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index d287274..612a4f4 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -229,6 +229,7 @@ extern struct fwd_engine rx_only_engine;
 extern struct fwd_engine tx_only_engine;
 extern struct fwd_engine csum_fwd_engine;
 extern struct fwd_engine icmp_echo_engine;
+extern struct fwd_engine udp_echo_engine;
 #ifdef RTE_LIBRTE_IEEE1588
 extern struct fwd_engine ieee1588_fwd_engine;
 #endif
diff --git a/doc/guides/testpmd_app_ug/run_app.rst 
b/doc/guides/testpmd_app_ug/run_app.rst
index 54ae2b2..6ad168a 100644
--- a/doc/guides/testpmd_app_ug/run_app.rst
+++ b/doc/guides/testpmd_app_ug/run_app.rst
@@ -315,7 +315,7 @@ They must be separated from the EAL options, shown in the 
previous section, with

 *   --forward-mode=N

-    Set forwarding mode. (N: 
io|mac|mac_retry|mac_swap|flowgen|rxonly|txonly|csum|icmpecho|ieee1588)
+    Set forwarding mode. (N: 
io|mac|mac_retry|mac_swap|flowgen|rxonly|txonly|csum|icmpecho|udpecho|ieee1588)

 *   --rss-ip

diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst 
b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 3f076c8..1be0ae8 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -609,7 +609,7 @@ set fwd

 Set the packet forwarding mode:

-set fwd (io|mac|mac_retry|macswap|flowgen|rxonly|txonly|csum|icmpecho)
+set fwd (io|mac|mac_retry|macswap|flowgen|rxonly|txonly|csum|icmpecho|udpecho)

 The available information categories are:

@@ -633,7 +633,9 @@ The available information categories are:

 *   csum: changes the checksum field with HW or SW methods depending on the 
offload flags on the packet.

-*   icmpecho: receives a burst of packets, lookup for IMCP echo requests and, 
if any, send back ICMP echo replies.
+*   icmpecho: receives a burst of packets, lookup for ICMP echo requests and, 
if any, send back ICMP echo replies.
+
+*   udpecho: receives a burst of packets, lookup for UDP echo requests and, if 
any, send back UDP echo replies.

 *   ieee1588: demonstrate L2 IEEE1588 V2 PTP timestamping for RX and TX. 
Requires ``CONFIG_RTE_LIBRTE_IEEE1588=y``.
     Note: TX timestamping is only available in the "Full Featured" TX path. To 
force ``testpmd`` into this mode set ``--txqflags=0``.
-- 
2.4.3

Reply via email to