From 8c2959a0632cf46b36601bceb91acac34512362e Mon Sep 17 00:00:00 2001
From: Neal Cardwell <ncardwell@google.com>
Date: Tue, 12 Nov 2013 12:54:12 -0500
Subject: [PATCH] net-test: packetdrill: support remote prefixes of arbitrary
 length

Allow the --remote_ip config parameter to be a prefix, not just a
single address. The entire remote prefix is routed to the tun device
or remote packetdrill machine.

The goal here is to all tests to use more than one remote IP. The
immediate motivation is testing GRE, where there is a remote IP for
the TCP endpoint and a separate remote IP for the GRE decapsulator.
But eventually we'll also want to allow testing multiple concurrent
TCP connections from multiple remote IPs addresses as well.

Here are examples of the remote prefix you get for various values of
the --remote_ip field. These are chosen for convenience and backwards
compatibility with existing tests that are already using the
--remote_ip parameter.

o Default:

configuration                      remote prefix
------------------------------     -----------------
IPv4, no --remote_ip            -> 192.0.2.0/24   (default)
v4/6, no --remote_ip            -> 192.0.2.0/24   (default)
IPv6, no --remote_ip            -> 2001:DB8::0/32 (default)

o Explicit IP without prefix length (prefix includes all bits):

configuration                      remote prefix
------------------------------     -----------------
IPv4 --remote_ip=10.248.0.3     -> 10.248.0.3/32
v4/6 --remote_ip=10.248.0.3     -> 10.248.0.3/32
IPv6 --remote_ip=2001:db8::3    -> 2001:db8::3/128

o Explicit with prefix length:

configuration                      remote prefix
------------------------------     -----------------
IPv4 --remote_ip=10.248.0.3/16  -> 10.248.0.0/16
v4/6 --remote_ip=10.248.0.3/16  -> 10.248.0.0/16
IPv6 --remote_ip=2001:db8::3/16 -> 2001::0/16

Change-Id: Ibc95c3419d66bcf1bbfd8a1fc7650d0003345ef2
---
 gtests/net/packetdrill/config.c             | 37 ++++++++++++++++++---
 gtests/net/packetdrill/config.h             |  3 ++
 gtests/net/packetdrill/netdev.c             | 14 ++++----
 gtests/net/packetdrill/wire_client_netdev.c | 14 ++++----
 4 files changed, 49 insertions(+), 19 deletions(-)

diff --git a/gtests/net/packetdrill/config.c b/gtests/net/packetdrill/config.c
index 981308ff..5abe1b23 100644
--- a/gtests/net/packetdrill/config.c
+++ b/gtests/net/packetdrill/config.c
@@ -29,6 +29,7 @@
 
 #include "config.h"
 #include "logging.h"
+#include "ip_prefix.h"
 
 /* For the sake of clarity, we require long option names, e.g. --foo,
  * for all options except -v.
@@ -130,7 +131,7 @@ void show_usage(void)
  * - remote address: 192.0.2.0/24 TEST-NET-1 range (RFC 5737)
  */
 
-#define DEFAULT_V4_LIVE_REMOTE_IP_STRING   "192.0.2.1"
+#define DEFAULT_V4_LIVE_REMOTE_IP_STRING   "192.0.2.1/24"
 #define DEFAULT_V4_LIVE_LOCAL_IP_STRING    "192.168.0.1"
 #define DEFAULT_V4_LIVE_GATEWAY_IP_STRING  "192.168.0.2"
 #define DEFAULT_V4_LIVE_NETMASK_IP_STRING  "255.255.0.0"
@@ -146,7 +147,7 @@ void show_usage(void)
  * - remote address: 2001:DB8::/32 documentation prefix (RFC 3849)
  */
 
-#define DEFAULT_V6_LIVE_REMOTE_IP_STRING   "2001:DB8::1"
+#define DEFAULT_V6_LIVE_REMOTE_IP_STRING   "2001:DB8::1/32"
 #define DEFAULT_V6_LIVE_LOCAL_IP_STRING    "fd3d:fa7b:d17d::1"
 #define DEFAULT_V6_LIVE_GATEWAY_IP_STRING  "fd3d:fa7b:d17d::2"
 #define DEFAULT_V6_LIVE_PREFIX_LEN         48
