-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmpls.h
114 lines (100 loc) · 3.71 KB
/
mpls.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
* 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: [email protected] (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 "types.h"
#include <stdlib.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__ */