blob: ab8c06df4d558676546970e1bb2a6d9968866812 [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
21/*
22 * pool of all MPLS Label DPOs
23 */
24mpls_label_dpo_t *mpls_label_dpo_pool;
25
Neale Ranns31ed7442018-02-23 05:29:09 -080026/**
27 * Strings for the flags
28 */
29const char* mpls_label_dpo_attr_names[] = MPLS_LABEL_DPO_ATTR_NAMES;
30
31/**
32 * registered DPO types for each of the label sub-types. And there's a
33 * subtype for each of the flag combinations.
34 */
35static dpo_type_t mpls_label_dpo_types[1 << MPLS_LABEL_DPO_ATTR_MAX];
36
Neale Ranns0bfe5d82016-08-25 15:29:12 +010037static mpls_label_dpo_t *
38mpls_label_dpo_alloc (void)
39{
40 mpls_label_dpo_t *mld;
41
42 pool_get_aligned(mpls_label_dpo_pool, mld, CLIB_CACHE_LINE_BYTES);
Dave Barachb7b92992018-10-17 10:38:51 -040043 clib_memset(mld, 0, sizeof(*mld));
Neale Ranns0bfe5d82016-08-25 15:29:12 +010044
45 dpo_reset(&mld->mld_dpo);
46
47 return (mld);
48}
49
50static index_t
51mpls_label_dpo_get_index (mpls_label_dpo_t *mld)
52{
53 return (mld - mpls_label_dpo_pool);
54}
55
Neale Ranns31ed7442018-02-23 05:29:09 -080056void
57mpls_label_dpo_create (fib_mpls_label_t *label_stack,
Neale Ranns0bfe5d82016-08-25 15:29:12 +010058 mpls_eos_bit_t eos,
Neale Rannsad422ed2016-11-02 14:20:04 +000059 dpo_proto_t payload_proto,
Neale Ranns31ed7442018-02-23 05:29:09 -080060 mpls_label_dpo_flags_t flags,
61 const dpo_id_t *parent,
62 dpo_id_t *dpo)
Neale Ranns0bfe5d82016-08-25 15:29:12 +010063{
64 mpls_label_dpo_t *mld;
Neale Ranns31ed7442018-02-23 05:29:09 -080065 dpo_type_t dtype;
Neale Rannsad422ed2016-11-02 14:20:04 +000066 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010067
Neale Ranns31ed7442018-02-23 05:29:09 -080068 if ((DPO_PROTO_IP4 != payload_proto) &&
69 (DPO_PROTO_IP6 != payload_proto))
70 {
71 /*
72 * remove unsupported configuration
73 */
74 flags &= ~MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR;
75 }
76
Neale Ranns0bfe5d82016-08-25 15:29:12 +010077 mld = mpls_label_dpo_alloc();
Neale Ranns31ed7442018-02-23 05:29:09 -080078 mld->mld_flags = flags;
79 dtype = mpls_label_dpo_types[flags];
Neale Rannsf363ebd2017-12-06 00:45:33 -080080
81 if (MPLS_LABEL_DPO_MAX_N_LABELS < vec_len(label_stack))
82 {
83 clib_warning("Label stack size exceeded");
Neale Ranns31ed7442018-02-23 05:29:09 -080084 dpo_stack(dtype,
Neale Rannsf363ebd2017-12-06 00:45:33 -080085 mld->mld_payload_proto,
86 &mld->mld_dpo,
87 drop_dpo_get(DPO_PROTO_MPLS));
Neale Rannsf363ebd2017-12-06 00:45:33 -080088 }
Neale Ranns31ed7442018-02-23 05:29:09 -080089 else
Neale Rannsad422ed2016-11-02 14:20:04 +000090 {
Neale Ranns31ed7442018-02-23 05:29:09 -080091 mld->mld_n_labels = vec_len(label_stack);
92 mld->mld_n_hdr_bytes = mld->mld_n_labels * sizeof(mld->mld_hdr[0]);
93 mld->mld_payload_proto = payload_proto;
94
95 /*
96 * construct label rewrite headers for each value passed.
97 * get the header in network byte order since we will paint it
98 * on a packet in the data-plane
99 */
100 for (ii = 0; ii < mld->mld_n_labels-1; ii++)
101 {
102 vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl,
103 label_stack[ii].fml_value);
104 vnet_mpls_uc_set_exp(&mld->mld_hdr[ii].label_exp_s_ttl,
105 label_stack[ii].fml_exp);
106 vnet_mpls_uc_set_s(&mld->mld_hdr[ii].label_exp_s_ttl,
107 MPLS_NON_EOS);
108 if (0 != label_stack[ii].fml_ttl)
109 {
110 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
111 label_stack[ii].fml_ttl);
112 }
113 else
114 {
115 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
116 MPLS_LABEL_DEFAULT_TTL);
117 }
118 mld->mld_hdr[ii].label_exp_s_ttl =
119 clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
120 }
121
122 /*
123 * the inner most label
124 */
125 ii = mld->mld_n_labels-1;
126
127 vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl,
128 label_stack[ii].fml_value);
129 vnet_mpls_uc_set_exp(&mld->mld_hdr[ii].label_exp_s_ttl,
130 label_stack[ii].fml_exp);
131 vnet_mpls_uc_set_s(&mld->mld_hdr[ii].label_exp_s_ttl, eos);
132 if (0 != label_stack[ii].fml_ttl)
133 {
134 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
135 label_stack[ii].fml_ttl);
136 }
137 else
138 {
139 vnet_mpls_uc_set_ttl(&mld->mld_hdr[ii].label_exp_s_ttl,
140 MPLS_LABEL_DEFAULT_TTL);
141 }
142 mld->mld_hdr[ii].label_exp_s_ttl =
143 clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
144
145 /*
146 * pipe/uniform mode is only supported for the bottom of stack label
147 */
148 if (FIB_MPLS_LSP_MODE_UNIFORM == label_stack[ii].fml_mode)
149 {
150 mld->mld_flags |= MPLS_LABEL_DPO_FLAG_UNIFORM_MODE;
151 }
152 else
153 {
154 mld->mld_flags &= ~MPLS_LABEL_DPO_FLAG_UNIFORM_MODE;
155 }
156 dtype = mpls_label_dpo_types[mld->mld_flags];
157
158 /*
159 * stack this label object on its parent.
160 */
161 dpo_stack(dtype,
162 mld->mld_payload_proto,
163 &mld->mld_dpo,
164 parent);
Neale Rannsad422ed2016-11-02 14:20:04 +0000165 }
166
Neale Ranns31ed7442018-02-23 05:29:09 -0800167 dpo_set(dpo,
168 dtype,
169 mld->mld_payload_proto,
170 mpls_label_dpo_get_index(mld));
171}
Neale Rannsad422ed2016-11-02 14:20:04 +0000172
Neale Ranns31ed7442018-02-23 05:29:09 -0800173u8*
174format_mpls_label_dpo_flags (u8 *s, va_list *args)
175{
176 mpls_label_dpo_flags_t flags = va_arg (*args, int);
177 mpls_label_dpo_attr_t attr;
Neale Rannsad422ed2016-11-02 14:20:04 +0000178
Neale Ranns31ed7442018-02-23 05:29:09 -0800179 FOR_EACH_MPLS_LABEL_DPO_ATTR(attr)
180 {
181 if ((1 << attr) & flags)
182 {
183 s = format(s, "%s,", mpls_label_dpo_attr_names[attr]);
184 }
185 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100186
Neale Ranns31ed7442018-02-23 05:29:09 -0800187 return (s);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100188}
189
190u8*
191format_mpls_label_dpo (u8 *s, va_list *args)
192{
193 index_t index = va_arg (*args, index_t);
194 u32 indent = va_arg (*args, u32);
195 mpls_unicast_header_t hdr;
196 mpls_label_dpo_t *mld;
Neale Rannsad422ed2016-11-02 14:20:04 +0000197 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100198
Neale Ranns15002542017-09-10 04:39:11 -0700199 if (pool_is_free_index(mpls_label_dpo_pool, index))
200 {
201 /*
202 * the packet trace can be printed after the DPO has been deleted
203 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800204 return (format(s, "mpls-label[???,%d]:", index));
Neale Ranns15002542017-09-10 04:39:11 -0700205 }
206
207 mld = mpls_label_dpo_get(index);
Neale Ranns7c922dc2018-08-30 06:12:27 -0700208 s = format(s, "mpls-label[%U@%d]:",
Neale Ranns31ed7442018-02-23 05:29:09 -0800209 format_mpls_label_dpo_flags,
210 (int) mld->mld_flags, index);
Neale Ranns15002542017-09-10 04:39:11 -0700211
Neale Rannsad422ed2016-11-02 14:20:04 +0000212 for (ii = 0; ii < mld->mld_n_labels; ii++)
213 {
214 hdr.label_exp_s_ttl =
215 clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
216 s = format(s, "%U", format_mpls_header, hdr);
217 }
218
219 s = format(s, "\n%U", format_white_space, indent);
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000220 s = format(s, "%U", format_dpo_id, &mld->mld_dpo, indent+2);
221
222 return (s);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100223}
224
225static void
226mpls_label_dpo_lock (dpo_id_t *dpo)
227{
228 mpls_label_dpo_t *mld;
229
230 mld = mpls_label_dpo_get(dpo->dpoi_index);
231
232 mld->mld_locks++;
233}
234
235static void
236mpls_label_dpo_unlock (dpo_id_t *dpo)
237{
238 mpls_label_dpo_t *mld;
239
240 mld = mpls_label_dpo_get(dpo->dpoi_index);
241
242 mld->mld_locks--;
243
244 if (0 == mld->mld_locks)
245 {
246 dpo_reset(&mld->mld_dpo);
247 pool_put(mpls_label_dpo_pool, mld);
248 }
249}
250
251/**
252 * @brief A struct to hold tracing information for the MPLS label imposition
253 * node.
254 */
255typedef struct mpls_label_imposition_trace_t_
256{
257 /**
258 * The MPLS header imposed
259 */
260 mpls_unicast_header_t hdr;
Neale Ranns31ed7442018-02-23 05:29:09 -0800261
262 /**
263 * TTL imposed - only valid for uniform LSPs
264 */
265 u8 ttl;
266
267 /**
268 * TTL imposed - only valid for uniform LSPs
269 */
270 u8 exp;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100271} mpls_label_imposition_trace_t;
272
Neale Ranns696e88d2017-03-16 07:34:55 -0400273always_inline mpls_unicast_header_t *
274mpls_label_paint (vlib_buffer_t * b0,
Neale Ranns31ed7442018-02-23 05:29:09 -0800275 mpls_label_dpo_t *mld0)
Neale Ranns696e88d2017-03-16 07:34:55 -0400276{
277 mpls_unicast_header_t *hdr0;
278
279 vlib_buffer_advance(b0, -(mld0->mld_n_hdr_bytes));
280
281 hdr0 = vlib_buffer_get_current(b0);
282
Pablo Camarillo5d73eec2017-04-24 17:51:56 +0200283 if (1 == mld0->mld_n_labels)
Neale Ranns696e88d2017-03-16 07:34:55 -0400284 {
285 /* optimise for the common case of one label */
286 *hdr0 = mld0->mld_hdr[0];
287 }
288 else
289 {
Dave Barach178cf492018-11-13 16:34:13 -0500290 clib_memcpy_fast(hdr0, mld0->mld_hdr, mld0->mld_n_hdr_bytes);
Neale Ranns696e88d2017-03-16 07:34:55 -0400291 hdr0 = hdr0 + (mld0->mld_n_labels - 1);
292 }
Neale Ranns31ed7442018-02-23 05:29:09 -0800293
294 return (hdr0);
295}
296
297/**
298 * Paint on an MPLS label and fixup the TTL
299 */
300always_inline mpls_unicast_header_t *
301mpls_label_paint_w_ttl (vlib_buffer_t * b0,
302 mpls_label_dpo_t *mld0,
303 u8 ttl0)
304{
305 mpls_unicast_header_t *hdr0;
306
307 hdr0 = mpls_label_paint(b0, mld0);
308
Neale Ranns696e88d2017-03-16 07:34:55 -0400309 /* fixup the TTL for the inner most label */
310 ((char*)hdr0)[3] = ttl0;
311
312 return (hdr0);
313}
314
Neale Ranns31ed7442018-02-23 05:29:09 -0800315/**
316 * Paint on an MPLS label and fixup the TTL and EXP bits.
317 */
318always_inline mpls_unicast_header_t *
319mpls_label_paint_w_ttl_exp (vlib_buffer_t * b0,
320 mpls_label_dpo_t *mld0,
321 u8 ttl0,
322 u8 exp0)
323{
324 mpls_unicast_header_t *hdr0;
325
326 hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
327
328 /* fixup the EXP for the inner most label */
329 ((char*)hdr0)[2] |= (exp0 << 1);
330
331 return (hdr0);
332}
333
334/**
335 * Paint on an MPLS label and fixup the TTL and EXP bits
336 * When the EXP bits are *already* bit shift to the correct place in
337 * in the 2nd byte (i.e. they were read from another label)
338 */
339always_inline mpls_unicast_header_t *
340mpls_label_paint_w_ttl_mpls_exp (vlib_buffer_t * b0,
341 mpls_label_dpo_t *mld0,
342 u8 ttl0,
343 u8 exp0)
344{
345 mpls_unicast_header_t *hdr0;
346
347 hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
348
349 /* fixup the EXP for the inner most label */
350 ((char*)hdr0)[2] |= exp0;
351
352 return (hdr0);
353}
354
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100355always_inline uword
Neale Rannsad422ed2016-11-02 14:20:04 +0000356mpls_label_imposition_inline (vlib_main_t * vm,
357 vlib_node_runtime_t * node,
358 vlib_frame_t * from_frame,
Neale Ranns31ed7442018-02-23 05:29:09 -0800359 const dpo_proto_t dproto,
360 const mpls_label_dpo_flags_t flags)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100361{
362 u32 n_left_from, next_index, * from, * to_next;
363
364 from = vlib_frame_vector_args (from_frame);
365 n_left_from = from_frame->n_vectors;
366
367 next_index = node->cached_next_index;
368
369 while (n_left_from > 0)
370 {
371 u32 n_left_to_next;
372
373 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
374
Neale Ranns696e88d2017-03-16 07:34:55 -0400375 while (n_left_from >= 8 && n_left_to_next >= 4)
Neale Ranns9ca18c62016-12-10 21:08:09 +0000376 {
Neale Ranns696e88d2017-03-16 07:34:55 -0400377 u32 bi0, mldi0, bi1, mldi1, bi2, mldi2, bi3, mldi3;
378 mpls_unicast_header_t *hdr0, *hdr1, *hdr2, *hdr3;
379 mpls_label_dpo_t *mld0, *mld1, *mld2, *mld3;
380 vlib_buffer_t * b0, *b1, * b2, *b3;
381 u32 next0, next1, next2, next3;
Neale Ranns31ed7442018-02-23 05:29:09 -0800382 u8 ttl0, ttl1, ttl2, ttl3;
383 u8 exp0, exp1, exp2, exp3;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000384
385 bi0 = to_next[0] = from[0];
386 bi1 = to_next[1] = from[1];
Neale Ranns696e88d2017-03-16 07:34:55 -0400387 bi2 = to_next[2] = from[2];
388 bi3 = to_next[3] = from[3];
Neale Ranns9ca18c62016-12-10 21:08:09 +0000389
390 /* Prefetch next iteration. */
391 {
Neale Ranns696e88d2017-03-16 07:34:55 -0400392 vlib_buffer_t * p2, * p3, *p4, *p5;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000393
394 p2 = vlib_get_buffer (vm, from[2]);
395 p3 = vlib_get_buffer (vm, from[3]);
Neale Ranns696e88d2017-03-16 07:34:55 -0400396 p4 = vlib_get_buffer (vm, from[4]);
397 p5 = vlib_get_buffer (vm, from[5]);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000398
399 vlib_prefetch_buffer_header (p2, STORE);
400 vlib_prefetch_buffer_header (p3, STORE);
Neale Ranns696e88d2017-03-16 07:34:55 -0400401 vlib_prefetch_buffer_header (p4, STORE);
402 vlib_prefetch_buffer_header (p5, STORE);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000403
404 CLIB_PREFETCH (p2->data, sizeof (hdr0[0]), STORE);
405 CLIB_PREFETCH (p3->data, sizeof (hdr0[0]), STORE);
Neale Ranns696e88d2017-03-16 07:34:55 -0400406 CLIB_PREFETCH (p4->data, sizeof (hdr0[0]), STORE);
407 CLIB_PREFETCH (p5->data, sizeof (hdr0[0]), STORE);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000408 }
409
Neale Ranns696e88d2017-03-16 07:34:55 -0400410 from += 4;
411 to_next += 4;
412 n_left_from -= 4;
413 n_left_to_next -= 4;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000414
415 b0 = vlib_get_buffer (vm, bi0);
416 b1 = vlib_get_buffer (vm, bi1);
Neale Ranns696e88d2017-03-16 07:34:55 -0400417 b2 = vlib_get_buffer (vm, bi2);
418 b3 = vlib_get_buffer (vm, bi3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000419
420 /* dst lookup was done by ip4 lookup */
421 mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
422 mldi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
Neale Ranns696e88d2017-03-16 07:34:55 -0400423 mldi2 = vnet_buffer(b2)->ip.adj_index[VLIB_TX];
424 mldi3 = vnet_buffer(b3)->ip.adj_index[VLIB_TX];
Neale Ranns9ca18c62016-12-10 21:08:09 +0000425 mld0 = mpls_label_dpo_get(mldi0);
426 mld1 = mpls_label_dpo_get(mldi1);
Neale Ranns696e88d2017-03-16 07:34:55 -0400427 mld2 = mpls_label_dpo_get(mldi2);
428 mld3 = mpls_label_dpo_get(mldi3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000429
Neale Ranns31ed7442018-02-23 05:29:09 -0800430 if (DPO_PROTO_MPLS != dproto)
Neale Ranns9ca18c62016-12-10 21:08:09 +0000431 {
432 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800433 * These are the non-MPLS payload imposition cases
Neale Ranns9ca18c62016-12-10 21:08:09 +0000434 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800435 if (DPO_PROTO_IP4 == dproto)
436 {
437 ip4_header_t * ip0 = vlib_buffer_get_current(b0);
438 ip4_header_t * ip1 = vlib_buffer_get_current(b1);
439 ip4_header_t * ip2 = vlib_buffer_get_current(b2);
440 ip4_header_t * ip3 = vlib_buffer_get_current(b3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000441
Neale Ranns31ed7442018-02-23 05:29:09 -0800442 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
443 {
444 /*
445 * decrement the TTL on ingress to the LSP
446 */
447 u32 checksum0;
448 u32 checksum1;
449 u32 checksum2;
450 u32 checksum3;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000451
Neale Ranns31ed7442018-02-23 05:29:09 -0800452 checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
453 checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
454 checksum2 = ip2->checksum + clib_host_to_net_u16 (0x0100);
455 checksum3 = ip3->checksum + clib_host_to_net_u16 (0x0100);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000456
Neale Ranns31ed7442018-02-23 05:29:09 -0800457 checksum0 += checksum0 >= 0xffff;
458 checksum1 += checksum1 >= 0xffff;
459 checksum2 += checksum2 >= 0xffff;
460 checksum3 += checksum3 >= 0xffff;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000461
Neale Ranns31ed7442018-02-23 05:29:09 -0800462 ip0->checksum = checksum0;
463 ip1->checksum = checksum1;
464 ip2->checksum = checksum2;
465 ip3->checksum = checksum3;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000466
Neale Ranns31ed7442018-02-23 05:29:09 -0800467 ip0->ttl -= 1;
468 ip1->ttl -= 1;
469 ip2->ttl -= 1;
470 ip3->ttl -= 1;
471 }
472
473 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
474 {
475 ttl1 = ip1->ttl;
476 ttl0 = ip0->ttl;
477 ttl3 = ip3->ttl;
478 ttl2 = ip2->ttl;
479 /* by default copy the 3 most significant bits */
480 exp0 = ip_dscp_to_mpls_exp(ip0->tos);
481 exp1 = ip_dscp_to_mpls_exp(ip1->tos);
482 exp2 = ip_dscp_to_mpls_exp(ip2->tos);
483 exp3 = ip_dscp_to_mpls_exp(ip3->tos);
484 }
485 }
486 else if (DPO_PROTO_IP6 == dproto)
487 {
488 /*
489 * decrement the TTL on ingress to the LSP
490 */
491 ip6_header_t * ip0 = vlib_buffer_get_current(b0);
492 ip6_header_t * ip1 = vlib_buffer_get_current(b1);
493 ip6_header_t * ip2 = vlib_buffer_get_current(b2);
494 ip6_header_t * ip3 = vlib_buffer_get_current(b3);
495
496 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
497 {
498 ip0->hop_limit -= 1;
499 ip1->hop_limit -= 1;
500 ip2->hop_limit -= 1;
501 ip3->hop_limit -= 1;
502 }
503 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
504 {
505 ttl0 = ip0->hop_limit;
506 ttl1 = ip1->hop_limit;
507 ttl2 = ip2->hop_limit;
508 ttl3 = ip3->hop_limit;
509 /* by default copy the 3 most significant bits */
510 exp0 = ip_dscp_to_mpls_exp(
511 ip6_traffic_class_network_order(ip0));
512 exp1 = ip_dscp_to_mpls_exp(
513 ip6_traffic_class_network_order(ip1));
514 exp2 = ip_dscp_to_mpls_exp(
515 ip6_traffic_class_network_order(ip2));
516 exp3 = ip_dscp_to_mpls_exp(
517 ip6_traffic_class_network_order(ip3));
518 }
519 }
520 else
521 {
522 /*
523 * nothing to change in the ethernet header
524 */
525 ttl0 = ttl1 = ttl2 = ttl3 = MPLS_LABEL_DEFAULT_TTL;
526 exp0 = exp1 = exp2 = exp3 = MPLS_LABEL_DEFAULT_EXP;
527 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000528 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800529 * These are the non-MPLS payload imposition cases.
530 * Based on the LSP mode either, for uniform, copy down the TTL
531 * and EXP from the payload or, for pipe mode, slap on the value
532 * requested from config
Neale Ranns9ca18c62016-12-10 21:08:09 +0000533 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800534 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
535 {
536 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
537 hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
538 hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
539 hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
540 }
541 else
542 {
543 hdr0 = mpls_label_paint(b0, mld0);
544 hdr1 = mpls_label_paint(b1, mld1);
545 hdr2 = mpls_label_paint(b2, mld2);
546 hdr3 = mpls_label_paint(b3, mld3);
547 }
Neale Rannsda78f952017-05-24 09:15:43 -0700548 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000549 else
550 {
551 /*
552 * else, the packet to be encapped is an MPLS packet
Neale Ranns31ed7442018-02-23 05:29:09 -0800553 * there are two cases to consider:
554 * 1 - this is an MPLS label swap at an LSP midpoint.
555 * recognisable because mpls.first = 1. In this case the
556 * TTL must be set to the current value -1.
557 * 2 - The MPLS packet is recursing (or being injected into)
558 * this LSP, in which case the pipe/uniform rules apply
559 *
Neale Ranns9ca18c62016-12-10 21:08:09 +0000560 */
561 if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
562 {
563 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800564 * The first label to be imposed on the packet. this is a
565 * label swap.in which case we stashed the TTL and EXP bits
566 * in the packet in the lookup node
Neale Ranns9ca18c62016-12-10 21:08:09 +0000567 */
568 ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
569
570 ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800571 exp0 = vnet_buffer(b0)->mpls.exp;
572 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000573 }
574 else
575 {
576 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800577 * not the first label. implying we are recusring down a
578 * chain of output labels. Each layer is considered a new
579 * LSP - hence the TTL/EXP are pipe/uniform handled
Neale Ranns9ca18c62016-12-10 21:08:09 +0000580 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800581 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
582 {
583 hdr0 = vlib_buffer_get_current(b0);
584 ttl0 = ((u8*)hdr0)[3];
585 exp0 = ((u8*)hdr0)[2] & 0xe;
586 hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
587 }
588 else
589 {
590 hdr0 = mpls_label_paint(b0, mld0);
591 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000592 }
593 if (PREDICT_TRUE(vnet_buffer(b1)->mpls.first))
594 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800595 ASSERT(0 != vnet_buffer (b1)->mpls.ttl);
596
Neale Ranns9ca18c62016-12-10 21:08:09 +0000597 ttl1 = vnet_buffer(b1)->mpls.ttl - 1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800598 exp1 = vnet_buffer(b1)->mpls.exp;
599 hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000600 }
601 else
602 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800603 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
604 {
605 hdr1 = vlib_buffer_get_current(b1);
606 ttl1 = ((u8*)hdr1)[3];
607 exp1 = ((u8*)hdr1)[2] & 0xe;
608 hdr1 = mpls_label_paint_w_ttl_mpls_exp(b1, mld1, ttl1, exp1);
609 }
610 else
611 {
612 hdr1 = mpls_label_paint(b1, mld1);
613 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000614 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400615 if (PREDICT_TRUE(vnet_buffer(b2)->mpls.first))
616 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800617 ASSERT(0 != vnet_buffer (b2)->mpls.ttl);
Neale Ranns696e88d2017-03-16 07:34:55 -0400618
619 ttl2 = vnet_buffer(b2)->mpls.ttl - 1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800620 exp2 = vnet_buffer(b2)->mpls.exp;
621 hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
Neale Ranns696e88d2017-03-16 07:34:55 -0400622 }
623 else
624 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800625 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
626 {
627 hdr2 = vlib_buffer_get_current(b2);
628 ttl2 = ((u8*)hdr2)[3];
629 exp2 = ((u8*)hdr2)[2] & 0xe;
630 hdr2 = mpls_label_paint_w_ttl_mpls_exp(b2, mld2, ttl2, exp2);
631 }
632 else
633 {
634 hdr2 = mpls_label_paint(b2, mld2);
635 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400636 }
637 if (PREDICT_TRUE(vnet_buffer(b3)->mpls.first))
638 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800639 ASSERT(0 != vnet_buffer (b3)->mpls.ttl);
640
Neale Ranns696e88d2017-03-16 07:34:55 -0400641 ttl3 = vnet_buffer(b3)->mpls.ttl - 1;
Neale Ranns19bd1902018-03-19 02:32:57 -0700642 exp3 = vnet_buffer(b3)->mpls.exp;
Neale Ranns31ed7442018-02-23 05:29:09 -0800643 hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
Neale Ranns696e88d2017-03-16 07:34:55 -0400644 }
645 else
646 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800647 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
648 {
649 hdr3 = vlib_buffer_get_current(b3);
650 ttl3 = ((u8*)hdr3)[3];
651 exp3 = ((u8*)hdr3)[2] & 0xe;
652 hdr3 = mpls_label_paint_w_ttl_mpls_exp(b3, mld3, ttl3, exp3);
653 }
654 else
655 {
656 hdr3 = mpls_label_paint(b3, mld3);
657 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400658 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000659
Neale Ranns31ed7442018-02-23 05:29:09 -0800660 vnet_buffer(b0)->mpls.first = 0;
661 vnet_buffer(b1)->mpls.first = 0;
662 vnet_buffer(b2)->mpls.first = 0;
663 vnet_buffer(b3)->mpls.first = 0;
664 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000665
666 next0 = mld0->mld_dpo.dpoi_next_node;
667 next1 = mld1->mld_dpo.dpoi_next_node;
Neale Ranns696e88d2017-03-16 07:34:55 -0400668 next2 = mld2->mld_dpo.dpoi_next_node;
669 next3 = mld3->mld_dpo.dpoi_next_node;
Neale Ranns31ed7442018-02-23 05:29:09 -0800670
Neale Ranns9ca18c62016-12-10 21:08:09 +0000671 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
672 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = mld1->mld_dpo.dpoi_index;
Neale Ranns696e88d2017-03-16 07:34:55 -0400673 vnet_buffer(b2)->ip.adj_index[VLIB_TX] = mld2->mld_dpo.dpoi_index;
674 vnet_buffer(b3)->ip.adj_index[VLIB_TX] = mld3->mld_dpo.dpoi_index;
Neale Ranns9ca18c62016-12-10 21:08:09 +0000675
676 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
677 {
678 mpls_label_imposition_trace_t *tr =
679 vlib_add_trace (vm, node, b0, sizeof (*tr));
680 tr->hdr = *hdr0;
Neale Ranns31ed7442018-02-23 05:29:09 -0800681 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
682 {
683 tr->ttl = ttl0;
684 tr->exp = exp0;
685 }
686 else
687 {
688 tr->ttl = tr->exp = 0;
689 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000690 }
691 if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
692 {
693 mpls_label_imposition_trace_t *tr =
694 vlib_add_trace (vm, node, b1, sizeof (*tr));
695 tr->hdr = *hdr1;
Neale Ranns31ed7442018-02-23 05:29:09 -0800696 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
697 {
698 tr->ttl = ttl1;
699 tr->exp = exp1;
700 }
701 else
702 {
703 tr->ttl = tr->exp = 0;
704 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000705 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400706 if (PREDICT_FALSE(b2->flags & VLIB_BUFFER_IS_TRACED))
707 {
708 mpls_label_imposition_trace_t *tr =
709 vlib_add_trace (vm, node, b2, sizeof (*tr));
710 tr->hdr = *hdr2;
Neale Ranns31ed7442018-02-23 05:29:09 -0800711 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
712 {
713 tr->ttl = ttl2;
714 tr->exp = exp2;
715 }
716 else
717 {
718 tr->ttl = tr->exp = 0;
719 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400720 }
721 if (PREDICT_FALSE(b3->flags & VLIB_BUFFER_IS_TRACED))
722 {
723 mpls_label_imposition_trace_t *tr =
724 vlib_add_trace (vm, node, b3, sizeof (*tr));
725 tr->hdr = *hdr3;
Neale Ranns31ed7442018-02-23 05:29:09 -0800726 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
727 {
728 tr->ttl = ttl3;
729 tr->exp = exp3;
730 }
731 else
732 {
733 tr->ttl = tr->exp = 0;
734 }
Neale Ranns696e88d2017-03-16 07:34:55 -0400735 }
Neale Ranns9ca18c62016-12-10 21:08:09 +0000736
Neale Ranns696e88d2017-03-16 07:34:55 -0400737 vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next,
Neale Ranns9ca18c62016-12-10 21:08:09 +0000738 n_left_to_next,
Neale Ranns696e88d2017-03-16 07:34:55 -0400739 bi0, bi1, bi2, bi3,
740 next0, next1, next2, next3);
Neale Ranns9ca18c62016-12-10 21:08:09 +0000741 }
742
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100743 while (n_left_from > 0 && n_left_to_next > 0)
744 {
745 mpls_unicast_header_t *hdr0;
746 mpls_label_dpo_t *mld0;
747 vlib_buffer_t * b0;
748 u32 bi0, mldi0;
Neale Ranns31ed7442018-02-23 05:29:09 -0800749 u8 ttl0, exp0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100750 u32 next0;
751
752 bi0 = from[0];
753 to_next[0] = bi0;
754 from += 1;
755 to_next += 1;
756 n_left_from -= 1;
757 n_left_to_next -= 1;
758
759 b0 = vlib_get_buffer (vm, bi0);
760
761 /* dst lookup was done by ip4 lookup */
762 mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
763 mld0 = mpls_label_dpo_get(mldi0);
764
Neale Ranns31ed7442018-02-23 05:29:09 -0800765 if (DPO_PROTO_MPLS != dproto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000766 {
Neale Ranns31ed7442018-02-23 05:29:09 -0800767 if (DPO_PROTO_IP4 == dproto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000768 {
769 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800770 * decrement the TTL on ingress to the LSP
Neale Rannsad422ed2016-11-02 14:20:04 +0000771 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800772 ip4_header_t * ip0 = vlib_buffer_get_current(b0);
773 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
774 {
775 u32 checksum0;
Neale Rannsad422ed2016-11-02 14:20:04 +0000776
Neale Ranns31ed7442018-02-23 05:29:09 -0800777 checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
778 checksum0 += checksum0 >= 0xffff;
779
780 ip0->checksum = checksum0;
781 ip0->ttl -= 1;
782 }
783 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
784 {
785 ttl0 = ip0->ttl;
786 exp0 = ip_dscp_to_mpls_exp(ip0->tos);
787 }
788 }
789 else if (DPO_PROTO_IP6 == dproto)
790 {
791 /*
792 * decrement the TTL on ingress to the LSP
793 */
794 ip6_header_t * ip0 = vlib_buffer_get_current(b0);
795
796 if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
797 {
798 ip0->hop_limit -= 1;
799 }
800 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
801 {
802 ttl0 = ip0->hop_limit;
803 exp0 = ip_dscp_to_mpls_exp(
804 ip6_traffic_class_network_order(ip0));
805 }
Neale Rannsad422ed2016-11-02 14:20:04 +0000806 }
807 else
808 {
809 /*
Neale Ranns31ed7442018-02-23 05:29:09 -0800810 * nothing to change in the ethernet header
Neale Rannsad422ed2016-11-02 14:20:04 +0000811 */
Neale Ranns31ed7442018-02-23 05:29:09 -0800812 ttl0 = MPLS_LABEL_DEFAULT_TTL;
813 exp0 = MPLS_LABEL_DEFAULT_EXP;
814 }
815
816 /*
817 * These are the non-MPLS payload imposition cases.
818 * Based on the LSP mode either, for uniform, copy down the TTL
819 * from the payload or, for pipe mode, slap on the value
820 * requested from config
821 */
822 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
823 {
824 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
825 }
826 else
827 {
828 hdr0 = mpls_label_paint(b0, mld0);
Neale Rannsad422ed2016-11-02 14:20:04 +0000829 }
830 }
Neale Ranns31ed7442018-02-23 05:29:09 -0800831 else
832 {
833 if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
834 {
835 ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
Neale Rannsad422ed2016-11-02 14:20:04 +0000836
Neale Ranns31ed7442018-02-23 05:29:09 -0800837 ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
838 exp0 = vnet_buffer(b0)->mpls.exp;
839 hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
840 }
841 else
842 {
843 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
844 {
845 hdr0 = vlib_buffer_get_current(b0);
846 ttl0 = ((u8*)hdr0)[3];
847 exp0 = ((u8*)hdr0)[2] & 0xe;
848 hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
849 }
850 else
851 {
852 hdr0 = mpls_label_paint(b0, mld0);
853 }
854 }
Neale Rannsad422ed2016-11-02 14:20:04 +0000855
Neale Ranns31ed7442018-02-23 05:29:09 -0800856 vnet_buffer(b0)->mpls.first = 0;
857 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100858
859 next0 = mld0->mld_dpo.dpoi_next_node;
860 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
861
Neale Ranns9ca18c62016-12-10 21:08:09 +0000862 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100863 {
864 mpls_label_imposition_trace_t *tr =
865 vlib_add_trace (vm, node, b0, sizeof (*tr));
866 tr->hdr = *hdr0;
Neale Ranns31ed7442018-02-23 05:29:09 -0800867 if (flags & MPLS_LABEL_DPO_FLAG_UNIFORM_MODE)
868 {
869 tr->ttl = ttl0;
870 tr->exp = exp0;
871 }
872 else
873 {
874 tr->ttl = tr->exp = 0;
875 }
876 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100877
878 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
879 n_left_to_next, bi0, next0);
880 }
881 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
882 }
883 return from_frame->n_vectors;
884}
885
886static u8 *
887format_mpls_label_imposition_trace (u8 * s, va_list * args)
888{
889 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
890 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
891 mpls_label_imposition_trace_t * t;
892 mpls_unicast_header_t hdr;
Christophe Fontained3c008d2017-10-02 18:10:54 +0200893 u32 indent;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100894
895 t = va_arg (*args, mpls_label_imposition_trace_t *);
896 indent = format_get_indent (s);
897 hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
898
899 s = format (s, "%Umpls-header:%U",
900 format_white_space, indent,
901 format_mpls_header, hdr);
902 return (s);
903}
904
Neale Rannsad422ed2016-11-02 14:20:04 +0000905static uword
Neale Ranns31ed7442018-02-23 05:29:09 -0800906mpls_mpls_label_imposition_pipe (vlib_main_t * vm,
907 vlib_node_runtime_t * node,
908 vlib_frame_t * frame)
Neale Rannsad422ed2016-11-02 14:20:04 +0000909{
Neale Ranns31ed7442018-02-23 05:29:09 -0800910 return (mpls_label_imposition_inline(vm, node, frame,
911 DPO_PROTO_MPLS,
912 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsad422ed2016-11-02 14:20:04 +0000913}
914
Neale Ranns31ed7442018-02-23 05:29:09 -0800915VLIB_REGISTER_NODE (mpls_mpls_label_imposition_pipe_node) = {
916 .function = mpls_mpls_label_imposition_pipe,
917 .name = "mpls-label-imposition-pipe",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100918 .vector_size = sizeof (u32),
919
920 .format_trace = format_mpls_label_imposition_trace,
921 .n_next_nodes = 1,
922 .next_nodes = {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800923 [0] = "mpls-drop",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100924 }
925};
Neale Ranns31ed7442018-02-23 05:29:09 -0800926VLIB_NODE_FUNCTION_MULTIARCH (mpls_mpls_label_imposition_pipe_node,
927 mpls_mpls_label_imposition_pipe)
Neale Rannsad422ed2016-11-02 14:20:04 +0000928
929static uword
Neale Ranns31ed7442018-02-23 05:29:09 -0800930ip4_mpls_label_imposition_pipe (vlib_main_t * vm,
931 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_IP4,
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 (ip4_mpls_label_imposition_pipe_node) = {
940 .function = ip4_mpls_label_imposition_pipe,
941 .name = "ip4-mpls-label-imposition-pipe",
Neale Rannsad422ed2016-11-02 14:20:04 +0000942 .vector_size = sizeof (u32),
943
944 .format_trace = format_mpls_label_imposition_trace,
945 .n_next_nodes = 1,
946 .next_nodes = {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800947 [0] = "ip4-drop",
Neale Rannsad422ed2016-11-02 14:20:04 +0000948 }
949};
Neale Ranns31ed7442018-02-23 05:29:09 -0800950VLIB_NODE_FUNCTION_MULTIARCH (ip4_mpls_label_imposition_pipe_node,
951 ip4_mpls_label_imposition_pipe)
Neale Rannsad422ed2016-11-02 14:20:04 +0000952
953static uword
Neale Ranns31ed7442018-02-23 05:29:09 -0800954ip6_mpls_label_imposition_pipe (vlib_main_t * vm,
955 vlib_node_runtime_t * node,
956 vlib_frame_t * frame)
Neale Rannsad422ed2016-11-02 14:20:04 +0000957{
Neale Ranns31ed7442018-02-23 05:29:09 -0800958 return (mpls_label_imposition_inline(vm, node, frame,
959 DPO_PROTO_IP6,
960 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsad422ed2016-11-02 14:20:04 +0000961}
962
Neale Ranns31ed7442018-02-23 05:29:09 -0800963VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_node) = {
964 .function = ip6_mpls_label_imposition_pipe,
965 .name = "ip6-mpls-label-imposition-pipe",
Neale Rannsad422ed2016-11-02 14:20:04 +0000966 .vector_size = sizeof (u32),
967
968 .format_trace = format_mpls_label_imposition_trace,
969 .n_next_nodes = 1,
970 .next_nodes = {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800971 [0] = "ip6-drop",
Neale Rannsad422ed2016-11-02 14:20:04 +0000972 }
973};
Neale Ranns31ed7442018-02-23 05:29:09 -0800974VLIB_NODE_FUNCTION_MULTIARCH (ip6_mpls_label_imposition_pipe_node,
975 ip6_mpls_label_imposition_pipe)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100976
Neale Rannsda78f952017-05-24 09:15:43 -0700977static uword
Neale Ranns31ed7442018-02-23 05:29:09 -0800978ethernet_mpls_label_imposition_pipe (vlib_main_t * vm,
979 vlib_node_runtime_t * node,
980 vlib_frame_t * frame)
Neale Rannsda78f952017-05-24 09:15:43 -0700981{
Neale Ranns31ed7442018-02-23 05:29:09 -0800982 return (mpls_label_imposition_inline(vm, node, frame,
983 DPO_PROTO_ETHERNET,
984 MPLS_LABEL_DPO_FLAG_NONE));
Neale Rannsda78f952017-05-24 09:15:43 -0700985}
986
Neale Ranns31ed7442018-02-23 05:29:09 -0800987VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_pipe_node) = {
988 .function = ethernet_mpls_label_imposition_pipe,
989 .name = "ethernet-mpls-label-imposition-pipe",
Neale Rannsda78f952017-05-24 09:15:43 -0700990 .vector_size = sizeof (u32),
991
992 .format_trace = format_mpls_label_imposition_trace,
993 .n_next_nodes = 1,
994 .next_nodes = {
995 [0] = "error-drop",
996 }
997};
Neale Ranns31ed7442018-02-23 05:29:09 -0800998
999VLIB_NODE_FUNCTION_MULTIARCH (ethernet_mpls_label_imposition_pipe_node,
1000 ethernet_mpls_label_imposition_pipe)
1001
1002static uword
1003mpls_mpls_label_imposition_uniform (vlib_main_t * vm,
1004 vlib_node_runtime_t * node,
1005 vlib_frame_t * frame)
1006{
1007 return (mpls_label_imposition_inline(vm, node, frame,
1008 DPO_PROTO_MPLS,
1009 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1010}
1011
1012VLIB_REGISTER_NODE (mpls_mpls_label_imposition_uniform_node) = {
1013 .function = mpls_mpls_label_imposition_uniform,
1014 .name = "mpls-label-imposition-uniform",
1015 .vector_size = sizeof (u32),
1016
1017 .format_trace = format_mpls_label_imposition_trace,
1018 .n_next_nodes = 1,
1019 .next_nodes = {
1020 [0] = "mpls-drop",
1021 }
1022};
1023VLIB_NODE_FUNCTION_MULTIARCH (mpls_mpls_label_imposition_uniform_node,
1024 mpls_mpls_label_imposition_uniform)
1025
1026static uword
1027ip4_mpls_label_imposition_uniform (vlib_main_t * vm,
1028 vlib_node_runtime_t * node,
1029 vlib_frame_t * frame)
1030{
1031 return (mpls_label_imposition_inline(vm, node, frame,
1032 DPO_PROTO_IP4,
1033 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1034}
1035
1036VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_node) = {
1037 .function = ip4_mpls_label_imposition_uniform,
1038 .name = "ip4-mpls-label-imposition-uniform",
1039 .vector_size = sizeof (u32),
1040
1041 .format_trace = format_mpls_label_imposition_trace,
1042 .n_next_nodes = 1,
1043 .next_nodes = {
1044 [0] = "ip4-drop",
1045 }
1046};
1047VLIB_NODE_FUNCTION_MULTIARCH (ip4_mpls_label_imposition_uniform_node,
1048 ip4_mpls_label_imposition_uniform)
1049
1050static uword
1051ip6_mpls_label_imposition_uniform (vlib_main_t * vm,
1052 vlib_node_runtime_t * node,
1053 vlib_frame_t * frame)
1054{
1055 return (mpls_label_imposition_inline(vm, node, frame,
1056 DPO_PROTO_IP6,
1057 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1058}
1059
1060VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_node) = {
1061 .function = ip6_mpls_label_imposition_uniform,
1062 .name = "ip6-mpls-label-imposition-uniform",
1063 .vector_size = sizeof (u32),
1064
1065 .format_trace = format_mpls_label_imposition_trace,
1066 .n_next_nodes = 1,
1067 .next_nodes = {
1068 [0] = "ip6-drop",
1069 }
1070};
1071VLIB_NODE_FUNCTION_MULTIARCH (ip6_mpls_label_imposition_uniform_node,
1072 ip6_mpls_label_imposition_uniform)
1073
1074static uword
1075ethernet_mpls_label_imposition_uniform (vlib_main_t * vm,
1076 vlib_node_runtime_t * node,
1077 vlib_frame_t * frame)
1078{
1079 return (mpls_label_imposition_inline(vm, node, frame,
1080 DPO_PROTO_ETHERNET,
1081 MPLS_LABEL_DPO_FLAG_UNIFORM_MODE));
1082}
1083
1084VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_uniform_node) = {
1085 .function = ethernet_mpls_label_imposition_uniform,
1086 .name = "ethernet-mpls-label-imposition-uniform",
1087 .vector_size = sizeof (u32),
1088
1089 .format_trace = format_mpls_label_imposition_trace,
1090 .n_next_nodes = 1,
1091 .next_nodes = {
1092 [0] = "error-drop",
1093 }
1094};
1095
1096VLIB_NODE_FUNCTION_MULTIARCH (ethernet_mpls_label_imposition_uniform_node,
1097 ethernet_mpls_label_imposition_uniform)
1098
1099static uword
1100ip4_mpls_label_imposition_pipe_no_ip_ttl_decr (vlib_main_t * vm,
1101 vlib_node_runtime_t * node,
1102 vlib_frame_t * frame)
1103{
1104 return (mpls_label_imposition_inline(vm, node, frame,
1105 DPO_PROTO_IP4,
1106 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR));
1107}
1108
1109VLIB_REGISTER_NODE (ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node) = {
1110 .function = ip4_mpls_label_imposition_pipe_no_ip_ttl_decr,
1111 .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};
1120VLIB_NODE_FUNCTION_MULTIARCH (ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node,
1121 ip4_mpls_label_imposition_pipe_no_ip_ttl_decr)
1122
1123static uword
1124ip6_mpls_label_imposition_pipe_no_ip_ttl_decr (vlib_main_t * vm,
1125 vlib_node_runtime_t * node,
1126 vlib_frame_t * frame)
1127{
1128 return (mpls_label_imposition_inline(vm, node, frame,
1129 DPO_PROTO_IP6,
1130 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR));
1131}
1132
1133VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node) = {
1134 .function = ip6_mpls_label_imposition_pipe_no_ip_ttl_decr,
1135 .name = "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
1136 .vector_size = sizeof (u32),
1137
1138 .format_trace = format_mpls_label_imposition_trace,
1139 .n_next_nodes = 1,
1140 .next_nodes = {
1141 [0] = "ip6-drop",
1142 }
1143};
1144VLIB_NODE_FUNCTION_MULTIARCH (ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node,
1145 ip6_mpls_label_imposition_pipe_no_ip_ttl_decr)
1146
1147static uword
1148ip4_mpls_label_imposition_uniform_no_ip_ttl_decr (vlib_main_t * vm,
1149 vlib_node_runtime_t * node,
1150 vlib_frame_t * frame)
1151{
1152 return (mpls_label_imposition_inline(vm, node, frame,
1153 DPO_PROTO_IP4,
1154 (MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
1155 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR)));
1156}
1157
1158VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node) = {
1159 .function = ip4_mpls_label_imposition_uniform_no_ip_ttl_decr,
1160 .name = "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
1161 .vector_size = sizeof (u32),
1162
1163 .format_trace = format_mpls_label_imposition_trace,
1164 .n_next_nodes = 1,
1165 .next_nodes = {
1166 [0] = "ip4-drop",
1167 }
1168};
1169VLIB_NODE_FUNCTION_MULTIARCH (ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node,
1170 ip4_mpls_label_imposition_uniform_no_ip_ttl_decr)
1171
1172static uword
1173ip6_mpls_label_imposition_uniform_no_ip_ttl_decr (vlib_main_t * vm,
1174 vlib_node_runtime_t * node,
1175 vlib_frame_t * frame)
1176{
1177 return (mpls_label_imposition_inline(vm, node, frame,
1178 DPO_PROTO_IP6,
1179 (MPLS_LABEL_DPO_FLAG_UNIFORM_MODE |
1180 MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR)));
1181}
1182
1183VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node) = {
1184 .function = ip6_mpls_label_imposition_uniform_no_ip_ttl_decr,
1185 .name = "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
1186 .vector_size = sizeof (u32),
1187
1188 .format_trace = format_mpls_label_imposition_trace,
1189 .n_next_nodes = 1,
1190 .next_nodes = {
1191 [0] = "ip6-drop",
1192 }
1193};
1194VLIB_NODE_FUNCTION_MULTIARCH (ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node,
1195 ip6_mpls_label_imposition_uniform_no_ip_ttl_decr)
1196
Neale Rannsda78f952017-05-24 09:15:43 -07001197
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001198static void
1199mpls_label_dpo_mem_show (void)
1200{
1201 fib_show_memory_usage("MPLS label",
1202 pool_elts(mpls_label_dpo_pool),
1203 pool_len(mpls_label_dpo_pool),
1204 sizeof(mpls_label_dpo_t));
1205}
1206
Neale Ranns2303cb12018-02-21 04:57:17 -08001207/**
1208 * Interpose a label DPO. used in the FIB unit tests
1209 */
1210static void
1211mpls_label_interpose (const dpo_id_t *original,
1212 const dpo_id_t *parent,
1213 dpo_id_t *clone)
1214{
1215 mpls_label_dpo_t *mld, *mld_clone;
1216
1217 mld_clone = mpls_label_dpo_alloc();
1218 mld = mpls_label_dpo_get(original->dpoi_index);
1219
1220 mld_clone->mld_locks = 0;
Dave Barach178cf492018-11-13 16:34:13 -05001221 clib_memcpy_fast(&mld_clone->mld_hdr,
Neale Ranns2303cb12018-02-21 04:57:17 -08001222 &mld->mld_hdr,
1223 sizeof(mld_clone->mld_hdr));
1224 mld_clone->mld_payload_proto = mld->mld_payload_proto;
1225 mld_clone->mld_n_labels = mld->mld_n_labels;
1226 mld_clone->mld_n_hdr_bytes = mld->mld_n_hdr_bytes;
1227
1228 dpo_stack(mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE],
1229 mld_clone->mld_payload_proto,
1230 &mld_clone->mld_dpo,
1231 parent);
1232
1233 dpo_set(clone,
1234 mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE],
1235 mld_clone->mld_payload_proto,
1236 mpls_label_dpo_get_index(mld_clone));
1237}
1238
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001239const static dpo_vft_t mld_vft = {
1240 .dv_lock = mpls_label_dpo_lock,
1241 .dv_unlock = mpls_label_dpo_unlock,
1242 .dv_format = format_mpls_label_dpo,
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001243 .dv_mem_show = mpls_label_dpo_mem_show,
Neale Ranns2303cb12018-02-21 04:57:17 -08001244 .dv_mk_interpose = mpls_label_interpose,
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}