@@ -216,6 +217,17 @@ void set_default_config(struct config *config)
 	config->wire_server_device	= "eth0";
 }
 
+static void set_remote_ip_and_prefix(struct config *config)
+{
+	config->live_remote_ip = config->live_remote_prefix.ip;
+	ip_to_string(&config->live_remote_ip,
+		     config->live_remote_ip_string);
+
+	ip_prefix_normalize(&config->live_remote_prefix);
+	ip_prefix_to_string(&config->live_remote_prefix,
+			    config->live_remote_prefix_string);
+}
+
 /* Here's a table summarizing the types of various entities in the
  * different flavors of IP that we support:
  *
@@ -230,8 +242,13 @@ void set_default_config(struct config *config)
 static void finalize_ipv4_config(struct config *config)
 {
 	set_ipv4_defaults(config);
+
 	config->live_local_ip	= ipv4_parse(config->live_local_ip_string);
-	config->live_remote_ip	= ipv4_parse(config->live_remote_ip_string);
+
+	config->live_remote_prefix =
+		ipv4_prefix_parse(config->live_remote_ip_string);
+	set_remote_ip_and_prefix(config);
+
 	config->live_prefix_len =
 		netmask_to_prefix(config->live_netmask_ip_string);
 	config->live_gateway_ip = ipv4_parse(config->live_gateway_ip_string);
@@ -245,8 +262,13 @@ static void finalize_ipv4_config(struct config *config)
 static void finalize_ipv4_mapped_ipv6_config(struct config *config)
 {
 	set_ipv4_defaults(config);
+
 	config->live_local_ip	= ipv4_parse(config->live_local_ip_string);
-	config->live_remote_ip	= ipv4_parse(config->live_remote_ip_string);
+
+	config->live_remote_prefix =
+		ipv4_prefix_parse(config->live_remote_ip_string);
+	set_remote_ip_and_prefix(config);
+
 	config->live_prefix_len =
 		netmask_to_prefix(config->live_netmask_ip_string);
 	config->live_gateway_ip = ipv4_parse(config->live_gateway_ip_string);
@@ -260,8 +282,13 @@ static void finalize_ipv4_mapped_ipv6_config(struct config *config)
 static void finalize_ipv6_config(struct config *config)
 {
 	set_ipv6_defaults(config);
+
 	config->live_local_ip	= ipv6_parse(config->live_local_ip_string);
-	config->live_remote_ip	= ipv6_parse(config->live_remote_ip_string);
+
+	config->live_remote_prefix =
+		ipv6_prefix_parse(config->live_remote_ip_string);
+	set_remote_ip_and_prefix(config);
+
 	config->live_prefix_len	= DEFAULT_V6_LIVE_PREFIX_LEN;
 	config->live_gateway_ip = ipv6_parse(config->live_gateway_ip_string);
 	config->live_bind_ip	= ipv6_parse("::");
diff --git a/gtests/net/packetdrill/config.h b/gtests/net/packetdrill/config.h
index ab6ee711..79518285 100644
--- a/gtests/net/packetdrill/config.h
+++ b/gtests/net/packetdrill/config.h
@@ -32,6 +32,7 @@
 #include <unistd.h>
 #include <getopt.h>
 #include "ip_address.h"
+#include "ip_prefix.h"
 #include "script.h"
 
 #define TUN_DRIVER_SPEED_CUR	0	/* don't change current speed */
