blob: 6d18a06945986379c959209e3eb9347a6a20b547 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * map.c : MAP support
3 *
4 * Copyright (c) 2015 Cisco and/or its affiliates.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Neale Ranns0bfe5d82016-08-25 15:29:12 +010018#include <vnet/fib/fib_table.h>
19#include <vnet/fib/ip6_fib.h>
20#include <vnet/adj/adj.h>
21#include <vnet/map/map_dpo.h>
Christophe Fontaineb4bd28a2017-05-31 11:27:19 +020022#include <vppinfra/crc32.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010023
Ed Warnickecb9cada2015-12-08 15:45:58 -070024#include "map.h"
25
Dave Wallace71612d62017-10-24 01:32:41 -040026map_main_t map_main;
27
Ed Warnickecb9cada2015-12-08 15:45:58 -070028/*
29 * This code supports the following MAP modes:
Damjan Marion607de1a2016-08-16 22:53:54 +020030 *
Ed Warnickecb9cada2015-12-08 15:45:58 -070031 * Algorithmic Shared IPv4 address (ea_bits_len > 0):
32 * ea_bits_len + ip4_prefix > 32
33 * psid_length > 0, ip6_prefix < 64, ip4_prefix <= 32
34 * Algorithmic Full IPv4 address (ea_bits_len > 0):
35 * ea_bits_len + ip4_prefix = 32
36 * psid_length = 0, ip6_prefix < 64, ip4_prefix <= 32
37 * Algorithmic IPv4 prefix (ea_bits_len > 0):
38 * ea_bits_len + ip4_prefix < 32
39 * psid_length = 0, ip6_prefix < 64, ip4_prefix <= 32
40 *
41 * Independent Shared IPv4 address (ea_bits_len = 0):
42 * ip4_prefix = 32
43 * psid_length > 0
44 * Rule IPv6 address = 128, Rule PSID Set
45 * Independent Full IPv4 address (ea_bits_len = 0):
46 * ip4_prefix = 32
47 * psid_length = 0, ip6_prefix = 128
48 * Independent IPv4 prefix (ea_bits_len = 0):
49 * ip4_prefix < 32
50 * psid_length = 0, ip6_prefix = 128
51 *
52 */
53
54/*
55 * This code supports MAP-T:
56 *
57 * With DMR prefix length equal to 96.
58 *
59 */
60
61
Ed Warnickecb9cada2015-12-08 15:45:58 -070062
63int
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -070064map_create_domain (ip4_address_t * ip4_prefix,
65 u8 ip4_prefix_len,
66 ip6_address_t * ip6_prefix,
67 u8 ip6_prefix_len,
68 ip6_address_t * ip6_src,
69 u8 ip6_src_len,
70 u8 ea_bits_len,
71 u8 psid_offset,
72 u8 psid_length, u32 * map_domain_index, u16 mtu, u8 flags)
Ed Warnickecb9cada2015-12-08 15:45:58 -070073{
Ole Troan07e7eab2016-08-25 00:24:08 +020074 u8 suffix_len, suffix_shift;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010075 map_main_t *mm = &map_main;
Neale Ranns948e00f2016-10-20 13:39:34 +010076 dpo_id_t dpo_v4 = DPO_INVALID;
77 dpo_id_t dpo_v6 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010078 map_domain_t *d;
Ed Warnickecb9cada2015-12-08 15:45:58 -070079
Ed Warnickecb9cada2015-12-08 15:45:58 -070080 /* Sanity check on the src prefix length */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -070081 if (flags & MAP_DOMAIN_TRANSLATION)
82 {
83 if (ip6_src_len != 96)
84 {
85 clib_warning ("MAP-T only supports ip6_src_len = 96 for now.");
Ed Warnickecb9cada2015-12-08 15:45:58 -070086 return -1;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -070087 }
88 }
89 else
90 {
91 if (ip6_src_len != 128)
92 {
93 clib_warning
Ole Troan07e7eab2016-08-25 00:24:08 +020094 ("MAP-E requires a BR address, not a prefix (ip6_src_len should "
95 "be 128).");
Ed Warnickecb9cada2015-12-08 15:45:58 -070096 return -1;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -070097 }
98 }
Ed Warnickecb9cada2015-12-08 15:45:58 -070099
Ole Troan07e7eab2016-08-25 00:24:08 +0200100 /* How many, and which bits to grab from the IPv4 DA */
101 if (ip4_prefix_len + ea_bits_len < 32)
102 {
103 flags |= MAP_DOMAIN_PREFIX;
Ole Troand575e692016-08-25 12:26:47 +0200104 suffix_shift = 32 - ip4_prefix_len - ea_bits_len;
105 suffix_len = ea_bits_len;
Ole Troan07e7eab2016-08-25 00:24:08 +0200106 }
107 else
108 {
109 suffix_shift = 0;
110 suffix_len = 32 - ip4_prefix_len;
111 }
112
113 /* EA bits must be within the first 64 bits */
114 if (ea_bits_len > 0 && ((ip6_prefix_len + ea_bits_len) > 64 ||
115 ip6_prefix_len + suffix_len + psid_length > 64))
116 {
117 clib_warning
118 ("Embedded Address bits must be within the first 64 bits of "
119 "the IPv6 prefix");
120 return -1;
121 }
122
Ed Warnickecb9cada2015-12-08 15:45:58 -0700123 /* Get domain index */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700124 pool_get_aligned (mm->domains, d, CLIB_CACHE_LINE_BYTES);
125 memset (d, 0, sizeof (*d));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700126 *map_domain_index = d - mm->domains;
127
128 /* Init domain struct */
129 d->ip4_prefix.as_u32 = ip4_prefix->as_u32;
130 d->ip4_prefix_len = ip4_prefix_len;
131 d->ip6_prefix = *ip6_prefix;
132 d->ip6_prefix_len = ip6_prefix_len;
133 d->ip6_src = *ip6_src;
134 d->ip6_src_len = ip6_src_len;
135 d->ea_bits_len = ea_bits_len;
136 d->psid_offset = psid_offset;
137 d->psid_length = psid_length;
138 d->mtu = mtu;
139 d->flags = flags;
Ole Troan07e7eab2016-08-25 00:24:08 +0200140 d->suffix_shift = suffix_shift;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700141 d->suffix_mask = (1 << suffix_len) - 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700142
143 d->psid_shift = 16 - psid_length - psid_offset;
144 d->psid_mask = (1 << d->psid_length) - 1;
145 d->ea_shift = 64 - ip6_prefix_len - suffix_len - d->psid_length;
146
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100147 /* MAP data-plane object */
148 if (d->flags & MAP_DOMAIN_TRANSLATION)
149 map_t_dpo_create (DPO_PROTO_IP4, *map_domain_index, &dpo_v4);
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700150 else
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100151 map_dpo_create (DPO_PROTO_IP4, *map_domain_index, &dpo_v4);
152
153 /* Create ip4 route */
154 fib_prefix_t pfx = {
155 .fp_proto = FIB_PROTOCOL_IP4,
156 .fp_len = d->ip4_prefix_len,
157 .fp_addr = {
158 .ip4 = d->ip4_prefix,
159 }
160 ,
161 };
162 fib_table_entry_special_dpo_add (0, &pfx,
163 FIB_SOURCE_MAP,
164 FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4);
165 dpo_reset (&dpo_v4);
166
167 /*
Neale Ranns9705c382017-02-20 20:29:41 -0800168 * construct a DPO to use the v6 domain
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100169 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100170 if (d->flags & MAP_DOMAIN_TRANSLATION)
171 map_t_dpo_create (DPO_PROTO_IP6, *map_domain_index, &dpo_v6);
172 else
173 map_dpo_create (DPO_PROTO_IP6, *map_domain_index, &dpo_v6);
174
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100175 /*
Neale Ranns9705c382017-02-20 20:29:41 -0800176 * Multiple MAP domains may share same source IPv6 TEP. Which is just dandy.
177 * We are not tracking the sharing. So a v4 lookup to find the correct
178 * domain post decap/trnaslate is always done
179 *
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100180 * Create ip6 route. This is a reference counted add. If the prefix
181 * already exists and is MAP sourced, it is now MAP source n+1 times
182 * and will need to be removed n+1 times.
183 */
Neale Ranns9705c382017-02-20 20:29:41 -0800184 fib_prefix_t pfx6 = {
185 .fp_proto = FIB_PROTOCOL_IP6,
186 .fp_len = d->ip6_src_len,
187 .fp_addr.ip6 = d->ip6_src,
188 };
189
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100190 fib_table_entry_special_dpo_add (0, &pfx6,
191 FIB_SOURCE_MAP,
192 FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v6);
193 dpo_reset (&dpo_v6);
194
Ed Warnickecb9cada2015-12-08 15:45:58 -0700195 /* Validate packet/byte counters */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700196 map_domain_counter_lock (mm);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700197 int i;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700198 for (i = 0; i < vec_len (mm->simple_domain_counters); i++)
199 {
200 vlib_validate_simple_counter (&mm->simple_domain_counters[i],
201 *map_domain_index);
202 vlib_zero_simple_counter (&mm->simple_domain_counters[i],
203 *map_domain_index);
204 }
205 for (i = 0; i < vec_len (mm->domain_counters); i++)
206 {
207 vlib_validate_combined_counter (&mm->domain_counters[i],
208 *map_domain_index);
209 vlib_zero_combined_counter (&mm->domain_counters[i], *map_domain_index);
210 }
211 map_domain_counter_unlock (mm);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700212
213 return 0;
214}
215
216/*
217 * map_delete_domain
218 */
219int
220map_delete_domain (u32 map_domain_index)
221{
222 map_main_t *mm = &map_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223 map_domain_t *d;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700224
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700225 if (pool_is_free_index (mm->domains, map_domain_index))
226 {
227 clib_warning ("MAP domain delete: domain does not exist: %d",
228 map_domain_index);
229 return -1;
230 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700231
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700232 d = pool_elt_at_index (mm->domains, map_domain_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700233
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100234 fib_prefix_t pfx = {
235 .fp_proto = FIB_PROTOCOL_IP4,
236 .fp_len = d->ip4_prefix_len,
237 .fp_addr = {
238 .ip4 = d->ip4_prefix,
239 }
240 ,
241 };
242 fib_table_entry_special_remove (0, &pfx, FIB_SOURCE_MAP);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700243
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100244 fib_prefix_t pfx6 = {
245 .fp_proto = FIB_PROTOCOL_IP6,
246 .fp_len = d->ip6_src_len,
247 .fp_addr = {
248 .ip6 = d->ip6_src,
249 }
250 ,
251 };
252 fib_table_entry_special_remove (0, &pfx6, FIB_SOURCE_MAP);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700253
Ed Warnickecb9cada2015-12-08 15:45:58 -0700254 /* Deleting rules */
255 if (d->rules)
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700256 clib_mem_free (d->rules);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700257
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700258 pool_put (mm->domains, d);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700259
260 return 0;
261}
262
263int
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700264map_add_del_psid (u32 map_domain_index, u16 psid, ip6_address_t * tep,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700265 u8 is_add)
266{
267 map_domain_t *d;
268 map_main_t *mm = &map_main;
269
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700270 if (pool_is_free_index (mm->domains, map_domain_index))
271 {
272 clib_warning ("MAP rule: domain does not exist: %d", map_domain_index);
273 return -1;
274 }
275 d = pool_elt_at_index (mm->domains, map_domain_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700276
277 /* Rules are only used in 1:1 independent case */
278 if (d->ea_bits_len > 0)
279 return (-1);
280
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700281 if (!d->rules)
282 {
283 u32 l = (0x1 << d->psid_length) * sizeof (ip6_address_t);
284 d->rules = clib_mem_alloc_aligned (l, CLIB_CACHE_LINE_BYTES);
285 if (!d->rules)
286 return -1;
287 memset (d->rules, 0, l);
288 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700289
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700290 if (psid >= (0x1 << d->psid_length))
291 {
292 clib_warning ("MAP rule: PSID outside bounds: %d [%d]", psid,
293 0x1 << d->psid_length);
294 return -1;
295 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700296
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700297 if (is_add)
298 {
299 d->rules[psid] = *tep;
300 }
301 else
302 {
303 memset (&d->rules[psid], 0, sizeof (ip6_address_t));
304 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700305 return 0;
306}
307
308#ifdef MAP_SKIP_IP6_LOOKUP
Neale Ranns80823802017-02-20 18:23:41 -0800309/**
310 * Pre-resolvd per-protocol global next-hops
311 */
312map_main_pre_resolved_t pre_resolved[FIB_PROTOCOL_MAX];
313
314static void
315map_pre_resolve_init (map_main_pre_resolved_t * pr)
316{
317 pr->fei = FIB_NODE_INDEX_INVALID;
318 fib_node_init (&pr->node, FIB_NODE_TYPE_MAP_E);
319}
320
321static u8 *
Christophe Fontained3c008d2017-10-02 18:10:54 +0200322format_map_pre_resolve (u8 * s, va_list * ap)
Neale Ranns80823802017-02-20 18:23:41 -0800323{
Christophe Fontained3c008d2017-10-02 18:10:54 +0200324 map_main_pre_resolved_t *pr = va_arg (*ap, map_main_pre_resolved_t *);
Neale Ranns80823802017-02-20 18:23:41 -0800325
326 if (FIB_NODE_INDEX_INVALID != pr->fei)
327 {
328 fib_prefix_t pfx;
329
330 fib_entry_get_prefix (pr->fei, &pfx);
331
332 return (format (s, "%U (%u)",
333 format_ip46_address, &pfx.fp_addr, IP46_TYPE_ANY,
334 pr->dpo.dpoi_index));
335 }
336 else
337 {
338 return (format (s, "un-set"));
339 }
340}
341
342
343/**
344 * Function definition to inform the FIB node that its last lock has gone.
345 */
346static void
347map_last_lock_gone (fib_node_t * node)
348{
349 /*
350 * The MAP is a root of the graph. As such
351 * it never has children and thus is never locked.
352 */
353 ASSERT (0);
354}
355
356static map_main_pre_resolved_t *
357map_from_fib_node (fib_node_t * node)
358{
359#if (CLIB_DEBUG > 0)
360 ASSERT (FIB_NODE_TYPE_MAP_E == node->fn_type);
361#endif
362 return ((map_main_pre_resolved_t *)
363 (((char *) node) -
364 STRUCT_OFFSET_OF (map_main_pre_resolved_t, node)));
365}
366
367static void
368map_stack (map_main_pre_resolved_t * pr)
369{
370 const dpo_id_t *dpo;
371
372 dpo = fib_entry_contribute_ip_forwarding (pr->fei);
373
374 dpo_copy (&pr->dpo, dpo);
375}
376
377/**
378 * Function definition to backwalk a FIB node
379 */
380static fib_node_back_walk_rc_t
381map_back_walk (fib_node_t * node, fib_node_back_walk_ctx_t * ctx)
382{
383 map_stack (map_from_fib_node (node));
384
385 return (FIB_NODE_BACK_WALK_CONTINUE);
386}
387
388/**
389 * Function definition to get a FIB node from its index
390 */
391static fib_node_t *
392map_fib_node_get (fib_node_index_t index)
393{
394 return (&pre_resolved[index].node);
395}
396
397/*
398 * Virtual function table registered by MPLS GRE tunnels
399 * for participation in the FIB object graph.
400 */
401const static fib_node_vft_t map_vft = {
402 .fnv_get = map_fib_node_get,
403 .fnv_last_lock = map_last_lock_gone,
404 .fnv_back_walk = map_back_walk,
405};
406
407static void
408map_fib_resolve (map_main_pre_resolved_t * pr,
409 fib_protocol_t proto, u8 len, const ip46_address_t * addr)
410{
411 fib_prefix_t pfx = {
412 .fp_proto = proto,
413 .fp_len = len,
414 .fp_addr = *addr,
415 };
416
417 pr->fei = fib_table_entry_special_add (0, // default fib
418 &pfx,
Neale Rannsa0558302017-04-13 00:44:52 -0700419 FIB_SOURCE_RR, FIB_ENTRY_FLAG_NONE);
Neale Ranns80823802017-02-20 18:23:41 -0800420 pr->sibling = fib_entry_child_add (pr->fei, FIB_NODE_TYPE_MAP_E, proto);
421 map_stack (pr);
422}
423
Ed Warnickecb9cada2015-12-08 15:45:58 -0700424static void
Neale Ranns69b7aa42017-03-10 03:04:12 -0800425map_fib_unresolve (map_main_pre_resolved_t * pr,
426 fib_protocol_t proto, u8 len, const ip46_address_t * addr)
427{
428 fib_prefix_t pfx = {
429 .fp_proto = proto,
430 .fp_len = len,
431 .fp_addr = *addr,
432 };
433
434 fib_entry_child_remove (pr->fei, pr->sibling);
435
436 fib_table_entry_special_remove (0, // default fib
437 &pfx, FIB_SOURCE_RR);
438 dpo_reset (&pr->dpo);
439
440 pr->fei = FIB_NODE_INDEX_INVALID;
441 pr->sibling = FIB_NODE_INDEX_INVALID;
442}
443
444static void
445map_pre_resolve (ip4_address_t * ip4, ip6_address_t * ip6, int is_del)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700446{
Neale Ranns80823802017-02-20 18:23:41 -0800447 if (ip6 && (ip6->as_u64[0] != 0 || ip6->as_u64[1] != 0))
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700448 {
Neale Ranns80823802017-02-20 18:23:41 -0800449 ip46_address_t addr = {
450 .ip6 = *ip6,
451 };
Neale Ranns69b7aa42017-03-10 03:04:12 -0800452 if (is_del)
453 map_fib_unresolve (&pre_resolved[FIB_PROTOCOL_IP6],
454 FIB_PROTOCOL_IP6, 128, &addr);
455 else
456 map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP6],
457 FIB_PROTOCOL_IP6, 128, &addr);
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700458 }
Neale Ranns80823802017-02-20 18:23:41 -0800459 if (ip4 && (ip4->as_u32 != 0))
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700460 {
Neale Ranns80823802017-02-20 18:23:41 -0800461 ip46_address_t addr = {
462 .ip4 = *ip4,
463 };
Neale Ranns69b7aa42017-03-10 03:04:12 -0800464 if (is_del)
465 map_fib_unresolve (&pre_resolved[FIB_PROTOCOL_IP4],
466 FIB_PROTOCOL_IP4, 32, &addr);
467 else
468 map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP4],
469 FIB_PROTOCOL_IP4, 32, &addr);
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700470 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700471}
472#endif
473
474static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700475map_security_check_command_fn (vlib_main_t * vm,
476 unformat_input_t * input,
477 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700478{
479 unformat_input_t _line_input, *line_input = &_line_input;
480 map_main_t *mm = &map_main;
Billy McFalla9a20e72017-02-15 11:39:12 -0500481 clib_error_t *error = NULL;
482
Ed Warnickecb9cada2015-12-08 15:45:58 -0700483 /* Get a line of input. */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700484 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700485 return 0;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700486
487 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
488 {
489 if (unformat (line_input, "off"))
490 mm->sec_check = false;
491 else if (unformat (line_input, "on"))
492 mm->sec_check = true;
493 else
Billy McFalla9a20e72017-02-15 11:39:12 -0500494 {
495 error = clib_error_return (0, "unknown input `%U'",
496 format_unformat_error, line_input);
497 goto done;
498 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700499 }
Billy McFalla9a20e72017-02-15 11:39:12 -0500500
501done:
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700502 unformat_free (line_input);
Billy McFalla9a20e72017-02-15 11:39:12 -0500503
504 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700505}
506
507static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700508map_security_check_frag_command_fn (vlib_main_t * vm,
509 unformat_input_t * input,
510 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700511{
512 unformat_input_t _line_input, *line_input = &_line_input;
513 map_main_t *mm = &map_main;
Billy McFalla9a20e72017-02-15 11:39:12 -0500514 clib_error_t *error = NULL;
515
Ed Warnickecb9cada2015-12-08 15:45:58 -0700516 /* Get a line of input. */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700517 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700518 return 0;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700519
520 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
521 {
522 if (unformat (line_input, "off"))
523 mm->sec_check_frag = false;
524 else if (unformat (line_input, "on"))
525 mm->sec_check_frag = true;
526 else
Billy McFalla9a20e72017-02-15 11:39:12 -0500527 {
528 error = clib_error_return (0, "unknown input `%U'",
529 format_unformat_error, line_input);
530 goto done;
531 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700532 }
Billy McFalla9a20e72017-02-15 11:39:12 -0500533
534done:
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700535 unformat_free (line_input);
Billy McFalla9a20e72017-02-15 11:39:12 -0500536
537 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700538}
539
540static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700541map_add_domain_command_fn (vlib_main_t * vm,
542 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700543{
544 unformat_input_t _line_input, *line_input = &_line_input;
545 ip4_address_t ip4_prefix;
546 ip6_address_t ip6_prefix;
547 ip6_address_t ip6_src;
Dave Barach042ffb42016-08-12 09:26:47 -0400548 u32 ip6_prefix_len = 0, ip4_prefix_len = 0, map_domain_index, ip6_src_len;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700549 u32 num_m_args = 0;
550 /* Optional arguments */
Dave Barach042ffb42016-08-12 09:26:47 -0400551 u32 ea_bits_len = 0, psid_offset = 0, psid_length = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700552 u32 mtu = 0;
553 u8 flags = 0;
554 ip6_src_len = 128;
Billy McFalla9a20e72017-02-15 11:39:12 -0500555 clib_error_t *error = NULL;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700556
557 /* Get a line of input. */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700558 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700559 return 0;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700560
561 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
562 {
563 if (unformat
564 (line_input, "ip4-pfx %U/%d", unformat_ip4_address, &ip4_prefix,
565 &ip4_prefix_len))
566 num_m_args++;
567 else
568 if (unformat
569 (line_input, "ip6-pfx %U/%d", unformat_ip6_address, &ip6_prefix,
570 &ip6_prefix_len))
571 num_m_args++;
572 else
573 if (unformat
574 (line_input, "ip6-src %U/%d", unformat_ip6_address, &ip6_src,
575 &ip6_src_len))
576 num_m_args++;
577 else
578 if (unformat
579 (line_input, "ip6-src %U", unformat_ip6_address, &ip6_src))
580 num_m_args++;
581 else if (unformat (line_input, "ea-bits-len %d", &ea_bits_len))
582 num_m_args++;
583 else if (unformat (line_input, "psid-offset %d", &psid_offset))
584 num_m_args++;
585 else if (unformat (line_input, "psid-len %d", &psid_length))
586 num_m_args++;
587 else if (unformat (line_input, "mtu %d", &mtu))
588 num_m_args++;
589 else if (unformat (line_input, "map-t"))
590 flags |= MAP_DOMAIN_TRANSLATION;
591 else
Billy McFalla9a20e72017-02-15 11:39:12 -0500592 {
593 error = clib_error_return (0, "unknown input `%U'",
594 format_unformat_error, line_input);
595 goto done;
596 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700597 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700598
599 if (num_m_args < 3)
Billy McFalla9a20e72017-02-15 11:39:12 -0500600 {
601 error = clib_error_return (0, "mandatory argument(s) missing");
602 goto done;
603 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700604
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700605 map_create_domain (&ip4_prefix, ip4_prefix_len,
606 &ip6_prefix, ip6_prefix_len, &ip6_src, ip6_src_len,
607 ea_bits_len, psid_offset, psid_length, &map_domain_index,
608 mtu, flags);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700609
Billy McFalla9a20e72017-02-15 11:39:12 -0500610done:
611 unformat_free (line_input);
612
613 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700614}
615
616static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700617map_del_domain_command_fn (vlib_main_t * vm,
618 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700619{
620 unformat_input_t _line_input, *line_input = &_line_input;
621 u32 num_m_args = 0;
622 u32 map_domain_index;
Billy McFalla9a20e72017-02-15 11:39:12 -0500623 clib_error_t *error = NULL;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700624
625 /* Get a line of input. */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700626 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700627 return 0;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700628
629 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
630 {
631 if (unformat (line_input, "index %d", &map_domain_index))
632 num_m_args++;
633 else
Billy McFalla9a20e72017-02-15 11:39:12 -0500634 {
635 error = clib_error_return (0, "unknown input `%U'",
636 format_unformat_error, line_input);
637 goto done;
638 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700639 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700640
641 if (num_m_args != 1)
Billy McFalla9a20e72017-02-15 11:39:12 -0500642 {
643 error = clib_error_return (0, "mandatory argument(s) missing");
644 goto done;
645 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700646
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700647 map_delete_domain (map_domain_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700648
Billy McFalla9a20e72017-02-15 11:39:12 -0500649done:
650 unformat_free (line_input);
651
652 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700653}
654
655static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700656map_add_rule_command_fn (vlib_main_t * vm,
657 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700658{
659 unformat_input_t _line_input, *line_input = &_line_input;
660 ip6_address_t tep;
661 u32 num_m_args = 0;
Dave Barach042ffb42016-08-12 09:26:47 -0400662 u32 psid = 0, map_domain_index;
Billy McFalla9a20e72017-02-15 11:39:12 -0500663 clib_error_t *error = NULL;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700664
Ed Warnickecb9cada2015-12-08 15:45:58 -0700665 /* Get a line of input. */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700666 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700667 return 0;
668
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700669 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
670 {
671 if (unformat (line_input, "index %d", &map_domain_index))
672 num_m_args++;
673 else if (unformat (line_input, "psid %d", &psid))
674 num_m_args++;
675 else
676 if (unformat (line_input, "ip6-dst %U", unformat_ip6_address, &tep))
677 num_m_args++;
678 else
Billy McFalla9a20e72017-02-15 11:39:12 -0500679 {
680 error = clib_error_return (0, "unknown input `%U'",
681 format_unformat_error, line_input);
682 goto done;
683 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700684 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700685
686 if (num_m_args != 3)
Billy McFalla9a20e72017-02-15 11:39:12 -0500687 {
688 error = clib_error_return (0, "mandatory argument(s) missing");
689 goto done;
690 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700691
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700692 if (map_add_del_psid (map_domain_index, psid, &tep, 1) != 0)
693 {
Billy McFalla9a20e72017-02-15 11:39:12 -0500694 error = clib_error_return (0, "Failing to add Mapping Rule");
695 goto done;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700696 }
Billy McFalla9a20e72017-02-15 11:39:12 -0500697
698done:
699 unformat_free (line_input);
700
701 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700702}
703
704#if MAP_SKIP_IP6_LOOKUP
705static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700706map_pre_resolve_command_fn (vlib_main_t * vm,
707 unformat_input_t * input,
708 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700709{
710 unformat_input_t _line_input, *line_input = &_line_input;
Neale Ranns80823802017-02-20 18:23:41 -0800711 ip4_address_t ip4nh, *p_v4 = NULL;
712 ip6_address_t ip6nh, *p_v6 = NULL;
Billy McFalla9a20e72017-02-15 11:39:12 -0500713 clib_error_t *error = NULL;
Neale Ranns69b7aa42017-03-10 03:04:12 -0800714 int is_del = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700715
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700716 memset (&ip4nh, 0, sizeof (ip4nh));
717 memset (&ip6nh, 0, sizeof (ip6nh));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700718
719 /* Get a line of input. */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700720 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700721 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700722
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700723 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
724 {
725 if (unformat (line_input, "ip4-nh %U", unformat_ip4_address, &ip4nh))
Neale Ranns80823802017-02-20 18:23:41 -0800726 p_v4 = &ip4nh;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700727 else
728 if (unformat (line_input, "ip6-nh %U", unformat_ip6_address, &ip6nh))
Neale Ranns80823802017-02-20 18:23:41 -0800729 p_v6 = &ip6nh;
Neale Ranns69b7aa42017-03-10 03:04:12 -0800730 else if (unformat (line_input, "del"))
731 is_del = 1;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700732 else
Billy McFalla9a20e72017-02-15 11:39:12 -0500733 {
734 error = clib_error_return (0, "unknown input `%U'",
735 format_unformat_error, line_input);
736 goto done;
737 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700738 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700739
Neale Ranns69b7aa42017-03-10 03:04:12 -0800740 map_pre_resolve (p_v4, p_v6, is_del);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700741
Billy McFalla9a20e72017-02-15 11:39:12 -0500742done:
743 unformat_free (line_input);
744
745 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700746}
747#endif
748
749static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700750map_icmp_relay_source_address_command_fn (vlib_main_t * vm,
751 unformat_input_t * input,
752 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700753{
754 unformat_input_t _line_input, *line_input = &_line_input;
755 ip4_address_t icmp_src_address;
756 map_main_t *mm = &map_main;
Billy McFalla9a20e72017-02-15 11:39:12 -0500757 clib_error_t *error = NULL;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700758
Ole Troancda94822016-01-07 14:37:25 +0100759 mm->icmp4_src_address.as_u32 = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700760
761 /* Get a line of input. */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700762 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700763 return 0;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700764
765 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
766 {
767 if (unformat
768 (line_input, "%U", unformat_ip4_address, &icmp_src_address))
769 mm->icmp4_src_address = icmp_src_address;
770 else
Billy McFalla9a20e72017-02-15 11:39:12 -0500771 {
772 error = clib_error_return (0, "unknown input `%U'",
773 format_unformat_error, line_input);
774 goto done;
775 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700776 }
Billy McFalla9a20e72017-02-15 11:39:12 -0500777
778done:
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700779 unformat_free (line_input);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700780
Billy McFalla9a20e72017-02-15 11:39:12 -0500781 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700782}
783
784static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700785map_icmp_unreachables_command_fn (vlib_main_t * vm,
786 unformat_input_t * input,
787 vlib_cli_command_t * cmd)
Ole Troancda94822016-01-07 14:37:25 +0100788{
789 unformat_input_t _line_input, *line_input = &_line_input;
790 map_main_t *mm = &map_main;
791 int num_m_args = 0;
Billy McFalla9a20e72017-02-15 11:39:12 -0500792 clib_error_t *error = NULL;
Ole Troancda94822016-01-07 14:37:25 +0100793
794 /* Get a line of input. */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700795 if (!unformat_user (input, unformat_line_input, line_input))
Ole Troancda94822016-01-07 14:37:25 +0100796 return 0;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700797
798 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
799 {
800 num_m_args++;
801 if (unformat (line_input, "on"))
802 mm->icmp6_enabled = true;
803 else if (unformat (line_input, "off"))
804 mm->icmp6_enabled = false;
805 else
Billy McFalla9a20e72017-02-15 11:39:12 -0500806 {
807 error = clib_error_return (0, "unknown input `%U'",
808 format_unformat_error, line_input);
809 goto done;
810 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700811 }
Ole Troancda94822016-01-07 14:37:25 +0100812
813
814 if (num_m_args != 1)
Billy McFalla9a20e72017-02-15 11:39:12 -0500815 error = clib_error_return (0, "mandatory argument(s) missing");
Ole Troancda94822016-01-07 14:37:25 +0100816
Billy McFalla9a20e72017-02-15 11:39:12 -0500817done:
818 unformat_free (line_input);
819
820 return error;
Ole Troancda94822016-01-07 14:37:25 +0100821}
822
823static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700824map_fragment_command_fn (vlib_main_t * vm,
825 unformat_input_t * input, vlib_cli_command_t * cmd)
Ole Troan9fb87552016-01-13 22:30:43 +0100826{
827 unformat_input_t _line_input, *line_input = &_line_input;
828 map_main_t *mm = &map_main;
Billy McFalla9a20e72017-02-15 11:39:12 -0500829 clib_error_t *error = NULL;
Ole Troan9fb87552016-01-13 22:30:43 +0100830
831 /* Get a line of input. */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700832 if (!unformat_user (input, unformat_line_input, line_input))
Ole Troan9fb87552016-01-13 22:30:43 +0100833 return 0;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700834
835 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
836 {
837 if (unformat (line_input, "inner"))
838 mm->frag_inner = true;
839 else if (unformat (line_input, "outer"))
840 mm->frag_inner = false;
841 else
Billy McFalla9a20e72017-02-15 11:39:12 -0500842 {
843 error = clib_error_return (0, "unknown input `%U'",
844 format_unformat_error, line_input);
845 goto done;
846 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700847 }
Billy McFalla9a20e72017-02-15 11:39:12 -0500848
849done:
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700850 unformat_free (line_input);
Ole Troan9fb87552016-01-13 22:30:43 +0100851
Billy McFalla9a20e72017-02-15 11:39:12 -0500852 return error;
Ole Troan9fb87552016-01-13 22:30:43 +0100853}
854
855static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700856map_fragment_df_command_fn (vlib_main_t * vm,
857 unformat_input_t * input,
858 vlib_cli_command_t * cmd)
Ole Troan9fb87552016-01-13 22:30:43 +0100859{
860 unformat_input_t _line_input, *line_input = &_line_input;
861 map_main_t *mm = &map_main;
Billy McFalla9a20e72017-02-15 11:39:12 -0500862 clib_error_t *error = NULL;
Ole Troan9fb87552016-01-13 22:30:43 +0100863
864 /* Get a line of input. */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700865 if (!unformat_user (input, unformat_line_input, line_input))
Ole Troan9fb87552016-01-13 22:30:43 +0100866 return 0;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700867
868 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
869 {
870 if (unformat (line_input, "on"))
871 mm->frag_ignore_df = true;
872 else if (unformat (line_input, "off"))
873 mm->frag_ignore_df = false;
874 else
Billy McFalla9a20e72017-02-15 11:39:12 -0500875 {
876 error = clib_error_return (0, "unknown input `%U'",
877 format_unformat_error, line_input);
878 goto done;
879 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700880 }
Billy McFalla9a20e72017-02-15 11:39:12 -0500881
882done:
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700883 unformat_free (line_input);
Ole Troan9fb87552016-01-13 22:30:43 +0100884
Billy McFalla9a20e72017-02-15 11:39:12 -0500885 return error;
Ole Troan9fb87552016-01-13 22:30:43 +0100886}
887
888static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700889map_traffic_class_command_fn (vlib_main_t * vm,
890 unformat_input_t * input,
891 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700892{
893 unformat_input_t _line_input, *line_input = &_line_input;
894 map_main_t *mm = &map_main;
895 u32 tc = 0;
Billy McFalla9a20e72017-02-15 11:39:12 -0500896 clib_error_t *error = NULL;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700897
898 mm->tc_copy = false;
899
900 /* Get a line of input. */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700901 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700902 return 0;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700903
904 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
905 {
906 if (unformat (line_input, "copy"))
907 mm->tc_copy = true;
908 else if (unformat (line_input, "%x", &tc))
909 mm->tc = tc & 0xff;
910 else
Billy McFalla9a20e72017-02-15 11:39:12 -0500911 {
912 error = clib_error_return (0, "unknown input `%U'",
913 format_unformat_error, line_input);
914 goto done;
915 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700916 }
Billy McFalla9a20e72017-02-15 11:39:12 -0500917
918done:
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700919 unformat_free (line_input);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700920
Billy McFalla9a20e72017-02-15 11:39:12 -0500921 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700922}
923
924static u8 *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700925format_map_domain (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700926{
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700927 map_domain_t *d = va_arg (*args, map_domain_t *);
928 bool counters = va_arg (*args, int);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700929 map_main_t *mm = &map_main;
930 ip6_address_t ip6_prefix;
931
932 if (d->rules)
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700933 memset (&ip6_prefix, 0, sizeof (ip6_prefix));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700934 else
935 ip6_prefix = d->ip6_prefix;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700936
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700937 s = format (s,
938 "[%d] ip4-pfx %U/%d ip6-pfx %U/%d ip6-src %U/%d ea_bits_len %d psid-offset %d psid-len %d mtu %d %s",
939 d - mm->domains,
940 format_ip4_address, &d->ip4_prefix, d->ip4_prefix_len,
941 format_ip6_address, &ip6_prefix, d->ip6_prefix_len,
942 format_ip6_address, &d->ip6_src, d->ip6_src_len,
943 d->ea_bits_len, d->psid_offset, d->psid_length, d->mtu,
944 (d->flags & MAP_DOMAIN_TRANSLATION) ? "map-t" : "");
Ole Troan366ac6e2016-01-06 12:40:28 +0100945
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700946 if (counters)
947 {
948 map_domain_counter_lock (mm);
949 vlib_counter_t v;
950 vlib_get_combined_counter (&mm->domain_counters[MAP_DOMAIN_COUNTER_TX],
951 d - mm->domains, &v);
952 s = format (s, " TX: %lld/%lld", v.packets, v.bytes);
953 vlib_get_combined_counter (&mm->domain_counters[MAP_DOMAIN_COUNTER_RX],
954 d - mm->domains, &v);
955 s = format (s, " RX: %lld/%lld", v.packets, v.bytes);
956 map_domain_counter_unlock (mm);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700957 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700958 s = format (s, "\n");
959
960 if (d->rules)
961 {
962 int i;
963 ip6_address_t dst;
964 for (i = 0; i < (0x1 << d->psid_length); i++)
965 {
966 dst = d->rules[i];
967 if (dst.as_u64[0] == 0 && dst.as_u64[1] == 0)
968 continue;
969 s = format (s,
970 " rule psid: %d ip6-dst %U\n", i, format_ip6_address,
971 &dst);
972 }
973 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700974 return s;
975}
976
977static u8 *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700978format_map_ip4_reass (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700979{
980 map_main_t *mm = &map_main;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700981 map_ip4_reass_t *r = va_arg (*args, map_ip4_reass_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700982 map_ip4_reass_key_t *k = &r->key;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700983 f64 now = vlib_time_now (mm->vlib_main);
984 f64 lifetime = (((f64) mm->ip4_reass_conf_lifetime_ms) / 1000);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700985 f64 dt = (r->ts + lifetime > now) ? (r->ts + lifetime - now) : -1;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700986 s = format (s,
987 "ip4-reass src=%U dst=%U protocol=%d identifier=%d port=%d lifetime=%.3lf\n",
988 format_ip4_address, &k->src.as_u8, format_ip4_address,
989 &k->dst.as_u8, k->protocol,
990 clib_net_to_host_u16 (k->fragment_id),
991 (r->port >= 0) ? clib_net_to_host_u16 (r->port) : -1, dt);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700992 return s;
993}
994
995static u8 *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700996format_map_ip6_reass (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700997{
998 map_main_t *mm = &map_main;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -0700999 map_ip6_reass_t *r = va_arg (*args, map_ip6_reass_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001000 map_ip6_reass_key_t *k = &r->key;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001001 f64 now = vlib_time_now (mm->vlib_main);
1002 f64 lifetime = (((f64) mm->ip6_reass_conf_lifetime_ms) / 1000);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001003 f64 dt = (r->ts + lifetime > now) ? (r->ts + lifetime - now) : -1;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001004 s = format (s,
1005 "ip6-reass src=%U dst=%U protocol=%d identifier=%d lifetime=%.3lf\n",
1006 format_ip6_address, &k->src.as_u8, format_ip6_address,
1007 &k->dst.as_u8, k->protocol,
1008 clib_net_to_host_u32 (k->fragment_id), dt);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001009 return s;
1010}
1011
1012static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001013show_map_domain_command_fn (vlib_main_t * vm, unformat_input_t * input,
1014 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001015{
1016 unformat_input_t _line_input, *line_input = &_line_input;
1017 map_main_t *mm = &map_main;
1018 map_domain_t *d;
1019 bool counters = false;
1020 u32 map_domain_index = ~0;
Billy McFalla9a20e72017-02-15 11:39:12 -05001021 clib_error_t *error = NULL;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001022
1023 /* Get a line of input. */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001024 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001025 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001026
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001027 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1028 {
1029 if (unformat (line_input, "counters"))
1030 counters = true;
1031 else if (unformat (line_input, "index %d", &map_domain_index))
1032 ;
1033 else
Billy McFalla9a20e72017-02-15 11:39:12 -05001034 {
1035 error = clib_error_return (0, "unknown input `%U'",
1036 format_unformat_error, line_input);
1037 goto done;
1038 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001039 }
1040
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001041 if (pool_elts (mm->domains) == 0)
1042 vlib_cli_output (vm, "No MAP domains are configured...");
1043
1044 if (map_domain_index == ~0)
1045 {
1046 /* *INDENT-OFF* */
1047 pool_foreach(d, mm->domains, ({vlib_cli_output(vm, "%U", format_map_domain, d, counters);}));
1048 /* *INDENT-ON* */
1049 }
1050 else
1051 {
1052 if (pool_is_free_index (mm->domains, map_domain_index))
1053 {
Billy McFalla9a20e72017-02-15 11:39:12 -05001054 error = clib_error_return (0, "MAP domain does not exists %d",
1055 map_domain_index);
1056 goto done;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001057 }
1058
1059 d = pool_elt_at_index (mm->domains, map_domain_index);
1060 vlib_cli_output (vm, "%U", format_map_domain, d, counters);
1061 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001062
Billy McFalla9a20e72017-02-15 11:39:12 -05001063done:
1064 unformat_free (line_input);
1065
1066 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001067}
1068
1069static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001070show_map_fragments_command_fn (vlib_main_t * vm, unformat_input_t * input,
1071 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001072{
1073 map_main_t *mm = &map_main;
1074 map_ip4_reass_t *f4;
1075 map_ip6_reass_t *f6;
1076
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001077 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001078 pool_foreach(f4, mm->ip4_reass_pool, ({vlib_cli_output (vm, "%U", format_map_ip4_reass, f4);}));
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001079 /* *INDENT-ON* */
1080 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001081 pool_foreach(f6, mm->ip6_reass_pool, ({vlib_cli_output (vm, "%U", format_map_ip6_reass, f6);}));
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001082 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001083 return (0);
1084}
1085
1086u64
1087map_error_counter_get (u32 node_index, map_error_t map_error)
1088{
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001089 vlib_main_t *vm = vlib_get_main ();
1090 vlib_node_runtime_t *error_node = vlib_node_get_runtime (vm, node_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001091 vlib_error_main_t *em = &vm->error_main;
1092 vlib_error_t e = error_node->errors[map_error];
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001093 vlib_node_t *n = vlib_get_node (vm, node_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001094 u32 ci;
1095
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001096 ci = vlib_error_get_code (e);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001097 ASSERT (ci < n->n_errors);
1098 ci += n->error_heap_index;
1099
1100 return (em->counters[ci]);
1101}
1102
1103static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001104show_map_stats_command_fn (vlib_main_t * vm, unformat_input_t * input,
1105 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001106{
1107 map_main_t *mm = &map_main;
1108 map_domain_t *d;
1109 int domains = 0, rules = 0, domaincount = 0, rulecount = 0;
1110 if (pool_elts (mm->domains) == 0)
Ole Troanc08b0962017-06-26 18:12:37 +02001111 {
1112 vlib_cli_output (vm, "No MAP domains are configured...");
1113 return 0;
1114 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001115
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001116 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001117 pool_foreach(d, mm->domains, ({
1118 if (d->rules) {
1119 rulecount+= 0x1 << d->psid_length;
1120 rules += sizeof(ip6_address_t) * 0x1 << d->psid_length;
1121 }
1122 domains += sizeof(*d);
1123 domaincount++;
1124 }));
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001125 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001126
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001127 vlib_cli_output (vm, "MAP domains structure: %d\n", sizeof (map_domain_t));
1128 vlib_cli_output (vm, "MAP domains: %d (%d bytes)\n", domaincount, domains);
1129 vlib_cli_output (vm, "MAP rules: %d (%d bytes)\n", rulecount, rules);
1130 vlib_cli_output (vm, "Total: %d bytes)\n", rules + domains);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001131
1132#if MAP_SKIP_IP6_LOOKUP
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001133 vlib_cli_output (vm,
Neale Ranns80823802017-02-20 18:23:41 -08001134 "MAP pre-resolve: IP6 next-hop: %U, IP4 next-hop: %U\n",
1135 format_map_pre_resolve, &pre_resolved[FIB_PROTOCOL_IP6],
1136 format_map_pre_resolve, &pre_resolved[FIB_PROTOCOL_IP4]);
1137
Ed Warnickecb9cada2015-12-08 15:45:58 -07001138#endif
1139
1140 if (mm->tc_copy)
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001141 vlib_cli_output (vm, "MAP traffic-class: copy");
Ed Warnickecb9cada2015-12-08 15:45:58 -07001142 else
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001143 vlib_cli_output (vm, "MAP traffic-class: %x", mm->tc);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001144
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001145 vlib_cli_output (vm,
1146 "MAP IPv6 inbound security check: %s, fragmented packet security check: %s",
1147 mm->sec_check ? "enabled" : "disabled",
1148 mm->sec_check_frag ? "enabled" : "disabled");
Ed Warnickecb9cada2015-12-08 15:45:58 -07001149
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001150 vlib_cli_output (vm, "ICMP-relay IPv4 source address: %U\n",
1151 format_ip4_address, &mm->icmp4_src_address);
1152 vlib_cli_output (vm, "ICMP6 unreachables sent for unmatched packets: %s\n",
1153 mm->icmp6_enabled ? "enabled" : "disabled");
1154 vlib_cli_output (vm, "Inner fragmentation: %s\n",
1155 mm->frag_inner ? "enabled" : "disabled");
1156 vlib_cli_output (vm, "Fragment packets regardless of DF flag: %s\n",
1157 mm->frag_ignore_df ? "enabled" : "disabled");
Ed Warnickecb9cada2015-12-08 15:45:58 -07001158
1159 /*
1160 * Counters
1161 */
1162 vlib_combined_counter_main_t *cm = mm->domain_counters;
1163 u64 total_pkts[MAP_N_DOMAIN_COUNTER];
1164 u64 total_bytes[MAP_N_DOMAIN_COUNTER];
1165 int which, i;
1166 vlib_counter_t v;
1167
1168 memset (total_pkts, 0, sizeof (total_pkts));
1169 memset (total_bytes, 0, sizeof (total_bytes));
1170
1171 map_domain_counter_lock (mm);
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001172 vec_foreach (cm, mm->domain_counters)
1173 {
Ed Warnickecb9cada2015-12-08 15:45:58 -07001174 which = cm - mm->domain_counters;
1175
Neale Ranns1bd01092017-03-15 15:41:17 -04001176 for (i = 0; i < vlib_combined_counter_n_counters (cm); i++)
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001177 {
1178 vlib_get_combined_counter (cm, i, &v);
1179 total_pkts[which] += v.packets;
1180 total_bytes[which] += v.bytes;
1181 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001182 }
1183 map_domain_counter_unlock (mm);
1184
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001185 vlib_cli_output (vm, "Encapsulated packets: %lld bytes: %lld\n",
1186 total_pkts[MAP_DOMAIN_COUNTER_TX],
1187 total_bytes[MAP_DOMAIN_COUNTER_TX]);
1188 vlib_cli_output (vm, "Decapsulated packets: %lld bytes: %lld\n",
1189 total_pkts[MAP_DOMAIN_COUNTER_RX],
1190 total_bytes[MAP_DOMAIN_COUNTER_RX]);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001191
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001192 vlib_cli_output (vm, "ICMP relayed packets: %d\n",
1193 vlib_get_simple_counter (&mm->icmp_relayed, 0));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001194
1195 return 0;
1196}
1197
1198static clib_error_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001199map_params_reass_command_fn (vlib_main_t * vm, unformat_input_t * input,
1200 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001201{
1202 unformat_input_t _line_input, *line_input = &_line_input;
1203 u32 lifetime = ~0;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001204 f64 ht_ratio = (MAP_IP4_REASS_CONF_HT_RATIO_MAX + 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001205 u32 pool_size = ~0;
1206 u64 buffers = ~(0ull);
1207 u8 ip4 = 0, ip6 = 0;
1208
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001209 if (!unformat_user (input, unformat_line_input, line_input))
1210 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001211
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001212 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1213 {
Ole Troan58a90a42016-08-04 10:19:17 +02001214 if (unformat (line_input, "lifetime %u", &lifetime))
1215 ;
1216 else if (unformat (line_input, "ht-ratio %lf", &ht_ratio))
1217 ;
1218 else if (unformat (line_input, "pool-size %u", &pool_size))
1219 ;
1220 else if (unformat (line_input, "buffers %llu", &buffers))
1221 ;
1222 else if (unformat (line_input, "ip4"))
1223 ip4 = 1;
1224 else if (unformat (line_input, "ip6"))
1225 ip6 = 1;
1226 else
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001227 {
1228 unformat_free (line_input);
1229 return clib_error_return (0, "invalid input");
1230 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001231 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001232 unformat_free (line_input);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001233
1234 if (!ip4 && !ip6)
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001235 return clib_error_return (0, "must specify ip4 and/or ip6");
Ed Warnickecb9cada2015-12-08 15:45:58 -07001236
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001237 if (ip4)
1238 {
1239 if (pool_size != ~0 && pool_size > MAP_IP4_REASS_CONF_POOL_SIZE_MAX)
1240 return clib_error_return (0, "invalid ip4-reass pool-size ( > %d)",
1241 MAP_IP4_REASS_CONF_POOL_SIZE_MAX);
1242 if (ht_ratio != (MAP_IP4_REASS_CONF_HT_RATIO_MAX + 1)
1243 && ht_ratio > MAP_IP4_REASS_CONF_HT_RATIO_MAX)
1244 return clib_error_return (0, "invalid ip4-reass ht-ratio ( > %d)",
1245 MAP_IP4_REASS_CONF_HT_RATIO_MAX);
1246 if (lifetime != ~0 && lifetime > MAP_IP4_REASS_CONF_LIFETIME_MAX)
1247 return clib_error_return (0, "invalid ip4-reass lifetime ( > %d)",
1248 MAP_IP4_REASS_CONF_LIFETIME_MAX);
1249 if (buffers != ~(0ull) && buffers > MAP_IP4_REASS_CONF_BUFFERS_MAX)
1250 return clib_error_return (0, "invalid ip4-reass buffers ( > %ld)",
1251 MAP_IP4_REASS_CONF_BUFFERS_MAX);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001252 }
1253
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001254 if (ip6)
1255 {
1256 if (pool_size != ~0 && pool_size > MAP_IP6_REASS_CONF_POOL_SIZE_MAX)
1257 return clib_error_return (0, "invalid ip6-reass pool-size ( > %d)",
1258 MAP_IP6_REASS_CONF_POOL_SIZE_MAX);
1259 if (ht_ratio != (MAP_IP4_REASS_CONF_HT_RATIO_MAX + 1)
1260 && ht_ratio > MAP_IP6_REASS_CONF_HT_RATIO_MAX)
1261 return clib_error_return (0, "invalid ip6-reass ht-log2len ( > %d)",
1262 MAP_IP6_REASS_CONF_HT_RATIO_MAX);
1263 if (lifetime != ~0 && lifetime > MAP_IP6_REASS_CONF_LIFETIME_MAX)
1264 return clib_error_return (0, "invalid ip6-reass lifetime ( > %d)",
1265 MAP_IP6_REASS_CONF_LIFETIME_MAX);
1266 if (buffers != ~(0ull) && buffers > MAP_IP6_REASS_CONF_BUFFERS_MAX)
1267 return clib_error_return (0, "invalid ip6-reass buffers ( > %ld)",
1268 MAP_IP6_REASS_CONF_BUFFERS_MAX);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001269 }
1270
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001271 if (ip4)
1272 {
1273 u32 reass = 0, packets = 0;
1274 if (pool_size != ~0)
1275 {
1276 if (map_ip4_reass_conf_pool_size (pool_size, &reass, &packets))
1277 {
1278 vlib_cli_output (vm, "Could not set ip4-reass pool-size");
1279 }
1280 else
1281 {
1282 vlib_cli_output (vm,
1283 "Setting ip4-reass pool-size (destroyed-reassembly=%u , dropped-fragments=%u)",
1284 reass, packets);
1285 }
1286 }
1287 if (ht_ratio != (MAP_IP4_REASS_CONF_HT_RATIO_MAX + 1))
1288 {
1289 if (map_ip4_reass_conf_ht_ratio (ht_ratio, &reass, &packets))
1290 {
1291 vlib_cli_output (vm, "Could not set ip4-reass ht-log2len");
1292 }
1293 else
1294 {
1295 vlib_cli_output (vm,
1296 "Setting ip4-reass ht-log2len (destroyed-reassembly=%u , dropped-fragments=%u)",
1297 reass, packets);
1298 }
1299 }
1300 if (lifetime != ~0)
1301 {
1302 if (map_ip4_reass_conf_lifetime (lifetime))
1303 vlib_cli_output (vm, "Could not set ip4-reass lifetime");
1304 else
1305 vlib_cli_output (vm, "Setting ip4-reass lifetime");
1306 }
1307 if (buffers != ~(0ull))
1308 {
1309 if (map_ip4_reass_conf_buffers (buffers))
1310 vlib_cli_output (vm, "Could not set ip4-reass buffers");
1311 else
1312 vlib_cli_output (vm, "Setting ip4-reass buffers");
1313 }
1314
1315 if (map_main.ip4_reass_conf_buffers >
1316 map_main.ip4_reass_conf_pool_size *
1317 MAP_IP4_REASS_MAX_FRAGMENTS_PER_REASSEMBLY)
1318 {
1319 vlib_cli_output (vm,
1320 "Note: 'ip4-reass buffers' > pool-size * max-fragments-per-reassembly.");
1321 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001322 }
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001323
1324 if (ip6)
1325 {
1326 u32 reass = 0, packets = 0;
1327 if (pool_size != ~0)
1328 {
1329 if (map_ip6_reass_conf_pool_size (pool_size, &reass, &packets))
1330 {
1331 vlib_cli_output (vm, "Could not set ip6-reass pool-size");
1332 }
1333 else
1334 {
1335 vlib_cli_output (vm,
1336 "Setting ip6-reass pool-size (destroyed-reassembly=%u , dropped-fragments=%u)",
1337 reass, packets);
1338 }
1339 }
1340 if (ht_ratio != (MAP_IP4_REASS_CONF_HT_RATIO_MAX + 1))
1341 {
1342 if (map_ip6_reass_conf_ht_ratio (ht_ratio, &reass, &packets))
1343 {
1344 vlib_cli_output (vm, "Could not set ip6-reass ht-log2len");
1345 }
1346 else
1347 {
1348 vlib_cli_output (vm,
1349 "Setting ip6-reass ht-log2len (destroyed-reassembly=%u , dropped-fragments=%u)",
1350 reass, packets);
1351 }
1352 }
1353 if (lifetime != ~0)
1354 {
1355 if (map_ip6_reass_conf_lifetime (lifetime))
1356 vlib_cli_output (vm, "Could not set ip6-reass lifetime");
1357 else
1358 vlib_cli_output (vm, "Setting ip6-reass lifetime");
1359 }
1360 if (buffers != ~(0ull))
1361 {
1362 if (map_ip6_reass_conf_buffers (buffers))
1363 vlib_cli_output (vm, "Could not set ip6-reass buffers");
1364 else
1365 vlib_cli_output (vm, "Setting ip6-reass buffers");
1366 }
1367
1368 if (map_main.ip6_reass_conf_buffers >
1369 map_main.ip6_reass_conf_pool_size *
1370 MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY)
1371 {
1372 vlib_cli_output (vm,
1373 "Note: 'ip6-reass buffers' > pool-size * max-fragments-per-reassembly.");
1374 }
1375 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001376
1377 return 0;
1378}
1379
1380
1381/*
1382 * packet trace format function
1383 */
1384u8 *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001385format_map_trace (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001386{
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001387 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1388 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001389 map_trace_t *t = va_arg (*args, map_trace_t *);
1390 u32 map_domain_index = t->map_domain_index;
1391 u16 port = t->port;
1392
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001393 s =
1394 format (s, "MAP domain index: %d L4 port: %u", map_domain_index,
1395 clib_net_to_host_u16 (port));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001396
1397 return s;
1398}
1399
1400static_always_inline map_ip4_reass_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001401map_ip4_reass_lookup (map_ip4_reass_key_t * k, u32 bucket, f64 now)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001402{
1403 map_main_t *mm = &map_main;
1404 u32 ri = mm->ip4_reass_hash_table[bucket];
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001405 while (ri != MAP_REASS_INDEX_NONE)
1406 {
1407 map_ip4_reass_t *r = pool_elt_at_index (mm->ip4_reass_pool, ri);
1408 if (r->key.as_u64[0] == k->as_u64[0] &&
1409 r->key.as_u64[1] == k->as_u64[1] &&
1410 now < r->ts + (((f64) mm->ip4_reass_conf_lifetime_ms) / 1000))
1411 {
1412 return r;
1413 }
1414 ri = r->bucket_next;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001415 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001416 return NULL;
1417}
1418
1419#define map_ip4_reass_pool_index(r) (r - map_main.ip4_reass_pool)
1420
1421void
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001422map_ip4_reass_free (map_ip4_reass_t * r, u32 ** pi_to_drop)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001423{
1424 map_main_t *mm = &map_main;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001425 map_ip4_reass_get_fragments (r, pi_to_drop);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001426
1427 // Unlink in hash bucket
1428 map_ip4_reass_t *r2 = NULL;
1429 u32 r2i = mm->ip4_reass_hash_table[r->bucket];
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001430 while (r2i != map_ip4_reass_pool_index (r))
1431 {
1432 ASSERT (r2i != MAP_REASS_INDEX_NONE);
1433 r2 = pool_elt_at_index (mm->ip4_reass_pool, r2i);
1434 r2i = r2->bucket_next;
1435 }
1436 if (r2)
1437 {
1438 r2->bucket_next = r->bucket_next;
1439 }
1440 else
1441 {
1442 mm->ip4_reass_hash_table[r->bucket] = r->bucket_next;
1443 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001444
1445 // Unlink in list
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001446 if (r->fifo_next == map_ip4_reass_pool_index (r))
1447 {
1448 mm->ip4_reass_fifo_last = MAP_REASS_INDEX_NONE;
1449 }
1450 else
1451 {
1452 if (mm->ip4_reass_fifo_last == map_ip4_reass_pool_index (r))
1453 mm->ip4_reass_fifo_last = r->fifo_prev;
1454 pool_elt_at_index (mm->ip4_reass_pool, r->fifo_prev)->fifo_next =
1455 r->fifo_next;
1456 pool_elt_at_index (mm->ip4_reass_pool, r->fifo_next)->fifo_prev =
1457 r->fifo_prev;
1458 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001459
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001460 pool_put (mm->ip4_reass_pool, r);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001461 mm->ip4_reass_allocated--;
1462}
1463
1464map_ip4_reass_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001465map_ip4_reass_get (u32 src, u32 dst, u16 fragment_id,
1466 u8 protocol, u32 ** pi_to_drop)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001467{
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001468 map_ip4_reass_t *r;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001469 map_main_t *mm = &map_main;
1470 map_ip4_reass_key_t k = {.src.data_u32 = src,
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001471 .dst.data_u32 = dst,
1472 .fragment_id = fragment_id,
1473 .protocol = protocol
1474 };
Ed Warnickecb9cada2015-12-08 15:45:58 -07001475
1476 u32 h = 0;
Christophe Fontaineb4bd28a2017-05-31 11:27:19 +02001477#ifdef clib_crc32c_uses_intrinsics
1478 h = clib_crc32c ((u8 *) k.as_u32, 16);
1479#else
1480 u64 tmp = k.as_u32[0] ^ k.as_u32[1] ^ k.as_u32[2] ^ k.as_u32[3];
1481 h = clib_xxhash (tmp);
1482#endif
Ed Warnickecb9cada2015-12-08 15:45:58 -07001483 h = h >> (32 - mm->ip4_reass_ht_log2len);
1484
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001485 f64 now = vlib_time_now (mm->vlib_main);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001486
1487 //Cache garbage collection
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001488 while (mm->ip4_reass_fifo_last != MAP_REASS_INDEX_NONE)
1489 {
1490 map_ip4_reass_t *last =
1491 pool_elt_at_index (mm->ip4_reass_pool, mm->ip4_reass_fifo_last);
1492 if (last->ts + (((f64) mm->ip4_reass_conf_lifetime_ms) / 1000) < now)
1493 map_ip4_reass_free (last, pi_to_drop);
1494 else
1495 break;
1496 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001497
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001498 if ((r = map_ip4_reass_lookup (&k, h, now)))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001499 return r;
1500
1501 if (mm->ip4_reass_allocated >= mm->ip4_reass_conf_pool_size)
1502 return NULL;
1503
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001504 pool_get (mm->ip4_reass_pool, r);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001505 mm->ip4_reass_allocated++;
1506 int i;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001507 for (i = 0; i < MAP_IP4_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001508 r->fragments[i] = ~0;
1509
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001510 u32 ri = map_ip4_reass_pool_index (r);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001511
1512 //Link in new bucket
1513 r->bucket = h;
1514 r->bucket_next = mm->ip4_reass_hash_table[h];
1515 mm->ip4_reass_hash_table[h] = ri;
1516
1517 //Link in fifo
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001518 if (mm->ip4_reass_fifo_last != MAP_REASS_INDEX_NONE)
1519 {
1520 r->fifo_next =
1521 pool_elt_at_index (mm->ip4_reass_pool,
1522 mm->ip4_reass_fifo_last)->fifo_next;
1523 r->fifo_prev = mm->ip4_reass_fifo_last;
1524 pool_elt_at_index (mm->ip4_reass_pool, r->fifo_prev)->fifo_next = ri;
1525 pool_elt_at_index (mm->ip4_reass_pool, r->fifo_next)->fifo_prev = ri;
1526 }
1527 else
1528 {
1529 r->fifo_next = r->fifo_prev = ri;
1530 mm->ip4_reass_fifo_last = ri;
1531 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001532
1533 //Set other fields
1534 r->ts = now;
1535 r->key = k;
1536 r->port = -1;
1537#ifdef MAP_IP4_REASS_COUNT_BYTES
1538 r->expected_total = 0xffff;
1539 r->forwarded = 0;
1540#endif
1541
1542 return r;
1543}
1544
1545int
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001546map_ip4_reass_add_fragment (map_ip4_reass_t * r, u32 pi)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001547{
1548 if (map_main.ip4_reass_buffered_counter >= map_main.ip4_reass_conf_buffers)
1549 return -1;
1550
1551 int i;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001552 for (i = 0; i < MAP_IP4_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
1553 if (r->fragments[i] == ~0)
1554 {
1555 r->fragments[i] = pi;
1556 map_main.ip4_reass_buffered_counter++;
1557 return 0;
1558 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001559 return -1;
1560}
1561
1562static_always_inline map_ip6_reass_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001563map_ip6_reass_lookup (map_ip6_reass_key_t * k, u32 bucket, f64 now)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001564{
1565 map_main_t *mm = &map_main;
1566 u32 ri = mm->ip6_reass_hash_table[bucket];
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001567 while (ri != MAP_REASS_INDEX_NONE)
1568 {
1569 map_ip6_reass_t *r = pool_elt_at_index (mm->ip6_reass_pool, ri);
1570 if (now < r->ts + (((f64) mm->ip6_reass_conf_lifetime_ms) / 1000) &&
1571 r->key.as_u64[0] == k->as_u64[0] &&
1572 r->key.as_u64[1] == k->as_u64[1] &&
1573 r->key.as_u64[2] == k->as_u64[2] &&
1574 r->key.as_u64[3] == k->as_u64[3] &&
1575 r->key.as_u64[4] == k->as_u64[4])
1576 return r;
1577 ri = r->bucket_next;
1578 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001579 return NULL;
1580}
1581
1582#define map_ip6_reass_pool_index(r) (r - map_main.ip6_reass_pool)
1583
1584void
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001585map_ip6_reass_free (map_ip6_reass_t * r, u32 ** pi_to_drop)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001586{
1587 map_main_t *mm = &map_main;
1588 int i;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001589 for (i = 0; i < MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
1590 if (r->fragments[i].pi != ~0)
1591 {
1592 vec_add1 (*pi_to_drop, r->fragments[i].pi);
1593 r->fragments[i].pi = ~0;
1594 map_main.ip6_reass_buffered_counter--;
1595 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001596
1597 // Unlink in hash bucket
1598 map_ip6_reass_t *r2 = NULL;
1599 u32 r2i = mm->ip6_reass_hash_table[r->bucket];
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001600 while (r2i != map_ip6_reass_pool_index (r))
1601 {
1602 ASSERT (r2i != MAP_REASS_INDEX_NONE);
1603 r2 = pool_elt_at_index (mm->ip6_reass_pool, r2i);
1604 r2i = r2->bucket_next;
1605 }
1606 if (r2)
1607 {
1608 r2->bucket_next = r->bucket_next;
1609 }
1610 else
1611 {
1612 mm->ip6_reass_hash_table[r->bucket] = r->bucket_next;
1613 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001614
1615 // Unlink in list
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001616 if (r->fifo_next == map_ip6_reass_pool_index (r))
1617 {
1618 //Single element in the list, list is now empty
1619 mm->ip6_reass_fifo_last = MAP_REASS_INDEX_NONE;
1620 }
1621 else
1622 {
1623 if (mm->ip6_reass_fifo_last == map_ip6_reass_pool_index (r)) //First element
1624 mm->ip6_reass_fifo_last = r->fifo_prev;
1625 pool_elt_at_index (mm->ip6_reass_pool, r->fifo_prev)->fifo_next =
1626 r->fifo_next;
1627 pool_elt_at_index (mm->ip6_reass_pool, r->fifo_next)->fifo_prev =
1628 r->fifo_prev;
1629 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001630
1631 // Free from pool if necessary
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001632 pool_put (mm->ip6_reass_pool, r);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001633 mm->ip6_reass_allocated--;
1634}
1635
1636map_ip6_reass_t *
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001637map_ip6_reass_get (ip6_address_t * src, ip6_address_t * dst, u32 fragment_id,
1638 u8 protocol, u32 ** pi_to_drop)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001639{
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001640 map_ip6_reass_t *r;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001641 map_main_t *mm = &map_main;
1642 map_ip6_reass_key_t k = {
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001643 .src = *src,
1644 .dst = *dst,
1645 .fragment_id = fragment_id,
1646 .protocol = protocol
1647 };
Ed Warnickecb9cada2015-12-08 15:45:58 -07001648
1649 u32 h = 0;
1650 int i;
Christophe Fontaineb4bd28a2017-05-31 11:27:19 +02001651
1652#ifdef clib_crc32c_uses_intrinsics
1653 h = clib_crc32c ((u8 *) k.as_u32, 40);
1654#else
1655 u64 tmp =
1656 k.as_u64[0] ^ k.as_u64[1] ^ k.as_u64[2] ^ k.as_u64[3] ^ k.as_u64[4];
1657 h = clib_xxhash (tmp);
1658#endif
1659
Ed Warnickecb9cada2015-12-08 15:45:58 -07001660 h = h >> (32 - mm->ip6_reass_ht_log2len);
1661
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001662 f64 now = vlib_time_now (mm->vlib_main);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001663
1664 //Cache garbage collection
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001665 while (mm->ip6_reass_fifo_last != MAP_REASS_INDEX_NONE)
1666 {
1667 map_ip6_reass_t *last =
1668 pool_elt_at_index (mm->ip6_reass_pool, mm->ip6_reass_fifo_last);
1669 if (last->ts + (((f64) mm->ip6_reass_conf_lifetime_ms) / 1000) < now)
1670 map_ip6_reass_free (last, pi_to_drop);
1671 else
1672 break;
1673 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001674
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001675 if ((r = map_ip6_reass_lookup (&k, h, now)))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001676 return r;
1677
1678 if (mm->ip6_reass_allocated >= mm->ip6_reass_conf_pool_size)
1679 return NULL;
1680
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001681 pool_get (mm->ip6_reass_pool, r);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001682 mm->ip6_reass_allocated++;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001683 for (i = 0; i < MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
1684 {
1685 r->fragments[i].pi = ~0;
1686 r->fragments[i].next_data_len = 0;
1687 r->fragments[i].next_data_offset = 0;
1688 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001689
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001690 u32 ri = map_ip6_reass_pool_index (r);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001691
1692 //Link in new bucket
1693 r->bucket = h;
1694 r->bucket_next = mm->ip6_reass_hash_table[h];
1695 mm->ip6_reass_hash_table[h] = ri;
1696
1697 //Link in fifo
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001698 if (mm->ip6_reass_fifo_last != MAP_REASS_INDEX_NONE)
1699 {
1700 r->fifo_next =
1701 pool_elt_at_index (mm->ip6_reass_pool,
1702 mm->ip6_reass_fifo_last)->fifo_next;
1703 r->fifo_prev = mm->ip6_reass_fifo_last;
1704 pool_elt_at_index (mm->ip6_reass_pool, r->fifo_prev)->fifo_next = ri;
1705 pool_elt_at_index (mm->ip6_reass_pool, r->fifo_next)->fifo_prev = ri;
1706 }
1707 else
1708 {
1709 r->fifo_next = r->fifo_prev = ri;
1710 mm->ip6_reass_fifo_last = ri;
1711 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001712
1713 //Set other fields
1714 r->ts = now;
1715 r->key = k;
1716 r->ip4_header.ip_version_and_header_length = 0;
1717#ifdef MAP_IP6_REASS_COUNT_BYTES
1718 r->expected_total = 0xffff;
1719 r->forwarded = 0;
1720#endif
1721 return r;
1722}
1723
1724int
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001725map_ip6_reass_add_fragment (map_ip6_reass_t * r, u32 pi,
1726 u16 data_offset, u16 next_data_offset,
1727 u8 * data_start, u16 data_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001728{
1729 map_ip6_fragment_t *f = NULL, *prev_f = NULL;
1730 u16 copied_len = (data_len > 20) ? 20 : data_len;
1731
1732 if (map_main.ip6_reass_buffered_counter >= map_main.ip6_reass_conf_buffers)
1733 return -1;
1734
1735 //Lookup for fragments for the current buffer
1736 //and the one before that
1737 int i;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001738 for (i = 0; i < MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
1739 {
1740 if (data_offset && r->fragments[i].next_data_offset == data_offset)
1741 {
1742 prev_f = &r->fragments[i]; // This is buffer for previous packet
1743 }
1744 else if (r->fragments[i].next_data_offset == next_data_offset)
1745 {
1746 f = &r->fragments[i]; // This is a buffer for the current packet
1747 }
1748 else if (r->fragments[i].next_data_offset == 0)
1749 { //Available
1750 if (f == NULL)
1751 f = &r->fragments[i];
1752 else if (prev_f == NULL)
1753 prev_f = &r->fragments[i];
1754 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001755 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001756
1757 if (!f || f->pi != ~0)
1758 return -1;
1759
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001760 if (data_offset)
1761 {
1762 if (!prev_f)
1763 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001764
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001765 clib_memcpy (prev_f->next_data, data_start, copied_len);
1766 prev_f->next_data_len = copied_len;
1767 prev_f->next_data_offset = data_offset;
1768 }
1769 else
1770 {
1771 if (((ip4_header_t *) data_start)->ip_version_and_header_length != 0x45)
1772 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001773
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001774 if (r->ip4_header.ip_version_and_header_length == 0)
1775 clib_memcpy (&r->ip4_header, data_start, sizeof (ip4_header_t));
1776 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001777
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001778 if (data_len > 20)
1779 {
1780 f->next_data_offset = next_data_offset;
1781 f->pi = pi;
1782 map_main.ip6_reass_buffered_counter++;
1783 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001784 return 0;
1785}
1786
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001787void
1788map_ip4_reass_reinit (u32 * trashed_reass, u32 * dropped_packets)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001789{
1790 map_main_t *mm = &map_main;
1791 int i;
1792
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001793 if (dropped_packets)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001794 *dropped_packets = mm->ip4_reass_buffered_counter;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001795 if (trashed_reass)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001796 *trashed_reass = mm->ip4_reass_allocated;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001797 if (mm->ip4_reass_fifo_last != MAP_REASS_INDEX_NONE)
1798 {
1799 u16 ri = mm->ip4_reass_fifo_last;
1800 do
1801 {
1802 map_ip4_reass_t *r = pool_elt_at_index (mm->ip4_reass_pool, ri);
1803 for (i = 0; i < MAP_IP4_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
1804 if (r->fragments[i] != ~0)
1805 map_ip4_drop_pi (r->fragments[i]);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001806
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001807 ri = r->fifo_next;
1808 pool_put (mm->ip4_reass_pool, r);
1809 }
1810 while (ri != mm->ip4_reass_fifo_last);
1811 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001812
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001813 vec_free (mm->ip4_reass_hash_table);
1814 vec_resize (mm->ip4_reass_hash_table, 1 << mm->ip4_reass_ht_log2len);
1815 for (i = 0; i < (1 << mm->ip4_reass_ht_log2len); i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001816 mm->ip4_reass_hash_table[i] = MAP_REASS_INDEX_NONE;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001817 pool_free (mm->ip4_reass_pool);
1818 pool_alloc (mm->ip4_reass_pool, mm->ip4_reass_conf_pool_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001819
1820 mm->ip4_reass_allocated = 0;
1821 mm->ip4_reass_fifo_last = MAP_REASS_INDEX_NONE;
1822 mm->ip4_reass_buffered_counter = 0;
1823}
1824
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001825u8
1826map_get_ht_log2len (f32 ht_ratio, u16 pool_size)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001827{
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001828 u32 desired_size = (u32) (pool_size * ht_ratio);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001829 u8 i;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001830 for (i = 1; i < 31; i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001831 if ((1 << i) >= desired_size)
1832 return i;
1833 return 4;
1834}
1835
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001836int
1837map_ip4_reass_conf_ht_ratio (f32 ht_ratio, u32 * trashed_reass,
1838 u32 * dropped_packets)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001839{
1840 map_main_t *mm = &map_main;
1841 if (ht_ratio > MAP_IP4_REASS_CONF_HT_RATIO_MAX)
1842 return -1;
1843
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001844 map_ip4_reass_lock ();
Ed Warnickecb9cada2015-12-08 15:45:58 -07001845 mm->ip4_reass_conf_ht_ratio = ht_ratio;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001846 mm->ip4_reass_ht_log2len =
1847 map_get_ht_log2len (ht_ratio, mm->ip4_reass_conf_pool_size);
1848 map_ip4_reass_reinit (trashed_reass, dropped_packets);
1849 map_ip4_reass_unlock ();
Ed Warnickecb9cada2015-12-08 15:45:58 -07001850 return 0;
1851}
1852
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001853int
1854map_ip4_reass_conf_pool_size (u16 pool_size, u32 * trashed_reass,
1855 u32 * dropped_packets)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001856{
1857 map_main_t *mm = &map_main;
1858 if (pool_size > MAP_IP4_REASS_CONF_POOL_SIZE_MAX)
1859 return -1;
1860
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001861 map_ip4_reass_lock ();
Ed Warnickecb9cada2015-12-08 15:45:58 -07001862 mm->ip4_reass_conf_pool_size = pool_size;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001863 map_ip4_reass_reinit (trashed_reass, dropped_packets);
1864 map_ip4_reass_unlock ();
Ed Warnickecb9cada2015-12-08 15:45:58 -07001865 return 0;
1866}
1867
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001868int
1869map_ip4_reass_conf_lifetime (u16 lifetime_ms)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001870{
1871 map_main.ip4_reass_conf_lifetime_ms = lifetime_ms;
1872 return 0;
1873}
1874
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001875int
1876map_ip4_reass_conf_buffers (u32 buffers)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001877{
1878 map_main.ip4_reass_conf_buffers = buffers;
1879 return 0;
1880}
1881
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001882void
1883map_ip6_reass_reinit (u32 * trashed_reass, u32 * dropped_packets)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001884{
1885 map_main_t *mm = &map_main;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001886 if (dropped_packets)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001887 *dropped_packets = mm->ip6_reass_buffered_counter;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001888 if (trashed_reass)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001889 *trashed_reass = mm->ip6_reass_allocated;
1890 int i;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001891 if (mm->ip6_reass_fifo_last != MAP_REASS_INDEX_NONE)
1892 {
1893 u16 ri = mm->ip6_reass_fifo_last;
1894 do
1895 {
1896 map_ip6_reass_t *r = pool_elt_at_index (mm->ip6_reass_pool, ri);
1897 for (i = 0; i < MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
1898 if (r->fragments[i].pi != ~0)
1899 map_ip6_drop_pi (r->fragments[i].pi);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001900
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001901 ri = r->fifo_next;
1902 pool_put (mm->ip6_reass_pool, r);
1903 }
1904 while (ri != mm->ip6_reass_fifo_last);
1905 mm->ip6_reass_fifo_last = MAP_REASS_INDEX_NONE;
1906 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001907
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001908 vec_free (mm->ip6_reass_hash_table);
1909 vec_resize (mm->ip6_reass_hash_table, 1 << mm->ip6_reass_ht_log2len);
1910 for (i = 0; i < (1 << mm->ip6_reass_ht_log2len); i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001911 mm->ip6_reass_hash_table[i] = MAP_REASS_INDEX_NONE;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001912 pool_free (mm->ip6_reass_pool);
1913 pool_alloc (mm->ip6_reass_pool, mm->ip4_reass_conf_pool_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001914
1915 mm->ip6_reass_allocated = 0;
1916 mm->ip6_reass_buffered_counter = 0;
1917}
1918
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001919int
1920map_ip6_reass_conf_ht_ratio (f32 ht_ratio, u32 * trashed_reass,
1921 u32 * dropped_packets)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001922{
1923 map_main_t *mm = &map_main;
1924 if (ht_ratio > MAP_IP6_REASS_CONF_HT_RATIO_MAX)
1925 return -1;
1926
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001927 map_ip6_reass_lock ();
Ed Warnickecb9cada2015-12-08 15:45:58 -07001928 mm->ip6_reass_conf_ht_ratio = ht_ratio;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001929 mm->ip6_reass_ht_log2len =
1930 map_get_ht_log2len (ht_ratio, mm->ip6_reass_conf_pool_size);
1931 map_ip6_reass_reinit (trashed_reass, dropped_packets);
1932 map_ip6_reass_unlock ();
Ed Warnickecb9cada2015-12-08 15:45:58 -07001933 return 0;
1934}
1935
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001936int
1937map_ip6_reass_conf_pool_size (u16 pool_size, u32 * trashed_reass,
1938 u32 * dropped_packets)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001939{
1940 map_main_t *mm = &map_main;
1941 if (pool_size > MAP_IP6_REASS_CONF_POOL_SIZE_MAX)
1942 return -1;
1943
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001944 map_ip6_reass_lock ();
Ed Warnickecb9cada2015-12-08 15:45:58 -07001945 mm->ip6_reass_conf_pool_size = pool_size;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001946 map_ip6_reass_reinit (trashed_reass, dropped_packets);
1947 map_ip6_reass_unlock ();
Ed Warnickecb9cada2015-12-08 15:45:58 -07001948 return 0;
1949}
1950
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001951int
1952map_ip6_reass_conf_lifetime (u16 lifetime_ms)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001953{
1954 map_main.ip6_reass_conf_lifetime_ms = lifetime_ms;
1955 return 0;
1956}
1957
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001958int
1959map_ip6_reass_conf_buffers (u32 buffers)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001960{
1961 map_main.ip6_reass_conf_buffers = buffers;
1962 return 0;
1963}
1964
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07001965/* *INDENT-OFF* */
Ole Troan96eefd42016-09-12 12:25:30 +02001966
1967/*?
1968 * Configure MAP reassembly behaviour
1969 *
1970 * @cliexpar
1971 * @cliexstart{map params reassembly}
1972 * @cliexend
1973 ?*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07001974VLIB_CLI_COMMAND(map_ip4_reass_lifetime_command, static) = {
1975 .path = "map params reassembly",
Ole Troan96eefd42016-09-12 12:25:30 +02001976 .short_help = "map params reassembly [ip4 | ip6] [lifetime <lifetime-ms>] "
1977 "[pool-size <pool-size>] [buffers <buffers>] "
1978 "[ht-ratio <ht-ratio>]",
Ed Warnickecb9cada2015-12-08 15:45:58 -07001979 .function = map_params_reass_command_fn,
1980};
1981
Ole Troan96eefd42016-09-12 12:25:30 +02001982/*?
1983 * Set or copy the IP TOS/Traffic Class field
1984 *
1985 * @cliexpar
1986 * @cliexstart{map params traffic-class}
1987 *
1988 * This command is used to set the traffic-class field in translated
1989 * or encapsulated packets. If copy is specifed (the default) then the
1990 * traffic-class/TOS field is copied from the original packet to the
1991 * translated / encapsulating header.
1992 * @cliexend
1993 ?*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07001994VLIB_CLI_COMMAND(map_traffic_class_command, static) = {
1995 .path = "map params traffic-class",
Ole Troan96eefd42016-09-12 12:25:30 +02001996 .short_help = "map params traffic-class {0x0-0xff | copy}",
Ed Warnickecb9cada2015-12-08 15:45:58 -07001997 .function = map_traffic_class_command_fn,
1998};
1999
Ole Troan96eefd42016-09-12 12:25:30 +02002000/*?
2001 * Bypass IP4/IP6 lookup
2002 *
2003 * @cliexpar
2004 * @cliexstart{map params pre-resolve}
2005 *
2006 * Bypass a second FIB lookup of the translated or encapsulated
2007 * packet, and forward the packet directly to the specified
2008 * next-hop. This optimization trades forwarding flexibility for
2009 * performance.
2010 * @cliexend
2011 ?*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07002012VLIB_CLI_COMMAND(map_pre_resolve_command, static) = {
2013 .path = "map params pre-resolve",
Ole Troan96eefd42016-09-12 12:25:30 +02002014 .short_help = " map params pre-resolve {ip4-nh <address>} "
2015 "| {ip6-nh <address>}",
Ed Warnickecb9cada2015-12-08 15:45:58 -07002016 .function = map_pre_resolve_command_fn,
2017};
2018
Ole Troan96eefd42016-09-12 12:25:30 +02002019/*?
2020 * Enable or disable the MAP-E inbound security check
2021 *
2022 * @cliexpar
2023 * @cliexstart{map params security-check}
2024 *
2025 * By default, a decapsulated packet's IPv4 source address will be
2026 * verified against the outer header's IPv6 source address. Disabling
2027 * this feature will allow IPv4 source address spoofing.
2028 * @cliexend
2029 ?*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07002030VLIB_CLI_COMMAND(map_security_check_command, static) = {
2031 .path = "map params security-check",
Ole Troan96eefd42016-09-12 12:25:30 +02002032 .short_help = "map params security-check on|off",
Ed Warnickecb9cada2015-12-08 15:45:58 -07002033 .function = map_security_check_command_fn,
2034};
2035
Ole Troan96eefd42016-09-12 12:25:30 +02002036/*?
2037 * Specifiy the IPv4 source address used for relayed ICMP error messages
2038 *
2039 * @cliexpar
2040 * @cliexstart{map params icmp source-address}
2041 *
2042 * This command specifies which IPv4 source address (must be local to
2043 * the system), that is used for relayed received IPv6 ICMP error
2044 * messages.
2045 * @cliexend
2046 ?*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07002047VLIB_CLI_COMMAND(map_icmp_relay_source_address_command, static) = {
Ole Troancda94822016-01-07 14:37:25 +01002048 .path = "map params icmp source-address",
Ole Troan96eefd42016-09-12 12:25:30 +02002049 .short_help = "map params icmp source-address <ip4-address>",
Ed Warnickecb9cada2015-12-08 15:45:58 -07002050 .function = map_icmp_relay_source_address_command_fn,
2051};
2052
Ole Troan96eefd42016-09-12 12:25:30 +02002053/*?
2054 * Send IPv6 ICMP unreachables
2055 *
2056 * @cliexpar
2057 * @cliexstart{map params icmp6 unreachables}
2058 *
2059 * Send IPv6 ICMP unreachable messages back if security check fails or
2060 * no MAP domain exists.
2061 * @cliexend
2062 ?*/
Ole Troancda94822016-01-07 14:37:25 +01002063VLIB_CLI_COMMAND(map_icmp_unreachables_command, static) = {
Ole Troan9fb87552016-01-13 22:30:43 +01002064 .path = "map params icmp6 unreachables",
Ole Troan96eefd42016-09-12 12:25:30 +02002065 .short_help = "map params icmp6 unreachables {on|off}",
Ole Troancda94822016-01-07 14:37:25 +01002066 .function = map_icmp_unreachables_command_fn,
2067};
2068
Ole Troan96eefd42016-09-12 12:25:30 +02002069/*?
2070 * Configure MAP fragmentation behaviour
2071 *
2072 * @cliexpar
2073 * @cliexstart{map params fragment}
2074 * @cliexend
2075 ?*/
Ole Troan9fb87552016-01-13 22:30:43 +01002076VLIB_CLI_COMMAND(map_fragment_command, static) = {
2077 .path = "map params fragment",
Ole Troan96eefd42016-09-12 12:25:30 +02002078 .short_help = "map params fragment inner|outer",
Ole Troan9fb87552016-01-13 22:30:43 +01002079 .function = map_fragment_command_fn,
2080};
2081
Ole Troan96eefd42016-09-12 12:25:30 +02002082/*?
2083 * Ignore the IPv4 Don't fragment bit
2084 *
2085 * @cliexpar
2086 * @cliexstart{map params fragment ignore-df}
2087 *
2088 * Allows fragmentation of the IPv4 packet even if the DF bit is
2089 * set. The choice between inner or outer fragmentation of tunnel
2090 * packets is complicated. The benefit of inner fragmentation is that
2091 * the ultimate endpoint must reassemble, instead of the tunnel
2092 * endpoint.
2093 * @cliexend
2094 ?*/
Ole Troan9fb87552016-01-13 22:30:43 +01002095VLIB_CLI_COMMAND(map_fragment_df_command, static) = {
2096 .path = "map params fragment ignore-df",
Ole Troan96eefd42016-09-12 12:25:30 +02002097 .short_help = "map params fragment ignore-df on|off",
Ole Troan9fb87552016-01-13 22:30:43 +01002098 .function = map_fragment_df_command_fn,
2099};
2100
Ole Troan96eefd42016-09-12 12:25:30 +02002101/*?
2102 * Specifiy if the inbound security check should be done on fragments
2103 *
2104 * @cliexpar
2105 * @cliexstart{map params security-check fragments}
2106 *
2107 * Typically the inbound on-decapsulation security check is only done
2108 * on the first packet. The packet that contains the L4
2109 * information. While a security check on every fragment is possible,
2110 * it has a cost. State must be created on the first fragment.
2111 * @cliexend
2112 ?*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07002113VLIB_CLI_COMMAND(map_security_check_frag_command, static) = {
2114 .path = "map params security-check fragments",
Ole Troan96eefd42016-09-12 12:25:30 +02002115 .short_help = "map params security-check fragments on|off",
Ed Warnickecb9cada2015-12-08 15:45:58 -07002116 .function = map_security_check_frag_command_fn,
2117};
2118
Ole Troan96eefd42016-09-12 12:25:30 +02002119/*?
2120 * Add MAP domain
2121 *
2122 * @cliexpar
2123 * @cliexstart{map add domain}
2124 * @cliexend
2125 ?*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07002126VLIB_CLI_COMMAND(map_add_domain_command, static) = {
2127 .path = "map add domain",
Ole Troan96eefd42016-09-12 12:25:30 +02002128 .short_help = "map add domain ip4-pfx <ip4-pfx> ip6-pfx <ip6-pfx> "
2129 "ip6-src <ip6-pfx> ea-bits-len <n> psid-offset <n> psid-len <n> "
2130 "[map-t] [mtu <mtu>]",
Ed Warnickecb9cada2015-12-08 15:45:58 -07002131 .function = map_add_domain_command_fn,
2132};
2133
Ole Troan96eefd42016-09-12 12:25:30 +02002134/*?
2135 * Add MAP rule to a domain
2136 *
2137 * @cliexpar
2138 * @cliexstart{map add rule}
2139 * @cliexend
2140 ?*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07002141VLIB_CLI_COMMAND(map_add_rule_command, static) = {
2142 .path = "map add rule",
Ole Troan96eefd42016-09-12 12:25:30 +02002143 .short_help = "map add rule index <domain> psid <psid> ip6-dst <ip6-addr>",
Ed Warnickecb9cada2015-12-08 15:45:58 -07002144 .function = map_add_rule_command_fn,
2145};
2146
Ole Troan96eefd42016-09-12 12:25:30 +02002147/*?
2148 * Delete MAP domain
2149 *
2150 * @cliexpar
2151 * @cliexstart{map del domain}
2152 * @cliexend
2153 ?*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07002154VLIB_CLI_COMMAND(map_del_command, static) = {
2155 .path = "map del domain",
Ole Troan96eefd42016-09-12 12:25:30 +02002156 .short_help = "map del domain index <domain>",
Ed Warnickecb9cada2015-12-08 15:45:58 -07002157 .function = map_del_domain_command_fn,
2158};
2159
Ole Troan96eefd42016-09-12 12:25:30 +02002160/*?
2161 * Show MAP domains
2162 *
2163 * @cliexpar
2164 * @cliexstart{show map domain}
2165 * @cliexend
2166 ?*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07002167VLIB_CLI_COMMAND(show_map_domain_command, static) = {
2168 .path = "show map domain",
Ole Troan96eefd42016-09-12 12:25:30 +02002169 .short_help = "show map domain index <n> [counters]",
Ed Warnickecb9cada2015-12-08 15:45:58 -07002170 .function = show_map_domain_command_fn,
2171};
2172
Ole Troan96eefd42016-09-12 12:25:30 +02002173/*?
2174 * Show MAP statistics
2175 *
2176 * @cliexpar
2177 * @cliexstart{show map stats}
2178 * @cliexend
2179 ?*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07002180VLIB_CLI_COMMAND(show_map_stats_command, static) = {
2181 .path = "show map stats",
Ole Troan96eefd42016-09-12 12:25:30 +02002182 .short_help = "show map stats",
Ed Warnickecb9cada2015-12-08 15:45:58 -07002183 .function = show_map_stats_command_fn,
2184};
2185
Ole Troan96eefd42016-09-12 12:25:30 +02002186/*?
2187 * Show MAP fragmentation information
2188 *
2189 * @cliexpar
2190 * @cliexstart{show map fragments}
2191 * @cliexend
2192 ?*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07002193VLIB_CLI_COMMAND(show_map_fragments_command, static) = {
2194 .path = "show map fragments",
Ole Troan96eefd42016-09-12 12:25:30 +02002195 .short_help = "show map fragments",
Ed Warnickecb9cada2015-12-08 15:45:58 -07002196 .function = show_map_fragments_command_fn,
2197};
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07002198/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07002199
2200/*
2201 * map_init
2202 */
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07002203clib_error_t *
2204map_init (vlib_main_t * vm)
Ed Warnickecb9cada2015-12-08 15:45:58 -07002205{
2206 map_main_t *mm = &map_main;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07002207 mm->vnet_main = vnet_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -07002208 mm->vlib_main = vm;
2209
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07002210#ifdef MAP_SKIP_IP6_LOOKUP
Neale Ranns80823802017-02-20 18:23:41 -08002211 fib_protocol_t proto;
2212
2213 FOR_EACH_FIB_PROTOCOL (proto)
2214 {
2215 map_pre_resolve_init (&pre_resolved[proto]);
2216 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07002217#endif
2218
2219 /* traffic class */
2220 mm->tc = 0;
2221 mm->tc_copy = true;
2222
2223 /* Inbound security check */
2224 mm->sec_check = true;
2225 mm->sec_check_frag = false;
2226
Ole Troancda94822016-01-07 14:37:25 +01002227 /* ICMP6 Type 1, Code 5 for security check failure */
2228 mm->icmp6_enabled = false;
2229
Ole Troan9fb87552016-01-13 22:30:43 +01002230 /* Inner or outer fragmentation */
2231 mm->frag_inner = false;
2232 mm->frag_ignore_df = false;
2233
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07002234 vec_validate (mm->domain_counters, MAP_N_DOMAIN_COUNTER - 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07002235 mm->domain_counters[MAP_DOMAIN_COUNTER_RX].name = "rx";
2236 mm->domain_counters[MAP_DOMAIN_COUNTER_TX].name = "tx";
2237
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07002238 vlib_validate_simple_counter (&mm->icmp_relayed, 0);
2239 vlib_zero_simple_counter (&mm->icmp_relayed, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -07002240
2241 /* IP4 virtual reassembly */
2242 mm->ip4_reass_hash_table = 0;
2243 mm->ip4_reass_pool = 0;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07002244 mm->ip4_reass_lock =
2245 clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES, CLIB_CACHE_LINE_BYTES);
dongjuan01e078f2017-09-07 14:58:56 +08002246 *mm->ip4_reass_lock = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07002247 mm->ip4_reass_conf_ht_ratio = MAP_IP4_REASS_HT_RATIO_DEFAULT;
2248 mm->ip4_reass_conf_lifetime_ms = MAP_IP4_REASS_LIFETIME_DEFAULT;
2249 mm->ip4_reass_conf_pool_size = MAP_IP4_REASS_POOL_SIZE_DEFAULT;
2250 mm->ip4_reass_conf_buffers = MAP_IP4_REASS_BUFFERS_DEFAULT;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07002251 mm->ip4_reass_ht_log2len =
2252 map_get_ht_log2len (mm->ip4_reass_conf_ht_ratio,
2253 mm->ip4_reass_conf_pool_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -07002254 mm->ip4_reass_fifo_last = MAP_REASS_INDEX_NONE;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07002255 map_ip4_reass_reinit (NULL, NULL);
Ed Warnickecb9cada2015-12-08 15:45:58 -07002256
2257 /* IP6 virtual reassembly */
2258 mm->ip6_reass_hash_table = 0;
2259 mm->ip6_reass_pool = 0;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07002260 mm->ip6_reass_lock =
2261 clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES, CLIB_CACHE_LINE_BYTES);
dongjuan01e078f2017-09-07 14:58:56 +08002262 *mm->ip6_reass_lock = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07002263 mm->ip6_reass_conf_ht_ratio = MAP_IP6_REASS_HT_RATIO_DEFAULT;
2264 mm->ip6_reass_conf_lifetime_ms = MAP_IP6_REASS_LIFETIME_DEFAULT;
2265 mm->ip6_reass_conf_pool_size = MAP_IP6_REASS_POOL_SIZE_DEFAULT;
2266 mm->ip6_reass_conf_buffers = MAP_IP6_REASS_BUFFERS_DEFAULT;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07002267 mm->ip6_reass_ht_log2len =
2268 map_get_ht_log2len (mm->ip6_reass_conf_ht_ratio,
2269 mm->ip6_reass_conf_pool_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -07002270 mm->ip6_reass_fifo_last = MAP_REASS_INDEX_NONE;
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07002271 map_ip6_reass_reinit (NULL, NULL);
Ed Warnickecb9cada2015-12-08 15:45:58 -07002272
Neale Ranns80823802017-02-20 18:23:41 -08002273#ifdef MAP_SKIP_IP6_LOOKUP
2274 fib_node_register_type (FIB_NODE_TYPE_MAP_E, &map_vft);
2275#endif
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002276 map_dpo_module_init ();
2277
Ed Warnickecb9cada2015-12-08 15:45:58 -07002278 return 0;
2279}
2280
Keith Burns (alagalah)06e3d072016-08-07 08:43:18 -07002281VLIB_INIT_FUNCTION (map_init);
2282
2283/*
2284 * fd.io coding-style-patch-verification: ON
2285 *
2286 * Local Variables:
2287 * eval: (c-set-style "gnu")
2288 * End:
2289 */