diff --git a/gtests/net/packetdrill/Makefile.common b/gtests/net/packetdrill/Makefile.common
index 1f2d45ab0593cc016a4e8787b7d259e6875256c4..89e3e19abd424bceda6e21b2a396237f7614d6f0 100644
--- a/gtests/net/packetdrill/Makefile.common
+++ b/gtests/net/packetdrill/Makefile.common
@@ -10,7 +10,8 @@ lexer.o: lexer.l parser.o
 	flex -olexer.c lexer.l
 	$(CC) -O2 -g -Wall -c lexer.c
 
-packetdrill-lib := checksum.o code.o config.o hash.o hash_map.o ip_address.o \
+packetdrill-lib := \
+         checksum.o code.o config.o hash.o hash_map.o ip_address.o ip_prefix.o \
          netdev.o net_utils.o \
          packet.o packet_socket_linux.o packet_socket_pcap.o \
          packet_checksum.o packet_parser.o packet_to_string.o \
diff --git a/gtests/net/packetdrill/ip_address.h b/gtests/net/packetdrill/ip_address.h
index 596f5f9318a8d46c8d617646f6ca3341b261b0a6..1c5b8a418f7d0f430d56f555c3a4853941bcffae 100644
--- a/gtests/net/packetdrill/ip_address.h
+++ b/gtests/net/packetdrill/ip_address.h
@@ -35,6 +35,7 @@ struct ip_address {
 	union {
 		struct in_addr v4;
 		struct in6_addr v6;
+		u8 bytes[16];
 	} ip;				/* IP address (network order) */
 };
 
