blob: 683b544951365b0ee7aa74225d5d048e5f783ccb [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
Filip Tehlareb9a27f2019-03-07 01:42:11 -080021#ifndef CLIB_MARCH_VARIANT
Neale Ranns0bfe5d82016-08-25 15:29:12 +010022/*
23 * pool of all MPLS Label DPOs
24 */
25mpls_label_dpo_t *mpls_label_dpo_pool;
26
Neale Ranns31ed7442018-02-23 05:29:09 -080027/**
28 * Strings for the flags
29 */
30const char* mpls_label_dpo_attr_names[] = MPLS_LABEL_DPO_ATTR_NAMES;
31
32/**
33 * registered DPO types for each of the label sub-types. And there's a
34 * subtype for each of the flag combinations.
35 */
36static dpo_type_t mpls_label_dpo_types[1 << MPLS_LABEL_DPO_ATTR_MAX];
37
Neale Ranns0bfe5d82016-08-25 15:29:12 +010038static mpls_label_dpo_t *
39mpls_label_dpo_alloc (void)
40{
41 mpls_label_dpo_t *mld;
Dave Barach26d890e2020-06-05 09:42:50 -040042 vlib_main_t *vm;
43 u8 did_barrier_sync;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010044
Dave Barach26d890e2020-06-05 09:42:50 -040045 dpo_pool_barrier_sync (vm, mpls_label_dpo_pool, did_barrier_sync);
Neale Ranns0bfe5d82016-08-25 15:29:12 +010046 pool_get_aligned(mpls_label_dpo_pool, mld, CLIB_CACHE_LINE_BYTES);
Dave Barach26d890e2020-06-05 09:42:50 -040047 dpo_pool_barrier_release (vm, did_barrier_sync);
48
Dave Barachb7b92992018-10-17 10:38:51 -040049 clib_memset(mld, 0, sizeof(*mld));
Neale Ranns0bfe5d82016-08-25 15:29:12 +010050
51 dpo_reset(&mld->mld_dpo);
52
53 return (mld);
54}
55
56static index_t
57mpls_label_dpo_get_index (mpls_label_dpo_t *mld)
58{
59 return (mld - mpls_label_dpo_pool);
60}
61
Neale Ranns31ed7442018-02-23 05:29:09 -080062void
63mpls_label_dpo_create (fib_mpls_label_t *label_stack,
Neale Ranns0bfe5d82016-08-25 15:29:12 +010064 mpls_eos_bit_t eos,
Neale Rannsad422ed2016-11-02 14:20:04 +000065 dpo_proto_t payload_proto,
Neale Ranns31ed7442018-02-23 05:29:09 -080066 mpls_label_dpo_flags_t flags,
67 const dpo_id_t *parent,
68 dpo_id_t *dpo)
Neale Ranns0bfe5d82016-08-25 15:29:12 +010069{
70 mpls_label_dpo_t *mld;
Neale Ranns31ed7442018-02-23 05:29:09 -080071 dpo_type_t dtype;
Neale Rannsad422ed2016-11-02 14:20:04 +000072 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010073
Neale Ranns31ed7442018-02-23 05:29:09 -080074 if ((DPO_PROTO_IP4 != payload_proto) &&
75 (DPO_PROTO_IP6 != payload_proto))
76 {
77 /*
78 * remove unsupported configuration
79 */
80 flags &= ~MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR;
81 }
82
Neale Ranns0bfe5d82016-08-25 15:29:12 +010083 mld = mpls_label_dpo_alloc();
Neale Ranns31ed7442018-02-23 05:29:09 -080084 mld->mld_flags = flags;
85 dtype = mpls_label_dpo_types[flags];
Neale Rannsf363ebd2017-12-06 00:45:33 -080086
87 if (MPLS_LABEL_DPO_MAX_N_LABELS < vec_len(label_stack))
88 {
89 clib_warning("Label stack size exceeded");
Neale Ranns31ed7442018-02-23 05:29:09 -080090 dpo_stack(dtype,
Neale Rannsf363ebd2017-12-06 00:45:33 -080091 mld->mld_payload_proto,
92 &mld->mld_dpo,
93 drop_dpo_get(DPO_PROTO_MPLS));
Neale Rannsf363ebd2017-12-06 00:45:33 -080094 }
Neale Ranns31ed7442018-02-23 05:29:09 -080095 else
Neale Rannsad422ed2016-11-02 14:20:04 +000096 {
Neale Ranns31ed7442018-02-23 05:29:09 -080097 mld->mld_n_labels = vec_len(label_stack);
98 mld->mld_n_hdr_bytes = mld->mld_n_labels * sizeof(mld->mld_hdr[0]);
99 mld->mld_payload_proto = payload_proto;
100
101 /*
102 * construct label rewrite headers for each value passed.
103 * get the header in network byte order since we will paint it
104 * on a packet in the data-plane
105 */
106 for (ii = 0; ii < mld->mld_n_labels-1; ii++)
107 {
108 vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl,
109 label_stack[ii].fml_value);
110 vnet_mpls_uc_set_exp(&mld->mld_hdr[ii].label_exp_s_ttl,
111 label_stack[ii].fml_exp);
112 vnet_mpls_uc_set_s(&mld->mld_hdr[ii].label_exp_s_ttl,
113 MPLS_NON_EOS);
114 if (0 != label_stack[ii].fml_ttl)
115 {
116 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
117 label_stack[ii].fml_ttl);
118 }
119 else
120 {
121 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
122 MPLS_LABEL_DEFAULT_TTL);
123 }
124 mld->mld_hdr[ii].label_exp_s_ttl =
125 clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
126 }
127
128 /*
129 * the inner most label
130 */
131 ii = mld->mld_n_labels-1;
132
133 vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl,
134 label_stack[ii].fml_value);
135 vnet_mpls_uc_set_exp(&mld->mld_hdr[ii].label_exp_s_ttl,
136 label_stack[ii].fml_exp);
137 vnet_mpls_uc_set_s(&mld->mld_hdr[ii].label_exp_s_ttl, eos);
138 if (0 != label_stack[ii].fml_ttl)
139 {
140 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
141 label_stack[ii].fml_ttl);
142 }
143 else
144 {
145 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
146 MPLS_LABEL_DEFAULT_TTL);
147 }
148 mld->mld_hdr[ii].label_exp_s_ttl =
149 clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
150
151 /*
152 * pipe/uniform mode is only supported for the bottom of stack label
153 */
154 if (FIB_MPLS_LSP_MODE_UNIFORM == label_stack[ii].fml_mode)
155 {
156 mld->mld_flags |= MPLS_LABEL_DPO_FLAG_UNIFORM_MODE;
157 }
158 else
159 {
160 mld->mld_flags &= ~MPLS_LABEL_DPO_FLAG_UNIFORM_MODE;
161 }
162 dtype = mpls_label_dpo_types[mld->mld_flags];
163
164 /*
165 * stack this label object on its parent.
166 */
167 dpo_stack(dtype,
168 mld->mld_payload_proto,
169 &mld->mld_dpo,
170 parent);
Neale Rannsad422ed2016-11-02 14:20:04 +0000171 }
172
Neale Ranns31ed7442018-02-23 05:29:09 -0800173 dpo_set(dpo,
174 dtype,
175 mld->mld_payload_proto,
176 mpls_label_dpo_get_index(mld));
177}
Neale Rannsad422ed2016-11-02 14:20:04 +0000178
Neale Ranns31ed7442018-02-23 05:29:09 -0800179u8*
180format_mpls_label_dpo_flags (u8 *s, va_list *args)
181{
182 mpls_label_dpo_flags_t flags = va_arg (*args, int);
183 mpls_label_dpo_attr_t attr;
Neale Rannsad422ed2016-11-02 14:20:04 +0000184
Neale Ranns31ed7442018-02-23 05:29:09 -0800185 FOR_EACH_MPLS_LABEL_DPO_ATTR(attr)
186 {
187 if ((1 << attr) & flags)
188 {
189 s = format(s, "%s,", mpls_label_dpo_attr_names[attr]);
190 }
191 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100192
Neale Ranns31ed7442018-02-23 05:29:09 -0800193 return (s);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100194}
195
196u8*
197format_mpls_label_dpo (u8 *s, va_list *args)
198{
199 index_t index = va_arg (*args, index_t);
200 u32 indent = va_arg (*args, u32);
201 mpls_unicast_header_t hdr;
202 mpls_label_dpo_t *mld;
Neale Rannsad422ed2016-11-02 14:20:04 +0000203 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100204
Neale Ranns15002542017-09-10 04:39:11 -0700205 if (pool_is_free_index(mpls_label_dpo_pool, index))
206 {
207 /*
208 * the packet trace can be printed after the DPO has been deleted
209 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800210 return (format(s, "mpls-label[???,%d]:", index));
Neale Ranns15002542017-09-10 04:39:11 -0700211 }
212
213 mld = mpls_label_dpo_get(index);
Neale Ranns7c922dc2018-08-30 06:12:27 -0700214 s = format(s, "mpls-label[%U@%d]:",
Neale Ranns31ed7442018-02-23 05:29:09 -0800215 format_mpls_label_dpo_flags,
216 (int) mld->mld_flags, index);
Neale Ranns15002542017-09-10 04:39:11 -0700217
Neale Rannsad422ed2016-11-02 14:20:04 +0000218 for (ii = 0; ii < mld->mld_n_labels; ii++)
219 {
220 hdr.label_exp_s_ttl =
221 clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
222 s = format(s, "%U", format_mpls_header, hdr);
223 }
224
225 s = format(s, "\n%U", format_white_space, indent);
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000226 s = format(s, "%U", format_dpo_id, &mld->mld_dpo, indent+2);
227
228 return (s);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100229}
230
231static void
232mpls_label_dpo_lock (dpo_id_t *dpo)
233{
234 mpls_label_dpo_t *mld;
235
236 mld = mpls_label_dpo_get(dpo->dpoi_index);
237
238 mld->mld_locks++;
239}
240
241static void
242mpls_label_dpo_unlock (dpo_id_t *dpo)
243{
244 mpls_label_dpo_t *mld;
245
246 mld = mpls_label_dpo_get(dpo->dpoi_index);
247
248 mld->mld_locks--;
249
250 if (0 == mld->mld_locks)
251 {
252 dpo_reset(&mld->mld_dpo);
253 pool_put(mpls_label_dpo_pool, mld);
254 }
255}
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800256#endif /* CLIB_MARCH_VARIANT */
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100257
258/**
259 * @brief A struct to hold tracing information for the MPLS label imposition
260 * node.
261 */
262typedef struct mpls_label_imposition_trace_t_
263{
264 /**
265 * The MPLS header imposed
266 */
267 mpls_unicast_header_t hdr;
Neale Ranns31ed7442018-02-23 05:29:09 -0800268
269 /**
270 * TTL imposed - only valid for uniform LSPs
271 */
272 u8 ttl;
273
274 /**
275 * TTL imposed - only valid for uniform LSPs
276 */
277 u8 exp;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100278} mpls_label_imposition_trace_t;
279
Neale Ranns696e88d2017-03-16 07:34:55 -0400280always_inline mpls_unicast_header_t *
281mpls_label_paint (vlib_buffer_t * b0,
Neale Ranns31ed7442018-02-23 05:29:09 -0800282 mpls_label_dpo_t *mld0)
Neale Ranns696e88d2017-03-16 07:34:55 -0400283{
284 mpls_unicast_header_t *hdr0;
285
286 vlib_buffer_advance(b0, -(mld0->mld_n_hdr_bytes));
287
288 hdr0 = vlib_buffer_get_current(b0);
289
Pablo Camarillo5d73eec2017-04-24 17:51:56 +0200290 if (1 == mld0->mld_n_labels)
Neale Ranns696e88d2017-03-16 07:34:55 -0400291 {
292 /* optimise for the common case of one label */
293 *hdr0 = mld0->mld_hdr[0];
294 }
295 else
296 {
Dave Barach178cf492018-11-13 16:34:13 -0500297 clib_memcpy_fast(hdr0, mld0->mld_hdr, mld0->mld_n_hdr_bytes);
Neale Ranns696e88d2017-03-16 07:34:55 -0400298 hdr0 = hdr0 + (mld0->mld_n_labels - 1);
299 }
Neale Ranns31ed7442018-02-23 05:29:09 -0800300
301 return (hdr0);
302}
303
304/**
305 * Paint on an MPLS label and fixup the TTL
306 */
307always_inline mpls_unicast_header_t *
308mpls_label_paint_w_ttl (vlib_buffer_t * b0,
309 mpls_label_dpo_t *mld0,
310 u8 ttl0)
311{
312 mpls_unicast_header_t *hdr0;
313
314 hdr0 = mpls_label_paint(b0, mld0);
315
Neale Ranns696e88d2017-03-16 07:34:55 -0400316 /* fixup the TTL for the inner most label */
317 ((char*)hdr0)[3] = ttl0;
318
319 return (hdr0);
320}
321
Neale Ranns31ed7442018-02-23 05:29:09 -0800322/**
323 * Paint on an MPLS label and fixup the TTL and EXP bits.
324 */
325always_inline mpls_unicast_header_t *
326mpls_label_paint_w_ttl_exp (vlib_buffer_t * b0,
327 mpls_label_dpo_t *mld0,
328 u8 ttl0,
329 u8 exp0)
330{
331 mpls_unicast_header_t *hdr0;
332
333 hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
334
335 /* fixup the EXP for the inner most label */
336 ((char*)hdr0)[2] |= (exp0 << 1);
337
338 return (hdr0);
339}
340
341/**
342 * Paint on an MPLS label and fixup the TTL and EXP bits
343 * When the EXP bits are *already* bit shift to the correct place in
344 * in the 2nd byte (i.e. they were read from another label)
345 */
346always_inline mpls_unicast_header_t *
347mpls_label_paint_w_ttl_mpls_exp (vlib_buffer_t * b0,
348 mpls_label_dpo_t *mld0,
349 u8 ttl0,
350 u8 exp0)
351{
352 mpls_unicast_header_t *hdr0;
353
354 hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
355
356 /* fixup the EXP for the inner most label */
357 ((char*)hdr0)[2] |= exp0;
358
359 return (hdr0);
360}
361
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100362always_inline uword
Neale Rannsad422ed2016-11-02 14:20:04 +0000363mpls_label_imposition_inline (vlib_main_t * vm,
364 vlib_node_runtime_t * node,
365 vlib_frame_t * from_frame,
Neale Ranns31ed7442018-02-23 05:29:09 -0800366 const dpo_proto_t dproto,
367 const mpls_label_dpo_flags_t flags)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100368{
369 u32 n_left_from, next_index, * from, * to_next;
370
371 from = vlib_frame_vector_args (from_frame);
372 n_left_from = from_frame->n_vectors;
373
374 next_index = node->cached_next_index;
375
376 while (n_left_from > 0)
377 {
378 u32 n_left_to_next;
379
380 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
381
Neale Ranns696e88d2017-03-16 07:34:55 -0400382 while (n_left_from >= 8 && n_left_to_next >= 4)
Neale Ranns9ca18c62016-12-10 21:08:09 +0000383 {
Neale Ranns696e88d2017-03-16 07:34:55 -0400384 u32 bi0, mldi0, bi1, mldi1, bi2, mldi2, bi3, mldi3;
385 mpls_unicast_header_t *hdr0, *hdr1, *hdr2, *hdr3;
386 mpls_label_dpo_t *mld0, *mld1, *mld2, *mld3;
387 vlib_buffer_t * b0, *b1, * b2, *b3;
388 u32 next0, next1, next2, next3;
Neale Ranns31ed7442018-02-23 05:29:09 -0800389 u8 ttl0, ttl1, ttl2, ttl3;
390 u8 exp0, exp1, exp2, exp3;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000391
392 bi0 = to_next[0] = from[0];
393 bi1 = to_next[1] = from[1];
Neale Ranns696e88d2017-03-16 07:34:55 -0400394 bi2 = to_next[2] = from[2];
395 bi3 = to_next[3] = from[3];
Neale Ranns9ca18c62016-12-10 21:08:09 +0000396
397 /* Prefetch next iteration. */
398 {
Neale Ranns696e88d2017-03-16 07:34:55 -0400399 vlib_buffer_t * p2, * p3, *p4, *p5;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000400
401 p2 = vlib_get_buffer (vm, from[2]);
402 p3 = vlib_get_buffer (vm, from[3]);
Neale Ranns696e88d2017-03-16 07:34:55 -0400403 p4 = vlib_get_buffer (vm, from[4]);
404 p5 = vlib_get_buffer (vm, from[5]);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000405
406 vlib_prefetch_buffer_header (p2, STORE);
407 vlib_prefetch_buffer_header (p3, STORE);
Neale Ranns696e88d2017-03-16 07:34:55 -0400408 vlib_prefetch_buffer_header (p4, STORE);
409 vlib_prefetch_buffer_header (p5, STORE);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000410
411 CLIB_PREFETCH (p2->data, sizeof (hdr0[0]), STORE);
412 CLIB_PREFETCH (p3->data, sizeof (hdr0[0]), STORE);
Neale Ranns696e88d2017-03-16 07:34:55 -0400413 CLIB_PREFETCH (p4->data, sizeof (hdr0[0]), STORE);
414 CLIB_PREFETCH (p5->data, sizeof (hdr0[0]), STORE);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000415 }
416
Neale Ranns696e88d2017-03-16 07:34:55 -0400417 from += 4;
418 to_next += 4;
419 n_left_from -= 4;
420 n_left_to_next -= 4;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000421
422 b0 = vlib_get_buffer (vm, bi0);
423 b1 = vlib_get_buffer (vm, bi1);
Neale Ranns696e88d2017-03-16 07:34:55 -0400424 b2 = vlib_get_buffer (vm, bi2);
425 b3 = vlib_get_buffer (vm, bi3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000426
427 /* dst lookup was done by ip4 lookup */
428 mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
429 mldi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
Neale Ranns696e88d2017-03-16 07:34:55 -0400430 mldi2 = vnet_buffer(b2)->ip.adj_index[VLIB_TX];
431 mldi3 = vnet_buffer(b3)->ip.adj_index[VLIB_TX];
Neale Ranns9ca18c62016-12-10 21:08:09 +0000432 mld0 = mpls_label_dpo_get(mldi0);
433 mld1 = mpls_label_dpo_get(mldi1);
Neale Ranns696e88d2017-03-16 07:34:55 -0400434 mld2 = mpls_label_dpo_get(mldi2);
435 mld3 = mpls_label_dpo_get(mldi3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000436
Neale Ranns31ed7442018-02-23 05:29:09 -0800437 if (DPO_PROTO_MPLS != dproto)
Neale Ranns9ca18c62016-12-10 21:08:09 +0000438 {
439 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800440 * These are the non-MPLS payload imposition cases
Neale Ranns9ca18c62016-12-10 21:08:09 +0000441 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800442 if (DPO_PROTO_IP4 == dproto)
443 {
444 ip4_header_t * ip0 = vlib_buffer_get_current(b0);
445 ip4_header_t * ip1 = vlib_buffer_get_current(b1);
446 ip4_header_t * ip2 = vlib_buffer_get_current(b2);
447 ip4_header_t * ip3 = vlib_buffer_get_current(b3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000448
Neale Ranns31ed7442018-02-23 05:29:09 -0800449 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
450 {
451 /*
452 * decrement the TTL on ingress to the LSP
453 */
454 u32 checksum0;
455 u32 checksum1;
456 u32 checksum2;
457 u32 checksum3;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000458
Neale Ranns31ed7442018-02-23 05:29:09 -0800459 checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
460 checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
461 checksum2 = ip2->checksum + clib_host_to_net_u16 (0x0100);
462 checksum3 = ip3->checksum + clib_host_to_net_u16 (0x0100);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000463
Neale Ranns31ed7442018-02-23 05:29:09 -0800464 checksum0 += checksum0 >= 0xffff;
465 checksum1 += checksum1 >= 0xffff;
466 checksum2 += checksum2 >= 0xffff;
467 checksum3 += checksum3 >= 0xffff;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000468
Neale Ranns31ed7442018-02-23 05:29:09 -0800469 ip0->checksum = checksum0;
470 ip1->checksum = checksum1;
471 ip2->checksum = checksum2;
472 ip3->checksum = checksum3;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000473
Neale Ranns31ed7442018-02-23 05:29:09 -0800474 ip0->ttl -= 1;
475 ip1->ttl -= 1;
476 ip2->ttl -= 1;
477 ip3->ttl -= 1;
478 }
479
480 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
481 {
482 ttl1 = ip1->ttl;
483 ttl0 = ip0->ttl;
484 ttl3 = ip3->ttl;
485 ttl2 = ip2->ttl;
486 /* by default copy the 3 most significant bits */
487 exp0 = ip_dscp_to_mpls_exp(ip0->tos);
488 exp1 = ip_dscp_to_mpls_exp(ip1->tos);
489 exp2 = ip_dscp_to_mpls_exp(ip2->tos);
490 exp3 = ip_dscp_to_mpls_exp(ip3->tos);
491 }
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530492
493 /* save the payload proto information in mpls opaque */
494 vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP4;
495 vnet_buffer(b1)->mpls.pyld_proto = DPO_PROTO_IP4;
496 vnet_buffer(b2)->mpls.pyld_proto = DPO_PROTO_IP4;
497 vnet_buffer(b3)->mpls.pyld_proto = DPO_PROTO_IP4;
Neale Ranns31ed7442018-02-23 05:29:09 -0800498 }
499 else if (DPO_PROTO_IP6 == dproto)
500 {
501 /*
502 * decrement the TTL on ingress to the LSP
503 */
504 ip6_header_t * ip0 = vlib_buffer_get_current(b0);
505 ip6_header_t * ip1 = vlib_buffer_get_current(b1);
506 ip6_header_t * ip2 = vlib_buffer_get_current(b2);
507 ip6_header_t * ip3 = vlib_buffer_get_current(b3);
508
509 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
510 {
511 ip0->hop_limit -= 1;
512 ip1->hop_limit -= 1;
513 ip2->hop_limit -= 1;
514 ip3->hop_limit -= 1;
515 }
516 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
517 {
518 ttl0 = ip0->hop_limit;
519 ttl1 = ip1->hop_limit;
520 ttl2 = ip2->hop_limit;
521 ttl3 = ip3->hop_limit;
522 /* by default copy the 3 most significant bits */
523 exp0 = ip_dscp_to_mpls_exp(
524 ip6_traffic_class_network_order(ip0));
525 exp1 = ip_dscp_to_mpls_exp(
526 ip6_traffic_class_network_order(ip1));
527 exp2 = ip_dscp_to_mpls_exp(
528 ip6_traffic_class_network_order(ip2));
529 exp3 = ip_dscp_to_mpls_exp(
530 ip6_traffic_class_network_order(ip3));
531 }
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530532
533 /* save the payload proto information in mpls opaque */
534 vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP6;
535 vnet_buffer(b1)->mpls.pyld_proto = DPO_PROTO_IP6;
536 vnet_buffer(b2)->mpls.pyld_proto = DPO_PROTO_IP6;
537 vnet_buffer(b3)->mpls.pyld_proto = DPO_PROTO_IP6;
Neale Ranns31ed7442018-02-23 05:29:09 -0800538 }
539 else
540 {
541 /*
542 * nothing to change in the ethernet header
543 */
544 ttl0 = ttl1 = ttl2 = ttl3 = MPLS_LABEL_DEFAULT_TTL;
545 exp0 = exp1 = exp2 = exp3 = MPLS_LABEL_DEFAULT_EXP;
546 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000547 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800548 * These are the non-MPLS payload imposition cases.
549 * Based on the LSP mode either, for uniform, copy down the TTL
550 * and EXP from the payload or, for pipe mode, slap on the value
551 * requested from config
Neale Ranns9ca18c62016-12-10 21:08:09 +0000552 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800553 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
554 {
555 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
556 hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
557 hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
558 hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
559 }
560 else
561 {
562 hdr0 = mpls_label_paint(b0, mld0);
563 hdr1 = mpls_label_paint(b1, mld1);
564 hdr2 = mpls_label_paint(b2, mld2);
565 hdr3 = mpls_label_paint(b3, mld3);
566 }
Neale Rannsda78f952017-05-24 09:15:43 -0700567 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000568 else
569 {
570 /*
571 * else, the packet to be encapped is an MPLS packet
Neale Ranns31ed7442018-02-23 05:29:09 -0800572 * there are two cases to consider:
573 * 1 - this is an MPLS label swap at an LSP midpoint.
574 * recognisable because mpls.first = 1. In this case the
575 * TTL must be set to the current value -1.
576 * 2 - The MPLS packet is recursing (or being injected into)
577 * this LSP, in which case the pipe/uniform rules apply
578 *
Neale Ranns9ca18c62016-12-10 21:08:09 +0000579 */
580 if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
581 {
582 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800583 * The first label to be imposed on the packet. this is a
584 * label swap.in which case we stashed the TTL and EXP bits
585 * in the packet in the lookup node
Neale Ranns9ca18c62016-12-10 21:08:09 +0000586 */
587 ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
588
589 ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800590 exp0 = vnet_buffer(b0)->mpls.exp;
591 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000592 }
593 else
594 {
595 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800596 * not the first label. implying we are recusring down a
597 * chain of output labels. Each layer is considered a new
598 * LSP - hence the TTL/EXP are pipe/uniform handled
Neale Ranns9ca18c62016-12-10 21:08:09 +0000599 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800600 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
601 {
602 hdr0 = vlib_buffer_get_current(b0);
603 ttl0 = ((u8*)hdr0)[3];
604 exp0 = ((u8*)hdr0)[2] & 0xe;
605 hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
606 }
607 else
608 {
609 hdr0 = mpls_label_paint(b0, mld0);
610 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000611 }
612 if (PREDICT_TRUE(vnet_buffer(b1)->mpls.first))
613 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800614 ASSERT(0 != vnet_buffer (b1)->mpls.ttl);
615
Neale Ranns9ca18c62016-12-10 21:08:09 +0000616 ttl1 = vnet_buffer(b1)->mpls.ttl - 1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800617 exp1 = vnet_buffer(b1)->mpls.exp;
618 hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000619 }
620 else
621 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800622 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
623 {
624 hdr1 = vlib_buffer_get_current(b1);
625 ttl1 = ((u8*)hdr1)[3];
626 exp1 = ((u8*)hdr1)[2] & 0xe;
627 hdr1 = mpls_label_paint_w_ttl_mpls_exp(b1, mld1, ttl1, exp1);
628 }
629 else
630 {
631 hdr1 = mpls_label_paint(b1, mld1);
632 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000633 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400634 if (PREDICT_TRUE(vnet_buffer(b2)->mpls.first))
635 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800636 ASSERT(0 != vnet_buffer (b2)->mpls.ttl);
Neale Ranns696e88d2017-03-16 07:34:55 -0400637
638 ttl2 = vnet_buffer(b2)->mpls.ttl - 1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800639 exp2 = vnet_buffer(b2)->mpls.exp;
640 hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
Neale Ranns696e88d2017-03-16 07:34:55 -0400641 }
642 else
643 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800644 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
645 {
646 hdr2 = vlib_buffer_get_current(b2);
647 ttl2 = ((u8*)hdr2)[3];
648 exp2 = ((u8*)hdr2)[2] & 0xe;
649 hdr2 = mpls_label_paint_w_ttl_mpls_exp(b2, mld2, ttl2, exp2);
650 }
651 else
652 {
653 hdr2 = mpls_label_paint(b2, mld2);
654 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400655 }
656 if (PREDICT_TRUE(vnet_buffer(b3)->mpls.first))
657 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800658 ASSERT(0 != vnet_buffer (b3)->mpls.ttl);
659
Neale Ranns696e88d2017-03-16 07:34:55 -0400660 ttl3 = vnet_buffer(b3)->mpls.ttl - 1;
Neale Ranns19bd1902018-03-19 02:32:57 -0700661 exp3 = vnet_buffer(b3)->mpls.exp;
Neale Ranns31ed7442018-02-23 05:29:09 -0800662 hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
Neale Ranns696e88d2017-03-16 07:34:55 -0400663 }
664 else
665 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800666 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
667 {
668 hdr3 = vlib_buffer_get_current(b3);
669 ttl3 = ((u8*)hdr3)[3];
670 exp3 = ((u8*)hdr3)[2] & 0xe;
671 hdr3 = mpls_label_paint_w_ttl_mpls_exp(b3, mld3, ttl3, exp3);
672 }
673 else
674 {
675 hdr3 = mpls_label_paint(b3, mld3);
676 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400677 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000678
Neale Ranns31ed7442018-02-23 05:29:09 -0800679 vnet_buffer(b0)->mpls.first = 0;
680 vnet_buffer(b1)->mpls.first = 0;
681 vnet_buffer(b2)->mpls.first = 0;
682 vnet_buffer(b3)->mpls.first = 0;
683 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000684
685 next0 = mld0->mld_dpo.dpoi_next_node;
686 next1 = mld1->mld_dpo.dpoi_next_node;
Neale Ranns696e88d2017-03-16 07:34:55 -0400687 next2 = mld2->mld_dpo.dpoi_next_node;
688 next3 = mld3->mld_dpo.dpoi_next_node;
Neale Ranns31ed7442018-02-23 05:29:09 -0800689
Neale Ranns9ca18c62016-12-10 21:08:09 +0000690 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
691 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = mld1->mld_dpo.dpoi_index;
Neale Ranns696e88d2017-03-16 07:34:55 -0400692 vnet_buffer(b2)->ip.adj_index[VLIB_TX] = mld2->mld_dpo.dpoi_index;
693 vnet_buffer(b3)->ip.adj_index[VLIB_TX] = mld3->mld_dpo.dpoi_index;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000694
695 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
696 {
697 mpls_label_imposition_trace_t *tr =
698 vlib_add_trace (vm, node, b0, sizeof (*tr));
699 tr->hdr = *hdr0;
Neale Ranns31ed7442018-02-23 05:29:09 -0800700 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
701 {
702 tr->ttl = ttl0;
703 tr->exp = exp0;
704 }
705 else
706 {
707 tr->ttl = tr->exp = 0;
708 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000709 }
710 if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
711 {
712 mpls_label_imposition_trace_t *tr =
713 vlib_add_trace (vm, node, b1, sizeof (*tr));
714 tr->hdr = *hdr1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800715 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
716 {
717 tr->ttl = ttl1;
718 tr->exp = exp1;
719 }
720 else
721 {
722 tr->ttl = tr->exp = 0;
723 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000724 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400725 if (PREDICT_FALSE(b2->flags & VLIB_BUFFER_IS_TRACED))
726 {
727 mpls_label_imposition_trace_t *tr =
728 vlib_add_trace (vm, node, b2, sizeof (*tr));
729 tr->hdr = *hdr2;
Neale Ranns31ed7442018-02-23 05:29:09 -0800730 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
731 {
732 tr->ttl = ttl2;
733 tr->exp = exp2;
734 }
735 else
736 {
737 tr->ttl = tr->exp = 0;
738 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400739 }
740 if (PREDICT_FALSE(b3->flags & VLIB_BUFFER_IS_TRACED))
741 {
742 mpls_label_imposition_trace_t *tr =
743 vlib_add_trace (vm, node, b3, sizeof (*tr));
744 tr->hdr = *hdr3;
Neale Ranns31ed7442018-02-23 05:29:09 -0800745 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
746 {
747 tr->ttl = ttl3;
748 tr->exp = exp3;
749 }
750 else
751 {
752 tr->ttl = tr->exp = 0;
753 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400754 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000755
Neale Ranns696e88d2017-03-16 07:34:55 -0400756 vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next,
Neale Ranns9ca18c62016-12-10 21:08:09 +0000757 n_left_to_next,
Neale Ranns696e88d2017-03-16 07:34:55 -0400758 bi0, bi1, bi2, bi3,
759 next0, next1, next2, next3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000760 }
761
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100762 while (n_left_from > 0 && n_left_to_next > 0)
763 {
764 mpls_unicast_header_t *hdr0;
765 mpls_label_dpo_t *mld0;
766 vlib_buffer_t * b0;
767 u32 bi0, mldi0;
Neale Ranns31ed7442018-02-23 05:29:09 -0800768 u8 ttl0, exp0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100769 u32 next0;
770
771 bi0 = from[0];
772 to_next[0] = bi0;
773 from += 1;
774 to_next += 1;
775 n_left_from -= 1;
776 n_left_to_next -= 1;
777
778 b0 = vlib_get_buffer (vm, bi0);
779
780 /* dst lookup was done by ip4 lookup */
781 mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
782 mld0 = mpls_label_dpo_get(mldi0);
783
Neale Ranns31ed7442018-02-23 05:29:09 -0800784 if (DPO_PROTO_MPLS != dproto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000785 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800786 if (DPO_PROTO_IP4 == dproto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000787 {
788 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800789 * decrement the TTL on ingress to the LSP
Neale Rannsad422ed2016-11-02 14:20:04 +0000790 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800791 ip4_header_t * ip0 = vlib_buffer_get_current(b0);
792 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
793 {
794 u32 checksum0;
Neale Rannsad422ed2016-11-02 14:20:04 +0000795
Neale Ranns31ed7442018-02-23 05:29:09 -0800796 checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
797 checksum0 += checksum0 >= 0xffff;
798
799 ip0->checksum = checksum0;
800 ip0->ttl -= 1;
801 }
802 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
803 {
804 ttl0 = ip0->ttl;
805 exp0 = ip_dscp_to_mpls_exp(ip0->tos);
806 }
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530807
808 /* save the payload proto information in mpls opaque */
809 vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP4;
Neale Ranns31ed7442018-02-23 05:29:09 -0800810 }
811 else if (DPO_PROTO_IP6 == dproto)
812 {
813 /*
814 * decrement the TTL on ingress to the LSP
815 */
816 ip6_header_t * ip0 = vlib_buffer_get_current(b0);
817
818 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
819 {
820 ip0->hop_limit -= 1;
821 }
822 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
823 {
824 ttl0 = ip0->hop_limit;
825 exp0 = ip_dscp_to_mpls_exp(
826 ip6_traffic_class_network_order(ip0));
827 }
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530828
829 /* save the payload proto information in mpls opaque */
830 vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP6;
Neale Rannsad422ed2016-11-02 14:20:04 +0000831 }
832 else
833 {
834 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800835 * nothing to change in the ethernet header
Neale Rannsad422ed2016-11-02 14:20:04 +0000836 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800837 ttl0 = MPLS_LABEL_DEFAULT_TTL;
838 exp0 = MPLS_LABEL_DEFAULT_EXP;
839 }
840
841 /*
842 * These are the non-MPLS payload imposition cases.
843 * Based on the LSP mode either, for uniform, copy down the TTL
844 * from the payload or, for pipe mode, slap on the value
845 * requested from config
846 */
847 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
848 {
849 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
850 }
851 else
852 {
853 hdr0 = mpls_label_paint(b0, mld0);
Neale Rannsad422ed2016-11-02 14:20:04 +0000854 }
855 }
Neale Ranns31ed7442018-02-23 05:29:09 -0800856 else
857 {
858 if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
859 {
860 ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
Neale Rannsad422ed2016-11-02 14:20:04 +0000861
Neale Ranns31ed7442018-02-23 05:29:09 -0800862 ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
863 exp0 = vnet_buffer(b0)->mpls.exp;
864 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
865 }
866 else
867 {
868 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
869 {
870 hdr0 = vlib_buffer_get_current(b0);
871 ttl0 = ((u8*)hdr0)[3];
872 exp0 = ((u8*)hdr0)[2] & 0xe;
873 hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
874 }
875 else
876 {
877 hdr0 = mpls_label_paint(b0, mld0);
878 }
879 }
Neale Rannsad422ed2016-11-02 14:20:04 +0000880
Neale Ranns31ed7442018-02-23 05:29:09 -0800881 vnet_buffer(b0)->mpls.first = 0;
882 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100883
884 next0 = mld0->mld_dpo.dpoi_next_node;
885 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
886
Neale Ranns9ca18c62016-12-10 21:08:09 +0000887 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100888 {
889 mpls_label_imposition_trace_t *tr =
890 vlib_add_trace (vm, node, b0, sizeof (*tr));
891 tr->hdr = *hdr0;
Neale Ranns31ed7442018-02-23 05:29:09 -0800892 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
893 {
894 tr->ttl = ttl0;
895 tr->exp = exp0;
896 }
897 else
898 {
899 tr->ttl = tr->exp = 0;
900 }
901 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100902
903 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
904 n_left_to_next, bi0, next0);
905 }
906 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
907 }
908 return from_frame->n_vectors;
909}
910
911static u8 *
912format_mpls_label_imposition_trace (u8 * s, va_list * args)
913{
914 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
915 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
916 mpls_label_imposition_trace_t * t;
917 mpls_unicast_header_t hdr;
Christophe Fontained3c008d2017-10-02 18:10:54 +0200918 u32 indent;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100919
920 t = va_arg (*args, mpls_label_imposition_trace_t *);
921 indent = format_get_indent (s);
922 hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
923
924 s = format (s, "%Umpls-header:%U",
925 format_white_space, indent,
926 format_mpls_header, hdr);
927 return (s);
928}
929
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800930VLIB_NODE_FN (mpls_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -0800931 vlib_node_runtime_t * node,
932 vlib_frame_t * frame)
Neale Rannsad422ed2016-11-02 14:20:04 +0000933{
Neale Ranns31ed7442018-02-23 05:29:09 -0800934 return (mpls_label_imposition_inline(vm, node, frame,
935 DPO_PROTO_MPLS,
936 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsad422ed2016-11-02 14:20:04 +0000937}
938
Neale Ranns31ed7442018-02-23 05:29:09 -0800939VLIB_REGISTER_NODE (mpls_mpls_label_imposition_pipe_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -0800940 .name = "mpls-label-imposition-pipe",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100941 .vector_size = sizeof (u32),
942
943 .format_trace = format_mpls_label_imposition_trace,
944 .n_next_nodes = 1,
945 .next_nodes = {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800946 [0] = "mpls-drop",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100947 }
948};
Neale Rannsad422ed2016-11-02 14:20:04 +0000949
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800950VLIB_NODE_FN (ip4_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -0800951 vlib_node_runtime_t * node,
952 vlib_frame_t * frame)
Neale Rannsad422ed2016-11-02 14:20:04 +0000953{
Neale Ranns31ed7442018-02-23 05:29:09 -0800954 return (mpls_label_imposition_inline(vm, node, frame,
955 DPO_PROTO_IP4,
956 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsad422ed2016-11-02 14:20:04 +0000957}
958
Neale Ranns31ed7442018-02-23 05:29:09 -0800959VLIB_REGISTER_NODE (ip4_mpls_label_imposition_pipe_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -0800960 .name = "ip4-mpls-label-imposition-pipe",
Neale Rannsad422ed2016-11-02 14:20:04 +0000961 .vector_size = sizeof (u32),
962
963 .format_trace = format_mpls_label_imposition_trace,
964 .n_next_nodes = 1,
965 .next_nodes = {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800966 [0] = "ip4-drop",
Neale Rannsad422ed2016-11-02 14:20:04 +0000967 }
968};
Neale Rannsad422ed2016-11-02 14:20:04 +0000969
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800970VLIB_NODE_FN (ip6_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -0800971 vlib_node_runtime_t * node,
972 vlib_frame_t * frame)
Neale Rannsad422ed2016-11-02 14:20:04 +0000973{
Neale Ranns31ed7442018-02-23 05:29:09 -0800974 return (mpls_label_imposition_inline(vm, node, frame,
975 DPO_PROTO_IP6,
976 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsad422ed2016-11-02 14:20:04 +0000977}
978
Neale Ranns31ed7442018-02-23 05:29:09 -0800979VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -0800980 .name = "ip6-mpls-label-imposition-pipe",
Neale Rannsad422ed2016-11-02 14:20:04 +0000981 .vector_size = sizeof (u32),
982
983 .format_trace = format_mpls_label_imposition_trace,
984 .n_next_nodes = 1,
985 .next_nodes = {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800986 [0] = "ip6-drop",
Neale Rannsad422ed2016-11-02 14:20:04 +0000987 }
988};
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100989
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800990VLIB_NODE_FN (ethernet_mpls_label_imposition_pipe_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -0800991 vlib_node_runtime_t * node,
992 vlib_frame_t * frame)
Neale Rannsda78f952017-05-24 09:15:43 -0700993{
Neale Ranns31ed7442018-02-23 05:29:09 -0800994 return (mpls_label_imposition_inline(vm, node, frame,
995 DPO_PROTO_ETHERNET,
996 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsda78f952017-05-24 09:15:43 -0700997}
998
Neale Ranns31ed7442018-02-23 05:29:09 -0800999VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_pipe_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001000 .name = "ethernet-mpls-label-imposition-pipe",
Neale Rannsda78f952017-05-24 09:15:43 -07001001 .vector_size = sizeof (u32),
1002
1003 .format_trace = format_mpls_label_imposition_trace,
1004 .n_next_nodes = 1,
1005 .next_nodes = {
1006 [0] = "error-drop",
1007 }
1008};
Neale Ranns31ed7442018-02-23 05:29:09 -08001009
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001010VLIB_NODE_FN (mpls_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001011 vlib_node_runtime_t * node,
1012 vlib_frame_t * frame)
1013{
1014 return (mpls_label_imposition_inline(vm, node, frame,
1015 DPO_PROTO_MPLS,
1016 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1017}
1018
1019VLIB_REGISTER_NODE (mpls_mpls_label_imposition_uniform_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001020 .name = "mpls-label-imposition-uniform",
1021 .vector_size = sizeof (u32),
1022
1023 .format_trace = format_mpls_label_imposition_trace,
1024 .n_next_nodes = 1,
1025 .next_nodes = {
1026 [0] = "mpls-drop",
1027 }
1028};
Neale Ranns31ed7442018-02-23 05:29:09 -08001029
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001030VLIB_NODE_FN (ip4_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001031 vlib_node_runtime_t * node,
1032 vlib_frame_t * frame)
1033{
1034 return (mpls_label_imposition_inline(vm, node, frame,
1035 DPO_PROTO_IP4,
1036 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1037}
1038
1039VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001040 .name = "ip4-mpls-label-imposition-uniform",
1041 .vector_size = sizeof (u32),
1042
1043 .format_trace = format_mpls_label_imposition_trace,
1044 .n_next_nodes = 1,
1045 .next_nodes = {
1046 [0] = "ip4-drop",
1047 }
1048};
Neale Ranns31ed7442018-02-23 05:29:09 -08001049
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001050VLIB_NODE_FN (ip6_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001051 vlib_node_runtime_t * node,
1052 vlib_frame_t * frame)
1053{
1054 return (mpls_label_imposition_inline(vm, node, frame,
1055 DPO_PROTO_IP6,
1056 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1057}
1058
1059VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001060 .name = "ip6-mpls-label-imposition-uniform",
1061 .vector_size = sizeof (u32),
1062
1063 .format_trace = format_mpls_label_imposition_trace,
1064 .n_next_nodes = 1,
1065 .next_nodes = {
1066 [0] = "ip6-drop",
1067 }
1068};
Neale Ranns31ed7442018-02-23 05:29:09 -08001069
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001070VLIB_NODE_FN (ethernet_mpls_label_imposition_uniform_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001071 vlib_node_runtime_t * node,
1072 vlib_frame_t * frame)
1073{
1074 return (mpls_label_imposition_inline(vm, node, frame,
1075 DPO_PROTO_ETHERNET,
1076 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1077}
1078
1079VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_uniform_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001080 .name = "ethernet-mpls-label-imposition-uniform",
1081 .vector_size = sizeof (u32),
1082
1083 .format_trace = format_mpls_label_imposition_trace,
1084 .n_next_nodes = 1,
1085 .next_nodes = {
1086 [0] = "error-drop",
1087 }
1088};
1089
Neale Ranns31ed7442018-02-23 05:29:09 -08001090
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001091VLIB_NODE_FN (ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001092 vlib_node_runtime_t * node,
1093 vlib_frame_t * frame)
1094{
1095 return (mpls_label_imposition_inline(vm, node, frame,
1096 DPO_PROTO_IP4,
1097 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR));
1098}
1099
1100VLIB_REGISTER_NODE (ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001101 .name = "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
1102 .vector_size = sizeof (u32),
1103
1104 .format_trace = format_mpls_label_imposition_trace,
1105 .n_next_nodes = 1,
1106 .next_nodes = {
1107 [0] = "ip4-drop",
1108 }
1109};
Neale Ranns31ed7442018-02-23 05:29:09 -08001110
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001111VLIB_NODE_FN (ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001112 vlib_node_runtime_t * node,
1113 vlib_frame_t * frame)
1114{
1115 return (mpls_label_imposition_inline(vm, node, frame,
1116 DPO_PROTO_IP6,
1117 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR));
1118}
1119
1120VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001121 .name = "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
1122 .vector_size = sizeof (u32),
1123
1124 .format_trace = format_mpls_label_imposition_trace,
1125 .n_next_nodes = 1,
1126 .next_nodes = {
1127 [0] = "ip6-drop",
1128 }
1129};
Neale Ranns31ed7442018-02-23 05:29:09 -08001130
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001131VLIB_NODE_FN (ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001132 vlib_node_runtime_t * node,
1133 vlib_frame_t * frame)
1134{
1135 return (mpls_label_imposition_inline(vm, node, frame,
1136 DPO_PROTO_IP4,
1137 (MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
1138 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR)));
1139}
1140
1141VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001142 .name = "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
1143 .vector_size = sizeof (u32),
1144
1145 .format_trace = format_mpls_label_imposition_trace,
1146 .n_next_nodes = 1,
1147 .next_nodes = {
1148 [0] = "ip4-drop",
1149 }
1150};
Neale Ranns31ed7442018-02-23 05:29:09 -08001151
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001152VLIB_NODE_FN (ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node) (vlib_main_t * vm,
Neale Ranns31ed7442018-02-23 05:29:09 -08001153 vlib_node_runtime_t * node,
1154 vlib_frame_t * frame)
1155{
1156 return (mpls_label_imposition_inline(vm, node, frame,
1157 DPO_PROTO_IP6,
1158 (MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
1159 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR)));
1160}
1161
1162VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node) = {
Neale Ranns31ed7442018-02-23 05:29:09 -08001163 .name = "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
1164 .vector_size = sizeof (u32),
1165
1166 .format_trace = format_mpls_label_imposition_trace,
1167 .n_next_nodes = 1,
1168 .next_nodes = {
1169 [0] = "ip6-drop",
1170 }
1171};
Neale Ranns31ed7442018-02-23 05:29:09 -08001172
Neale Rannsda78f952017-05-24 09:15:43 -07001173
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001174#ifndef CLIB_MARCH_VARIANT
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001175static void
1176mpls_label_dpo_mem_show (void)
1177{
1178 fib_show_memory_usage("MPLS label",
1179 pool_elts(mpls_label_dpo_pool),
1180 pool_len(mpls_label_dpo_pool),
1181 sizeof(mpls_label_dpo_t));
1182}
1183
Neale Ranns2303cb12018-02-21 04:57:17 -08001184/**
1185 * Interpose a label DPO. used in the FIB unit tests
1186 */
1187static void
1188mpls_label_interpose (const dpo_id_t *original,
1189 const dpo_id_t *parent,
1190 dpo_id_t *clone)
1191{
1192 mpls_label_dpo_t *mld, *mld_clone;
1193
1194 mld_clone = mpls_label_dpo_alloc();
1195 mld = mpls_label_dpo_get(original->dpoi_index);
1196
1197 mld_clone->mld_locks = 0;
Dave Barach178cf492018-11-13 16:34:13 -05001198 clib_memcpy_fast(&mld_clone->mld_hdr,
Neale Ranns2303cb12018-02-21 04:57:17 -08001199 &mld->mld_hdr,
1200 sizeof(mld_clone->mld_hdr));
1201 mld_clone->mld_payload_proto = mld->mld_payload_proto;
1202 mld_clone->mld_n_labels = mld->mld_n_labels;
1203 mld_clone->mld_n_hdr_bytes = mld->mld_n_hdr_bytes;
1204
1205 dpo_stack(mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE],
1206 mld_clone->mld_payload_proto,
1207 &mld_clone->mld_dpo,
1208 parent);
1209
1210 dpo_set(clone,
1211 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE],
1212 mld_clone->mld_payload_proto,
1213 mpls_label_dpo_get_index(mld_clone));
1214}
1215
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001216const static dpo_vft_t mld_vft = {
1217 .dv_lock = mpls_label_dpo_lock,
1218 .dv_unlock = mpls_label_dpo_unlock,
1219 .dv_format = format_mpls_label_dpo,
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001220 .dv_mem_show = mpls_label_dpo_mem_show,
Neale Ranns2303cb12018-02-21 04:57:17 -08001221 .dv_mk_interpose = mpls_label_interpose,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001222};
1223
Neale Ranns31ed7442018-02-23 05:29:09 -08001224const static char* const mpls_label_imp_pipe_ip4_nodes[] =
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001225{
Neale Ranns31ed7442018-02-23 05:29:09 -08001226 "ip4-mpls-label-imposition-pipe",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001227 NULL,
1228};
Neale Ranns31ed7442018-02-23 05:29:09 -08001229const static char* const mpls_label_imp_pipe_ip6_nodes[] =
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001230{
Neale Ranns31ed7442018-02-23 05:29:09 -08001231 "ip6-mpls-label-imposition-pipe",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001232 NULL,
1233};
Neale Ranns31ed7442018-02-23 05:29:09 -08001234const static char* const mpls_label_imp_pipe_mpls_nodes[] =
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001235{
Neale Ranns31ed7442018-02-23 05:29:09 -08001236 "mpls-label-imposition-pipe",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001237 NULL,
1238};
Neale Ranns31ed7442018-02-23 05:29:09 -08001239const static char* const mpls_label_imp_pipe_ethernet_nodes[] =
Neale Rannsda78f952017-05-24 09:15:43 -07001240{
Neale Ranns31ed7442018-02-23 05:29:09 -08001241 "ethernet-mpls-label-imposition-pipe",
Neale Rannsda78f952017-05-24 09:15:43 -07001242 NULL,
1243};
1244
Neale Ranns31ed7442018-02-23 05:29:09 -08001245const static char* const * const mpls_label_imp_pipe_nodes[DPO_PROTO_NUM] =
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001246{
Neale Ranns31ed7442018-02-23 05:29:09 -08001247 [DPO_PROTO_IP4] = mpls_label_imp_pipe_ip4_nodes,
1248 [DPO_PROTO_IP6] = mpls_label_imp_pipe_ip6_nodes,
1249 [DPO_PROTO_MPLS] = mpls_label_imp_pipe_mpls_nodes,
1250 [DPO_PROTO_ETHERNET] = mpls_label_imp_pipe_ethernet_nodes,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001251};
1252
Neale Ranns31ed7442018-02-23 05:29:09 -08001253const static char* const mpls_label_imp_uniform_ip4_nodes[] =
1254{
1255 "ip4-mpls-label-imposition-uniform",
1256 NULL,
1257};
1258const static char* const mpls_label_imp_uniform_ip6_nodes[] =
1259{
1260 "ip6-mpls-label-imposition-uniform",
1261 NULL,
1262};
1263const static char* const mpls_label_imp_uniform_mpls_nodes[] =
1264{
1265 "mpls-label-imposition-uniform",
1266 NULL,
1267};
1268const static char* const mpls_label_imp_uniform_ethernet_nodes[] =
1269{
1270 "ethernet-mpls-label-imposition-uniform",
1271 NULL,
1272};
1273
1274const static char* const * const mpls_label_imp_uniform_nodes[DPO_PROTO_NUM] =
1275{
1276 [DPO_PROTO_IP4] = mpls_label_imp_uniform_ip4_nodes,
1277 [DPO_PROTO_IP6] = mpls_label_imp_uniform_ip6_nodes,
1278 [DPO_PROTO_MPLS] = mpls_label_imp_uniform_mpls_nodes,
1279 [DPO_PROTO_ETHERNET] = mpls_label_imp_uniform_ethernet_nodes,
1280};
1281
1282const static char* const mpls_label_imp_pipe_no_ip_tll_decr_ip4_nodes[] =
1283{
1284 "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
1285 NULL,
1286};
1287const static char* const mpls_label_imp_pipe_no_ip_tll_decr_ip6_nodes[] =
1288{
1289 "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
1290 NULL,
1291};
1292
1293const static char* const * const mpls_label_imp_pipe_no_ip_tll_decr_nodes[DPO_PROTO_NUM] =
1294{
1295 [DPO_PROTO_IP4] = mpls_label_imp_pipe_no_ip_tll_decr_ip4_nodes,
1296 [DPO_PROTO_IP6] = mpls_label_imp_pipe_no_ip_tll_decr_ip6_nodes,
1297};
1298
1299const static char* const mpls_label_imp_uniform_no_ip_tll_decr_ip4_nodes[] =
1300{
1301 "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
1302 NULL,
1303};
1304const static char* const mpls_label_imp_uniform_no_ip_tll_decr_ip6_nodes[] =
1305{
1306 "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
1307 NULL,
1308};
1309
1310const static char* const * const mpls_label_imp_uniform_no_ip_tll_decr_nodes[DPO_PROTO_NUM] =
1311{
1312 [DPO_PROTO_IP4] = mpls_label_imp_uniform_no_ip_tll_decr_ip4_nodes,
1313 [DPO_PROTO_IP6] = mpls_label_imp_uniform_no_ip_tll_decr_ip6_nodes,
1314};
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001315
1316void
1317mpls_label_dpo_module_init (void)
1318{
Neale Ranns31ed7442018-02-23 05:29:09 -08001319 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE] =
1320 dpo_register_new_type(&mld_vft,
1321 mpls_label_imp_pipe_nodes);
1322 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR] =
1323 dpo_register_new_type(&mld_vft,
1324 mpls_label_imp_pipe_no_ip_tll_decr_nodes);
1325 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_UNIFORM_MODE] =
1326 dpo_register_new_type(&mld_vft,
1327 mpls_label_imp_uniform_nodes);
1328 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
1329 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR] =
1330 dpo_register_new_type(&mld_vft,
1331 mpls_label_imp_uniform_no_ip_tll_decr_nodes);
1332}
1333
1334dpo_type_t
1335mpls_label_dpo_get_type (mpls_label_dpo_flags_t flags)
1336{
1337 return (mpls_label_dpo_types[flags]);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001338}
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001339#endif /* CLIB_MARCH_VARIANT */