From ef51e071db7b371786def6b2ea30410663ed8409 Mon Sep 17 00:00:00 2001 From: Neal Cardwell <ncardwell@google.com> Date: Fri, 22 Nov 2013 11:57:25 -0500 Subject: [PATCH] net-test: packetdrill MPLS support: parse MPLS label stacks in packets Code to parse on-the-wire packets using an encapsulation layer that is an MPLS label stack. Change-Id: I62585d491303cd8bd85c8afe5b652c4f1be572d9 --- gtests/net/packetdrill/packet_parser.c | 72 ++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/gtests/net/packetdrill/packet_parser.c b/gtests/net/packetdrill/packet_parser.c index 6001c800..697c5aa1 100644 --- a/gtests/net/packetdrill/packet_parser.c +++ b/gtests/net/packetdrill/packet_parser.c @@ -48,6 +48,8 @@ static int parse_ipv4(struct packet *packet, u8 *header_start, u8 *packet_end, char **error); static int parse_ipv6(struct packet *packet, u8 *header_start, u8 *packet_end, char **error); +static int parse_mpls(struct packet *packet, u8 *header_start, u8 *packet_end, + char **error); static int parse_layer3_packet_by_proto(struct packet *packet, u16 proto, u8 *header_start, u8 *packet_end, char **error); @@ -55,12 +57,11 @@ static int parse_layer4(struct packet *packet, u8 *header_start, int layer4_protocol, int layer4_bytes, u8 *packet_end, bool *is_inner, char **error); -static int parse_layer2_packet(struct packet *packet, int in_bytes, - char **error) +static int parse_layer2_packet(struct packet *packet, + u8 *header_start, u8 *packet_end, + char **error) { - u8 *p = packet->buffer; - /* Note that packet_end points to the byte beyond the end of packet. */ - u8 *packet_end = packet->buffer + in_bytes; + u8 *p = header_start; struct ether_header *ether = NULL; /* Find Ethernet header */ @@ -122,6 +123,9 @@ static int parse_layer3_packet_by_proto(struct packet *packet, asprintf(error, "Bad IP version for ETHERTYPE_IPV6"); goto error_out; } + } else if ((proto == ETHERTYPE_MPLS_UC) || + (proto == ETHERTYPE_MPLS_MC)) { + return parse_mpls(packet, p, packet_end, error); } else { return PACKET_UNKNOWN_L4; } @@ -130,12 +134,12 @@ error_out: return PACKET_BAD; } -static int parse_layer3_packet(struct packet *packet, int in_bytes, - char **error) +static int parse_layer3_packet(struct packet *packet, + u8 *header_start, u8 *packet_end, + char **error) { - u8 *p = packet->buffer; + u8 *p = header_start; /* Note that packet_end points to the byte beyond the end of packet. */ - u8 *packet_end = packet->buffer + in_bytes; struct ipv4 *ip = NULL; /* Examine IPv4/IPv6 header. */ @@ -164,11 +168,16 @@ int parse_packet(struct packet *packet, int in_bytes, char *message = NULL; /* human-readable error summary */ char *hex = NULL; /* hex dump of bad packet */ enum packet_parse_result_t result = PACKET_BAD; + u8 *header_start = packet->buffer; + /* packet_end points to the byte beyond the end of packet. */ + u8 *packet_end = packet->buffer + in_bytes; if (layer == PACKET_LAYER_2_ETHERNET) - result = parse_layer2_packet(packet, in_bytes, error); + result = parse_layer2_packet(packet, header_start, packet_end, + error); else if (layer == PACKET_LAYER_3_IP) - result = parse_layer3_packet(packet, in_bytes, error); + result = parse_layer3_packet(packet, header_start, packet_end, + error); else assert(!"bad layer"); @@ -483,6 +492,47 @@ error_out: return PACKET_BAD; } +int parse_mpls(struct packet *packet, u8 *header_start, u8 *packet_end, + char **error) +{ + struct header *mpls_header = NULL; + u8 *p = header_start; + int mpls_header_bytes = 0; + int mpls_total_bytes = packet_end - p; + bool is_stack_bottom = false; + + do { + struct mpls *mpls_entry = (struct mpls *)(p); + + if (p + sizeof(struct mpls) > packet_end) { + asprintf(error, "MPLS stack entry overflows packet"); + goto error_out; + } + + is_stack_bottom = mpls_entry_stack(mpls_entry); + + p += sizeof(struct mpls); + mpls_header_bytes += sizeof(struct mpls); + } while (!is_stack_bottom && p < packet_end); + + assert(mpls_header_bytes <= mpls_total_bytes); + + mpls_header = packet_append_header(packet, HEADER_MPLS, + mpls_header_bytes); + if (mpls_header == NULL) { + asprintf(error, "Too many nested headers at MPLS header"); + goto error_out; + } + mpls_header->total_bytes = mpls_total_bytes; + + /* Move on to the header inside the MPLS label stack. */ + assert(p <= packet_end); + return parse_layer3_packet(packet, p, packet_end, error); + +error_out: + return PACKET_BAD; +} + static int parse_layer4(struct packet *packet, u8 *layer4_start, int layer4_protocol, int layer4_bytes, u8 *packet_end, bool *is_inner, char **error) -- GitLab