diff --git a/gtests/net/packetdrill/ip_prefix.c b/gtests/net/packetdrill/ip_prefix.c
new file mode 100644
index 0000000000000000000000000000000000000000..044b94d6285051b8f775e3f667b8861f0fb613e8
--- /dev/null
+++ b/gtests/net/packetdrill/ip_prefix.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+/*
+ * Author: ncardwell@google.com (Neal Cardwell)
+ *
+ * Implementation for operations for IPv4 and IPv6 prefixes.
+ */
+
+#include "ip_prefix.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "logging.h"
+
+struct ip_prefix ip_to_prefix(const struct ip_address *ip, int prefix_len)
+{
+	int max_prefix_bits = 8 * ip_address_length(ip->address_family);
+	struct ip_prefix prefix;
+
+	if (prefix_len < 0 || prefix_len > max_prefix_bits)
+		die("invalid prefix_len: %d bits", prefix_len);
+
+	prefix.ip = *ip;
+	prefix.prefix_len = prefix_len;
+
+	return prefix;
+}
+
+void ip_prefix_normalize(struct ip_prefix *prefix)
+{
+	/* Find the byte and bit offset where the prefix ends. */
+	int bytes = prefix->prefix_len / 8;
+	int bits = prefix->prefix_len % 8;
+	int max_prefix_bytes = ip_address_length(prefix->ip.address_family);
+
+	/* Zero the bits beyond the prefix in the byte where it ends. */
+	if (bits != 0) {
+		int pos = 8 - bits;
+		prefix->ip.ip.bytes[bytes] &= ~((1U << pos) - 1);
+		++bytes;
+
+	}
+	/* Zero out the rest of the bytes in the address. */
+	memset(prefix->ip.ip.bytes + bytes, 0, max_prefix_bytes - bytes);
+}
+
+/* Parse and return a prefix length (in bits) like /16 or /64 from the
+ * end of a string, and die if the prefix is bigger than the given max
+ * length. Use the maximum length if there is no prefix in the string.
+ */
+static int prefix_len_parse(const char *prefix_string, int max_len)
+{
+	int prefix_len = 0;
+	const char *len_str = NULL;
+
+	len_str = strstr(prefix_string, "/");
+	if (len_str != NULL) {
+		/* Parse prefix len in string */
+		char *end = NULL;
+
+		++len_str;		/* advance beyond '/' */
+		errno = 0;
+		prefix_len = strtol(len_str, &end, 10);
+
+		if (errno != 0 || *end != '\0' ||
+		    (prefix_len < 0) || (prefix_len > max_len))
+			die("bad prefix length in prefix '%s'\n",
+			    prefix_string);
+	} else {
+		/* Default prefix length is all address bits */
+		prefix_len = max_len;
+	}
+
+	return prefix_len;
+}
+
+/* Copy the address part of a "<address>/<prefix>" string. */
+static char *copy_prefix_address(const char *prefix_string)
+{
+	const char *slash = strstr(prefix_string, "/");
+	int len = 0;
+	if (slash != NULL)
+		len = slash - prefix_string;
+	else
+		len = strlen(prefix_string);
+	return strndup(prefix_string, len);
+}
+
+struct ip_prefix ipv4_prefix_parse(const char *prefix_string)
+{
+	char *ip_str = copy_prefix_address(prefix_string);
+	struct ip_address ip = ipv4_parse(ip_str);
+	int prefix_len = prefix_len_parse(prefix_string,
+					  8 * ip_address_length(AF_INET));
+
+	free(ip_str);
+
+	return ip_to_prefix(&ip, prefix_len);
+}
+
+struct ip_prefix ipv6_prefix_parse(const char *prefix_string)
+{
+	char *ip_str = copy_prefix_address(prefix_string);
+	struct ip_address ip = ipv6_parse(ip_str);
+	int prefix_len = prefix_len_parse(prefix_string,
+					  8 * ip_address_length(AF_INET6));
+
+	free(ip_str);
+
+	return ip_to_prefix(&ip, prefix_len);
+}
+
+const char *ip_prefix_to_string(struct ip_prefix *prefix, char *buffer)
+{
+	char ip_str[ADDR_STR_LEN];
+	int bytes = 0;
+
+	memset(ip_str, 0, sizeof(ip_str));
+	ip_to_string(&prefix->ip, ip_str);
+
+	if (strlen(ip_str) + strlen("/128") + 1 > ADDR_STR_LEN)
+		die("address prefix would overflow buffer!");
+
+	bytes = snprintf(buffer, ADDR_STR_LEN, "%s/%d",
+			 ip_str, prefix->prefix_len);
+	if (bytes >= ADDR_STR_LEN)
+		die("address prefix overflowed buffer!");
+
+	return buffer;
+}
diff --git a/gtests/net/packetdrill/ip_prefix.h b/gtests/net/packetdrill/ip_prefix.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b82260d119c4db3f453bfd8ab6c54e6218ef792
--- /dev/null
+++ b/gtests/net/packetdrill/ip_prefix.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+/*
+ * Author: ncardwell@google.com (Neal Cardwell)
+ *
+ * Types and operations for IPv4 and IPv6 address prefixes.
+ */
+
+#ifndef __IP_PREFIX_H__
+#define __IP_PREFIX_H__
+
+#include "types.h"
+
+#include "ip_address.h"
+
+/* IPv4 or IPv6 address prefix. */
+struct ip_prefix {
+	struct ip_address ip;
+	int prefix_len;			/* prefix length in bits */
+};
+
+static inline void ip_prefix_reset(struct ip_prefix *prefix)
+{
+	memset(prefix, 0, sizeof(*prefix));
+}
+
+/* Parse a human-readable IPv4 prefix and return it. Print an error
+ * to stderr and exit if there is an error parsing the prefix.
+ */
+extern struct ip_prefix ipv4_prefix_parse(const char *prefix_string);
+
+/* Parse a human-readable IPv6 prefix and return it. Print an error
+ * to stderr and exit if there is an error parsing the prefix.
+ */
+extern struct ip_prefix ipv6_prefix_parse(const char *prefix_string);
+
+/* Fill in the given prefix using the first 'prefix_len' bits of the
+ * given IP address, zeroing out bits beyond the prefix length.
+ */
+extern struct ip_prefix ip_to_prefix(const struct ip_address *ip,
+				     int prefix_len);
+
+/* Zero the bits beyond the prefix length. */
+void ip_prefix_normalize(struct ip_prefix *prefix);
+
+/* Print a human-readable representation of the given IP prefix in the
+ * given buffer, which must be at least ADDR_STR_LEN bytes long.
+ * Returns a pointer to the given buffer.
+ */
+extern const char *ip_prefix_to_string(struct ip_prefix *prefix,
+				       char *buffer);
+
+#endif /* __IP_PREFIX_H__ */
diff --git a/gtests/net/packetdrill/types.h b/gtests/net/packetdrill/types.h
index 289f6af0e85c4e6ce508acb6685c220f2458933b..50d7edf2fd08637a5b38f889f0dafdb8250ee44f 100644
--- a/gtests/net/packetdrill/types.h
+++ b/gtests/net/packetdrill/types.h
@@ -122,8 +122,8 @@ enum ip_ecn_t {
 	ECN_NOCHECK,
 };
 
-/* Length of output buffer for inet_ntop. */
-#define ADDR_STR_LEN ((INET_ADDRSTRLEN + INET6_ADDRSTRLEN)+1)
+/* Length of output buffer for inet_ntop, plus prefix length (e.g. "/128"). */
+#define ADDR_STR_LEN ((INET_ADDRSTRLEN + INET6_ADDRSTRLEN)+5)
 
 /* Flavors of IP versions we support. */
 enum ip_version_t {