blob: b87cb1efcd21ea67ad2512a483221f09df5d0902 [file] [log] [blame]
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vnet/ip/ip.h>
17#include <vnet/dpo/mpls_label_dpo.h>
18#include <vnet/mpls/mpls.h>
Neale Rannsf363ebd2017-12-06 00:45:33 -080019#include <vnet/dpo/drop_dpo.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010020
Neale Ranns8f5fef22020-12-21 08:29:34 +000021// clang-format off
22
Filip Tehlareb9a27f2019-03-07 01:42:11 -080023#ifndef CLIB_MARCH_VARIANT
Neale Ranns0bfe5d82016-08-25 15:29:12 +010024/*
25 * pool of all MPLS Label DPOs
26 */
27mpls_label_dpo_t *mpls_label_dpo_pool;
28
Neale Ranns31ed7442018-02-23 05:29:09 -080029/**
30 * Strings for the flags
31 */
32const char* mpls_label_dpo_attr_names[] = MPLS_LABEL_DPO_ATTR_NAMES;
33
34/**
35 * registered DPO types for each of the label sub-types. And there's a
36 * subtype for each of the flag combinations.
37 */
38static dpo_type_t mpls_label_dpo_types[1 << MPLS_LABEL_DPO_ATTR_MAX];
39
Neale Ranns0bfe5d82016-08-25 15:29:12 +010040static mpls_label_dpo_t *
41mpls_label_dpo_alloc (void)
42{
43 mpls_label_dpo_t *mld;
Dave Barach26d890e2020-06-05 09:42:50 -040044 vlib_main_t *vm;
45 u8 did_barrier_sync;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010046
Dave Barach26d890e2020-06-05 09:42:50 -040047 dpo_pool_barrier_sync (vm, mpls_label_dpo_pool, did_barrier_sync);
Neale Ranns0bfe5d82016-08-25 15:29:12 +010048 pool_get_aligned(mpls_label_dpo_pool, mld, CLIB_CACHE_LINE_BYTES);
Dave Barach26d890e2020-06-05 09:42:50 -040049 dpo_pool_barrier_release (vm, did_barrier_sync);
50
Dave Barachb7b92992018-10-17 10:38:51 -040051 clib_memset(mld, 0, sizeof(*mld));
Neale Ranns0bfe5d82016-08-25 15:29:12 +010052
53 dpo_reset(&mld->mld_dpo);
54
55 return (mld);
56}
57
58static index_t
59mpls_label_dpo_get_index (mpls_label_dpo_t *mld)
60{
61 return (mld - mpls_label_dpo_pool);
62}
63
Neale Ranns31ed7442018-02-23 05:29:09 -080064void
65mpls_label_dpo_create (fib_mpls_label_t *label_stack,
Neale Ranns0bfe5d82016-08-25 15:29:12 +010066 mpls_eos_bit_t eos,
Neale Rannsad422ed2016-11-02 14:20:04 +000067 dpo_proto_t payload_proto,
Neale Ranns31ed7442018-02-23 05:29:09 -080068 mpls_label_dpo_flags_t flags,
69 const dpo_id_t *parent,
70 dpo_id_t *dpo)
Neale Ranns0bfe5d82016-08-25 15:29:12 +010071{
72 mpls_label_dpo_t *mld;
Neale Ranns31ed7442018-02-23 05:29:09 -080073 dpo_type_t dtype;
Neale Rannsad422ed2016-11-02 14:20:04 +000074 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010075
Neale Ranns31ed7442018-02-23 05:29:09 -080076 if ((DPO_PROTO_IP4 != payload_proto) &&
77 (DPO_PROTO_IP6 != payload_proto))
78 {
79 /*
80 * remove unsupported configuration
81 */
82 flags &= ~MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR;
83 }
84
Neale Ranns0bfe5d82016-08-25 15:29:12 +010085 mld = mpls_label_dpo_alloc();
Neale Ranns31ed7442018-02-23 05:29:09 -080086 mld->mld_flags = flags;
87 dtype = mpls_label_dpo_types[flags];
Neale Rannsf363ebd2017-12-06 00:45:33 -080088
89 if (MPLS_LABEL_DPO_MAX_N_LABELS < vec_len(label_stack))
90 {
91 clib_warning("Label stack size exceeded");
Neale Ranns31ed7442018-02-23 05:29:09 -080092 dpo_stack(dtype,
Neale Rannsf363ebd2017-12-06 00:45:33 -080093 mld->mld_payload_proto,
94 &mld->mld_dpo,
95 drop_dpo_get(DPO_PROTO_MPLS));
Neale Rannsf363ebd2017-12-06 00:45:33 -080096 }
Neale Ranns31ed7442018-02-23 05:29:09 -080097 else
Neale Rannsad422ed2016-11-02 14:20:04 +000098 {
Neale Ranns31ed7442018-02-23 05:29:09 -080099 mld->mld_n_labels = vec_len(label_stack);
100 mld->mld_n_hdr_bytes = mld->mld_n_labels * sizeof(mld->mld_hdr[0]);
101 mld->mld_payload_proto = payload_proto;
102
103 /*
104 * construct label rewrite headers for each value passed.
105 * get the header in network byte order since we will paint it
106 * on a packet in the data-plane
107 */
108 for (ii = 0; ii < mld->mld_n_labels-1; ii++)
109 {
110 vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl,
111 label_stack[ii].fml_value);
112 vnet_mpls_uc_set_exp(&mld->mld_hdr[ii].label_exp_s_ttl,
113 label_stack[ii].fml_exp);
114 vnet_mpls_uc_set_s(&mld->mld_hdr[ii].label_exp_s_ttl,
115 MPLS_NON_EOS);
116 if (0 != label_stack[ii].fml_ttl)
117 {
118 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
119 label_stack[ii].fml_ttl);
120 }
121 else
122 {
123 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
124 MPLS_LABEL_DEFAULT_TTL);
125 }
126 mld->mld_hdr[ii].label_exp_s_ttl =
127 clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
128 }
129
130 /*
131 * the inner most label
132 */
133 ii = mld->mld_n_labels-1;
134
135 vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl,
136 label_stack[ii].fml_value);
137 vnet_mpls_uc_set_exp(&mld->mld_hdr[ii].label_exp_s_ttl,
138 label_stack[ii].fml_exp);
139 vnet_mpls_uc_set_s(&mld->mld_hdr[ii].label_exp_s_ttl, eos);
140 if (0 != label_stack[ii].fml_ttl)
141 {
142 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
143 label_stack[ii].fml_ttl);
144 }
145 else
146 {
147 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
148 MPLS_LABEL_DEFAULT_TTL);
149 }
150 mld->mld_hdr[ii].label_exp_s_ttl =
151 clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
152
153 /*
154 * pipe/uniform mode is only supported for the bottom of stack label
155 */
156 if (FIB_MPLS_LSP_MODE_UNIFORM == label_stack[ii].fml_mode)
157 {
158 mld->mld_flags |= MPLS_LABEL_DPO_FLAG_UNIFORM_MODE;
159 }
160 else
161 {
162 mld->mld_flags &= ~MPLS_LABEL_DPO_FLAG_UNIFORM_MODE;
163 }
164 dtype = mpls_label_dpo_types[mld->mld_flags];
165
166 /*
167 * stack this label object on its parent.
168 */
169 dpo_stack(dtype,
170 mld->mld_payload_proto,
171 &mld->mld_dpo,
172 parent);
Neale Rannsad422ed2016-11-02 14:20:04 +0000173 }
174
Neale Ranns31ed7442018-02-23 05:29:09 -0800175 dpo_set(dpo,
176 dtype,
177 mld->mld_payload_proto,
178 mpls_label_dpo_get_index(mld));
179}
Neale Rannsad422ed2016-11-02 14:20:04 +0000180
Neale Ranns31ed7442018-02-23 05:29:09 -0800181u8*
182format_mpls_label_dpo_flags (u8 *s, va_list *args)
183{
184 mpls_label_dpo_flags_t flags = va_arg (*args, int);
185 mpls_label_dpo_attr_t attr;
Neale Rannsad422ed2016-11-02 14:20:04 +0000186
Neale Ranns31ed7442018-02-23 05:29:09 -0800187 FOR_EACH_MPLS_LABEL_DPO_ATTR(attr)
188 {
189 if ((1 << attr) & flags)
190 {
191 s = format(s, "%s,", mpls_label_dpo_attr_names[attr]);
192 }
193 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100194
Neale Ranns31ed7442018-02-23 05:29:09 -0800195 return (s);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100196}
197
198u8*
199format_mpls_label_dpo (u8 *s, va_list *args)
200{
201 index_t index = va_arg (*args, index_t);
202 u32 indent = va_arg (*args, u32);
203 mpls_unicast_header_t hdr;
204 mpls_label_dpo_t *mld;
Neale Rannsad422ed2016-11-02 14:20:04 +0000205 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100206
Neale Ranns15002542017-09-10 04:39:11 -0700207 if (pool_is_free_index(mpls_label_dpo_pool, index))
208 {
209 /*
210 * the packet trace can be printed after the DPO has been deleted
211 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800212 return (format(s, "mpls-label[???,%d]:", index));
Neale Ranns15002542017-09-10 04:39:11 -0700213 }
214
215 mld = mpls_label_dpo_get(index);
Neale Ranns7c922dc2018-08-30 06:12:27 -0700216 s = format(s, "mpls-label[%U@%d]:",
Neale Ranns31ed7442018-02-23 05:29:09 -0800217 format_mpls_label_dpo_flags,
218 (int) mld->mld_flags, index);
Neale Ranns15002542017-09-10 04:39:11 -0700219
Neale Rannsad422ed2016-11-02 14:20:04 +0000220 for (ii = 0; ii < mld->mld_n_labels; ii++)
221 {
222 hdr.label_exp_s_ttl =
223 clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
224 s = format(s, "%U", format_mpls_header, hdr);
225 }
226
227 s = format(s, "\n%U", format_white_space, indent);
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000228 s = format(s, "%U", format_dpo_id, &mld->mld_dpo, indent+2);
229
230 return (s);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100231}
232
233static void
234mpls_label_dpo_lock (dpo_id_t *dpo)
235{
236 mpls_label_dpo_t *mld;
237
238 mld = mpls_label_dpo_get(dpo->dpoi_index);
239
240 mld->mld_locks++;
241}
242
243static void
244mpls_label_dpo_unlock (dpo_id_t *dpo)
245{
246 mpls_label_dpo_t *mld;
247
248 mld = mpls_label_dpo_get(dpo->dpoi_index);
249
250 mld->mld_locks--;
251
252 if (0 == mld->mld_locks)
253 {
254 dpo_reset(&mld->mld_dpo);
255 pool_put(mpls_label_dpo_pool, mld);
256 }
257}
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800258#endif /* CLIB_MARCH_VARIANT */
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100259
260/**
261 * @brief A struct to hold tracing information for the MPLS label imposition
262 * node.
263 */
264typedef struct mpls_label_imposition_trace_t_
265{
266 /**
267 * The MPLS header imposed
268 */
269 mpls_unicast_header_t hdr;
Neale Ranns31ed7442018-02-23 05:29:09 -0800270
271 /**
272 * TTL imposed - only valid for uniform LSPs
273 */
274 u8 ttl;
275
276 /**
277 * TTL imposed - only valid for uniform LSPs
278 */
279 u8 exp;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100280} mpls_label_imposition_trace_t;
281
Neale Ranns696e88d2017-03-16 07:34:55 -0400282always_inline mpls_unicast_header_t *
283mpls_label_paint (vlib_buffer_t * b0,
Neale Ranns31ed7442018-02-23 05:29:09 -0800284 mpls_label_dpo_t *mld0)
Neale Ranns696e88d2017-03-16 07:34:55 -0400285{
286 mpls_unicast_header_t *hdr0;
287
288 vlib_buffer_advance(b0, -(mld0->mld_n_hdr_bytes));
289
290 hdr0 = vlib_buffer_get_current(b0);
291
Pablo Camarillo5d73eec2017-04-24 17:51:56 +0200292 if (1 == mld0->mld_n_labels)
Neale Ranns696e88d2017-03-16 07:34:55 -0400293 {
294 /* optimise for the common case of one label */
295 *hdr0 = mld0->mld_hdr[0];
296 }
297 else
298 {
Dave Barach178cf492018-11-13 16:34:13 -0500299 clib_memcpy_fast(hdr0, mld0->mld_hdr, mld0->mld_n_hdr_bytes);
Neale Ranns696e88d2017-03-16 07:34:55 -0400300 hdr0 = hdr0 + (mld0->mld_n_labels - 1);
301 }
Neale Ranns31ed7442018-02-23 05:29:09 -0800302
303 return (hdr0);
304}
305
306/**
307 * Paint on an MPLS label and fixup the TTL
308 */
309always_inline mpls_unicast_header_t *
310mpls_label_paint_w_ttl (vlib_buffer_t * b0,
311 mpls_label_dpo_t *mld0,
312 u8 ttl0)
313{
314 mpls_unicast_header_t *hdr0;
315
316 hdr0 = mpls_label_paint(b0, mld0);
317
Neale Ranns696e88d2017-03-16 07:34:55 -0400318 /* fixup the TTL for the inner most label */
319 ((char*)hdr0)[3] = ttl0;
320
321 return (hdr0);
322}
323
Neale Ranns31ed7442018-02-23 05:29:09 -0800324/**
325 * Paint on an MPLS label and fixup the TTL and EXP bits.
326 */
327always_inline mpls_unicast_header_t *
328mpls_label_paint_w_ttl_exp (vlib_buffer_t * b0,
329 mpls_label_dpo_t *mld0,
330 u8 ttl0,
331 u8 exp0)
332{
333 mpls_unicast_header_t *hdr0;
334
335 hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
336
337 /* fixup the EXP for the inner most label */
338 ((char*)hdr0)[2] |= (exp0 << 1);
339
340 return (hdr0);
341}
342
343/**
344 * Paint on an MPLS label and fixup the TTL and EXP bits
345 * When the EXP bits are *already* bit shift to the correct place in
346 * in the 2nd byte (i.e. they were read from another label)
347 */
348always_inline mpls_unicast_header_t *
349mpls_label_paint_w_ttl_mpls_exp (vlib_buffer_t * b0,
350 mpls_label_dpo_t *mld0,
351 u8 ttl0,
352 u8 exp0)
353{
354 mpls_unicast_header_t *hdr0;
355
356 hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
357
358 /* fixup the EXP for the inner most label */
359 ((char*)hdr0)[2] |= exp0;
360
361 return (hdr0);
362}
363
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100364always_inline uword
Neale Rannsad422ed2016-11-02 14:20:04 +0000365mpls_label_imposition_inline (vlib_main_t * vm,
366 vlib_node_runtime_t * node,
367 vlib_frame_t * from_frame,
Neale Ranns31ed7442018-02-23 05:29:09 -0800368 const dpo_proto_t dproto,
369 const mpls_label_dpo_flags_t flags)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100370{
371 u32 n_left_from, next_index, * from, * to_next;
372
373 from = vlib_frame_vector_args (from_frame);
374 n_left_from = from_frame->n_vectors;
375
376 next_index = node->cached_next_index;
377
378 while (n_left_from > 0)
379 {
380 u32 n_left_to_next;
381
382 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
383
Neale Ranns696e88d2017-03-16 07:34:55 -0400384 while (n_left_from >= 8 && n_left_to_next >= 4)
Neale Ranns9ca18c62016-12-10 21:08:09 +0000385 {
Neale Ranns696e88d2017-03-16 07:34:55 -0400386 u32 bi0, mldi0, bi1, mldi1, bi2, mldi2, bi3, mldi3;
387 mpls_unicast_header_t *hdr0, *hdr1, *hdr2, *hdr3;
388 mpls_label_dpo_t *mld0, *mld1, *mld2, *mld3;
389 vlib_buffer_t * b0, *b1, * b2, *b3;
390 u32 next0, next1, next2, next3;
Neale Ranns31ed7442018-02-23 05:29:09 -0800391 u8 ttl0, ttl1, ttl2, ttl3;
392 u8 exp0, exp1, exp2, exp3;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000393
394 bi0 = to_next[0] = from[0];
395 bi1 = to_next[1] = from[1];
Neale Ranns696e88d2017-03-16 07:34:55 -0400396 bi2 = to_next[2] = from[2];
397 bi3 = to_next[3] = from[3];
Neale Ranns9ca18c62016-12-10 21:08:09 +0000398
399 /* Prefetch next iteration. */
400 {
Neale Ranns696e88d2017-03-16 07:34:55 -0400401 vlib_buffer_t * p2, * p3, *p4, *p5;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000402
403 p2 = vlib_get_buffer (vm, from[2]);
404 p3 = vlib_get_buffer (vm, from[3]);
Neale Ranns696e88d2017-03-16 07:34:55 -0400405 p4 = vlib_get_buffer (vm, from[4]);
406 p5 = vlib_get_buffer (vm, from[5]);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000407
408 vlib_prefetch_buffer_header (p2, STORE);
409 vlib_prefetch_buffer_header (p3, STORE);
Neale Ranns696e88d2017-03-16 07:34:55 -0400410 vlib_prefetch_buffer_header (p4, STORE);
411 vlib_prefetch_buffer_header (p5, STORE);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000412
413 CLIB_PREFETCH (p2->data, sizeof (hdr0[0]), STORE);
414 CLIB_PREFETCH (p3->data, sizeof (hdr0[0]), STORE);
Neale Ranns696e88d2017-03-16 07:34:55 -0400415 CLIB_PREFETCH (p4->data, sizeof (hdr0[0]), STORE);
416 CLIB_PREFETCH (p5->data, sizeof (hdr0[0]), STORE);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000417 }
418
Neale Ranns696e88d2017-03-16 07:34:55 -0400419 from += 4;
420 to_next += 4;
421 n_left_from -= 4;
422 n_left_to_next -= 4;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000423
424 b0 = vlib_get_buffer (vm, bi0);
425 b1 = vlib_get_buffer (vm, bi1);
Neale Ranns696e88d2017-03-16 07:34:55 -0400426 b2 = vlib_get_buffer (vm, bi2);
427 b3 = vlib_get_buffer (vm, bi3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000428
429 /* dst lookup was done by ip4 lookup */
430 mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
431 mldi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
Neale Ranns696e88d2017-03-16 07:34:55 -0400432 mldi2 = vnet_buffer(b2)->ip.adj_index[VLIB_TX];
433 mldi3 = vnet_buffer(b3)->ip.adj_index[VLIB_TX];
Neale Ranns9ca18c62016-12-10 21:08:09 +0000434 mld0 = mpls_label_dpo_get(mldi0);
435 mld1 = mpls_label_dpo_get(mldi1);
Neale Ranns696e88d2017-03-16 07:34:55 -0400436 mld2 = mpls_label_dpo_get(mldi2);
437 mld3 = mpls_label_dpo_get(mldi3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000438
Neale Ranns31ed7442018-02-23 05:29:09 -0800439 if (DPO_PROTO_MPLS != dproto)
Neale Ranns9ca18c62016-12-10 21:08:09 +0000440 {
441 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800442 * These are the non-MPLS payload imposition cases
Neale Ranns9ca18c62016-12-10 21:08:09 +0000443 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800444 if (DPO_PROTO_IP4 == dproto)
445 {
446 ip4_header_t * ip0 = vlib_buffer_get_current(b0);
447 ip4_header_t * ip1 = vlib_buffer_get_current(b1);
448 ip4_header_t * ip2 = vlib_buffer_get_current(b2);
449 ip4_header_t * ip3 = vlib_buffer_get_current(b3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000450
Neale Ranns31ed7442018-02-23 05:29:09 -0800451 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
452 {
453 /*
454 * decrement the TTL on ingress to the LSP
455 */
456 u32 checksum0;
457 u32 checksum1;
458 u32 checksum2;
459 u32 checksum3;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000460
Neale Ranns31ed7442018-02-23 05:29:09 -0800461 checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
462 checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
463 checksum2 = ip2->checksum + clib_host_to_net_u16 (0x0100);
464 checksum3 = ip3->checksum + clib_host_to_net_u16 (0x0100);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000465
Neale Ranns31ed7442018-02-23 05:29:09 -0800466 checksum0 += checksum0 >= 0xffff;
467 checksum1 += checksum1 >= 0xffff;
468 checksum2 += checksum2 >= 0xffff;
469 checksum3 += checksum3 >= 0xffff;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000470
Neale Ranns31ed7442018-02-23 05:29:09 -0800471 ip0->checksum = checksum0;
472 ip1->checksum = checksum1;
473 ip2->checksum = checksum2;
474 ip3->checksum = checksum3;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000475
Neale Ranns31ed7442018-02-23 05:29:09 -0800476 ip0->ttl -= 1;
477 ip1->ttl -= 1;
478 ip2->ttl -= 1;
479 ip3->ttl -= 1;
480 }
481
482 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
483 {
484 ttl1 = ip1->ttl;
485 ttl0 = ip0->ttl;
486 ttl3 = ip3->ttl;
487 ttl2 = ip2->ttl;
488 /* by default copy the 3 most significant bits */
489 exp0 = ip_dscp_to_mpls_exp(ip0->tos);
490 exp1 = ip_dscp_to_mpls_exp(ip1->tos);
491 exp2 = ip_dscp_to_mpls_exp(ip2->tos);
492 exp3 = ip_dscp_to_mpls_exp(ip3->tos);
493 }
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530494
495 /* save the payload proto information in mpls opaque */
496 vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP4;
497 vnet_buffer(b1)->mpls.pyld_proto = DPO_PROTO_IP4;
498 vnet_buffer(b2)->mpls.pyld_proto = DPO_PROTO_IP4;
499 vnet_buffer(b3)->mpls.pyld_proto = DPO_PROTO_IP4;
Neale Ranns31ed7442018-02-23 05:29:09 -0800500 }
501 else if (DPO_PROTO_IP6 == dproto)
502 {
503 /*
504 * decrement the TTL on ingress to the LSP
505 */
506 ip6_header_t * ip0 = vlib_buffer_get_current(b0);
507 ip6_header_t * ip1 = vlib_buffer_get_current(b1);
508 ip6_header_t * ip2 = vlib_buffer_get_current(b2);
509 ip6_header_t * ip3 = vlib_buffer_get_current(b3);
510
511 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
512 {
513 ip0->hop_limit -= 1;
514 ip1->hop_limit -= 1;
515 ip2->hop_limit -= 1;
516 ip3->hop_limit -= 1;
517 }
518 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
519 {
520 ttl0 = ip0->hop_limit;
521 ttl1 = ip1->hop_limit;
522 ttl2 = ip2->hop_limit;
523 ttl3 = ip3->hop_limit;
524 /* by default copy the 3 most significant bits */
525 exp0 = ip_dscp_to_mpls_exp(
526 ip6_traffic_class_network_order(ip0));
527 exp1 = ip_dscp_to_mpls_exp(
528 ip6_traffic_class_network_order(ip1));
529 exp2 = ip_dscp_to_mpls_exp(
530 ip6_traffic_class_network_order(ip2));
531 exp3 = ip_dscp_to_mpls_exp(
532 ip6_traffic_class_network_order(ip3));
533 }
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530534
535 /* save the payload proto information in mpls opaque */
536 vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP6;
537 vnet_buffer(b1)->mpls.pyld_proto = DPO_PROTO_IP6;
538 vnet_buffer(b2)->mpls.pyld_proto = DPO_PROTO_IP6;
539 vnet_buffer(b3)->mpls.pyld_proto = DPO_PROTO_IP6;
Neale Ranns31ed7442018-02-23 05:29:09 -0800540 }
541 else
542 {
543 /*
544 * nothing to change in the ethernet header
545 */
546 ttl0 = ttl1 = ttl2 = ttl3 = MPLS_LABEL_DEFAULT_TTL;
547 exp0 = exp1 = exp2 = exp3 = MPLS_LABEL_DEFAULT_EXP;
548 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000549 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800550 * These are the non-MPLS payload imposition cases.
551 * Based on the LSP mode either, for uniform, copy down the TTL
552 * and EXP from the payload or, for pipe mode, slap on the value
553 * requested from config
Neale Ranns9ca18c62016-12-10 21:08:09 +0000554 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800555 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
556 {
557 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
558 hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
559 hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
560 hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
561 }
562 else
563 {
564 hdr0 = mpls_label_paint(b0, mld0);
565 hdr1 = mpls_label_paint(b1, mld1);
566 hdr2 = mpls_label_paint(b2, mld2);
567 hdr3 = mpls_label_paint(b3, mld3);
568 }
Neale Rannsda78f952017-05-24 09:15:43 -0700569 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000570 else
571 {
572 /*
573 * else, the packet to be encapped is an MPLS packet
Neale Ranns31ed7442018-02-23 05:29:09 -0800574 * there are two cases to consider:
575 * 1 - this is an MPLS label swap at an LSP midpoint.
576 * recognisable because mpls.first = 1. In this case the
577 * TTL must be set to the current value -1.
578 * 2 - The MPLS packet is recursing (or being injected into)
579 * this LSP, in which case the pipe/uniform rules apply
580 *
Neale Ranns9ca18c62016-12-10 21:08:09 +0000581 */
582 if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
583 {
584 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800585 * The first label to be imposed on the packet. this is a
586 * label swap.in which case we stashed the TTL and EXP bits
587 * in the packet in the lookup node
Neale Ranns9ca18c62016-12-10 21:08:09 +0000588 */
589 ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
590
591 ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800592 exp0 = vnet_buffer(b0)->mpls.exp;
593 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000594 }
595 else
596 {
597 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800598 * not the first label. implying we are recusring down a
599 * chain of output labels. Each layer is considered a new
600 * LSP - hence the TTL/EXP are pipe/uniform handled
Neale Ranns9ca18c62016-12-10 21:08:09 +0000601 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800602 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
603 {
604 hdr0 = vlib_buffer_get_current(b0);
605 ttl0 = ((u8*)hdr0)[3];
606 exp0 = ((u8*)hdr0)[2] & 0xe;
607 hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
608 }
609 else
610 {
611 hdr0 = mpls_label_paint(b0, mld0);
612 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000613 }
614 if (PREDICT_TRUE(vnet_buffer(b1)->mpls.first))
615 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800616 ASSERT(0 != vnet_buffer (b1)->mpls.ttl);
617
Neale Ranns9ca18c62016-12-10 21:08:09 +0000618 ttl1 = vnet_buffer(b1)->mpls.ttl - 1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800619 exp1 = vnet_buffer(b1)->mpls.exp;
620 hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000621 }
622 else
623 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800624 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
625 {
626 hdr1 = vlib_buffer_get_current(b1);
627 ttl1 = ((u8*)hdr1)[3];
628 exp1 = ((u8*)hdr1)[2] & 0xe;
629 hdr1 = mpls_label_paint_w_ttl_mpls_exp(b1, mld1, ttl1, exp1);
630 }
631 else
632 {
633 hdr1 = mpls_label_paint(b1, mld1);
634 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000635 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400636 if (PREDICT_TRUE(vnet_buffer(b2)->mpls.first))
637 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800638 ASSERT(0 != vnet_buffer (b2)->mpls.ttl);
Neale Ranns696e88d2017-03-16 07:34:55 -0400639
640 ttl2 = vnet_buffer(b2)->mpls.ttl - 1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800641 exp2 = vnet_buffer(b2)->mpls.exp;
642 hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
Neale Ranns696e88d2017-03-16 07:34:55 -0400643 }
644 else
645 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800646 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
647 {
648 hdr2 = vlib_buffer_get_current(b2);
649 ttl2 = ((u8*)hdr2)[3];
650 exp2 = ((u8*)hdr2)[2] & 0xe;
651 hdr2 = mpls_label_paint_w_ttl_mpls_exp(b2, mld2, ttl2, exp2);
652 }
653 else
654 {
655 hdr2 = mpls_label_paint(b2, mld2);
656 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400657 }
658 if (PREDICT_TRUE(vnet_buffer(b3)->mpls.first))
659 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800660 ASSERT(0 != vnet_buffer (b3)->mpls.ttl);
661
Neale Ranns696e88d2017-03-16 07:34:55 -0400662 ttl3 = vnet_buffer(b3)->mpls.ttl - 1;
Neale Ranns19bd1902018-03-19 02:32:57 -0700663 exp3 = vnet_buffer(b3)->mpls.exp;
Neale Ranns31ed7442018-02-23 05:29:09 -0800664 hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
Neale Ranns696e88d2017-03-16 07:34:55 -0400665 }
666 else
667 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800668 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
669 {
670 hdr3 = vlib_buffer_get_current(b3);
671 ttl3 = ((u8*)hdr3)[3];
672 exp3 = ((u8*)hdr3)[2] & 0xe;
673 hdr3 = mpls_label_paint_w_ttl_mpls_exp(b3, mld3, ttl3, exp3);
674 }
675 else
676 {
677 hdr3 = mpls_label_paint(b3, mld3);
678 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400679 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000680
Neale Ranns31ed7442018-02-23 05:29:09 -0800681 vnet_buffer(b0)->mpls.first = 0;
682 vnet_buffer(b1)->mpls.first = 0;
683 vnet_buffer(b2)->mpls.first = 0;
684 vnet_buffer(b3)->mpls.first = 0;
685 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000686
687 next0 = mld0->mld_dpo.dpoi_next_node;
688 next1 = mld1->mld_dpo.dpoi_next_node;
Neale Ranns696e88d2017-03-16 07:34:55 -0400689 next2 = mld2->mld_dpo.dpoi_next_node;
690 next3 = mld3->mld_dpo.dpoi_next_node;
Neale Ranns31ed7442018-02-23 05:29:09 -0800691
Neale Ranns9ca18c62016-12-10 21:08:09 +0000692 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
693 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = mld1->mld_dpo.dpoi_index;
Neale Ranns696e88d2017-03-16 07:34:55 -0400694 vnet_buffer(b2)->ip.adj_index[VLIB_TX] = mld2->mld_dpo.dpoi_index;
695 vnet_buffer(b3)->ip.adj_index[VLIB_TX] = mld3->mld_dpo.dpoi_index;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000696
697 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
698 {
699 mpls_label_imposition_trace_t *tr =
700 vlib_add_trace (vm, node, b0, sizeof (*tr));
701 tr->hdr = *hdr0;
Neale Ranns31ed7442018-02-23 05:29:09 -0800702 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
703 {
704 tr->ttl = ttl0;
705 tr->exp = exp0;
706 }
707 else
708 {
709 tr->ttl = tr->exp = 0;
710 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000711 }
712 if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
713 {
714 mpls_label_imposition_trace_t *tr =
715 vlib_add_trace (vm, node, b1, sizeof (*tr));
716 tr->hdr = *hdr1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800717 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
718 {
719 tr->ttl = ttl1;
720 tr->exp = exp1;
721 }
722 else
723 {
724 tr->ttl = tr->exp = 0;
725 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000726 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400727 if (PREDICT_FALSE(b2->flags & VLIB_BUFFER_IS_TRACED))
728 {
729 mpls_label_imposition_trace_t *tr =
730 vlib_add_trace (vm, node, b2, sizeof (*tr));
731 tr->hdr = *hdr2;
Neale Ranns31ed7442018-02-23 05:29:09 -0800732 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
733 {
734 tr->ttl = ttl2;
735 tr->exp = exp2;
736 }
737 else
738 {
739 tr->ttl = tr->exp = 0;
740 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400741 }
742 if (PREDICT_FALSE(b3->flags & VLIB_BUFFER_IS_TRACED))
743 {
744 mpls_label_imposition_trace_t *tr =
745 vlib_add_trace (vm, node, b3, sizeof (*tr));
746 tr->hdr = *hdr3;
Neale Ranns31ed7442018-02-23 05:29:09 -0800747 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
748 {
749 tr->ttl = ttl3;
750 tr->exp = exp3;
751 }
752 else
753 {
754 tr->ttl = tr->exp = 0;
755 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400756 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000757
Neale Ranns696e88d2017-03-16 07:34:55 -0400758 vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next,
Neale Ranns9ca18c62016-12-10 21:08:09 +0000759 n_left_to_next,
Neale Ranns696e88d2017-03-16 07:34:55 -0400760 bi0, bi1, bi2, bi3,
761 next0, next1, next2, next3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000762 }
763
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100764 while (n_left_from > 0 && n_left_to_next > 0)
765 {
766 mpls_unicast_header_t *hdr0;
767 mpls_label_dpo_t *mld0;
768 vlib_buffer_t * b0;
769 u32 bi0, mldi0;
Neale Ranns31ed7442018-02-23 05:29:09 -0800770 u8 ttl0, exp0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100771 u32 next0;
772
773 bi0 = from[0];
774 to_next[0] = bi0;
775 from += 1;
776 to_next += 1;
777 n_left_from -= 1;
778 n_left_to_next -= 1;
779
780 b0 = vlib_get_buffer (vm, bi0);
781
782 /* dst lookup was done by ip4 lookup */
783 mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
784 mld0 = mpls_label_dpo_get(mldi0);
785
Neale Ranns31ed7442018-02-23 05:29:09 -0800786 if (DPO_PROTO_MPLS != dproto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000787 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800788 if (DPO_PROTO_IP4 == dproto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000789 {
790 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800791 * decrement the TTL on ingress to the LSP
Neale Rannsad422ed2016-11-02 14:20:04 +0000792 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800793 ip4_header_t * ip0 = vlib_buffer_get_current(b0);
794 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
795 {
796 u32 checksum0;
Neale Rannsad422ed2016-11-02 14:20:04 +0000797
Neale Ranns31ed7442018-02-23 05:29:09 -0800798 checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
799 checksum0 += checksum0 >= 0xffff;
800
801 ip0->checksum = checksum0;
802 ip0->ttl -= 1;
803 }
804 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
805 {
806 ttl0 = ip0->ttl;
807 exp0 = ip_dscp_to_mpls_exp(ip0->tos);
808 }
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530809
810 /* save the payload proto information in mpls opaque */
811 vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP4;
Neale Ranns31ed7442018-02-23 05:29:09 -0800812 }
813 else if (DPO_PROTO_IP6 == dproto)
814 {
815 /*
816 * decrement the TTL on ingress to the LSP
817 */
818 ip6_header_t * ip0 = vlib_buffer_get_current(b0);
819
820 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
821 {
822 ip0->hop_limit -= 1;
823 }
824 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
825 {
826 ttl0 = ip0->hop_limit;
827 exp0 = ip_dscp_to_mpls_exp(
828 ip6_traffic_class_network_order(ip0));
829 }
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530830
831 /* save the payload proto information in mpls opaque */
832 vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP6;
Neale Rannsad422ed2016-11-02 14:20:04 +0000833 }
834 else
835 {
836 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800837 * nothing to change in the ethernet header
Neale Rannsad422ed2016-11-02 14:20:04 +0000838 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800839 ttl0 = MPLS_LABEL_DEFAULT_TTL;
840 exp0 = MPLS_LABEL_DEFAULT_EXP;
841 }
842
843 /*
844 * These are the non-MPLS payload imposition cases.
845 * Based on the LSP mode either, for uniform, copy down the TTL
846 * from the payload or, for pipe mode, slap on the value
847 * requested from config
848 */
849 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
850 {
851 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
852 }
853 else
854 {
855 hdr0 = mpls_label_paint(b0, mld0);
Neale Rannsad422ed2016-11-02 14:20:04 +0000856 }
857 }
Neale Ranns31ed7442018-02-23 05:29:09 -0800858 else
859 {
860 if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
861 {
862 ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
Neale Rannsad422ed2016-11-02 14:20:04 +0000863
Neale Ranns31ed7442018-02-23 05:29:09 -0800864 ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
865 exp0 = vnet_buffer(b0)->mpls.exp;
866 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
867 }
868 else
869 {
870 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
871 {
872 hdr0 = vlib_buffer_get_current(b0);
873 ttl0 = ((u8*)hdr0)[3];
874 exp0 = ((u8*)hdr0)[2] & 0xe;
875 hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
876 }
877 else
878 {
879 hdr0 = mpls_label_paint(b0, mld0);
880 }
881 }
Neale Rannsad422ed2016-11-02 14:20:04 +0000882
Neale Ranns31ed7442018-02-23 05:29:09 -0800883 vnet_buffer(b0)->mpls.first = 0;
884 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100885
886 next0 = mld0->mld_dpo.dpoi_next_node;
887 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
888
Neale Ranns9ca18c62016-12-10 21:08:09 +0000889 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100890 {
891 mpls_label_imposition_trace_t *tr =
892 vlib_add_trace (vm, node, b0, sizeof (*tr));
893 tr->hdr = *hdr0;
Neale Ranns31ed7442018-02-23 05:29:09 -0800894 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
895 {
896 tr->ttl = ttl0;
897 tr->exp = exp0;
898 }
899 else
900 {
901 tr->ttl = tr->exp = 0;
902 }
903 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100904
905 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
906 n_left_to_next, bi0, next0);
907 }
908 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
909 }
910 return from_frame->n_vectors;
911}
912
913static u8 *
914format_mpls_label_imposition_trace (u8 * s, va_list * args)
915{
916 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
917 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
918 mpls_label_imposition_trace_t * t;
919 mpls_unicast_header_t hdr;
Christophe Fontained3c008d2017-10-02 18:10:54 +0200920 u32 indent;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100921
922 t = va_arg (*args, mpls_label_imposition_trace_t *);
923 indent = format_get_indent (s);
924 hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
925
926 s = format (s, "%Umpls-header:%U",
927 format_white_space, indent,
928 format_mpls_header, hdr);
929 return (s);
930}
931
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800932VLIB_NODE_FN (mpls_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -0800933 vlib_node_runtime_t * node,
934 vlib_frame_t * frame)
Neale Rannsad422ed2016-11-02 14:20:04 +0000935{
Neale Ranns31ed7442018-02-23 05:29:09 -0800936 return (mpls_label_imposition_inline(vm, node, frame,
937 DPO_PROTO_MPLS,
938 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsad422ed2016-11-02 14:20:04 +0000939}
940
Neale Ranns31ed7442018-02-23 05:29:09 -0800941VLIB_REGISTER_NODE (mpls_mpls_label_imposition_pipe_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -0800942 .name = "mpls-label-imposition-pipe",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100943 .vector_size = sizeof (u32),
944
945 .format_trace = format_mpls_label_imposition_trace,
946 .n_next_nodes = 1,
947 .next_nodes = {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800948 [0] = "mpls-drop",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100949 }
950};
Neale Rannsad422ed2016-11-02 14:20:04 +0000951
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800952VLIB_NODE_FN (ip4_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -0800953 vlib_node_runtime_t * node,
954 vlib_frame_t * frame)
Neale Rannsad422ed2016-11-02 14:20:04 +0000955{
Neale Ranns31ed7442018-02-23 05:29:09 -0800956 return (mpls_label_imposition_inline(vm, node, frame,
957 DPO_PROTO_IP4,
958 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsad422ed2016-11-02 14:20:04 +0000959}
960
Neale Ranns31ed7442018-02-23 05:29:09 -0800961VLIB_REGISTER_NODE (ip4_mpls_label_imposition_pipe_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -0800962 .name = "ip4-mpls-label-imposition-pipe",
Neale Rannsad422ed2016-11-02 14:20:04 +0000963 .vector_size = sizeof (u32),
964
965 .format_trace = format_mpls_label_imposition_trace,
966 .n_next_nodes = 1,
967 .next_nodes = {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800968 [0] = "ip4-drop",
Neale Rannsad422ed2016-11-02 14:20:04 +0000969 }
970};
Neale Rannsad422ed2016-11-02 14:20:04 +0000971
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800972VLIB_NODE_FN (ip6_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -0800973 vlib_node_runtime_t * node,
974 vlib_frame_t * frame)
Neale Rannsad422ed2016-11-02 14:20:04 +0000975{
Neale Ranns31ed7442018-02-23 05:29:09 -0800976 return (mpls_label_imposition_inline(vm, node, frame,
977 DPO_PROTO_IP6,
978 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsad422ed2016-11-02 14:20:04 +0000979}
980
Neale Ranns31ed7442018-02-23 05:29:09 -0800981VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -0800982 .name = "ip6-mpls-label-imposition-pipe",
Neale Rannsad422ed2016-11-02 14:20:04 +0000983 .vector_size = sizeof (u32),
984
985 .format_trace = format_mpls_label_imposition_trace,
986 .n_next_nodes = 1,
987 .next_nodes = {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800988 [0] = "ip6-drop",
Neale Rannsad422ed2016-11-02 14:20:04 +0000989 }
990};
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100991
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800992VLIB_NODE_FN (ethernet_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -0800993 vlib_node_runtime_t * node,
994 vlib_frame_t * frame)
Neale Rannsda78f952017-05-24 09:15:43 -0700995{
Neale Ranns31ed7442018-02-23 05:29:09 -0800996 return (mpls_label_imposition_inline(vm, node, frame,
997 DPO_PROTO_ETHERNET,
998 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsda78f952017-05-24 09:15:43 -0700999}
1000
Neale Ranns31ed7442018-02-23 05:29:09 -08001001VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_pipe_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001002 .name = "ethernet-mpls-label-imposition-pipe",
Neale Rannsda78f952017-05-24 09:15:43 -07001003 .vector_size = sizeof (u32),
1004
1005 .format_trace = format_mpls_label_imposition_trace,
1006 .n_next_nodes = 1,
1007 .next_nodes = {
1008 [0] = "error-drop",
1009 }
1010};
Neale Ranns31ed7442018-02-23 05:29:09 -08001011
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001012VLIB_NODE_FN (mpls_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001013 vlib_node_runtime_t * node,
1014 vlib_frame_t * frame)
1015{
1016 return (mpls_label_imposition_inline(vm, node, frame,
1017 DPO_PROTO_MPLS,
1018 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1019}
1020
1021VLIB_REGISTER_NODE (mpls_mpls_label_imposition_uniform_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001022 .name = "mpls-label-imposition-uniform",
1023 .vector_size = sizeof (u32),
1024
1025 .format_trace = format_mpls_label_imposition_trace,
1026 .n_next_nodes = 1,
1027 .next_nodes = {
1028 [0] = "mpls-drop",
1029 }
1030};
Neale Ranns31ed7442018-02-23 05:29:09 -08001031
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001032VLIB_NODE_FN (ip4_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001033 vlib_node_runtime_t * node,
1034 vlib_frame_t * frame)
1035{
1036 return (mpls_label_imposition_inline(vm, node, frame,
1037 DPO_PROTO_IP4,
1038 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1039}
1040
1041VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001042 .name = "ip4-mpls-label-imposition-uniform",
1043 .vector_size = sizeof (u32),
1044
1045 .format_trace = format_mpls_label_imposition_trace,
1046 .n_next_nodes = 1,
1047 .next_nodes = {
1048 [0] = "ip4-drop",
1049 }
1050};
Neale Ranns31ed7442018-02-23 05:29:09 -08001051
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001052VLIB_NODE_FN (ip6_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001053 vlib_node_runtime_t * node,
1054 vlib_frame_t * frame)
1055{
1056 return (mpls_label_imposition_inline(vm, node, frame,
1057 DPO_PROTO_IP6,
1058 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1059}
1060
1061VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001062 .name = "ip6-mpls-label-imposition-uniform",
1063 .vector_size = sizeof (u32),
1064
1065 .format_trace = format_mpls_label_imposition_trace,
1066 .n_next_nodes = 1,
1067 .next_nodes = {
1068 [0] = "ip6-drop",
1069 }
1070};
Neale Ranns31ed7442018-02-23 05:29:09 -08001071
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001072VLIB_NODE_FN (ethernet_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001073 vlib_node_runtime_t * node,
1074 vlib_frame_t * frame)
1075{
1076 return (mpls_label_imposition_inline(vm, node, frame,
1077 DPO_PROTO_ETHERNET,
1078 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1079}
1080
1081VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_uniform_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001082 .name = "ethernet-mpls-label-imposition-uniform",
1083 .vector_size = sizeof (u32),
1084
1085 .format_trace = format_mpls_label_imposition_trace,
1086 .n_next_nodes = 1,
1087 .next_nodes = {
1088 [0] = "error-drop",
1089 }
1090};
1091
Neale Ranns31ed7442018-02-23 05:29:09 -08001092
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001093VLIB_NODE_FN (ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001094 vlib_node_runtime_t * node,
1095 vlib_frame_t * frame)
1096{
1097 return (mpls_label_imposition_inline(vm, node, frame,
1098 DPO_PROTO_IP4,
1099 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR));
1100}
1101
1102VLIB_REGISTER_NODE (ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001103 .name = "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
1104 .vector_size = sizeof (u32),
1105
1106 .format_trace = format_mpls_label_imposition_trace,
1107 .n_next_nodes = 1,
1108 .next_nodes = {
1109 [0] = "ip4-drop",
1110 }
1111};
Neale Ranns31ed7442018-02-23 05:29:09 -08001112
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001113VLIB_NODE_FN (ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001114 vlib_node_runtime_t * node,
1115 vlib_frame_t * frame)
1116{
1117 return (mpls_label_imposition_inline(vm, node, frame,
1118 DPO_PROTO_IP6,
1119 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR));
1120}
1121
1122VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001123 .name = "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
1124 .vector_size = sizeof (u32),
1125
1126 .format_trace = format_mpls_label_imposition_trace,
1127 .n_next_nodes = 1,
1128 .next_nodes = {
1129 [0] = "ip6-drop",
1130 }
1131};
Neale Ranns31ed7442018-02-23 05:29:09 -08001132
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001133VLIB_NODE_FN (ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001134 vlib_node_runtime_t * node,
1135 vlib_frame_t * frame)
1136{
1137 return (mpls_label_imposition_inline(vm, node, frame,
1138 DPO_PROTO_IP4,
1139 (MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
1140 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR)));
1141}
1142
1143VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001144 .name = "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
1145 .vector_size = sizeof (u32),
1146
1147 .format_trace = format_mpls_label_imposition_trace,
1148 .n_next_nodes = 1,
1149 .next_nodes = {
1150 [0] = "ip4-drop",
1151 }
1152};
Neale Ranns31ed7442018-02-23 05:29:09 -08001153
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001154VLIB_NODE_FN (ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001155 vlib_node_runtime_t * node,
1156 vlib_frame_t * frame)
1157{
1158 return (mpls_label_imposition_inline(vm, node, frame,
1159 DPO_PROTO_IP6,
1160 (MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
1161 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR)));
1162}
1163
1164VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001165 .name = "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
1166 .vector_size = sizeof (u32),
1167
1168 .format_trace = format_mpls_label_imposition_trace,
1169 .n_next_nodes = 1,
1170 .next_nodes = {
1171 [0] = "ip6-drop",
1172 }
1173};
Neale Ranns31ed7442018-02-23 05:29:09 -08001174
Neale Rannsda78f952017-05-24 09:15:43 -07001175
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001176#ifndef CLIB_MARCH_VARIANT
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001177static void
1178mpls_label_dpo_mem_show (void)
1179{
1180 fib_show_memory_usage("MPLS label",
1181 pool_elts(mpls_label_dpo_pool),
1182 pool_len(mpls_label_dpo_pool),
1183 sizeof(mpls_label_dpo_t));
1184}
1185
Neale Ranns2303cb12018-02-21 04:57:17 -08001186/**
1187 * Interpose a label DPO. used in the FIB unit tests
1188 */
1189static void
1190mpls_label_interpose (const dpo_id_t *original,
1191 const dpo_id_t *parent,
1192 dpo_id_t *clone)
1193{
1194 mpls_label_dpo_t *mld, *mld_clone;
1195
1196 mld_clone = mpls_label_dpo_alloc();
1197 mld = mpls_label_dpo_get(original->dpoi_index);
1198
1199 mld_clone->mld_locks = 0;
Dave Barach178cf492018-11-13 16:34:13 -05001200 clib_memcpy_fast(&mld_clone->mld_hdr,
Neale Ranns2303cb12018-02-21 04:57:17 -08001201 &mld->mld_hdr,
1202 sizeof(mld_clone->mld_hdr));
1203 mld_clone->mld_payload_proto = mld->mld_payload_proto;
1204 mld_clone->mld_n_labels = mld->mld_n_labels;
1205 mld_clone->mld_n_hdr_bytes = mld->mld_n_hdr_bytes;
1206
1207 dpo_stack(mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE],
1208 mld_clone->mld_payload_proto,
1209 &mld_clone->mld_dpo,
1210 parent);
1211
1212 dpo_set(clone,
1213 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE],
1214 mld_clone->mld_payload_proto,
1215 mpls_label_dpo_get_index(mld_clone));
1216}
1217
Neale Ranns8f5fef22020-12-21 08:29:34 +00001218static u16
1219mpls_label_dpo_get_mtu (const dpo_id_t *dpo)
1220{
1221 mpls_label_dpo_t *mld;
1222
1223 mld = mpls_label_dpo_get(dpo->dpoi_index);
1224
1225 /* return the parent's MTU minus the amount of header
1226 * this DPO imposes */
1227 return (dpo_get_mtu (&mld->mld_dpo) - sizeof(mpls_label_t) * mld->mld_n_labels);
1228}
1229
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001230const static dpo_vft_t mld_vft = {
1231 .dv_lock = mpls_label_dpo_lock,
1232 .dv_unlock = mpls_label_dpo_unlock,
1233 .dv_format = format_mpls_label_dpo,
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001234 .dv_mem_show = mpls_label_dpo_mem_show,
Neale Ranns2303cb12018-02-21 04:57:17 -08001235 .dv_mk_interpose = mpls_label_interpose,
Neale Ranns8f5fef22020-12-21 08:29:34 +00001236 .dv_get_mtu = mpls_label_dpo_get_mtu,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001237};
1238
Neale Ranns31ed7442018-02-23 05:29:09 -08001239const static char* const mpls_label_imp_pipe_ip4_nodes[] =
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001240{
Neale Ranns31ed7442018-02-23 05:29:09 -08001241 "ip4-mpls-label-imposition-pipe",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001242 NULL,
1243};
Neale Ranns31ed7442018-02-23 05:29:09 -08001244const static char* const mpls_label_imp_pipe_ip6_nodes[] =
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001245{
Neale Ranns31ed7442018-02-23 05:29:09 -08001246 "ip6-mpls-label-imposition-pipe",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001247 NULL,
1248};
Neale Ranns31ed7442018-02-23 05:29:09 -08001249const static char* const mpls_label_imp_pipe_mpls_nodes[] =
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001250{
Neale Ranns31ed7442018-02-23 05:29:09 -08001251 "mpls-label-imposition-pipe",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001252 NULL,
1253};
Neale Ranns31ed7442018-02-23 05:29:09 -08001254const static char* const mpls_label_imp_pipe_ethernet_nodes[] =
Neale Rannsda78f952017-05-24 09:15:43 -07001255{
Neale Ranns31ed7442018-02-23 05:29:09 -08001256 "ethernet-mpls-label-imposition-pipe",
Neale Rannsda78f952017-05-24 09:15:43 -07001257 NULL,
1258};
1259
Neale Ranns31ed7442018-02-23 05:29:09 -08001260const static char* const * const mpls_label_imp_pipe_nodes[DPO_PROTO_NUM] =
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001261{
Neale Ranns31ed7442018-02-23 05:29:09 -08001262 [DPO_PROTO_IP4] = mpls_label_imp_pipe_ip4_nodes,
1263 [DPO_PROTO_IP6] = mpls_label_imp_pipe_ip6_nodes,
1264 [DPO_PROTO_MPLS] = mpls_label_imp_pipe_mpls_nodes,
1265 [DPO_PROTO_ETHERNET] = mpls_label_imp_pipe_ethernet_nodes,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001266};
1267
Neale Ranns31ed7442018-02-23 05:29:09 -08001268const static char* const mpls_label_imp_uniform_ip4_nodes[] =
1269{
1270 "ip4-mpls-label-imposition-uniform",
1271 NULL,
1272};
1273const static char* const mpls_label_imp_uniform_ip6_nodes[] =
1274{
1275 "ip6-mpls-label-imposition-uniform",
1276 NULL,
1277};
1278const static char* const mpls_label_imp_uniform_mpls_nodes[] =
1279{
1280 "mpls-label-imposition-uniform",
1281 NULL,
1282};
1283const static char* const mpls_label_imp_uniform_ethernet_nodes[] =
1284{
1285 "ethernet-mpls-label-imposition-uniform",
1286 NULL,
1287};
1288
1289const static char* const * const mpls_label_imp_uniform_nodes[DPO_PROTO_NUM] =
1290{
1291 [DPO_PROTO_IP4] = mpls_label_imp_uniform_ip4_nodes,
1292 [DPO_PROTO_IP6] = mpls_label_imp_uniform_ip6_nodes,
1293 [DPO_PROTO_MPLS] = mpls_label_imp_uniform_mpls_nodes,
1294 [DPO_PROTO_ETHERNET] = mpls_label_imp_uniform_ethernet_nodes,
1295};
1296
1297const static char* const mpls_label_imp_pipe_no_ip_tll_decr_ip4_nodes[] =
1298{
1299 "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
1300 NULL,
1301};
1302const static char* const mpls_label_imp_pipe_no_ip_tll_decr_ip6_nodes[] =
1303{
1304 "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
1305 NULL,
1306};
1307
1308const static char* const * const mpls_label_imp_pipe_no_ip_tll_decr_nodes[DPO_PROTO_NUM] =
1309{
1310 [DPO_PROTO_IP4] = mpls_label_imp_pipe_no_ip_tll_decr_ip4_nodes,
1311 [DPO_PROTO_IP6] = mpls_label_imp_pipe_no_ip_tll_decr_ip6_nodes,
1312};
1313
1314const static char* const mpls_label_imp_uniform_no_ip_tll_decr_ip4_nodes[] =
1315{
1316 "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
1317 NULL,
1318};
1319const static char* const mpls_label_imp_uniform_no_ip_tll_decr_ip6_nodes[] =
1320{
1321 "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
1322 NULL,
1323};
1324
1325const static char* const * const mpls_label_imp_uniform_no_ip_tll_decr_nodes[DPO_PROTO_NUM] =
1326{
1327 [DPO_PROTO_IP4] = mpls_label_imp_uniform_no_ip_tll_decr_ip4_nodes,
1328 [DPO_PROTO_IP6] = mpls_label_imp_uniform_no_ip_tll_decr_ip6_nodes,
1329};
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001330
1331void
1332mpls_label_dpo_module_init (void)
1333{
Neale Ranns31ed7442018-02-23 05:29:09 -08001334 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE] =
1335 dpo_register_new_type(&mld_vft,
1336 mpls_label_imp_pipe_nodes);
1337 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR] =
1338 dpo_register_new_type(&mld_vft,
1339 mpls_label_imp_pipe_no_ip_tll_decr_nodes);
1340 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_UNIFORM_MODE] =
1341 dpo_register_new_type(&mld_vft,
1342 mpls_label_imp_uniform_nodes);
1343 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
1344 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR] =
1345 dpo_register_new_type(&mld_vft,
1346 mpls_label_imp_uniform_no_ip_tll_decr_nodes);
1347}
1348
1349dpo_type_t
1350mpls_label_dpo_get_type (mpls_label_dpo_flags_t flags)
1351{
1352 return (mpls_label_dpo_types[flags]);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001353}
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001354#endif /* CLIB_MARCH_VARIANT */
Neale Ranns8f5fef22020-12-21 08:29:34 +00001355
1356// clang-format on