blob: 872577dfbe176fa285e2f40746429880690feb56 [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;
Vladislav Grishenkod732f342023-04-11 01:17:29 +050087 mld->mld_payload_proto = payload_proto;
Neale Ranns31ed7442018-02-23 05:29:09 -080088 dtype = mpls_label_dpo_types[flags];
Neale Rannsf363ebd2017-12-06 00:45:33 -080089
90 if (MPLS_LABEL_DPO_MAX_N_LABELS < vec_len(label_stack))
91 {
92 clib_warning("Label stack size exceeded");
Neale Ranns31ed7442018-02-23 05:29:09 -080093 dpo_stack(dtype,
Neale Rannsf363ebd2017-12-06 00:45:33 -080094 mld->mld_payload_proto,
95 &mld->mld_dpo,
Vladislav Grishenkod732f342023-04-11 01:17:29 +050096 drop_dpo_get(mld->mld_payload_proto));
Neale Rannsf363ebd2017-12-06 00:45:33 -080097 }
Neale Ranns31ed7442018-02-23 05:29:09 -080098 else
Neale Rannsad422ed2016-11-02 14:20:04 +000099 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800100 mld->mld_n_labels = vec_len(label_stack);
101 mld->mld_n_hdr_bytes = mld->mld_n_labels * sizeof(mld->mld_hdr[0]);
Neale Ranns31ed7442018-02-23 05:29:09 -0800102
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 {
Vladislav Grishenko08ba4222023-04-10 18:02:12 +0500401 vlib_buffer_t *p4, *p5, *p6, *p7;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000402
Vladislav Grishenko08ba4222023-04-10 18:02:12 +0500403 p4 = vlib_get_buffer (vm, from[4]);
404 p5 = vlib_get_buffer (vm, from[5]);
405 p6 = vlib_get_buffer (vm, from[6]);
406 p7 = vlib_get_buffer (vm, from[7]);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000407
Vladislav Grishenko08ba4222023-04-10 18:02:12 +0500408 vlib_prefetch_buffer_header (p4, STORE);
409 vlib_prefetch_buffer_header (p5, STORE);
410 vlib_prefetch_buffer_header (p6, STORE);
411 vlib_prefetch_buffer_header (p7, STORE);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000412
Vladislav Grishenko08ba4222023-04-10 18:02:12 +0500413 CLIB_PREFETCH (p4->data, sizeof (hdr0[0]), STORE);
414 CLIB_PREFETCH (p5->data, sizeof (hdr0[0]), STORE);
415 CLIB_PREFETCH (p6->data, sizeof (hdr0[0]), STORE);
416 CLIB_PREFETCH (p7->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 Ranns9bd92ab2021-08-06 09:03:45 +0000442 * These are the non-MPLS payload imposition cases.
443 * Save the l3 offset
Neale Ranns9ca18c62016-12-10 21:08:09 +0000444 */
Neale Ranns9bd92ab2021-08-06 09:03:45 +0000445 vnet_buffer (b0)->l3_hdr_offset = b0->current_data;
446 vnet_buffer (b1)->l3_hdr_offset = b1->current_data;
447 vnet_buffer (b2)->l3_hdr_offset = b2->current_data;
448 vnet_buffer (b3)->l3_hdr_offset = b3->current_data;
449
Neale Ranns31ed7442018-02-23 05:29:09 -0800450 if (DPO_PROTO_IP4 == dproto)
451 {
452 ip4_header_t * ip0 = vlib_buffer_get_current(b0);
453 ip4_header_t * ip1 = vlib_buffer_get_current(b1);
454 ip4_header_t * ip2 = vlib_buffer_get_current(b2);
455 ip4_header_t * ip3 = vlib_buffer_get_current(b3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000456
Neale Ranns31ed7442018-02-23 05:29:09 -0800457 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
458 {
459 /*
460 * decrement the TTL on ingress to the LSP
461 */
462 u32 checksum0;
463 u32 checksum1;
464 u32 checksum2;
465 u32 checksum3;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000466
Neale Ranns31ed7442018-02-23 05:29:09 -0800467 checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
468 checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
469 checksum2 = ip2->checksum + clib_host_to_net_u16 (0x0100);
470 checksum3 = ip3->checksum + clib_host_to_net_u16 (0x0100);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000471
Neale Ranns31ed7442018-02-23 05:29:09 -0800472 checksum0 += checksum0 >= 0xffff;
473 checksum1 += checksum1 >= 0xffff;
474 checksum2 += checksum2 >= 0xffff;
475 checksum3 += checksum3 >= 0xffff;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000476
Neale Ranns31ed7442018-02-23 05:29:09 -0800477 ip0->checksum = checksum0;
478 ip1->checksum = checksum1;
479 ip2->checksum = checksum2;
480 ip3->checksum = checksum3;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000481
Neale Ranns31ed7442018-02-23 05:29:09 -0800482 ip0->ttl -= 1;
483 ip1->ttl -= 1;
484 ip2->ttl -= 1;
485 ip3->ttl -= 1;
486 }
487
488 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
489 {
490 ttl1 = ip1->ttl;
491 ttl0 = ip0->ttl;
492 ttl3 = ip3->ttl;
493 ttl2 = ip2->ttl;
494 /* by default copy the 3 most significant bits */
495 exp0 = ip_dscp_to_mpls_exp(ip0->tos);
496 exp1 = ip_dscp_to_mpls_exp(ip1->tos);
497 exp2 = ip_dscp_to_mpls_exp(ip2->tos);
498 exp3 = ip_dscp_to_mpls_exp(ip3->tos);
499 }
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530500
501 /* save the payload proto information in mpls opaque */
502 vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP4;
503 vnet_buffer(b1)->mpls.pyld_proto = DPO_PROTO_IP4;
504 vnet_buffer(b2)->mpls.pyld_proto = DPO_PROTO_IP4;
505 vnet_buffer(b3)->mpls.pyld_proto = DPO_PROTO_IP4;
Neale Ranns31ed7442018-02-23 05:29:09 -0800506 }
507 else if (DPO_PROTO_IP6 == dproto)
508 {
509 /*
510 * decrement the TTL on ingress to the LSP
511 */
512 ip6_header_t * ip0 = vlib_buffer_get_current(b0);
513 ip6_header_t * ip1 = vlib_buffer_get_current(b1);
514 ip6_header_t * ip2 = vlib_buffer_get_current(b2);
515 ip6_header_t * ip3 = vlib_buffer_get_current(b3);
516
517 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
518 {
519 ip0->hop_limit -= 1;
520 ip1->hop_limit -= 1;
521 ip2->hop_limit -= 1;
522 ip3->hop_limit -= 1;
523 }
524 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
525 {
526 ttl0 = ip0->hop_limit;
527 ttl1 = ip1->hop_limit;
528 ttl2 = ip2->hop_limit;
529 ttl3 = ip3->hop_limit;
530 /* by default copy the 3 most significant bits */
531 exp0 = ip_dscp_to_mpls_exp(
532 ip6_traffic_class_network_order(ip0));
533 exp1 = ip_dscp_to_mpls_exp(
534 ip6_traffic_class_network_order(ip1));
535 exp2 = ip_dscp_to_mpls_exp(
536 ip6_traffic_class_network_order(ip2));
537 exp3 = ip_dscp_to_mpls_exp(
538 ip6_traffic_class_network_order(ip3));
539 }
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530540
541 /* save the payload proto information in mpls opaque */
542 vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP6;
543 vnet_buffer(b1)->mpls.pyld_proto = DPO_PROTO_IP6;
544 vnet_buffer(b2)->mpls.pyld_proto = DPO_PROTO_IP6;
545 vnet_buffer(b3)->mpls.pyld_proto = DPO_PROTO_IP6;
Neale Ranns31ed7442018-02-23 05:29:09 -0800546 }
547 else
548 {
549 /*
550 * nothing to change in the ethernet header
551 */
552 ttl0 = ttl1 = ttl2 = ttl3 = MPLS_LABEL_DEFAULT_TTL;
553 exp0 = exp1 = exp2 = exp3 = MPLS_LABEL_DEFAULT_EXP;
554 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000555 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800556 * These are the non-MPLS payload imposition cases.
557 * Based on the LSP mode either, for uniform, copy down the TTL
558 * and EXP from the payload or, for pipe mode, slap on the value
559 * requested from config
Neale Ranns9ca18c62016-12-10 21:08:09 +0000560 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800561 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
562 {
563 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
564 hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
565 hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
566 hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
567 }
568 else
569 {
570 hdr0 = mpls_label_paint(b0, mld0);
571 hdr1 = mpls_label_paint(b1, mld1);
572 hdr2 = mpls_label_paint(b2, mld2);
573 hdr3 = mpls_label_paint(b3, mld3);
574 }
Neale Rannsda78f952017-05-24 09:15:43 -0700575 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000576 else
577 {
578 /*
579 * else, the packet to be encapped is an MPLS packet
Neale Ranns31ed7442018-02-23 05:29:09 -0800580 * there are two cases to consider:
581 * 1 - this is an MPLS label swap at an LSP midpoint.
582 * recognisable because mpls.first = 1. In this case the
583 * TTL must be set to the current value -1.
584 * 2 - The MPLS packet is recursing (or being injected into)
585 * this LSP, in which case the pipe/uniform rules apply
586 *
Neale Ranns9ca18c62016-12-10 21:08:09 +0000587 */
588 if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
589 {
590 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800591 * The first label to be imposed on the packet. this is a
592 * label swap.in which case we stashed the TTL and EXP bits
593 * in the packet in the lookup node
Neale Ranns9ca18c62016-12-10 21:08:09 +0000594 */
595 ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
596
597 ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800598 exp0 = vnet_buffer(b0)->mpls.exp;
599 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000600 }
601 else
602 {
603 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800604 * not the first label. implying we are recusring down a
605 * chain of output labels. Each layer is considered a new
606 * LSP - hence the TTL/EXP are pipe/uniform handled
Neale Ranns9ca18c62016-12-10 21:08:09 +0000607 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800608 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
609 {
610 hdr0 = vlib_buffer_get_current(b0);
611 ttl0 = ((u8*)hdr0)[3];
612 exp0 = ((u8*)hdr0)[2] & 0xe;
613 hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
614 }
615 else
616 {
617 hdr0 = mpls_label_paint(b0, mld0);
618 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000619 }
620 if (PREDICT_TRUE(vnet_buffer(b1)->mpls.first))
621 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800622 ASSERT(0 != vnet_buffer (b1)->mpls.ttl);
623
Neale Ranns9ca18c62016-12-10 21:08:09 +0000624 ttl1 = vnet_buffer(b1)->mpls.ttl - 1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800625 exp1 = vnet_buffer(b1)->mpls.exp;
626 hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000627 }
628 else
629 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800630 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
631 {
632 hdr1 = vlib_buffer_get_current(b1);
633 ttl1 = ((u8*)hdr1)[3];
634 exp1 = ((u8*)hdr1)[2] & 0xe;
635 hdr1 = mpls_label_paint_w_ttl_mpls_exp(b1, mld1, ttl1, exp1);
636 }
637 else
638 {
639 hdr1 = mpls_label_paint(b1, mld1);
640 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000641 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400642 if (PREDICT_TRUE(vnet_buffer(b2)->mpls.first))
643 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800644 ASSERT(0 != vnet_buffer (b2)->mpls.ttl);
Neale Ranns696e88d2017-03-16 07:34:55 -0400645
646 ttl2 = vnet_buffer(b2)->mpls.ttl - 1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800647 exp2 = vnet_buffer(b2)->mpls.exp;
648 hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
Neale Ranns696e88d2017-03-16 07:34:55 -0400649 }
650 else
651 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800652 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
653 {
654 hdr2 = vlib_buffer_get_current(b2);
655 ttl2 = ((u8*)hdr2)[3];
656 exp2 = ((u8*)hdr2)[2] & 0xe;
657 hdr2 = mpls_label_paint_w_ttl_mpls_exp(b2, mld2, ttl2, exp2);
658 }
659 else
660 {
661 hdr2 = mpls_label_paint(b2, mld2);
662 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400663 }
664 if (PREDICT_TRUE(vnet_buffer(b3)->mpls.first))
665 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800666 ASSERT(0 != vnet_buffer (b3)->mpls.ttl);
667
Neale Ranns696e88d2017-03-16 07:34:55 -0400668 ttl3 = vnet_buffer(b3)->mpls.ttl - 1;
Neale Ranns19bd1902018-03-19 02:32:57 -0700669 exp3 = vnet_buffer(b3)->mpls.exp;
Neale Ranns31ed7442018-02-23 05:29:09 -0800670 hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
Neale Ranns696e88d2017-03-16 07:34:55 -0400671 }
672 else
673 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800674 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
675 {
676 hdr3 = vlib_buffer_get_current(b3);
677 ttl3 = ((u8*)hdr3)[3];
678 exp3 = ((u8*)hdr3)[2] & 0xe;
679 hdr3 = mpls_label_paint_w_ttl_mpls_exp(b3, mld3, ttl3, exp3);
680 }
681 else
682 {
683 hdr3 = mpls_label_paint(b3, mld3);
684 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400685 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000686
Neale Ranns31ed7442018-02-23 05:29:09 -0800687 vnet_buffer(b0)->mpls.first = 0;
688 vnet_buffer(b1)->mpls.first = 0;
689 vnet_buffer(b2)->mpls.first = 0;
690 vnet_buffer(b3)->mpls.first = 0;
691 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000692
693 next0 = mld0->mld_dpo.dpoi_next_node;
694 next1 = mld1->mld_dpo.dpoi_next_node;
Neale Ranns696e88d2017-03-16 07:34:55 -0400695 next2 = mld2->mld_dpo.dpoi_next_node;
696 next3 = mld3->mld_dpo.dpoi_next_node;
Neale Ranns31ed7442018-02-23 05:29:09 -0800697
Neale Ranns9ca18c62016-12-10 21:08:09 +0000698 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
699 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = mld1->mld_dpo.dpoi_index;
Neale Ranns696e88d2017-03-16 07:34:55 -0400700 vnet_buffer(b2)->ip.adj_index[VLIB_TX] = mld2->mld_dpo.dpoi_index;
701 vnet_buffer(b3)->ip.adj_index[VLIB_TX] = mld3->mld_dpo.dpoi_index;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000702
703 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
704 {
705 mpls_label_imposition_trace_t *tr =
706 vlib_add_trace (vm, node, b0, sizeof (*tr));
707 tr->hdr = *hdr0;
Neale Ranns31ed7442018-02-23 05:29:09 -0800708 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
709 {
710 tr->ttl = ttl0;
711 tr->exp = exp0;
712 }
713 else
714 {
715 tr->ttl = tr->exp = 0;
716 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000717 }
718 if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
719 {
720 mpls_label_imposition_trace_t *tr =
721 vlib_add_trace (vm, node, b1, sizeof (*tr));
722 tr->hdr = *hdr1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800723 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
724 {
725 tr->ttl = ttl1;
726 tr->exp = exp1;
727 }
728 else
729 {
730 tr->ttl = tr->exp = 0;
731 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000732 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400733 if (PREDICT_FALSE(b2->flags & VLIB_BUFFER_IS_TRACED))
734 {
735 mpls_label_imposition_trace_t *tr =
736 vlib_add_trace (vm, node, b2, sizeof (*tr));
737 tr->hdr = *hdr2;
Neale Ranns31ed7442018-02-23 05:29:09 -0800738 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
739 {
740 tr->ttl = ttl2;
741 tr->exp = exp2;
742 }
743 else
744 {
745 tr->ttl = tr->exp = 0;
746 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400747 }
748 if (PREDICT_FALSE(b3->flags & VLIB_BUFFER_IS_TRACED))
749 {
750 mpls_label_imposition_trace_t *tr =
751 vlib_add_trace (vm, node, b3, sizeof (*tr));
752 tr->hdr = *hdr3;
Neale Ranns31ed7442018-02-23 05:29:09 -0800753 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
754 {
755 tr->ttl = ttl3;
756 tr->exp = exp3;
757 }
758 else
759 {
760 tr->ttl = tr->exp = 0;
761 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400762 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000763
Neale Ranns696e88d2017-03-16 07:34:55 -0400764 vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next,
Neale Ranns9ca18c62016-12-10 21:08:09 +0000765 n_left_to_next,
Neale Ranns696e88d2017-03-16 07:34:55 -0400766 bi0, bi1, bi2, bi3,
767 next0, next1, next2, next3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000768 }
769
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100770 while (n_left_from > 0 && n_left_to_next > 0)
771 {
772 mpls_unicast_header_t *hdr0;
773 mpls_label_dpo_t *mld0;
774 vlib_buffer_t * b0;
775 u32 bi0, mldi0;
Neale Ranns31ed7442018-02-23 05:29:09 -0800776 u8 ttl0, exp0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100777 u32 next0;
778
779 bi0 = from[0];
780 to_next[0] = bi0;
781 from += 1;
782 to_next += 1;
783 n_left_from -= 1;
784 n_left_to_next -= 1;
785
786 b0 = vlib_get_buffer (vm, bi0);
787
788 /* dst lookup was done by ip4 lookup */
789 mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
790 mld0 = mpls_label_dpo_get(mldi0);
791
Neale Ranns31ed7442018-02-23 05:29:09 -0800792 if (DPO_PROTO_MPLS != dproto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000793 {
Neale Ranns9bd92ab2021-08-06 09:03:45 +0000794 vnet_buffer (b0)->l3_hdr_offset = b0->current_data;
795
Neale Ranns31ed7442018-02-23 05:29:09 -0800796 if (DPO_PROTO_IP4 == dproto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000797 {
798 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800799 * decrement the TTL on ingress to the LSP
Neale Rannsad422ed2016-11-02 14:20:04 +0000800 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800801 ip4_header_t * ip0 = vlib_buffer_get_current(b0);
802 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
803 {
804 u32 checksum0;
Neale Rannsad422ed2016-11-02 14:20:04 +0000805
Neale Ranns31ed7442018-02-23 05:29:09 -0800806 checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
807 checksum0 += checksum0 >= 0xffff;
808
809 ip0->checksum = checksum0;
810 ip0->ttl -= 1;
811 }
812 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
813 {
814 ttl0 = ip0->ttl;
815 exp0 = ip_dscp_to_mpls_exp(ip0->tos);
816 }
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530817
818 /* save the payload proto information in mpls opaque */
819 vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP4;
Neale Ranns31ed7442018-02-23 05:29:09 -0800820 }
821 else if (DPO_PROTO_IP6 == dproto)
822 {
823 /*
824 * decrement the TTL on ingress to the LSP
825 */
826 ip6_header_t * ip0 = vlib_buffer_get_current(b0);
827
828 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
829 {
830 ip0->hop_limit -= 1;
831 }
832 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
833 {
834 ttl0 = ip0->hop_limit;
835 exp0 = ip_dscp_to_mpls_exp(
836 ip6_traffic_class_network_order(ip0));
837 }
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530838
839 /* save the payload proto information in mpls opaque */
840 vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP6;
Neale Rannsad422ed2016-11-02 14:20:04 +0000841 }
842 else
843 {
844 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800845 * nothing to change in the ethernet header
Neale Rannsad422ed2016-11-02 14:20:04 +0000846 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800847 ttl0 = MPLS_LABEL_DEFAULT_TTL;
848 exp0 = MPLS_LABEL_DEFAULT_EXP;
849 }
850
851 /*
852 * These are the non-MPLS payload imposition cases.
853 * Based on the LSP mode either, for uniform, copy down the TTL
854 * from the payload or, for pipe mode, slap on the value
855 * requested from config
856 */
857 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
858 {
859 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
860 }
861 else
862 {
863 hdr0 = mpls_label_paint(b0, mld0);
Neale Rannsad422ed2016-11-02 14:20:04 +0000864 }
865 }
Neale Ranns31ed7442018-02-23 05:29:09 -0800866 else
867 {
868 if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
869 {
870 ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
Neale Rannsad422ed2016-11-02 14:20:04 +0000871
Neale Ranns31ed7442018-02-23 05:29:09 -0800872 ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
873 exp0 = vnet_buffer(b0)->mpls.exp;
874 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
875 }
876 else
877 {
878 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
879 {
880 hdr0 = vlib_buffer_get_current(b0);
881 ttl0 = ((u8*)hdr0)[3];
882 exp0 = ((u8*)hdr0)[2] & 0xe;
883 hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
884 }
885 else
886 {
887 hdr0 = mpls_label_paint(b0, mld0);
888 }
889 }
Neale Rannsad422ed2016-11-02 14:20:04 +0000890
Neale Ranns31ed7442018-02-23 05:29:09 -0800891 vnet_buffer(b0)->mpls.first = 0;
892 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100893
894 next0 = mld0->mld_dpo.dpoi_next_node;
895 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
896
Neale Ranns9ca18c62016-12-10 21:08:09 +0000897 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100898 {
899 mpls_label_imposition_trace_t *tr =
900 vlib_add_trace (vm, node, b0, sizeof (*tr));
901 tr->hdr = *hdr0;
Neale Ranns31ed7442018-02-23 05:29:09 -0800902 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
903 {
904 tr->ttl = ttl0;
905 tr->exp = exp0;
906 }
907 else
908 {
909 tr->ttl = tr->exp = 0;
910 }
911 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100912
913 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
914 n_left_to_next, bi0, next0);
915 }
916 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
917 }
918 return from_frame->n_vectors;
919}
920
921static u8 *
922format_mpls_label_imposition_trace (u8 * s, va_list * args)
923{
924 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
925 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
926 mpls_label_imposition_trace_t * t;
927 mpls_unicast_header_t hdr;
Christophe Fontained3c008d2017-10-02 18:10:54 +0200928 u32 indent;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100929
930 t = va_arg (*args, mpls_label_imposition_trace_t *);
931 indent = format_get_indent (s);
932 hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
933
934 s = format (s, "%Umpls-header:%U",
935 format_white_space, indent,
936 format_mpls_header, hdr);
937 return (s);
938}
939
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800940VLIB_NODE_FN (mpls_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -0800941 vlib_node_runtime_t * node,
942 vlib_frame_t * frame)
Neale Rannsad422ed2016-11-02 14:20:04 +0000943{
Neale Ranns31ed7442018-02-23 05:29:09 -0800944 return (mpls_label_imposition_inline(vm, node, frame,
945 DPO_PROTO_MPLS,
946 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsad422ed2016-11-02 14:20:04 +0000947}
948
Neale Ranns31ed7442018-02-23 05:29:09 -0800949VLIB_REGISTER_NODE (mpls_mpls_label_imposition_pipe_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -0800950 .name = "mpls-label-imposition-pipe",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100951 .vector_size = sizeof (u32),
952
953 .format_trace = format_mpls_label_imposition_trace,
954 .n_next_nodes = 1,
955 .next_nodes = {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800956 [0] = "mpls-drop",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100957 }
958};
Neale Rannsad422ed2016-11-02 14:20:04 +0000959
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800960VLIB_NODE_FN (ip4_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -0800961 vlib_node_runtime_t * node,
962 vlib_frame_t * frame)
Neale Rannsad422ed2016-11-02 14:20:04 +0000963{
Neale Ranns31ed7442018-02-23 05:29:09 -0800964 return (mpls_label_imposition_inline(vm, node, frame,
965 DPO_PROTO_IP4,
966 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsad422ed2016-11-02 14:20:04 +0000967}
968
Neale Ranns31ed7442018-02-23 05:29:09 -0800969VLIB_REGISTER_NODE (ip4_mpls_label_imposition_pipe_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -0800970 .name = "ip4-mpls-label-imposition-pipe",
Neale Rannsad422ed2016-11-02 14:20:04 +0000971 .vector_size = sizeof (u32),
972
973 .format_trace = format_mpls_label_imposition_trace,
974 .n_next_nodes = 1,
975 .next_nodes = {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800976 [0] = "ip4-drop",
Neale Rannsad422ed2016-11-02 14:20:04 +0000977 }
978};
Neale Rannsad422ed2016-11-02 14:20:04 +0000979
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800980VLIB_NODE_FN (ip6_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -0800981 vlib_node_runtime_t * node,
982 vlib_frame_t * frame)
Neale Rannsad422ed2016-11-02 14:20:04 +0000983{
Neale Ranns31ed7442018-02-23 05:29:09 -0800984 return (mpls_label_imposition_inline(vm, node, frame,
985 DPO_PROTO_IP6,
986 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsad422ed2016-11-02 14:20:04 +0000987}
988
Neale Ranns31ed7442018-02-23 05:29:09 -0800989VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -0800990 .name = "ip6-mpls-label-imposition-pipe",
Neale Rannsad422ed2016-11-02 14:20:04 +0000991 .vector_size = sizeof (u32),
992
993 .format_trace = format_mpls_label_imposition_trace,
994 .n_next_nodes = 1,
995 .next_nodes = {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800996 [0] = "ip6-drop",
Neale Rannsad422ed2016-11-02 14:20:04 +0000997 }
998};
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100999
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001000VLIB_NODE_FN (ethernet_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001001 vlib_node_runtime_t * node,
1002 vlib_frame_t * frame)
Neale Rannsda78f952017-05-24 09:15:43 -07001003{
Neale Ranns31ed7442018-02-23 05:29:09 -08001004 return (mpls_label_imposition_inline(vm, node, frame,
1005 DPO_PROTO_ETHERNET,
1006 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsda78f952017-05-24 09:15:43 -07001007}
1008
Neale Ranns31ed7442018-02-23 05:29:09 -08001009VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_pipe_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001010 .name = "ethernet-mpls-label-imposition-pipe",
Neale Rannsda78f952017-05-24 09:15:43 -07001011 .vector_size = sizeof (u32),
1012
1013 .format_trace = format_mpls_label_imposition_trace,
1014 .n_next_nodes = 1,
1015 .next_nodes = {
1016 [0] = "error-drop",
1017 }
1018};
Neale Ranns31ed7442018-02-23 05:29:09 -08001019
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001020VLIB_NODE_FN (mpls_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001021 vlib_node_runtime_t * node,
1022 vlib_frame_t * frame)
1023{
1024 return (mpls_label_imposition_inline(vm, node, frame,
1025 DPO_PROTO_MPLS,
1026 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1027}
1028
1029VLIB_REGISTER_NODE (mpls_mpls_label_imposition_uniform_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001030 .name = "mpls-label-imposition-uniform",
1031 .vector_size = sizeof (u32),
1032
1033 .format_trace = format_mpls_label_imposition_trace,
1034 .n_next_nodes = 1,
1035 .next_nodes = {
1036 [0] = "mpls-drop",
1037 }
1038};
Neale Ranns31ed7442018-02-23 05:29:09 -08001039
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001040VLIB_NODE_FN (ip4_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001041 vlib_node_runtime_t * node,
1042 vlib_frame_t * frame)
1043{
1044 return (mpls_label_imposition_inline(vm, node, frame,
1045 DPO_PROTO_IP4,
1046 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1047}
1048
1049VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001050 .name = "ip4-mpls-label-imposition-uniform",
1051 .vector_size = sizeof (u32),
1052
1053 .format_trace = format_mpls_label_imposition_trace,
1054 .n_next_nodes = 1,
1055 .next_nodes = {
1056 [0] = "ip4-drop",
1057 }
1058};
Neale Ranns31ed7442018-02-23 05:29:09 -08001059
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001060VLIB_NODE_FN (ip6_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001061 vlib_node_runtime_t * node,
1062 vlib_frame_t * frame)
1063{
1064 return (mpls_label_imposition_inline(vm, node, frame,
1065 DPO_PROTO_IP6,
1066 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1067}
1068
1069VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001070 .name = "ip6-mpls-label-imposition-uniform",
1071 .vector_size = sizeof (u32),
1072
1073 .format_trace = format_mpls_label_imposition_trace,
1074 .n_next_nodes = 1,
1075 .next_nodes = {
1076 [0] = "ip6-drop",
1077 }
1078};
Neale Ranns31ed7442018-02-23 05:29:09 -08001079
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001080VLIB_NODE_FN (ethernet_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001081 vlib_node_runtime_t * node,
1082 vlib_frame_t * frame)
1083{
1084 return (mpls_label_imposition_inline(vm, node, frame,
1085 DPO_PROTO_ETHERNET,
1086 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1087}
1088
1089VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_uniform_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001090 .name = "ethernet-mpls-label-imposition-uniform",
1091 .vector_size = sizeof (u32),
1092
1093 .format_trace = format_mpls_label_imposition_trace,
1094 .n_next_nodes = 1,
1095 .next_nodes = {
1096 [0] = "error-drop",
1097 }
1098};
1099
Neale Ranns31ed7442018-02-23 05:29:09 -08001100
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001101VLIB_NODE_FN (ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001102 vlib_node_runtime_t * node,
1103 vlib_frame_t * frame)
1104{
1105 return (mpls_label_imposition_inline(vm, node, frame,
1106 DPO_PROTO_IP4,
1107 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR));
1108}
1109
1110VLIB_REGISTER_NODE (ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001111 .name = "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
1112 .vector_size = sizeof (u32),
1113
1114 .format_trace = format_mpls_label_imposition_trace,
1115 .n_next_nodes = 1,
1116 .next_nodes = {
1117 [0] = "ip4-drop",
1118 }
1119};
Neale Ranns31ed7442018-02-23 05:29:09 -08001120
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001121VLIB_NODE_FN (ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001122 vlib_node_runtime_t * node,
1123 vlib_frame_t * frame)
1124{
1125 return (mpls_label_imposition_inline(vm, node, frame,
1126 DPO_PROTO_IP6,
1127 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR));
1128}
1129
1130VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001131 .name = "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
1132 .vector_size = sizeof (u32),
1133
1134 .format_trace = format_mpls_label_imposition_trace,
1135 .n_next_nodes = 1,
1136 .next_nodes = {
1137 [0] = "ip6-drop",
1138 }
1139};
Neale Ranns31ed7442018-02-23 05:29:09 -08001140
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001141VLIB_NODE_FN (ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001142 vlib_node_runtime_t * node,
1143 vlib_frame_t * frame)
1144{
1145 return (mpls_label_imposition_inline(vm, node, frame,
1146 DPO_PROTO_IP4,
1147 (MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
1148 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR)));
1149}
1150
1151VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001152 .name = "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
1153 .vector_size = sizeof (u32),
1154
1155 .format_trace = format_mpls_label_imposition_trace,
1156 .n_next_nodes = 1,
1157 .next_nodes = {
1158 [0] = "ip4-drop",
1159 }
1160};
Neale Ranns31ed7442018-02-23 05:29:09 -08001161
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001162VLIB_NODE_FN (ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001163 vlib_node_runtime_t * node,
1164 vlib_frame_t * frame)
1165{
1166 return (mpls_label_imposition_inline(vm, node, frame,
1167 DPO_PROTO_IP6,
1168 (MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
1169 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR)));
1170}
1171
1172VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001173 .name = "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
1174 .vector_size = sizeof (u32),
1175
1176 .format_trace = format_mpls_label_imposition_trace,
1177 .n_next_nodes = 1,
1178 .next_nodes = {
1179 [0] = "ip6-drop",
1180 }
1181};
Neale Ranns31ed7442018-02-23 05:29:09 -08001182
Neale Rannsda78f952017-05-24 09:15:43 -07001183
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001184#ifndef CLIB_MARCH_VARIANT
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001185static void
1186mpls_label_dpo_mem_show (void)
1187{
1188 fib_show_memory_usage("MPLS label",
1189 pool_elts(mpls_label_dpo_pool),
1190 pool_len(mpls_label_dpo_pool),
1191 sizeof(mpls_label_dpo_t));
1192}
1193
Neale Ranns2303cb12018-02-21 04:57:17 -08001194/**
1195 * Interpose a label DPO. used in the FIB unit tests
1196 */
1197static void
1198mpls_label_interpose (const dpo_id_t *original,
1199 const dpo_id_t *parent,
1200 dpo_id_t *clone)
1201{
1202 mpls_label_dpo_t *mld, *mld_clone;
1203
1204 mld_clone = mpls_label_dpo_alloc();
1205 mld = mpls_label_dpo_get(original->dpoi_index);
1206
1207 mld_clone->mld_locks = 0;
Dave Barach178cf492018-11-13 16:34:13 -05001208 clib_memcpy_fast(&mld_clone->mld_hdr,
Neale Ranns2303cb12018-02-21 04:57:17 -08001209 &mld->mld_hdr,
1210 sizeof(mld_clone->mld_hdr));
1211 mld_clone->mld_payload_proto = mld->mld_payload_proto;
1212 mld_clone->mld_n_labels = mld->mld_n_labels;
1213 mld_clone->mld_n_hdr_bytes = mld->mld_n_hdr_bytes;
1214
1215 dpo_stack(mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE],
1216 mld_clone->mld_payload_proto,
1217 &mld_clone->mld_dpo,
1218 parent);
1219
1220 dpo_set(clone,
1221 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE],
1222 mld_clone->mld_payload_proto,
1223 mpls_label_dpo_get_index(mld_clone));
1224}
1225
Neale Ranns8f5fef22020-12-21 08:29:34 +00001226static u16
1227mpls_label_dpo_get_mtu (const dpo_id_t *dpo)
1228{
1229 mpls_label_dpo_t *mld;
1230
1231 mld = mpls_label_dpo_get(dpo->dpoi_index);
1232
1233 /* return the parent's MTU minus the amount of header
1234 * this DPO imposes */
1235 return (dpo_get_mtu (&mld->mld_dpo) - sizeof(mpls_label_t) * mld->mld_n_labels);
1236}
1237
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001238const static dpo_vft_t mld_vft = {
1239 .dv_lock = mpls_label_dpo_lock,
1240 .dv_unlock = mpls_label_dpo_unlock,
1241 .dv_format = format_mpls_label_dpo,
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001242 .dv_mem_show = mpls_label_dpo_mem_show,
Neale Ranns2303cb12018-02-21 04:57:17 -08001243 .dv_mk_interpose = mpls_label_interpose,
Neale Ranns8f5fef22020-12-21 08:29:34 +00001244 .dv_get_mtu = mpls_label_dpo_get_mtu,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001245};
1246
Neale Ranns31ed7442018-02-23 05:29:09 -08001247const static char* const mpls_label_imp_pipe_ip4_nodes[] =
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001248{
Neale Ranns31ed7442018-02-23 05:29:09 -08001249 "ip4-mpls-label-imposition-pipe",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001250 NULL,
1251};
Neale Ranns31ed7442018-02-23 05:29:09 -08001252const static char* const mpls_label_imp_pipe_ip6_nodes[] =
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001253{
Neale Ranns31ed7442018-02-23 05:29:09 -08001254 "ip6-mpls-label-imposition-pipe",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001255 NULL,
1256};
Neale Ranns31ed7442018-02-23 05:29:09 -08001257const static char* const mpls_label_imp_pipe_mpls_nodes[] =
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001258{
Neale Ranns31ed7442018-02-23 05:29:09 -08001259 "mpls-label-imposition-pipe",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001260 NULL,
1261};
Neale Ranns31ed7442018-02-23 05:29:09 -08001262const static char* const mpls_label_imp_pipe_ethernet_nodes[] =
Neale Rannsda78f952017-05-24 09:15:43 -07001263{
Neale Ranns31ed7442018-02-23 05:29:09 -08001264 "ethernet-mpls-label-imposition-pipe",
Neale Rannsda78f952017-05-24 09:15:43 -07001265 NULL,
1266};
1267
Neale Ranns31ed7442018-02-23 05:29:09 -08001268const static char* const * const mpls_label_imp_pipe_nodes[DPO_PROTO_NUM] =
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001269{
Neale Ranns31ed7442018-02-23 05:29:09 -08001270 [DPO_PROTO_IP4] = mpls_label_imp_pipe_ip4_nodes,
1271 [DPO_PROTO_IP6] = mpls_label_imp_pipe_ip6_nodes,
1272 [DPO_PROTO_MPLS] = mpls_label_imp_pipe_mpls_nodes,
1273 [DPO_PROTO_ETHERNET] = mpls_label_imp_pipe_ethernet_nodes,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001274};
1275
Neale Ranns31ed7442018-02-23 05:29:09 -08001276const static char* const mpls_label_imp_uniform_ip4_nodes[] =
1277{
1278 "ip4-mpls-label-imposition-uniform",
1279 NULL,
1280};
1281const static char* const mpls_label_imp_uniform_ip6_nodes[] =
1282{
1283 "ip6-mpls-label-imposition-uniform",
1284 NULL,
1285};
1286const static char* const mpls_label_imp_uniform_mpls_nodes[] =
1287{
1288 "mpls-label-imposition-uniform",
1289 NULL,
1290};
1291const static char* const mpls_label_imp_uniform_ethernet_nodes[] =
1292{
1293 "ethernet-mpls-label-imposition-uniform",
1294 NULL,
1295};
1296
1297const static char* const * const mpls_label_imp_uniform_nodes[DPO_PROTO_NUM] =
1298{
1299 [DPO_PROTO_IP4] = mpls_label_imp_uniform_ip4_nodes,
1300 [DPO_PROTO_IP6] = mpls_label_imp_uniform_ip6_nodes,
1301 [DPO_PROTO_MPLS] = mpls_label_imp_uniform_mpls_nodes,
1302 [DPO_PROTO_ETHERNET] = mpls_label_imp_uniform_ethernet_nodes,
1303};
1304
1305const static char* const mpls_label_imp_pipe_no_ip_tll_decr_ip4_nodes[] =
1306{
1307 "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
1308 NULL,
1309};
1310const static char* const mpls_label_imp_pipe_no_ip_tll_decr_ip6_nodes[] =
1311{
1312 "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
1313 NULL,
1314};
1315
1316const static char* const * const mpls_label_imp_pipe_no_ip_tll_decr_nodes[DPO_PROTO_NUM] =
1317{
1318 [DPO_PROTO_IP4] = mpls_label_imp_pipe_no_ip_tll_decr_ip4_nodes,
1319 [DPO_PROTO_IP6] = mpls_label_imp_pipe_no_ip_tll_decr_ip6_nodes,
1320};
1321
1322const static char* const mpls_label_imp_uniform_no_ip_tll_decr_ip4_nodes[] =
1323{
1324 "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
1325 NULL,
1326};
1327const static char* const mpls_label_imp_uniform_no_ip_tll_decr_ip6_nodes[] =
1328{
1329 "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
1330 NULL,
1331};
1332
1333const static char* const * const mpls_label_imp_uniform_no_ip_tll_decr_nodes[DPO_PROTO_NUM] =
1334{
1335 [DPO_PROTO_IP4] = mpls_label_imp_uniform_no_ip_tll_decr_ip4_nodes,
1336 [DPO_PROTO_IP6] = mpls_label_imp_uniform_no_ip_tll_decr_ip6_nodes,
1337};
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001338
1339void
1340mpls_label_dpo_module_init (void)
1341{
Neale Ranns31ed7442018-02-23 05:29:09 -08001342 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE] =
1343 dpo_register_new_type(&mld_vft,
1344 mpls_label_imp_pipe_nodes);
1345 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR] =
1346 dpo_register_new_type(&mld_vft,
1347 mpls_label_imp_pipe_no_ip_tll_decr_nodes);
1348 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_UNIFORM_MODE] =
1349 dpo_register_new_type(&mld_vft,
1350 mpls_label_imp_uniform_nodes);
1351 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
1352 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR] =
1353 dpo_register_new_type(&mld_vft,
1354 mpls_label_imp_uniform_no_ip_tll_decr_nodes);
1355}
1356
1357dpo_type_t
1358mpls_label_dpo_get_type (mpls_label_dpo_flags_t flags)
1359{
1360 return (mpls_label_dpo_types[flags]);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001361}
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001362#endif /* CLIB_MARCH_VARIANT */
Neale Ranns8f5fef22020-12-21 08:29:34 +00001363
1364// clang-format on