[dpdk-dev] [PATCH] app/testpmd: add engine for UDP echo server support

Thadeu Lima de Souza Cascardo cascardo at redhat.com
Fri Sep 4 19:17:37 CEST 2015


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



More information about the dev mailing list