diff options
Diffstat (limited to 'test/packetdrill/mpls.h')
-rw-r--r-- | test/packetdrill/mpls.h | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/test/packetdrill/mpls.h b/test/packetdrill/mpls.h new file mode 100644 index 0000000..b536437 --- /dev/null +++ b/test/packetdrill/mpls.h @@ -0,0 +1,113 @@ +/* + * 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 MPLS 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 MPLS .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 MPLS-related definitions here. + */ + +#ifndef __MPLS_HEADERS_H__ +#define __MPLS_HEADERS_H__ + +#include <stdlib.h> +#include "types.h" + +/* On-the-wire MPLS "label stack entry", per RFC 3032 and RFC 5462. */ +struct mpls { + __be32 entry; +}; + +/* Bit-shifting macros to access MPLS fields (the label straddles byte + * boundaries so there's no simple/clean way to use bit fields). + */ +#define MPLS_LABEL_MASK 0xfffff000 /* label */ +#define MPLS_LABEL_SHIFT 12 +#define MPLS_TC_MASK 0x00000e00 /* traffic class */ +#define MPLS_TC_SHIFT 9 +#define MPLS_STACK_MASK 0x00000100 /* is stack bottom? */ +#define MPLS_STACK_SHIFT 8 +#define MPLS_TTL_MASK 0x000000ff /* time to live */ +#define MPLS_TTL_SHIFT 0 + +/* Return the label from an MPLS label stack entry. */ +static inline u32 mpls_entry_label(const struct mpls *mpls) +{ + return (ntohl(mpls->entry) & MPLS_LABEL_MASK) >> MPLS_LABEL_SHIFT; +} + +/* Return the traffic class from an MPLS label stack entry. */ +static inline u8 mpls_entry_tc(const struct mpls *mpls) +{ + return (ntohl(mpls->entry) & MPLS_TC_MASK) >> MPLS_TC_SHIFT; +} + +/* Return the "is stack bottom?" bit from an MPLS label stack entry. */ +static inline bool mpls_entry_stack(const struct mpls *mpls) +{ + return (ntohl(mpls->entry) & MPLS_STACK_MASK) >> MPLS_STACK_SHIFT; +} + +/* Return the TTL from an MPLS label stack entry. */ +static inline u8 mpls_entry_ttl(const struct mpls *mpls) +{ + return (ntohl(mpls->entry) & MPLS_TTL_MASK) >> MPLS_TTL_SHIFT; +} + +/* Fill in an MPLS label stack entry with the given field values. */ +static inline void mpls_entry_set(u32 label, u8 traffic_class, + bool is_stack_bottom, u8 ttl, + struct mpls *mpls) +{ + mpls->entry = htonl((label << MPLS_LABEL_SHIFT) | + (traffic_class << MPLS_TC_SHIFT) | + (is_stack_bottom << MPLS_STACK_SHIFT) | + (ttl << MPLS_TTL_SHIFT)); +} + +/* Parse-time representation of an MPLS label stack entry. */ +#define MPLS_STACK_MAX_ENTRIES 6 /* maximum number of label entries */ +struct mpls_stack { + struct mpls entries[MPLS_STACK_MAX_ENTRIES]; + int length; /* number of MPLS label stack entries */ +}; + +/* Allocate and initialize a new MPLS label stack as empty. */ +static inline struct mpls_stack *mpls_stack_new(void) +{ + return calloc(1, sizeof(struct mpls_stack)); +} + +/* Appends the given MPLS label stack entry to the given stack. Returns + * STATUS_OK on success, or STATUS_ERR on error (if the label stack is full). + */ +static inline int mpls_stack_append(struct mpls_stack *stack, struct mpls mpls) +{ + if (stack->length >= ARRAY_SIZE(stack->entries)) + return STATUS_ERR; + stack->entries[stack->length++] = mpls; + return STATUS_OK; +} + +#endif /* __MPLS_HEADERS_H__ */ |