1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright 2015 Cumulus Networks, Inc.
12 #include <arpa/inet.h>
22 #define MPLS_LABEL_HELPSTR \
23 "Specify label(s) for this route\nOne or more " \
24 "labels in the range (16-1048575) separated by '/'\n"
26 /* Well-known MPLS label values (RFC 3032 etc). */
27 #define MPLS_LABEL_IPV4_EXPLICIT_NULL 0 /* [RFC3032] */
28 #define MPLS_LABEL_ROUTER_ALERT 1 /* [RFC3032] */
29 #define MPLS_LABEL_IPV6_EXPLICIT_NULL 2 /* [RFC3032] */
30 #define MPLS_LABEL_IMPLICIT_NULL 3 /* [RFC3032] */
31 #define MPLS_LABEL_ELI 7 /* [RFC6790] */
32 #define MPLS_LABEL_GAL 13 /* [RFC5586] */
33 #define MPLS_LABEL_OAM_ALERT 14 /* [RFC3429] */
34 #define MPLS_LABEL_EXTENSION 15 /* [RFC7274] */
35 #define MPLS_LABEL_MAX 1048575
36 #define MPLS_LABEL_VALUE_MASK 0x000FFFFF
37 #define MPLS_LABEL_NONE 0xFFFFFFFF /* for internal use only */
39 /* Minimum and maximum label values */
40 #define MPLS_LABEL_RESERVED_MIN 0
41 #define MPLS_LABEL_RESERVED_MAX 15
42 #define MPLS_LABEL_UNRESERVED_MIN 16
43 #define MPLS_LABEL_UNRESERVED_MAX 1048575
44 #define MPLS_LABEL_BASE_ANY 0
46 /* Default min and max SRGB label range */
47 /* Even if the SRGB allows to manage different Label space between routers,
48 * if an operator want to use the same SRGB for all its router, we must fix
49 * a common range. However, Cisco start its SRGB at 16000 and Juniper ends
50 * its SRGB at 16384 for OSPF. Thus, by fixing the minimum SRGB label to
51 * 8000 we could deal with both Cisco and Juniper.
53 #define MPLS_DEFAULT_MIN_SRGB_LABEL 8000
54 #define MPLS_DEFAULT_MAX_SRGB_LABEL 50000
55 #define MPLS_DEFAULT_MIN_SRGB_SIZE 5000
56 #define MPLS_DEFAULT_MAX_SRGB_SIZE 20000
58 /* Maximum # labels that can be pushed. */
59 #define MPLS_MAX_LABELS 16
61 #define IS_MPLS_RESERVED_LABEL(label) (label <= MPLS_LABEL_RESERVED_MAX)
63 #define IS_MPLS_UNRESERVED_LABEL(label) \
64 (label >= MPLS_LABEL_UNRESERVED_MIN \
65 && label <= MPLS_LABEL_UNRESERVED_MAX)
67 /* Definitions for a MPLS label stack entry (RFC 3032). This encodes the
68 * label, EXP, BOS and TTL fields.
70 typedef unsigned int mpls_lse_t
;
72 #define MPLS_LS_LABEL_MASK 0xFFFFF000
73 #define MPLS_LS_LABEL_SHIFT 12
74 #define MPLS_LS_EXP_MASK 0x00000E00
75 #define MPLS_LS_EXP_SHIFT 9
76 #define MPLS_LS_S_MASK 0x00000100
77 #define MPLS_LS_S_SHIFT 8
78 #define MPLS_LS_TTL_MASK 0x000000FF
79 #define MPLS_LS_TTL_SHIFT 0
81 #define MPLS_LABEL_VALUE(lse) \
82 ((lse & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT)
83 #define MPLS_LABEL_EXP(lse) ((lse & MPLS_LS_EXP_MASK) >> MPLS_LS_EXP_SHIFT)
84 #define MPLS_LABEL_BOS(lse) ((lse & MPLS_LS_S_MASK) >> MPLS_LS_S_SHIFT)
85 #define MPLS_LABEL_TTL(lse) ((lse & MPLS_LS_TTL_MASK) >> MPLS_LS_TTL_SHIFT)
87 #define IS_MPLS_LABEL_BOS(ls) (MPLS_LABEL_BOS(ls) == 1)
89 #define MPLS_LABEL_LEN_BITS 20
91 /* MPLS label value as a 32-bit (mostly we only care about the label value). */
92 typedef unsigned int mpls_label_t
;
94 struct mpls_label_stack
{
97 mpls_label_t label
[0]; /* 1 or more labels */
100 /* The MPLS explicit-null label is 0 which means when you memset a mpls_label_t
101 * to zero you have set that variable to explicit-null which was probably not
102 * your intent. The work-around is to use one bit to indicate if the
103 * mpls_label_t has been set by the user. MPLS_INVALID_LABEL has this bit clear
104 * so that we can use MPLS_INVALID_LABEL to initialize mpls_label_t variables.
106 #define MPLS_INVALID_LABEL 0xFFFDFFFF
110 ZEBRA_LSP_NONE
= 0, /* No LSP. */
111 ZEBRA_LSP_STATIC
= 1, /* Static LSP. */
112 ZEBRA_LSP_LDP
= 2, /* LDP LSP. */
113 ZEBRA_LSP_BGP
= 3, /* BGP LSP. */
114 ZEBRA_LSP_OSPF_SR
= 4,/* OSPF Segment Routing LSP. */
115 ZEBRA_LSP_ISIS_SR
= 5,/* IS-IS Segment Routing LSP. */
116 ZEBRA_LSP_SHARP
= 6, /* Identifier for test protocol */
117 ZEBRA_LSP_SRTE
= 7, /* SR-TE LSP */
118 ZEBRA_LSP_EVPN
= 8, /* EVPN VNI Label */
121 /* Functions for basic label operations. */
123 static inline void vni2label(vni_t vni
, mpls_label_t
*label
)
125 uint8_t *tag
= (uint8_t *)label
;
129 tag
[0] = (vni
>> 16) & 0xFF;
130 tag
[1] = (vni
>> 8) & 0xFF;
134 static inline vni_t
label2vni(const mpls_label_t
*label
)
136 uint8_t *tag
= (uint8_t *)label
;
141 vni
= ((uint32_t)*tag
++ << 16);
142 vni
|= (uint32_t)*tag
++ << 8;
143 vni
|= (uint32_t)(*tag
& 0xFF);
148 /* Encode a label stack entry from fields; convert to network byte-order as
149 * the Netlink interface expects MPLS labels to be in this format.
151 static inline mpls_lse_t
mpls_lse_encode(mpls_label_t label
, uint32_t ttl
,
152 uint32_t exp
, uint32_t bos
)
155 lse
= htonl((label
<< MPLS_LS_LABEL_SHIFT
) | (exp
<< MPLS_LS_EXP_SHIFT
)
156 | (bos
? (1 << MPLS_LS_S_SHIFT
) : 0)
157 | (ttl
<< MPLS_LS_TTL_SHIFT
));
161 /* Extract the fields from a label stack entry after converting to host-byte
162 * order. This is expected to be called only for messages received over the
165 static inline void mpls_lse_decode(mpls_lse_t lse
, mpls_label_t
*label
,
166 uint32_t *ttl
, uint32_t *exp
, uint32_t *bos
)
168 mpls_lse_t local_lse
;
170 local_lse
= ntohl(lse
);
171 *label
= MPLS_LABEL_VALUE(local_lse
);
172 *exp
= MPLS_LABEL_EXP(local_lse
);
173 *bos
= MPLS_LABEL_BOS(local_lse
);
174 *ttl
= MPLS_LABEL_TTL(local_lse
);
177 /* Invalid label index value (when used with BGP Prefix-SID). Should
178 * match the BGP definition.
180 #define MPLS_INVALID_LABEL_INDEX 0xFFFFFFFF
182 /* Printable string for labels (with consideration for reserved values). */
183 static inline char *label2str(mpls_label_t label
, enum lsp_types_t type
,
184 char *buf
, size_t len
)
186 if (type
== ZEBRA_LSP_EVPN
) {
187 snprintf(buf
, len
, "%u", label2vni(&label
));
192 case MPLS_LABEL_IPV4_EXPLICIT_NULL
:
193 strlcpy(buf
, "IPv4 Explicit Null", len
);
195 case MPLS_LABEL_ROUTER_ALERT
:
196 strlcpy(buf
, "Router Alert", len
);
198 case MPLS_LABEL_IPV6_EXPLICIT_NULL
:
199 strlcpy(buf
, "IPv6 Explicit Null", len
);
201 case MPLS_LABEL_IMPLICIT_NULL
:
202 strlcpy(buf
, "implicit-null", len
);
205 strlcpy(buf
, "Entropy Label Indicator", len
);
208 strlcpy(buf
, "Generic Associated Channel", len
);
210 case MPLS_LABEL_OAM_ALERT
:
211 strlcpy(buf
, "OAM Alert", len
);
213 case MPLS_LABEL_EXTENSION
:
214 strlcpy(buf
, "Extension", len
);
218 snprintf(buf
, len
, "Reserved (%u)", label
);
220 snprintf(buf
, len
, "%u", label
);
226 * String to label conversion, labels separated by '/'.
228 int mpls_str2label(const char *label_str
, uint8_t *num_labels
,
229 mpls_label_t
*labels
);
231 /* Generic string buffer for label-stack-to-str */
232 #define MPLS_LABEL_STRLEN 1024
235 * Label to string conversion, labels in string separated by '/'.
237 char *mpls_label2str(uint8_t num_labels
, const mpls_label_t
*labels
, char *buf
,
238 int len
, enum lsp_types_t type
, int pretty
);