From 460c15db80ce89cf855526580ccfd7ddc74da149 Mon Sep 17 00:00:00 2001 From: Neal Cardwell <ncardwell@google.com> Date: Mon, 4 Nov 2013 13:55:22 -0500 Subject: [PATCH] net-test: packetdrill encap support: basic header printing Basic support for printing encapsulation headers: IPv4, IPv6, GRE. Change-Id: I67b9e432c98a00ba2c19ac6ea25ea35592462ea9 --- gtests/net/packetdrill/packet_to_string.c | 76 +++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/gtests/net/packetdrill/packet_to_string.c b/gtests/net/packetdrill/packet_to_string.c index c3a354cb..64ab8f3c 100644 --- a/gtests/net/packetdrill/packet_to_string.c +++ b/gtests/net/packetdrill/packet_to_string.c @@ -51,6 +51,50 @@ static void packet_buffer_to_string(FILE *s, struct packet *packet) free(hex); } +static int ipv4_header_to_string(FILE *s, struct packet *packet, int layer, + enum dump_format_t format, char **error) +{ + char src_string[ADDR_STR_LEN]; + char dst_string[ADDR_STR_LEN]; + struct ip_address src_ip, dst_ip; + const struct ipv4 *ipv4 = packet->headers[layer].h.ipv4; + + ip_from_ipv4(&ipv4->src_ip, &src_ip); + ip_from_ipv4(&ipv4->dst_ip, &dst_ip); + + fprintf(s, "ipv4 %s > %s: ", + ip_to_string(&src_ip, src_string), + ip_to_string(&dst_ip, dst_string)); + + return STATUS_OK; +} + +static int ipv6_header_to_string(FILE *s, struct packet *packet, int layer, + enum dump_format_t format, char **error) +{ + char src_string[ADDR_STR_LEN]; + char dst_string[ADDR_STR_LEN]; + struct ip_address src_ip, dst_ip; + const struct ipv6 *ipv6 = packet->headers[layer].h.ipv6; + + ip_from_ipv6(&ipv6->src_ip, &src_ip); + ip_from_ipv6(&ipv6->dst_ip, &dst_ip); + + fprintf(s, "ipv6 %s > %s: ", + ip_to_string(&src_ip, src_string), + ip_to_string(&dst_ip, dst_string)); + + return STATUS_OK; +} + +static int gre_header_to_string(FILE *s, struct packet *packet, int layer, + enum dump_format_t format, char **error) +{ + fprintf(s, "gre: "); + + return STATUS_OK; +} + /* Print a string representation of the TCP packet: * direction opt_ip_info flags seq ack window tcp_options */ @@ -143,6 +187,28 @@ static int icmpv6_packet_to_string(FILE *s, struct packet *packet, return STATUS_OK; } +typedef int (*header_to_string_func)(FILE *s, struct packet *packet, int layer, + enum dump_format_t format, char **error); + +static int encap_header_to_string(FILE *s, struct packet *packet, int layer, + enum dump_format_t format, char **error) +{ + header_to_string_func printers[HEADER_NUM_TYPES] = { + [HEADER_IPV4] = ipv4_header_to_string, + [HEADER_IPV6] = ipv6_header_to_string, + [HEADER_GRE] = gre_header_to_string, + }; + header_to_string_func printer = NULL; + enum header_t type = packet->headers[layer].type; + + assert(type > HEADER_NONE); + assert(type < HEADER_NUM_TYPES); + printer = printers[type]; + assert(printer != NULL); + return printer(s, packet, layer, format, error); +} + + int packet_to_string(struct packet *packet, enum dump_format_t format, char **ascii_string, char **error) @@ -151,6 +217,16 @@ int packet_to_string(struct packet *packet, int result = STATUS_ERR; /* return value */ size_t size = 0; FILE *s = open_memstream(ascii_string, &size); /* output string */ + int i; + int header_count = packet_header_count(packet); + + /* Print any encapsulation headers preceding layer 3 and 4 headers. */ + for (i = 0; i < header_count - 2; ++i) { + if (packet->headers[i].type == HEADER_NONE) + break; + if (encap_header_to_string(s, packet, i, format, error)) + goto out; + } if ((packet->ipv4 == NULL) && (packet->ipv6 == NULL)) { fprintf(s, "[NO IP HEADER]"); -- GitLab