diff --git a/gtests/net/packetdrill/gre.h b/gtests/net/packetdrill/gre.h
new file mode 100644
index 0000000000000000000000000000000000000000..35a280aaa4c9f8c65cfe999080f8fbb3fdf4fb4f
--- /dev/null
+++ b/gtests/net/packetdrill/gre.h
@@ -0,0 +1,82 @@
+/*
+ * 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)
+ *
+ * Our own GRE header declarations, so we have something that's
+ * portable and somewhat more readable than a typical system header
+ * file.
+ *
+ * We cannot include the kernel's GRE .h files because this tool tries
+ * to compile and work for basically any Linux/BSD kernel version. So
+ * we declare our own version of various GRE-related definitions here.
+ */
+
+#ifndef __GRE_HEADERS_H__
+#define __GRE_HEADERS_H__
+
+#include "types.h"
+
+/* GRE header. See RFC 1701. */
+struct gre {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	__u16	recursion_control:3,
+		strict_route:1,
+		has_seq:1,
+		has_key:1,
+		has_routing:1,
+		has_checksum:1,
+		version:3,
+		reserved:4,
+		ack:1;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+	__u16	has_checksum:1,
+		has_routing:1,
+		has_key:1,
+		has_seq:1,
+		strict_route:1,
+		ack:1,
+		reserved:4,
+		version:3;
+#else
+# error "Please fix endianness defines"
+#endif
+	__be16 protocol;
+	/* bytes 4+ (optional) not defined here... */
+};
+
+/* Return the length in bytes of a GRE header. */
+static inline int gre_len(const struct gre *gre)
+{
+	int bytes = sizeof(*gre);
+
+	assert(gre->version == 0);	/* we only support v0 */
+	assert(!gre->has_routing);	/* routing info is variable-length! */
+
+	if (gre->has_checksum || gre->has_routing)
+		bytes += 4;
+	if (gre->has_key)
+		bytes += 4;
+	if (gre->has_seq)
+		bytes += 4;
+
+	return bytes;
+}
+
+#endif /* __GRE_HEADERS_H__ */
diff --git a/gtests/net/packetdrill/gre_packet.c b/gtests/net/packetdrill/gre_packet.c
new file mode 100644
index 0000000000000000000000000000000000000000..54c6011014842409c9b43f8f6f800a5756ce9e48
--- /dev/null
+++ b/gtests/net/packetdrill/gre_packet.c
@@ -0,0 +1,54 @@
+/*
+ * 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 module for formatting GRE packets.
+ */
+
+#include "gre_packet.h"
+
+#include "ip_packet.h"
+#include "gre.h"
+
+int gre_header_append(struct packet *packet, char **error)
+{
+	struct header *header;
+
+	header = packet_append_header(packet, HEADER_GRE, sizeof(struct gre));
+	if (header == NULL) {
+		asprintf(error, "too many headers");
+		return STATUS_ERR;
+	}
+
+	return STATUS_OK;
+}
+
+int gre_header_finish(struct packet *packet,
+		      struct header *header, struct header *next_inner)
+{
+	struct gre *gre = header->h.gre;
+	int gre_bytes = sizeof(struct gre) + next_inner->total_bytes;
+
+	gre->protocol = htons(header_type_info(next_inner->type)->eth_proto);
+
+	header->total_bytes = gre_bytes;
+
+	return STATUS_OK;
+}
diff --git a/gtests/net/packetdrill/gre_packet.h b/gtests/net/packetdrill/gre_packet.h
new file mode 100644
index 0000000000000000000000000000000000000000..cefe9d74fa17393f62f1b90836b08122bfad040b
--- /dev/null
+++ b/gtests/net/packetdrill/gre_packet.h
@@ -0,0 +1,44 @@
+/*
+ * 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)
+ *
+ * Interface for module for formatting GRE packets.
+ */
+
+#ifndef __GRE_PACKET_H__
+#define __GRE_PACKET_H__
+
+#include "types.h"
+
+#include "packet.h"
+
+/* Append a GRE header to the end of the given packet.  On success,
+ * return STATUS_OK; on error return STATUS_ERR and fill in a
+ * malloc-allocated error message in *error.
+ */
+extern int gre_header_append(struct packet *packet, char **error);
+
+/* Finalize the GRE header by filling in all necessary fields that
+ * were not filled in at parse time.
+ */
+extern int gre_header_finish(struct packet *packet,
+			     struct header *header, struct header *next_inner);
+
+#endif /* __GRE_PACKET_H__ */