From d0e56fddef6d4b8b94cadadbcd08e5f28a481340 Mon Sep 17 00:00:00 2001
From: Neal Cardwell <ncardwell@google.com>
Date: Mon, 4 Nov 2013 10:03:05 -0500
Subject: [PATCH] net-test: packetdrill encap support: refactor packet receive
 loops into one loop

Factor out the packet sniffing loop that's common to local and remote
mode, since it is nearly identical in both cases. This is in
preparation for fixing a bug that is found in both loops, so we can
make the fix in just one place.


Change-Id: Ic9a9b84b66a9f812866b1e29cd7c897f7c1d40cf
---
 gtests/net/packetdrill/netdev.c             | 20 +++++++++----
 gtests/net/packetdrill/netdev.h             | 12 ++++++++
 gtests/net/packetdrill/wire_server_netdev.c | 32 ++-------------------
 3 files changed, 28 insertions(+), 36 deletions(-)

diff --git a/gtests/net/packetdrill/netdev.c b/gtests/net/packetdrill/netdev.c
index 98a3f006..64ac611e 100644
--- a/gtests/net/packetdrill/netdev.c
+++ b/gtests/net/packetdrill/netdev.c
@@ -370,21 +370,28 @@ static int local_netdev_receive(struct netdev *a_netdev,
 
 	DEBUGP("local_netdev_receive\n");
 
+	return netdev_receive_loop(netdev->psock, PACKET_LAYER_3_IP,
+				   packet, error);
+}
+
+int netdev_receive_loop(struct packet_socket *psock,
+			enum packet_layer_t layer,
+			struct packet **packet,
+			char **error)
+{
 	assert(*packet == NULL);	/* should be no packet yet */
 	*packet = packet_new(PACKET_READ_BYTES);
 
 	while (1) {
 		int in_bytes = 0;
+		enum packet_parse_result_t result;
 
 		/* Sniff the next outbound packet from the kernel under test. */
-		if (packet_socket_receive(netdev->psock,
-					  DIRECTION_OUTBOUND,
+		if (packet_socket_receive(psock, DIRECTION_OUTBOUND,
 					  *packet, &in_bytes))
 			continue;
 
-		enum packet_parse_result_t result =
-			parse_packet(*packet, in_bytes,
-					     PACKET_LAYER_3_IP, error);
+		result = parse_packet(*packet, in_bytes, layer, error);
 		if (result == PACKET_OK) {
 			return STATUS_OK;
 		} else if (result == PACKET_BAD) {
@@ -392,7 +399,8 @@ static int local_netdev_receive(struct netdev *a_netdev,
 			*packet = NULL;
 			return STATUS_ERR;
 		} else {
-			DEBUGP("error parsing packet: %s\n", *error);
+			DEBUGP("parse_result:%d; error parsing packet: %s\n",
+			       result, *error);
 		}
 	}
 
diff --git a/gtests/net/packetdrill/netdev.h b/gtests/net/packetdrill/netdev.h
index 1eba6d0b..84e87a0a 100644
--- a/gtests/net/packetdrill/netdev.h
+++ b/gtests/net/packetdrill/netdev.h
@@ -30,6 +30,8 @@
 
 #include "config.h"
 #include "packet.h"
+#include "packet_parser.h"
+#include "packet_socket.h"
 
 struct netdev_ops;
 
@@ -79,6 +81,16 @@ static inline int netdev_receive(struct netdev *netdev,
 	return netdev->ops->receive(netdev, packet, error);
 }
 
+
+/* Keep sniffing packets leaving the kernel until we see one we know
+ * about and can parse. Return a pointer to the newly-allocated
+ * packet. Caller must free the packet with packet_free().
+ */
+extern int netdev_receive_loop(struct packet_socket *psock,
+			       enum packet_layer_t layer,
+			       struct packet **packet,
+			       char **error);
+
 /* Allocate and return a new netdev for purely local tests. */
 extern struct netdev *local_netdev_new(struct config *config);
 
diff --git a/gtests/net/packetdrill/wire_server_netdev.c b/gtests/net/packetdrill/wire_server_netdev.c
index fe57ce46..066566f2 100644
--- a/gtests/net/packetdrill/wire_server_netdev.c
+++ b/gtests/net/packetdrill/wire_server_netdev.c
@@ -191,36 +191,8 @@ static int wire_server_netdev_receive(struct netdev *a_netdev,
 
 	DEBUGP("wire_server_netdev_receive\n");
 
-	assert(*packet == NULL);	/* should be no packet yet */
-	*packet = packet_new(PACKET_READ_BYTES);
-
-	while (1) {
-		int in_bytes = 0;
-		enum packet_parse_result_t result;
-
-		/* Sniff the next inbound packet from the kernel under test. */
-		if (packet_socket_receive(netdev->psock,
-					  DIRECTION_INBOUND,
-					  *packet, &in_bytes))
-			continue;
-
-		result = parse_packet(*packet, in_bytes,
-					      PACKET_LAYER_2_ETHERNET,
-					      error);
-		if (result == PACKET_OK) {
-			return STATUS_OK;
-		} else if (result == PACKET_BAD) {
-			packet_free(*packet);
-			*packet = NULL;
-			return STATUS_ERR;
-		} else {
-			/* TODO: print these packets in verbose mode? */
-			DEBUGP("parse_result:%d; error parsing packet: %s\n",
-			       result, *error);
-		}
-	}
-
-	return STATUS_ERR;
+	return netdev_receive_loop(netdev->psock, PACKET_LAYER_2_ETHERNET,
+				   packet, error);
 }
 
 struct netdev_ops wire_server_netdev_ops = {
-- 
GitLab