@@ -54,10 +55,12 @@ struct config {
 
 	struct ip_address live_local_ip;	/* local interface IP */
 	struct ip_address live_remote_ip;	/* remote interface IP */
+	struct ip_prefix live_remote_prefix;	/* remote prefix under test */
 	struct ip_address live_gateway_ip;	/* gateway interface IP */
 
 	char live_local_ip_string[ADDR_STR_LEN];	/* human-readable IP */
 	char live_remote_ip_string[ADDR_STR_LEN];	/* human-readable IP */
+	char live_remote_prefix_string[ADDR_STR_LEN];	/* <addr>/<prefixlen> */
 
 	char live_gateway_ip_string[ADDR_STR_LEN];	/* local gateway IP */
 	char live_netmask_ip_string[ADDR_STR_LEN];	/* local netmask */
diff --git a/gtests/net/packetdrill/netdev.c b/gtests/net/packetdrill/netdev.c
index 37399b21..8cee434d 100644
--- a/gtests/net/packetdrill/netdev.c
+++ b/gtests/net/packetdrill/netdev.c
@@ -230,8 +230,8 @@ static void route_traffic_to_device(struct config *config,
 	asprintf(&route_command,
 		 "ip route del %s > /dev/null 2>&1 ; "
 		 "ip route add %s dev %s via %s > /dev/null 2>&1",
-		 config->live_remote_ip_string,
-		 config->live_remote_ip_string,
+		 config->live_remote_prefix_string,
+		 config->live_remote_prefix_string,
 		 netdev->name,
 		 config->live_gateway_ip_string);
 #endif
@@ -239,9 +239,9 @@ static void route_traffic_to_device(struct config *config,
 	if (config->wire_protocol == AF_INET) {
 		asprintf(&route_command,
 			 "route delete %s > /dev/null 2>&1 ; "
-			 "route add %s/32 %s > /dev/null",
-			 config->live_remote_ip_string,
-			 config->live_remote_ip_string,
+			 "route add %s %s > /dev/null",
+			 config->live_remote_prefix_string,
+			 config->live_remote_prefix_string,
 			 config->live_gateway_ip_string);
 	} else if (config->wire_protocol == AF_INET6) {
 		asprintf(&route_command,
@@ -251,8 +251,8 @@ static void route_traffic_to_device(struct config *config,
 #elif defined(__OpenBSD__) || defined(__NetBSD__)
 			 "route add -inet6 %s %s > /dev/null",
 #endif
-			 config->live_remote_ip_string,
-			 config->live_remote_ip_string,
+			 config->live_remote_prefix_string,
+			 config->live_remote_prefix_string,
 			 config->live_gateway_ip_string);
 	} else {
 		assert(!"bad wire protocol");
diff --git a/gtests/net/packetdrill/wire_client_netdev.c b/gtests/net/packetdrill/wire_client_netdev.c
index 86779cc3..ce4ebefc 100644
--- a/gtests/net/packetdrill/wire_client_netdev.c
+++ b/gtests/net/packetdrill/wire_client_netdev.c
@@ -70,9 +70,9 @@ static void route_traffic_to_wire_server(struct config *config,
 		 "ip %s route del %s > /dev/null 2>&1 ; "
 		 "ip %s route add %s dev %s via %s > /dev/null 2>&1",
 		 (config->wire_protocol == AF_INET6) ? "-6" : "",
-		 config->live_remote_ip_string,
+		 config->live_remote_prefix_string,
 		 (config->wire_protocol == AF_INET6) ? "-6" : "",
-		 config->live_remote_ip_string,
+		 config->live_remote_prefix_string,
 		 netdev->name,
 		 config->live_gateway_ip_string);
 #endif
@@ -80,16 +80,16 @@ static void route_traffic_to_wire_server(struct config *config,
 	if (config->wire_protocol == AF_INET) {
 		asprintf(&route_command,
 			 "route delete %s > /dev/null 2>&1 ; "
-			 "route add %s/32 %s > /dev/null 2>&1",
-			 config->live_remote_ip_string,
-			 config->live_remote_ip_string,
+			 "route add %s %s > /dev/null 2>&1",
+			 config->live_remote_prefix_string,
+			 config->live_remote_prefix_string,
 			 config->live_gateway_ip_string);
 	} else if (config->wire_protocol == AF_INET6) {
 		asprintf(&route_command,
 			 "route delete -inet6 %s > /dev/null 2>&1 ; "
 			 "route add -inet6 %s %s > /dev/null 2>&1",
-			 config->live_remote_ip_string,
-			 config->live_remote_ip_string,
+			 config->live_remote_prefix_string,
+			 config->live_remote_prefix_string,
 			 config->live_gateway_ip_string);
 	} else {
 		assert(!"bad wire protocol");
-- 
GitLab