blob: 78e730f5a5d34312e6c60021977a9dbbc3dbc481 [file] [log] [blame]
Florin Corase127a7e2016-02-18 22:20:01 +01001/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vnet/lisp-cp/control.h>
17#include <vnet/lisp-cp/packets.h>
18#include <vnet/lisp-cp/lisp_msg_serdes.h>
19#include <vnet/lisp-gpe/lisp_gpe.h>
20
Florin Corasf727db92016-06-23 15:01:58 +020021ip_interface_address_t *
22ip_interface_get_first_interface_address (ip_lookup_main_t *lm, u32 sw_if_index,
23 u8 loop)
24{
25 vnet_main_t *vnm = vnet_get_main ();
26 vnet_sw_interface_t * swif = vnet_get_sw_interface (vnm, sw_if_index);
27 if (loop && swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
28 sw_if_index = swif->unnumbered_sw_if_index;
29 u32 ia =
30 (vec_len((lm)->if_address_pool_index_by_sw_if_index) > (sw_if_index)) ?
31 vec_elt((lm)->if_address_pool_index_by_sw_if_index, (sw_if_index)) :
32 (u32) ~0;
33 return pool_elt_at_index((lm)->if_address_pool, ia);
34}
Filip Tehlar215104e2016-05-10 16:58:29 +020035
Florin Corasf727db92016-06-23 15:01:58 +020036void *
37ip_interface_get_first_address (ip_lookup_main_t * lm, u32 sw_if_index,
38 u8 version)
39{
40 ip_interface_address_t * ia;
Filip Tehlar195bcee2016-05-13 17:37:35 +020041
Florin Corasf727db92016-06-23 15:01:58 +020042 ia = ip_interface_get_first_interface_address (lm, sw_if_index, 1);
43 if (!ia)
44 return 0;
45 return ip_interface_address_get_address (lm, ia);
46}
Filip Tehlar195bcee2016-05-13 17:37:35 +020047
Florin Corase127a7e2016-02-18 22:20:01 +010048int
Florin Corasf727db92016-06-23 15:01:58 +020049ip_interface_get_first_ip_address (lisp_cp_main_t * lcm, u32 sw_if_index,
50 u8 version, ip_address_t * result)
51{
52 ip_lookup_main_t * lm;
53 void * addr;
54
55 lm = (version == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
56 addr = ip_interface_get_first_address (lm, sw_if_index, version);
57 if (!addr)
58 return 0;
59
60 ip_address_set (result, addr, version);
61 return 1;
62}
63
64static u32
65ip_fib_lookup_with_table (lisp_cp_main_t * lcm, u32 fib_index,
66 ip_address_t * dst)
67{
68 if (ip_addr_version (dst) == IP4)
69 return ip4_fib_lookup_with_table (lcm->im4, fib_index, &ip_addr_v4(dst),
70 0);
71 else
72 return ip6_fib_lookup_with_table (lcm->im6, fib_index, &ip_addr_v6(dst));
73}
74
75u32
76ip_fib_get_egress_iface_for_dst_with_lm (lisp_cp_main_t * lcm,
77 ip_address_t * dst,
78 ip_lookup_main_t * lm)
79{
80 u32 adj_index;
81 ip_adjacency_t * adj;
82
83 adj_index = ip_fib_lookup_with_table (lcm, 0, dst);
84 adj = ip_get_adjacency (lm, adj_index);
85
86 if (adj == 0)
87 return ~0;
88
89 /* we only want outgoing routes */
90 if (adj->lookup_next_index != IP_LOOKUP_NEXT_ARP
91 && adj->lookup_next_index != IP_LOOKUP_NEXT_REWRITE)
92 return ~0;
93
94 return adj->rewrite_header.sw_if_index;
95}
96
97/**
98 * Find the sw_if_index of the interface that would be used to egress towards
99 * dst.
100 */
101u32
102ip_fib_get_egress_iface_for_dst (lisp_cp_main_t * lcm, ip_address_t * dst)
103{
104 ip_lookup_main_t * lm;
105
106 lm = ip_addr_version (dst) == IP4 ?
107 &lcm->im4->lookup_main : &lcm->im6->lookup_main;
108
109 return ip_fib_get_egress_iface_for_dst_with_lm (lcm, dst, lm);
110}
111
112/**
113 * Find first IP of the interface that would be used to egress towards dst.
114 * Returns 1 if the address is found 0 otherwise.
115 */
116int
117ip_fib_get_first_egress_ip_for_dst (lisp_cp_main_t * lcm, ip_address_t * dst,
118 ip_address_t * result)
119{
120 u32 si;
121 ip_lookup_main_t * lm;
122 void * addr = 0;
123 u8 ipver;
124
125 ASSERT(result != 0);
126
127 ipver = ip_addr_version(dst);
128
129 lm = (ipver == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
130 si = ip_fib_get_egress_iface_for_dst_with_lm (lcm, dst, lm);
131
132 if ((u32) ~0 == si)
133 return 0;
134
135 /* find the first ip address */
136 addr = ip_interface_get_first_address (lm, si, ipver);
137 if (0 == addr)
138 return 0;
139
140 ip_address_set (result, addr, ipver);
141 return 1;
142}
143
144static int
145dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_add)
146{
147 uword * table_id, * intf;
148 vnet_lisp_gpe_add_del_iface_args_t _ai, *ai = &_ai;
149
150 table_id = hash_get(lcm->table_id_by_vni, vni);
151
152 if (!table_id)
153 {
154 clib_warning ("vni %d not associated to a vrf!", vni);
155 return VNET_API_ERROR_INVALID_VALUE;
156 }
157
158 intf = hash_get(lcm->dp_intf_by_vni, vni);
159
160 /* enable/disable data-plane interface */
161 if (is_add)
162 {
163 /* create interface */
164 if (!intf)
165 {
166 ai->is_add = 1;
167 ai->vni = vni;
168 ai->table_id = table_id[0];
169 vnet_lisp_gpe_add_del_iface (ai, 0);
170
171 /* keep track of vnis for which interfaces have been created */
172 hash_set(lcm->dp_intf_by_vni, vni, 1);
173 }
174 }
175 else
176 {
177 if (intf == 0)
178 {
179 clib_warning("interface for vni %d doesn't exist!", vni);
180 return VNET_API_ERROR_INVALID_VALUE;
181 }
182
183 ai->is_add = 0;
184 ai->vni = vni;
185 ai->table_id = table_id[0];
186 vnet_lisp_gpe_add_del_iface (ai, 0);
187 hash_unset(lcm->dp_intf_by_vni, vni);
188 }
189
190 return 0;
191}
192
193static void
194dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
195{
196 vnet_lisp_gpe_add_del_fwd_entry_args_t _a, * a = &_a;
197 fwd_entry_t * fe = 0;
198 uword * feip = 0;
199 memset(a, 0, sizeof(*a));
200
201 feip = hash_get(lcm->fwd_entry_by_mapping_index, dst_map_index);
202 if (!feip)
203 return;
204
205 fe = pool_elt_at_index(lcm->fwd_entry_pool, feip[0]);
206
207 /* delete dp fwd entry */
208 u32 sw_if_index;
209 a->is_add = 0;
210 a->dlocator = fe->dst_loc;
211 a->slocator = fe->src_loc;
212 a->vni = gid_address_vni(&a->deid);
213 gid_address_copy(&a->deid, &fe->deid);
214
215 vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
216
217 /* delete entry in fwd table */
218 hash_unset(lcm->fwd_entry_by_mapping_index, dst_map_index);
219 pool_put(lcm->fwd_entry_pool, fe);
220}
221
222/**
223 * Finds first remote locator with best (lowest) priority that has a local
224 * peer locator with an underlying route to it.
225 *
226 */
227static u32
228get_locator_pair (lisp_cp_main_t* lcm, mapping_t * lcl_map, mapping_t * rmt_map,
229 ip_address_t * lcl_loc, ip_address_t * rmt_loc)
230{
231 u32 i, minp = ~0, limitp = 0, li, check_index = 0, done = 0, esi;
232 locator_set_t * rmt_ls, * lcl_ls;
233 ip_address_t _lcl, * lcl = &_lcl;
234 locator_t * l, * rmt = 0;
235 uword * checked = 0;
236
237 rmt_ls = pool_elt_at_index(lcm->locator_set_pool, rmt_map->locator_set_index);
238 lcl_ls = pool_elt_at_index(lcm->locator_set_pool, lcl_map->locator_set_index);
239
240 if (!rmt_ls || vec_len(rmt_ls->locator_indices) == 0)
241 return 0;
242
243 while (!done)
244 {
245 rmt = 0;
246
247 /* find unvisited remote locator with best priority */
248 for (i = 0; i < vec_len(rmt_ls->locator_indices); i++)
249 {
250 if (0 != hash_get(checked, i))
251 continue;
252
253 li = vec_elt(rmt_ls->locator_indices, i);
254 l = pool_elt_at_index(lcm->locator_pool, li);
255
256 /* we don't support non-IP locators for now */
257 if (gid_address_type(&l->address) != GID_ADDR_IP_PREFIX)
258 continue;
259
260 if (l->priority < minp && l->priority >= limitp)
261 {
262 minp = l->priority;
263 rmt = l;
264 check_index = i;
265 }
266 }
267 /* check if a local locator with a route to remote locator exists */
268 if (rmt != 0)
269 {
270 esi = ip_fib_get_egress_iface_for_dst (
271 lcm, &gid_address_ip(&rmt->address));
272 if ((u32) ~0 == esi)
273 continue;
274
275 for (i = 0; i < vec_len(lcl_ls->locator_indices); i++)
276 {
277 li = vec_elt (lcl_ls->locator_indices, i);
278 locator_t * sl = pool_elt_at_index (lcm->locator_pool, li);
279
280 /* found local locator */
281 if (sl->sw_if_index == esi)
282 {
283 if (0 == ip_interface_get_first_ip_address (lcm,
284 sl->sw_if_index,
285 gid_address_ip_version(&rmt->address), lcl))
286 continue;
287
288 ip_address_copy(rmt_loc, &gid_address_ip(&rmt->address));
289 ip_address_copy(lcl_loc, lcl);
290 done = 2;
291 }
292 }
293
294 /* skip this remote locator in next searches */
295 limitp = minp;
296 hash_set(checked, check_index, 1);
297 }
298 else
299 done = 1;
300 }
301 hash_free(checked);
302 return (done == 2) ? 1 : 0;
303}
304
305static void
306dp_add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index)
307{
308 mapping_t * src_map, * dst_map;
309 u32 sw_if_index;
310 uword * feip = 0, * tidp;
311 fwd_entry_t* fe;
312 vnet_lisp_gpe_add_del_fwd_entry_args_t _a, * a = &_a;
313
314 memset (a, 0, sizeof(*a));
315
316 /* remove entry if it already exists */
317 feip = hash_get (lcm->fwd_entry_by_mapping_index, dst_map_index);
318 if (feip)
319 dp_del_fwd_entry (lcm, src_map_index, dst_map_index);
320
321 src_map = pool_elt_at_index (lcm->mapping_pool, src_map_index);
322 dst_map = pool_elt_at_index (lcm->mapping_pool, dst_map_index);
323
324 gid_address_copy (&a->deid, &dst_map->eid);
325 a->vni = gid_address_vni(&a->deid);
326
327 tidp = hash_get(lcm->table_id_by_vni, a->vni);
328 if (!tidp)
329 {
330 clib_warning("vni %d not associated to a vrf!", a->vni);
331 return;
332 }
333 a->table_id = tidp[0];
334
335 /* insert data plane forwarding entry */
336 a->is_add = 1;
337
338 /* find best locator pair that 1) verifies LISP policy 2) are connected */
339 if (0 == get_locator_pair (lcm, src_map, dst_map, &a->slocator, &a->dlocator))
340 {
341 /* negative entry */
342 a->is_negative = 1;
343 a->action = dst_map->action;
344 }
345
346 /* TODO remove */
347 u8 ipver = ip_prefix_version(&gid_address_ippref(&a->deid));
348 a->decap_next_index = (ipver == IP4) ?
349 LISP_GPE_INPUT_NEXT_IP4_INPUT : LISP_GPE_INPUT_NEXT_IP6_INPUT;
350
351 vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
352
353 /* add tunnel to fwd entry table XXX check return value from DP insertion */
354 pool_get (lcm->fwd_entry_pool, fe);
355 fe->dst_loc = a->dlocator;
356 fe->src_loc = a->slocator;
357 gid_address_copy (&fe->deid, &a->deid);
358 hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index,
359 fe - lcm->fwd_entry_pool);
360}
361
362/**
363 * Add/remove mapping to/from map-cache. Overwriting not allowed.
364 */
365int
366vnet_lisp_map_cache_add_del (vnet_lisp_add_del_mapping_args_t * a,
367 u32 * map_index_result)
Florin Corase127a7e2016-02-18 22:20:01 +0100368{
369 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
370 u32 mi, * map_indexp, map_index, i;
Filip Tehlar53f09e32016-05-19 14:25:44 +0200371 mapping_t * m, * old_map;
Florin Corase127a7e2016-02-18 22:20:01 +0100372 u32 ** eid_indexes;
373
Florin Corasf727db92016-06-23 15:01:58 +0200374 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->eid);
Filip Tehlar53f09e32016-05-19 14:25:44 +0200375 old_map = mi != ~0 ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
Florin Corase127a7e2016-02-18 22:20:01 +0100376 if (a->is_add)
377 {
378 /* TODO check if overwriting and take appropriate actions */
Filip Tehlar53f09e32016-05-19 14:25:44 +0200379 if (mi != GID_LOOKUP_MISS && !gid_address_cmp (&old_map->eid,
Florin Corasf727db92016-06-23 15:01:58 +0200380 &a->eid))
Florin Coras577c3552016-04-21 00:45:40 +0200381 {
Filip Tehlar324112f2016-06-02 16:07:38 +0200382 clib_warning ("eid %U found in the eid-table", format_gid_address,
Florin Corasf727db92016-06-23 15:01:58 +0200383 &a->eid);
Andrej Kozemcakb92feb62016-03-31 13:51:42 +0200384 return VNET_API_ERROR_VALUE_EXIST;
Florin Coras577c3552016-04-21 00:45:40 +0200385 }
Florin Corase127a7e2016-02-18 22:20:01 +0100386
387 pool_get(lcm->mapping_pool, m);
Florin Corasf727db92016-06-23 15:01:58 +0200388 gid_address_copy (&m->eid, &a->eid);
Florin Corase127a7e2016-02-18 22:20:01 +0100389 m->locator_set_index = a->locator_set_index;
390 m->ttl = a->ttl;
Filip Tehlar53f09e32016-05-19 14:25:44 +0200391 m->action = a->action;
Florin Corase127a7e2016-02-18 22:20:01 +0100392 m->local = a->local;
393
394 map_index = m - lcm->mapping_pool;
Florin Corasf727db92016-06-23 15:01:58 +0200395 gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->eid, map_index,
Florin Corase127a7e2016-02-18 22:20:01 +0100396 1);
397
398 if (pool_is_free_index(lcm->locator_set_pool, a->locator_set_index))
399 {
400 clib_warning("Locator set with index %d doesn't exist",
401 a->locator_set_index);
Andrej Kozemcakb92feb62016-03-31 13:51:42 +0200402 return VNET_API_ERROR_INVALID_VALUE;
Florin Corase127a7e2016-02-18 22:20:01 +0100403 }
404
405 /* add eid to list of eids supported by locator-set */
406 vec_validate (lcm->locator_set_to_eids, a->locator_set_index);
407 eid_indexes = vec_elt_at_index(lcm->locator_set_to_eids,
408 a->locator_set_index);
409 vec_add1(eid_indexes[0], map_index);
410
411 if (a->local)
412 {
413 /* mark as local */
414 vec_add1(lcm->local_mappings_indexes, map_index);
Florin Corase127a7e2016-02-18 22:20:01 +0100415 }
416 map_index_result[0] = map_index;
417 }
418 else
419 {
Florin Coras577c3552016-04-21 00:45:40 +0200420 if (mi == GID_LOOKUP_MISS)
421 {
Filip Tehlar324112f2016-06-02 16:07:38 +0200422 clib_warning("eid %U not found in the eid-table", format_gid_address,
Florin Corasf727db92016-06-23 15:01:58 +0200423 &a->eid);
Andrej Kozemcakb92feb62016-03-31 13:51:42 +0200424 return VNET_API_ERROR_INVALID_VALUE;
Florin Coras577c3552016-04-21 00:45:40 +0200425 }
Florin Corase127a7e2016-02-18 22:20:01 +0100426
427 /* clear locator-set to eids binding */
428 eid_indexes = vec_elt_at_index(lcm->locator_set_to_eids,
429 a->locator_set_index);
430 for (i = 0; i < vec_len(eid_indexes[0]); i++)
431 {
432 map_indexp = vec_elt_at_index(eid_indexes[0], i);
433 if (map_indexp[0] == mi)
434 break;
435 }
436 vec_del1(eid_indexes[0], i);
437
438 /* remove local mark if needed */
439 m = pool_elt_at_index(lcm->mapping_pool, mi);
440 if (m->local)
441 {
442 u32 k, * lm_indexp;
443 for (k = 0; k < vec_len(lcm->local_mappings_indexes); k++)
444 {
445 lm_indexp = vec_elt_at_index(lcm->local_mappings_indexes, k);
446 if (lm_indexp[0] == mi)
447 break;
448 }
449 vec_del1(lcm->local_mappings_indexes, k);
450 }
Florin Corase127a7e2016-02-18 22:20:01 +0100451
452 /* remove mapping from dictionary */
Florin Corasf727db92016-06-23 15:01:58 +0200453 gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->eid, 0, 0);
Filip Tehlar324112f2016-06-02 16:07:38 +0200454 gid_address_free (&m->eid);
Florin Corase127a7e2016-02-18 22:20:01 +0100455 pool_put_index (lcm->mapping_pool, mi);
456 }
457
458 return 0;
459}
460
Florin Corasf727db92016-06-23 15:01:58 +0200461/**
462 * Add/update/delete mapping to/in/from map-cache.
463 */
Florin Coras577c3552016-04-21 00:45:40 +0200464int
465vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a,
466 u32 * map_index_result)
467{
Florin Corasf727db92016-06-23 15:01:58 +0200468 uword * table_id;
469 u32 vni;
470
Florin Coras577c3552016-04-21 00:45:40 +0200471 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
472
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +0200473 if (vnet_lisp_enable_disable_status () == 0)
474 {
475 clib_warning ("LISP is disabled!");
476 return VNET_API_ERROR_LISP_DISABLED;
477 }
478
Florin Corasf727db92016-06-23 15:01:58 +0200479 vni = gid_address_vni(&a->eid);
Florin Coras7ef6d5b2016-04-29 15:36:29 +0200480 table_id = hash_get(lcm->table_id_by_vni, vni);
Florin Coras577c3552016-04-21 00:45:40 +0200481
482 if (!table_id)
483 {
Florin Coras7ef6d5b2016-04-29 15:36:29 +0200484 clib_warning ("vni %d not associated to a vrf!", vni);
Florin Coras577c3552016-04-21 00:45:40 +0200485 return VNET_API_ERROR_INVALID_VALUE;
486 }
487
Florin Corasf727db92016-06-23 15:01:58 +0200488 /* store/remove mapping from map-cache */
489 return vnet_lisp_map_cache_add_del (a, map_index_result);
Florin Coras577c3552016-04-21 00:45:40 +0200490}
491
Florin Corase127a7e2016-02-18 22:20:01 +0100492static clib_error_t *
493lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
494 vlib_cli_command_t * cmd)
495{
496 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
497 unformat_input_t _line_input, * line_input = &_line_input;
498 u8 is_add = 1;
499 gid_address_t eid;
500 ip_prefix_t * prefp = &gid_address_ippref(&eid);
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200501 u8 * mac = gid_address_mac(&eid);
Florin Corase127a7e2016-02-18 22:20:01 +0100502 gid_address_t * eids = 0;
503 clib_error_t * error = 0;
Filip Tehlar53f09e32016-05-19 14:25:44 +0200504 u8 * locator_set_name = 0;
Florin Corase127a7e2016-02-18 22:20:01 +0100505 u32 locator_set_index = 0, map_index = 0;
506 uword * p;
507 vnet_lisp_add_del_mapping_args_t _a, * a = &_a;
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +0200508 int rv = 0;
Filip Tehlar324112f2016-06-02 16:07:38 +0200509 u32 vni = 0;
Florin Corase127a7e2016-02-18 22:20:01 +0100510
Filip Tehlar324112f2016-06-02 16:07:38 +0200511 memset (&eid, 0, sizeof (eid));
Florin Corase127a7e2016-02-18 22:20:01 +0100512 /* Get a line of input. */
513 if (! unformat_user (input, unformat_line_input, line_input))
514 return 0;
515
516 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
517 {
518 if (unformat (line_input, "add"))
519 is_add = 1;
520 else if (unformat (line_input, "del"))
521 is_add = 0;
Filip Tehlar324112f2016-06-02 16:07:38 +0200522 else if (unformat (line_input, "vni %d", &vni))
523 gid_address_vni (&eid) = vni;
Florin Corase127a7e2016-02-18 22:20:01 +0100524 else if (unformat (line_input, "eid %U", unformat_ip_prefix, prefp))
525 {
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200526 gid_address_type (&eid) = GID_ADDR_IP_PREFIX;
527 vec_add1(eids, eid);
528 }
529 else if (unformat (line_input, "eid %U", unformat_mac_address, mac))
530 {
531 gid_address_type (&eid) = GID_ADDR_MAC;
Florin Corase127a7e2016-02-18 22:20:01 +0100532 vec_add1(eids, eid);
533 }
534 else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
535 {
536 p = hash_get_mem(lcm->locator_set_index_by_name, locator_set_name);
537 if (!p)
538 {
539 error = clib_error_return(0, "locator-set %s doesn't exist",
540 locator_set_name);
541 goto done;
542 }
543 locator_set_index = p[0];
544 }
545 else
546 {
547 error = unformat_parse_error(line_input);
548 goto done;
549 }
550 }
Florin Corase127a7e2016-02-18 22:20:01 +0100551 /* XXX treat batch configuration */
Filip Tehlar324112f2016-06-02 16:07:38 +0200552
Florin Corasf727db92016-06-23 15:01:58 +0200553 a->eid = eid;
Florin Corase127a7e2016-02-18 22:20:01 +0100554 a->is_add = is_add;
555 a->locator_set_index = locator_set_index;
556 a->local = 1;
557
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +0200558 rv = vnet_lisp_add_del_local_mapping (a, &map_index);
559 if (0 != rv)
560 {
Florin Corasf727db92016-06-23 15:01:58 +0200561 error = clib_error_return(0, "failed to %s local mapping!",
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +0200562 is_add ? "add" : "delete");
563 }
Florin Corase127a7e2016-02-18 22:20:01 +0100564 done:
565 vec_free(eids);
Filip Tehlar53f09e32016-05-19 14:25:44 +0200566 if (locator_set_name)
567 vec_free (locator_set_name);
Florin Corasf727db92016-06-23 15:01:58 +0200568 gid_address_free (&a->eid);
Florin Corase127a7e2016-02-18 22:20:01 +0100569 return error;
570}
571
572VLIB_CLI_COMMAND (lisp_add_del_local_eid_command) = {
573 .path = "lisp eid-table",
Filip Tehlar324112f2016-06-02 16:07:38 +0200574 .short_help = "lisp eid-table add/del [vni <vni>] eid <eid> "
575 "locator-set <locator-set>",
Florin Corase127a7e2016-02-18 22:20:01 +0100576 .function = lisp_add_del_local_eid_command_fn,
577};
578
Filip Tehlar324112f2016-06-02 16:07:38 +0200579int
580vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_add)
581{
582 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
583 uword * table_id, * vnip;
584
585 if (vnet_lisp_enable_disable_status () == 0)
586 {
587 clib_warning ("LISP is disabled!");
588 return -1;
589 }
590
591 if (vni == 0 || vrf == 0)
592 {
593 clib_warning ("can't add/del default vni-vrf mapping!");
594 return -1;
595 }
596
597 table_id = hash_get (lcm->table_id_by_vni, vni);
598 vnip = hash_get (lcm->vni_by_table_id, vrf);
599
600 if (is_add)
601 {
602 if (table_id || vnip)
603 {
Filip Tehlar2f653d02016-07-13 13:17:15 +0200604 clib_warning ("vni %d or vrf %d already used in vrf/vni "
Filip Tehlar324112f2016-06-02 16:07:38 +0200605 "mapping!", vni, vrf);
606 return -1;
607 }
608 hash_set (lcm->table_id_by_vni, vni, vrf);
609 hash_set (lcm->vni_by_table_id, vrf, vni);
Florin Corasf727db92016-06-23 15:01:58 +0200610
611 /* create dp iface */
612 dp_add_del_iface (lcm, vni, 1);
Filip Tehlar324112f2016-06-02 16:07:38 +0200613 }
614 else
615 {
616 if (!table_id || !vnip)
617 {
618 clib_warning ("vni %d or vrf %d not used in any vrf/vni! "
619 "mapping!", vni, vrf);
620 return -1;
621 }
622 hash_unset (lcm->table_id_by_vni, vni);
623 hash_unset (lcm->vni_by_table_id, vrf);
Florin Corasf727db92016-06-23 15:01:58 +0200624
625 /* remove dp iface */
626 dp_add_del_iface (lcm, vni, 0);
Filip Tehlar324112f2016-06-02 16:07:38 +0200627 }
628 return 0;
629}
630
631static clib_error_t *
632lisp_eid_table_map_command_fn (vlib_main_t * vm,
633 unformat_input_t * input,
634 vlib_cli_command_t * cmd)
635{
636 u8 is_add = 1;
637 u32 vni = 0, vrf = 0;
638 unformat_input_t _line_input, * line_input = &_line_input;
639
640 /* Get a line of input. */
641 if (! unformat_user (input, unformat_line_input, line_input))
642 return 0;
643
644 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
645 {
646 if (unformat (line_input, "del"))
647 is_add = 0;
648 else if (unformat (line_input, "vni %d", &vni))
649 ;
650 else if (unformat (line_input, "vrf %d", &vrf))
651 ;
652 else
653 {
654 return unformat_parse_error (line_input);
655 }
656 }
657 vnet_lisp_eid_table_map (vni, vrf, is_add);
658 return 0;
659}
660
661VLIB_CLI_COMMAND (lisp_eid_table_map_command) = {
662 .path = "lisp eid-table map",
663 .short_help = "lisp eid-table map [del] vni <vni> vrf <vrf>",
664 .function = lisp_eid_table_map_command_fn,
665};
666
Florin Corasf727db92016-06-23 15:01:58 +0200667
668/* return 0 if the two locator sets are identical 1 otherwise */
669static u8
670compare_locators (lisp_cp_main_t *lcm, u32 * old_ls_indexes,
671 locator_t * new_locators)
Filip Tehlar53f09e32016-05-19 14:25:44 +0200672{
Florin Corasf727db92016-06-23 15:01:58 +0200673 u32 i, old_li;
674 locator_t * old_loc, * new_loc;
Filip Tehlar53f09e32016-05-19 14:25:44 +0200675
Florin Corasf727db92016-06-23 15:01:58 +0200676 if (vec_len (old_ls_indexes) != vec_len(new_locators))
677 return 1;
Filip Tehlar53f09e32016-05-19 14:25:44 +0200678
Florin Corasf727db92016-06-23 15:01:58 +0200679 for (i = 0; i < vec_len(new_locators); i++)
Filip Tehlar53f09e32016-05-19 14:25:44 +0200680 {
Florin Corasf727db92016-06-23 15:01:58 +0200681 old_li = vec_elt(old_ls_indexes, i);
682 old_loc = pool_elt_at_index(lcm->locator_pool, old_li);
683
684 new_loc = vec_elt_at_index(new_locators, i);
685
686 if (locator_cmp (old_loc, new_loc))
687 return 1;
Filip Tehlar53f09e32016-05-19 14:25:44 +0200688 }
Florin Corasf727db92016-06-23 15:01:58 +0200689 return 0;
Filip Tehlar53f09e32016-05-19 14:25:44 +0200690}
691
Filip Tehlar195bcee2016-05-13 17:37:35 +0200692/**
Florin Corasf727db92016-06-23 15:01:58 +0200693 * Adds/removes/updates mapping. Does not program forwarding.
Filip Tehlar195bcee2016-05-13 17:37:35 +0200694 *
Florin Coras71893ac2016-07-10 20:09:32 +0200695 * @param eid end-host identifier
Filip Tehlar195bcee2016-05-13 17:37:35 +0200696 * @param rlocs vector of remote locators
697 * @param action action for negative map-reply
698 * @param is_add add mapping if non-zero, delete otherwise
Florin Coras71893ac2016-07-10 20:09:32 +0200699 * @param res_map_index the map-index that was created/updated/removed. It is
700 * set to ~0 if no action is taken.
Filip Tehlar195bcee2016-05-13 17:37:35 +0200701 * @return return code
702 */
703int
Florin Coras71893ac2016-07-10 20:09:32 +0200704vnet_lisp_add_del_mapping (gid_address_t * eid, locator_t * rlocs, u8 action,
Florin Corasf727db92016-06-23 15:01:58 +0200705 u8 authoritative, u32 ttl, u8 is_add,
706 u32 * res_map_index)
Filip Tehlar195bcee2016-05-13 17:37:35 +0200707{
Florin Corasf727db92016-06-23 15:01:58 +0200708 vnet_lisp_add_del_mapping_args_t _m_args, * m_args = &_m_args;
709 vnet_lisp_add_del_locator_set_args_t _ls_args, * ls_args = &_ls_args;
Filip Tehlar195bcee2016-05-13 17:37:35 +0200710 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
Florin Corasf727db92016-06-23 15:01:58 +0200711 u32 mi, ls_index = 0, dst_map_index;
712 mapping_t * old_map;
Filip Tehlar195bcee2016-05-13 17:37:35 +0200713
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +0200714 if (vnet_lisp_enable_disable_status() == 0)
715 {
716 clib_warning ("LISP is disabled!");
717 return VNET_API_ERROR_LISP_DISABLED;
718 }
719
Florin Corasf727db92016-06-23 15:01:58 +0200720 if (res_map_index)
721 res_map_index[0] = ~0;
Filip Tehlar58f886a2016-05-30 15:57:40 +0200722
Florin Corasf727db92016-06-23 15:01:58 +0200723 memset (m_args, 0, sizeof (m_args[0]));
724 memset (ls_args, 0, sizeof (ls_args[0]));
Filip Tehlar195bcee2016-05-13 17:37:35 +0200725
Florin Corasf727db92016-06-23 15:01:58 +0200726 ls_args->locators = rlocs;
Filip Tehlar195bcee2016-05-13 17:37:35 +0200727
Florin Coras71893ac2016-07-10 20:09:32 +0200728 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
Florin Corasf727db92016-06-23 15:01:58 +0200729 old_map = ((u32) ~0 != mi) ? pool_elt_at_index(lcm->mapping_pool, mi) : 0;
730
731 if (is_add)
Filip Tehlar195bcee2016-05-13 17:37:35 +0200732 {
Florin Corasf727db92016-06-23 15:01:58 +0200733 /* overwrite: if mapping already exists, decide if locators should be
734 * updated and be done */
Florin Coras71893ac2016-07-10 20:09:32 +0200735 if (old_map && gid_address_cmp (&old_map->eid, eid) == 0)
Filip Tehlar195bcee2016-05-13 17:37:35 +0200736 {
Filip Tehlar195bcee2016-05-13 17:37:35 +0200737 locator_set_t * old_ls;
Filip Tehlar195bcee2016-05-13 17:37:35 +0200738
739 /* update mapping attributes */
740 old_map->action = action;
Florin Corasf727db92016-06-23 15:01:58 +0200741 old_map->authoritative = authoritative;
742 old_map->ttl = ttl;
Filip Tehlar195bcee2016-05-13 17:37:35 +0200743
744 old_ls = pool_elt_at_index(lcm->locator_set_pool,
745 old_map->locator_set_index);
746 if (compare_locators (lcm, old_ls->locator_indices,
Florin Corasf727db92016-06-23 15:01:58 +0200747 ls_args->locators))
Filip Tehlar195bcee2016-05-13 17:37:35 +0200748 {
749 /* set locator-set index to overwrite */
Florin Corasf727db92016-06-23 15:01:58 +0200750 ls_args->is_add = 1;
751 ls_args->index = old_map->locator_set_index;
752 vnet_lisp_add_del_locator_set (ls_args, 0);
753 if (res_map_index)
754 res_map_index[0] = mi;
Filip Tehlar195bcee2016-05-13 17:37:35 +0200755 }
756 }
Florin Corasf727db92016-06-23 15:01:58 +0200757 /* new mapping */
758 else
759 {
760 ls_args->is_add = 1;
761 ls_args->index = ~0;
762
763 vnet_lisp_add_del_locator_set (ls_args, &ls_index);
764
765 /* add mapping */
Florin Coras71893ac2016-07-10 20:09:32 +0200766 gid_address_copy (&m_args->eid, eid);
Florin Corasf727db92016-06-23 15:01:58 +0200767 m_args->is_add = 1;
768 m_args->action = action;
769 m_args->locator_set_index = ls_index;
770 vnet_lisp_map_cache_add_del (m_args, &dst_map_index);
771
772 if (res_map_index)
773 res_map_index[0] = dst_map_index;
774 }
Filip Tehlar195bcee2016-05-13 17:37:35 +0200775 }
Florin Corasf727db92016-06-23 15:01:58 +0200776 else
777 {
Florin Coras71893ac2016-07-10 20:09:32 +0200778 if (old_map == 0 || gid_address_cmp (&old_map->eid, eid) != 0)
Florin Corasf727db92016-06-23 15:01:58 +0200779 {
780 clib_warning("cannot delete mapping for eid %U", format_gid_address,
Florin Coras71893ac2016-07-10 20:09:32 +0200781 eid);
Florin Corasf727db92016-06-23 15:01:58 +0200782 return -1;
783 }
784
785 m_args->is_add = 0;
Florin Coras71893ac2016-07-10 20:09:32 +0200786 gid_address_copy (&m_args->eid, eid);
Florin Corasf727db92016-06-23 15:01:58 +0200787 m_args->locator_set_index = old_map->locator_set_index;
788
789 /* delete mapping associated from map-cache */
790 vnet_lisp_map_cache_add_del (m_args, 0);
791
792 ls_args->is_add = 0;
793 ls_args->index = old_map->locator_set_index;
794 /* delete locator set */
795 vnet_lisp_add_del_locator_set (ls_args, 0);
Filip Tehlarb93222f2016-07-07 09:58:08 +0200796
797 /* return old mapping index */
798 res_map_index[0] = mi;
Florin Corasf727db92016-06-23 15:01:58 +0200799 }
800
Filip Tehlar195bcee2016-05-13 17:37:35 +0200801 /* success */
Florin Corasf727db92016-06-23 15:01:58 +0200802 return 0;
Filip Tehlar195bcee2016-05-13 17:37:35 +0200803}
804
Filip Tehlar58f886a2016-05-30 15:57:40 +0200805int
Florin Corasf727db92016-06-23 15:01:58 +0200806vnet_lisp_clear_all_remote_adjacencies (void)
Filip Tehlar58f886a2016-05-30 15:57:40 +0200807{
808 int rv = 0;
809 u32 mi, * map_indices = 0, * map_indexp;
810 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
811 vnet_lisp_add_del_mapping_args_t _dm_args, * dm_args = &_dm_args;
812 vnet_lisp_add_del_locator_set_args_t _ls, * ls = &_ls;
813
814 pool_foreach_index (mi, lcm->mapping_pool,
815 ({
816 vec_add1 (map_indices, mi);
817 }));
818
819 vec_foreach (map_indexp, map_indices)
820 {
821 mapping_t * map = pool_elt_at_index (lcm->mapping_pool, map_indexp[0]);
822 if (!map->local)
823 {
Florin Corasf727db92016-06-23 15:01:58 +0200824 dp_del_fwd_entry (lcm, 0, map_indexp[0]);
Filip Tehlar58f886a2016-05-30 15:57:40 +0200825
826 dm_args->is_add = 0;
Florin Corasf727db92016-06-23 15:01:58 +0200827 gid_address_copy (&dm_args->eid, &map->eid);
Filip Tehlar58f886a2016-05-30 15:57:40 +0200828 dm_args->locator_set_index = map->locator_set_index;
829
830 /* delete mapping associated to fwd entry */
Florin Corasf727db92016-06-23 15:01:58 +0200831 vnet_lisp_map_cache_add_del (dm_args, 0);
Filip Tehlar58f886a2016-05-30 15:57:40 +0200832
833 ls->is_add = 0;
834 ls->local = 0;
835 ls->index = map->locator_set_index;
836 /* delete locator set */
837 rv = vnet_lisp_add_del_locator_set (ls, 0);
838 if (rv != 0)
839 goto cleanup;
840 }
841 }
842
843cleanup:
844 if (map_indices)
845 vec_free (map_indices);
846 return rv;
847}
848
Filip Tehlar195bcee2016-05-13 17:37:35 +0200849/**
Florin Coras71893ac2016-07-10 20:09:32 +0200850 * Adds adjacency or removes forwarding entry associated to remote mapping.
851 * Note that adjacencies are not stored, they only result in forwarding entries
852 * being created.
Florin Corasf727db92016-06-23 15:01:58 +0200853 */
854int
Florin Coras71893ac2016-07-10 20:09:32 +0200855lisp_add_del_adjacency (lisp_cp_main_t * lcm, gid_address_t * local_eid,
856 gid_address_t * remote_eid, u8 is_add)
Florin Corasf727db92016-06-23 15:01:58 +0200857{
Florin Coras71893ac2016-07-10 20:09:32 +0200858 u32 local_mi, remote_mi = ~0;
Florin Corasf727db92016-06-23 15:01:58 +0200859
860 if (vnet_lisp_enable_disable_status () == 0)
861 {
862 clib_warning ("LISP is disabled!");
863 return VNET_API_ERROR_LISP_DISABLED;
864 }
865
Florin Coras71893ac2016-07-10 20:09:32 +0200866 remote_mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, remote_eid);
867 if (GID_LOOKUP_MISS == remote_mi)
868 {
869 clib_warning("Remote eid %U not found. Cannot add adjacency!",
870 format_gid_address, remote_eid);
Florin Corasf727db92016-06-23 15:01:58 +0200871
Florin Coras71893ac2016-07-10 20:09:32 +0200872 return -1;
873 }
874
875 if (is_add)
Florin Corasf727db92016-06-23 15:01:58 +0200876 {
877 /* TODO 1) check if src/dst 2) once we have src/dst working, use it in
878 * delete*/
879
880 /* check if source eid has an associated mapping. If pitr mode is on,
881 * just use the pitr's mapping */
Florin Coras71893ac2016-07-10 20:09:32 +0200882 local_mi = lcm->lisp_pitr ? lcm->pitr_map_index :
883 gid_dictionary_lookup (&lcm->mapping_index_by_gid, local_eid);
Florin Corasf727db92016-06-23 15:01:58 +0200884
885
Florin Coras71893ac2016-07-10 20:09:32 +0200886 if (GID_LOOKUP_MISS == local_mi)
Florin Corasf727db92016-06-23 15:01:58 +0200887 {
Florin Coras71893ac2016-07-10 20:09:32 +0200888 clib_warning("Local eid %U not found. Cannot add adjacency!",
889 format_gid_address, local_eid);
Florin Corasf727db92016-06-23 15:01:58 +0200890
891 return -1;
892 }
893
Florin Coras71893ac2016-07-10 20:09:32 +0200894 /* update forwarding */
895 dp_add_fwd_entry (lcm, local_mi, remote_mi);
Florin Corasf727db92016-06-23 15:01:58 +0200896 }
897 else
Florin Coras71893ac2016-07-10 20:09:32 +0200898 dp_del_fwd_entry (lcm, 0, remote_mi);
Florin Corasf727db92016-06-23 15:01:58 +0200899
900 return 0;
901}
902
903int
904vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a)
905{
906 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
Florin Coras71893ac2016-07-10 20:09:32 +0200907 return lisp_add_del_adjacency(lcm, &a->seid, &a->deid, a->is_add);
Florin Corasf727db92016-06-23 15:01:58 +0200908}
909
910/**
Filip Tehlar195bcee2016-05-13 17:37:35 +0200911 * Handler for add/del remote mapping CLI.
912 *
913 * @param vm vlib context
914 * @param input input from user
915 * @param cmd cmd
916 * @return pointer to clib error structure
917 */
918static clib_error_t *
919lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
920 unformat_input_t * input,
921 vlib_cli_command_t * cmd)
922{
923 clib_error_t * error = 0;
924 unformat_input_t _line_input, * line_input = &_line_input;
Filip Tehlar58f886a2016-05-30 15:57:40 +0200925 u8 is_add = 1, del_all = 0;
Filip Tehlar4d5cabd2016-07-07 15:40:36 +0200926 locator_t rloc, * rlocs = 0, * curr_rloc = 0;
Filip Tehlar195bcee2016-05-13 17:37:35 +0200927 ip_prefix_t * deid_ippref, * seid_ippref;
928 gid_address_t seid, deid;
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200929 u8 * dmac = gid_address_mac (&deid);
930 u8 * smac = gid_address_mac (&seid);
Florin Corasc86f3e52016-06-15 17:13:28 +0200931 u8 deid_set = 0, seid_set = 0;
Filip Tehlar53f09e32016-05-19 14:25:44 +0200932 u8 * s = 0;
Filip Tehlar4d5cabd2016-07-07 15:40:36 +0200933 u32 vni, action = ~0, p, w;
Florin Corasf727db92016-06-23 15:01:58 +0200934 int rv;
Filip Tehlar195bcee2016-05-13 17:37:35 +0200935
936 /* Get a line of input. */
937 if (! unformat_user (input, unformat_line_input, line_input))
938 return 0;
939
Florin Corasf727db92016-06-23 15:01:58 +0200940 memset(&deid, 0, sizeof(deid));
941 memset(&seid, 0, sizeof(seid));
942 memset(&rloc, 0, sizeof(rloc));
Filip Tehlar195bcee2016-05-13 17:37:35 +0200943
944 seid_ippref = &gid_address_ippref(&seid);
945 deid_ippref = &gid_address_ippref(&deid);
946
Filip Tehlar195bcee2016-05-13 17:37:35 +0200947 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
948 {
Filip Tehlar58f886a2016-05-30 15:57:40 +0200949 if (unformat (line_input, "del-all"))
950 del_all = 1;
951 else if (unformat (line_input, "del"))
Filip Tehlar195bcee2016-05-13 17:37:35 +0200952 is_add = 0;
Filip Tehlar58f886a2016-05-30 15:57:40 +0200953 else if (unformat (line_input, "add"))
Filip Tehlar195bcee2016-05-13 17:37:35 +0200954 ;
955 else if (unformat (line_input, "deid %U",
956 unformat_ip_prefix, deid_ippref))
957 {
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200958 gid_address_type (&deid) = GID_ADDR_IP_PREFIX;
959 deid_set = 1;
960 }
961 else if (unformat (line_input, "deid %U",
962 unformat_mac_address, dmac))
963 {
964 gid_address_type (&deid) = GID_ADDR_MAC;
Filip Tehlar195bcee2016-05-13 17:37:35 +0200965 deid_set = 1;
966 }
967 else if (unformat (line_input, "vni %u", &vni))
968 {
Filip Tehlar324112f2016-06-02 16:07:38 +0200969 gid_address_vni (&seid) = vni;
970 gid_address_vni (&deid) = vni;
Filip Tehlar195bcee2016-05-13 17:37:35 +0200971 }
972 else if (unformat (line_input, "seid %U",
973 unformat_ip_prefix, seid_ippref))
Florin Corasc86f3e52016-06-15 17:13:28 +0200974 {
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200975 gid_address_type (&seid) = GID_ADDR_IP_PREFIX;
976 seid_set = 1;
977 }
978 else if (unformat (line_input, "seid %U",
979 unformat_mac_address, smac))
980 {
981 gid_address_type (&seid) = GID_ADDR_MAC;
Florin Corasc86f3e52016-06-15 17:13:28 +0200982 seid_set = 1;
983 }
Filip Tehlar4d5cabd2016-07-07 15:40:36 +0200984 else if (unformat (line_input, "p %d w %d", &p, &w))
985 {
986 if (!curr_rloc)
987 {
988 clib_warning ("No RLOC configured for setting priority/weight!");
989 goto done;
990 }
991 curr_rloc->priority = p;
992 curr_rloc->weight = w;
993 }
994 else if (unformat (line_input, "rloc %U", unformat_ip_address,
995 &rloc.address))
996 {
997 vec_add1 (rlocs, rloc);
998 curr_rloc = &rlocs[vec_len (rlocs) - 1];
999 }
Filip Tehlar53f09e32016-05-19 14:25:44 +02001000 else if (unformat (line_input, "action %s", &s))
1001 {
1002 if (!strcmp ((char *)s, "no-action"))
1003 action = ACTION_NONE;
1004 if (!strcmp ((char *)s, "natively-forward"))
1005 action = ACTION_NATIVELY_FORWARDED;
1006 if (!strcmp ((char *)s, "send-map-request"))
1007 action = ACTION_SEND_MAP_REQUEST;
1008 else if (!strcmp ((char *)s, "drop"))
1009 action = ACTION_DROP;
1010 else
1011 {
1012 clib_warning ("invalid action: '%s'", s);
1013 goto done;
1014 }
1015 }
Filip Tehlar195bcee2016-05-13 17:37:35 +02001016 else
1017 {
1018 clib_warning ("parse error");
1019 goto done;
1020 }
1021 }
1022
Filip Tehlar58f886a2016-05-30 15:57:40 +02001023 if (!del_all)
Filip Tehlar195bcee2016-05-13 17:37:35 +02001024 {
Filip Tehlar58f886a2016-05-30 15:57:40 +02001025 if (!deid_set)
1026 {
1027 clib_warning ("missing deid!");
1028 goto done;
1029 }
Filip Tehlar195bcee2016-05-13 17:37:35 +02001030
Filip Tehlar8e39bb42016-06-24 14:16:34 +02001031 if (GID_ADDR_IP_PREFIX == gid_address_type (&deid))
Filip Tehlar58f886a2016-05-30 15:57:40 +02001032 {
Filip Tehlar8e39bb42016-06-24 14:16:34 +02001033 /* if seid not set, make sure the ip version is the same as that
1034 * of the deid. This ensures the seid to be configured will be
1035 * either 0/0 or ::/0 */
1036 if (!seid_set)
1037 ip_prefix_version(seid_ippref) = ip_prefix_version(deid_ippref);
1038
1039 if (is_add &&
1040 (ip_prefix_version (deid_ippref)
1041 != ip_prefix_version(seid_ippref)))
1042 {
1043 clib_warning ("source and destination EIDs are not"
1044 " in the same IP family!");
1045 goto done;
1046 }
Filip Tehlar58f886a2016-05-30 15:57:40 +02001047 }
Filip Tehlar195bcee2016-05-13 17:37:35 +02001048
Filip Tehlar58f886a2016-05-30 15:57:40 +02001049 if (is_add && (~0 == action)
1050 && 0 == vec_len (rlocs))
1051 {
1052 clib_warning ("no action set for negative map-reply!");
1053 goto done;
1054 }
Filip Tehlar195bcee2016-05-13 17:37:35 +02001055 }
Florin Corasf727db92016-06-23 15:01:58 +02001056 else
1057 {
1058 vnet_lisp_clear_all_remote_adjacencies ();
1059 goto done;
1060 }
Filip Tehlar195bcee2016-05-13 17:37:35 +02001061
Florin Corasf727db92016-06-23 15:01:58 +02001062 /* TODO build src/dst with seid*/
1063
1064 /* if it's a delete, clean forwarding */
1065 if (!is_add)
1066 {
1067 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
Florin Coras71893ac2016-07-10 20:09:32 +02001068 rv = lisp_add_del_adjacency (lcm, 0, &deid, /* is_add */ 0);
Florin Corasf727db92016-06-23 15:01:58 +02001069 }
1070 else
1071 {
1072 /* add as static remote mapping, i.e., not authoritative and infinite
1073 * ttl */
1074 rv = vnet_lisp_add_del_mapping (&deid, rlocs, action, 0, ~0, is_add, 0);
1075 }
1076
Filip Tehlar195bcee2016-05-13 17:37:35 +02001077 if (rv)
Florin Corasf727db92016-06-23 15:01:58 +02001078 clib_warning("failed to %s remote mapping!", is_add ? "add" : "delete");
Filip Tehlar195bcee2016-05-13 17:37:35 +02001079
1080done:
Filip Tehlar4d5cabd2016-07-07 15:40:36 +02001081 vec_free (rlocs);
Filip Tehlar195bcee2016-05-13 17:37:35 +02001082 unformat_free (line_input);
Filip Tehlar53f09e32016-05-19 14:25:44 +02001083 if (s)
1084 vec_free (s);
Filip Tehlar195bcee2016-05-13 17:37:35 +02001085 return error;
1086}
1087
1088VLIB_CLI_COMMAND (lisp_add_del_remote_mapping_command) = {
1089 .path = "lisp remote-mapping",
Filip Tehlar58f886a2016-05-30 15:57:40 +02001090 .short_help = "lisp remote-mapping add|del [del-all] vni <vni>"
Filip Tehlar53f09e32016-05-19 14:25:44 +02001091 "deid <dest-eid> seid <src-eid> [action <no-action|natively-forward|"
1092 "send-map-request|drop>] rloc <dst-locator> [rloc <dst-locator> ... ]",
Filip Tehlar195bcee2016-05-13 17:37:35 +02001093 .function = lisp_add_del_remote_mapping_command_fn,
1094};
1095
Florin Corasf727db92016-06-23 15:01:58 +02001096/**
1097 * Handler for add/del adjacency CLI.
1098 */
1099static clib_error_t *
1100lisp_add_del_adjacency_command_fn (vlib_main_t * vm, unformat_input_t * input,
1101 vlib_cli_command_t * cmd)
1102{
1103 clib_error_t * error = 0;
1104 unformat_input_t _line_input, * line_input = &_line_input;
1105 vnet_lisp_add_del_adjacency_args_t _a, * a = &_a;
1106 u8 is_add = 1;
1107 locator_t rloc, * rlocs = 0;
1108 ip_prefix_t * deid_ippref, * seid_ippref;
1109 gid_address_t seid, deid;
1110 u8 * dmac = gid_address_mac (&deid);
1111 u8 * smac = gid_address_mac (&seid);
1112 u8 deid_set = 0, seid_set = 0;
1113 u8 * s = 0;
1114 u32 vni, action = ~0;
1115 int rv;
1116
1117 /* Get a line of input. */
1118 if (! unformat_user (input, unformat_line_input, line_input))
1119 return 0;
1120
1121 memset(&deid, 0, sizeof(deid));
1122 memset(&seid, 0, sizeof(seid));
1123 memset(&rloc, 0, sizeof(rloc));
1124
1125 seid_ippref = &gid_address_ippref(&seid);
1126 deid_ippref = &gid_address_ippref(&deid);
1127
1128 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1129 {
1130 if (unformat (line_input, "del"))
1131 is_add = 0;
1132 else if (unformat (line_input, "add"))
1133 ;
1134 else if (unformat (line_input, "deid %U",
1135 unformat_ip_prefix, deid_ippref))
1136 {
1137 gid_address_type (&deid) = GID_ADDR_IP_PREFIX;
1138 deid_set = 1;
1139 }
1140 else if (unformat (line_input, "deid %U",
1141 unformat_mac_address, dmac))
1142 {
1143 gid_address_type (&deid) = GID_ADDR_MAC;
1144 deid_set = 1;
1145 }
1146 else if (unformat (line_input, "vni %u", &vni))
1147 {
1148 gid_address_vni (&seid) = vni;
1149 gid_address_vni (&deid) = vni;
1150 }
1151 else if (unformat (line_input, "seid %U",
1152 unformat_ip_prefix, seid_ippref))
1153 {
1154 gid_address_type (&seid) = GID_ADDR_IP_PREFIX;
1155 seid_set = 1;
1156 }
1157 else if (unformat (line_input, "seid %U",
1158 unformat_mac_address, smac))
1159 {
1160 gid_address_type (&seid) = GID_ADDR_MAC;
1161 seid_set = 1;
1162 }
Florin Corasf727db92016-06-23 15:01:58 +02001163 else
1164 {
1165 clib_warning ("parse error");
1166 goto done;
1167 }
1168 }
1169
1170 if (!deid_set)
1171 {
1172 clib_warning ("missing deid!");
1173 goto done;
1174 }
1175
1176 if (GID_ADDR_IP_PREFIX == gid_address_type (&deid))
1177 {
1178 /* if seid not set, make sure the ip version is the same as that
1179 * of the deid. This ensures the seid to be configured will be
1180 * either 0/0 or ::/0 */
1181 if (!seid_set)
1182 ip_prefix_version(seid_ippref) = ip_prefix_version(deid_ippref);
1183
1184 if (is_add &&
1185 (ip_prefix_version (deid_ippref)
1186 != ip_prefix_version(seid_ippref)))
1187 {
1188 clib_warning ("source and destination EIDs are not"
1189 " in the same IP family!");
1190 goto done;
1191 }
1192 }
1193
1194 if (is_add && (~0 == action)
1195 && 0 == vec_len (rlocs))
1196 {
1197 clib_warning ("no action set for negative map-reply!");
1198 goto done;
1199 }
1200
1201 memset(a, 0, sizeof(a[0]));
Florin Coras71893ac2016-07-10 20:09:32 +02001202 gid_address_copy (&a->seid, &deid);
1203 gid_address_copy (&a->deid, &seid);
1204
Florin Corasf727db92016-06-23 15:01:58 +02001205 a->is_add = is_add;
Florin Corasf727db92016-06-23 15:01:58 +02001206 rv = vnet_lisp_add_del_adjacency (a);
1207
1208 if (rv)
1209 clib_warning("failed to %s adjacency!", is_add ? "add" : "delete");
1210
1211done:
1212 unformat_free (line_input);
1213 if (s)
1214 vec_free (s);
1215 return error;
1216}
1217
1218VLIB_CLI_COMMAND (lisp_add_del_adjacency_command) = {
1219 .path = "lisp adjacency",
1220 .short_help = "lisp adjacency add|del vni <vni>"
1221 "deid <dest-eid> seid <src-eid> [action <no-action|natively-forward|"
1222 "send-map-request|drop>] rloc <dst-locator> [rloc <dst-locator> ... ]",
1223 .function = lisp_add_del_adjacency_command_fn,
1224};
1225
1226
Filip Tehlarf747cd82016-05-26 16:47:11 +02001227static clib_error_t *
1228lisp_show_map_resolvers_command_fn (vlib_main_t * vm,
1229 unformat_input_t * input,
1230 vlib_cli_command_t * cmd)
1231{
1232 ip_address_t * addr;
1233 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
1234
1235 vec_foreach (addr, lcm->map_resolvers)
1236 {
1237 vlib_cli_output (vm, "%U", format_ip_address, addr);
1238 }
1239 return 0;
1240}
1241
1242VLIB_CLI_COMMAND (lisp_show_map_resolvers_command) = {
1243 .path = "show lisp map-resolvers",
1244 .short_help = "show lisp map-resolvers",
1245 .function = lisp_show_map_resolvers_command_fn,
1246};
1247
Filip Tehlar53f09e32016-05-19 14:25:44 +02001248int
1249vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add)
1250{
1251 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
1252 u32 locator_set_index = ~0;
1253 mapping_t * m;
1254 uword * p;
1255
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +02001256 if (vnet_lisp_enable_disable_status () == 0)
1257 {
1258 clib_warning ("LISP is disabled!");
1259 return VNET_API_ERROR_LISP_DISABLED;
1260 }
1261
Filip Tehlar53f09e32016-05-19 14:25:44 +02001262 p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
1263 if (!p)
1264 {
1265 clib_warning ("locator-set %v doesn't exist", locator_set_name);
1266 return -1;
1267 }
1268 locator_set_index = p[0];
1269
1270 if (is_add)
1271 {
1272 pool_get (lcm->mapping_pool, m);
1273 m->locator_set_index = locator_set_index;
1274 m->local = 1;
1275 lcm->pitr_map_index = m - lcm->mapping_pool;
1276
1277 /* enable pitr mode */
1278 lcm->lisp_pitr = 1;
1279 }
1280 else
1281 {
1282 /* remove pitr mapping */
1283 pool_put_index (lcm->mapping_pool, lcm->pitr_map_index);
1284
1285 /* disable pitr mode */
1286 lcm->lisp_pitr = 0;
1287 }
1288 return 0;
1289}
1290
1291static clib_error_t *
1292lisp_pitr_set_locator_set_command_fn (vlib_main_t * vm,
1293 unformat_input_t * input,
1294 vlib_cli_command_t * cmd)
1295{
1296 u8 locator_name_set = 0;
1297 u8 * locator_set_name = 0;
1298 u8 is_add = 1;
1299 unformat_input_t _line_input, * line_input = &_line_input;
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +02001300 clib_error_t * error = 0;
1301 int rv = 0;
Filip Tehlar53f09e32016-05-19 14:25:44 +02001302
1303 /* Get a line of input. */
1304 if (! unformat_user (input, unformat_line_input, line_input))
1305 return 0;
1306
1307 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1308 {
1309 if (unformat (line_input, "ls %_%v%_", &locator_set_name))
1310 locator_name_set = 1;
1311 else if (unformat (line_input, "disable"))
1312 is_add = 0;
1313 else
1314 return clib_error_return (0, "parse error");
1315 }
1316
1317 if (!locator_name_set)
1318 {
1319 clib_warning ("No locator set specified!");
1320 goto done;
1321 }
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +02001322 rv = vnet_lisp_pitr_set_locator_set (locator_set_name, is_add);
1323 if (0 != rv)
1324 {
1325 error = clib_error_return(0, "failed to %s pitr!",
1326 is_add ? "add" : "delete");
1327 }
Filip Tehlar53f09e32016-05-19 14:25:44 +02001328
1329done:
1330 if (locator_set_name)
1331 vec_free (locator_set_name);
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +02001332 return error;
Filip Tehlar53f09e32016-05-19 14:25:44 +02001333}
1334
1335VLIB_CLI_COMMAND (lisp_pitr_set_locator_set_command) = {
1336 .path = "lisp pitr",
1337 .short_help = "lisp pitr [disable] ls <locator-set-name>",
1338 .function = lisp_pitr_set_locator_set_command_fn,
1339};
1340
Andrej Kozemcak914f91b2016-07-18 13:55:37 +02001341static clib_error_t *
1342lisp_show_pitr_command_fn (vlib_main_t * vm,
1343 unformat_input_t * input,
1344 vlib_cli_command_t * cmd)
1345{
1346 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
1347 mapping_t * m;
1348 locator_set_t * ls;
1349 u8 * tmp_str = 0;
1350
1351 vlib_cli_output (vm, "%=20s%=16s",
1352 "pitr", lcm->lisp_pitr ? "locator-set" : "");
1353
1354 if (!lcm->lisp_pitr) {
1355 vlib_cli_output (vm, "%=20s", "disable");
1356 return 0;
1357 }
1358
1359 if (~0 == lcm->pitr_map_index) {
1360 tmp_str = format(0, "N/A");
1361 } else {
1362 m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
1363 if (~0 != m->locator_set_index) {
1364 ls = pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
1365 tmp_str = format(0, "%s", ls->name);
1366 } else {
1367 tmp_str = format(0, "N/A");
1368 }
1369 }
1370 vec_add1(tmp_str, 0);
1371
1372 vlib_cli_output (vm, "%=20s%=16s",
1373 "enable", tmp_str);
1374
1375 vec_free(tmp_str);
1376
1377 return 0;
1378}
1379
1380VLIB_CLI_COMMAND (lisp_show_pitr_command) = {
1381 .path = "show lisp pitr",
1382 .short_help = "Show pitr",
1383 .function = lisp_show_pitr_command_fn,
1384};
Filip Tehlarb0ccf032016-06-22 09:18:12 +02001385
1386static u8 *
1387format_eid_entry (u8 * s, va_list * args)
1388{
1389 vnet_main_t * vnm = va_arg (*args, vnet_main_t *);
1390 lisp_cp_main_t * lcm = va_arg (*args, lisp_cp_main_t *);
1391 gid_address_t * gid = va_arg (*args, gid_address_t *);
1392 locator_set_t * ls = va_arg (*args, locator_set_t *);
1393 u32 * loc_index;
1394 u8 first_line = 1;
1395 u8 * loc;
1396
1397 u8 * type = ls->local ? format(0, "local(%s)", ls->name)
1398 : format(0, "remote");
1399
1400 if (vec_len (ls->locator_indices) == 0)
1401 {
1402 s = format (s, "%-35U%-20s", format_gid_address, gid, type);
1403 }
1404 else
1405 {
1406 vec_foreach (loc_index, ls->locator_indices)
1407 {
1408 locator_t * l = pool_elt_at_index (lcm->locator_pool, loc_index[0]);
1409 if (l->local)
1410 loc = format (0, "%U", format_vnet_sw_if_index_name, vnm,
1411 l->sw_if_index);
1412 else
1413 loc = format (0, "%U", format_ip_address,
1414 &gid_address_ip (&l->address));
1415
1416 if (first_line)
1417 {
1418 s = format (s, "%-35U%-20s%-v\n", format_gid_address,
1419 gid, type, loc);
1420 first_line = 0;
1421 }
1422 else
1423 s = format (s, "%55s%v\n", "", loc);
1424 }
1425 }
1426 return s;
1427}
1428
Florin Corase127a7e2016-02-18 22:20:01 +01001429static clib_error_t *
Filip Tehlarb0ccf032016-06-22 09:18:12 +02001430lisp_show_eid_table_command_fn (vlib_main_t * vm,
1431 unformat_input_t * input,
1432 vlib_cli_command_t * cmd)
Florin Corase127a7e2016-02-18 22:20:01 +01001433{
1434 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
1435 mapping_t * mapit;
Filip Tehlar1b1ee4f2016-07-04 11:43:11 +02001436 unformat_input_t _line_input, * line_input = &_line_input;
1437 u32 mi;
1438 gid_address_t eid;
1439 u8 print_all = 1;
1440
1441 memset (&eid, 0, sizeof(eid));
1442
1443 /* Get a line of input. */
1444 if (!unformat_user (input, unformat_line_input, line_input))
1445 return 0;
1446
1447 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1448 {
1449 if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
1450 print_all = 0;
1451 else
1452 return clib_error_return (0, "parse error: '%U'",
1453 format_unformat_error, line_input);
1454 }
Florin Corase127a7e2016-02-18 22:20:01 +01001455
Filip Tehlarb0ccf032016-06-22 09:18:12 +02001456 vlib_cli_output (vm, "%-35s%-20s%-s", "EID", "type", "locators");
Filip Tehlar1b1ee4f2016-07-04 11:43:11 +02001457
1458 if (print_all)
1459 {
1460 pool_foreach (mapit, lcm->mapping_pool,
1461 ({
1462 locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool,
1463 mapit->locator_set_index);
1464 vlib_cli_output (vm, "%U", format_eid_entry, lcm->vnet_main,
1465 lcm, &mapit->eid, ls);
1466 }));
1467 }
1468 else
1469 {
1470 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &eid);
1471 if ((u32)~0 == mi)
1472 return 0;
1473
1474 mapit = pool_elt_at_index (lcm->mapping_pool, mi);
1475 locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool,
1476 mapit->locator_set_index);
1477 vlib_cli_output (vm, "%U", format_eid_entry, lcm->vnet_main,
1478 lcm, &mapit->eid, ls);
1479 }
Florin Corase127a7e2016-02-18 22:20:01 +01001480
1481 return 0;
1482}
1483
Filip Tehlarb0ccf032016-06-22 09:18:12 +02001484VLIB_CLI_COMMAND (lisp_cp_show_eid_table_command) = {
Florin Corase127a7e2016-02-18 22:20:01 +01001485 .path = "show lisp eid-table",
Filip Tehlarb0ccf032016-06-22 09:18:12 +02001486 .short_help = "Shows EID table",
1487 .function = lisp_show_eid_table_command_fn,
Florin Corase127a7e2016-02-18 22:20:01 +01001488};
1489
1490/* cleans locator to locator-set data and removes locators not part of
1491 * any locator-set */
1492static void
1493clean_locator_to_locator_set (lisp_cp_main_t * lcm, u32 lsi)
1494{
Filip Tehlard1c5cc32016-05-30 10:39:20 +02001495 u32 i, j, *loc_indexp, *ls_indexp, **ls_indexes, *to_be_deleted = 0;
Florin Corase127a7e2016-02-18 22:20:01 +01001496 locator_set_t * ls = pool_elt_at_index(lcm->locator_set_pool, lsi);
1497 for (i = 0; i < vec_len(ls->locator_indices); i++)
1498 {
1499 loc_indexp = vec_elt_at_index(ls->locator_indices, i);
1500 ls_indexes = vec_elt_at_index(lcm->locator_to_locator_sets,
1501 loc_indexp[0]);
1502 for (j = 0; j < vec_len(ls_indexes[0]); j++)
1503 {
1504 ls_indexp = vec_elt_at_index(ls_indexes[0], j);
1505 if (ls_indexp[0] == lsi)
1506 break;
1507 }
1508
1509 /* delete index for removed locator-set*/
1510 vec_del1(ls_indexes[0], j);
1511
1512 /* delete locator if it's part of no locator-set */
1513 if (vec_len (ls_indexes[0]) == 0)
Filip Tehlard1c5cc32016-05-30 10:39:20 +02001514 {
1515 pool_put_index (lcm->locator_pool, loc_indexp[0]);
1516 vec_add1 (to_be_deleted, i);
1517 }
1518 }
1519
1520 if (to_be_deleted)
1521 {
1522 for (i = 0; i < vec_len (to_be_deleted); i++)
1523 {
1524 loc_indexp = vec_elt_at_index (to_be_deleted, i);
1525 vec_del1 (ls->locator_indices, loc_indexp[0]);
1526 }
1527 vec_free (to_be_deleted);
Florin Corase127a7e2016-02-18 22:20:01 +01001528 }
1529}
Filip Tehlard1c5cc32016-05-30 10:39:20 +02001530
Florin Corasf727db92016-06-23 15:01:58 +02001531static inline uword *
1532get_locator_set_index (vnet_lisp_add_del_locator_set_args_t * a, uword * p)
Andrej Kozemcak6a2e4392016-05-26 12:20:08 +02001533{
1534 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
1535
1536 ASSERT(a != NULL);
1537 ASSERT(p != NULL);
1538
1539 /* find locator-set */
1540 if (a->local)
1541 {
1542 p = hash_get_mem(lcm->locator_set_index_by_name, a->name);
1543 }
1544 else
1545 {
1546 *p = a->index;
1547 }
1548
1549 return p;
1550}
1551
Florin Corasf727db92016-06-23 15:01:58 +02001552static inline int
1553is_locator_in_locator_set (lisp_cp_main_t * lcm, locator_set_t * ls,
1554 locator_t * loc)
Andrej Kozemcak6a2e4392016-05-26 12:20:08 +02001555{
1556 locator_t * itloc;
1557 u32 * locit;
1558
1559 ASSERT(ls != NULL);
1560 ASSERT(loc != NULL);
1561
1562 vec_foreach(locit, ls->locator_indices)
1563 {
1564 itloc = pool_elt_at_index(lcm->locator_pool, locit[0]);
1565 if (itloc->sw_if_index == loc->sw_if_index ||
1566 !gid_address_cmp(&itloc->address, &loc->address))
1567 {
1568 clib_warning("Duplicate locator");
1569 return VNET_API_ERROR_VALUE_EXIST;
1570 }
1571 }
1572
1573 return 0;
1574}
1575
Florin Corasf727db92016-06-23 15:01:58 +02001576static inline void
1577remove_locator_from_locator_set (locator_set_t * ls, u32 * locit, u32 ls_index,
1578 u32 loc_id)
Andrej Kozemcak6a2e4392016-05-26 12:20:08 +02001579{
1580 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
1581 u32 ** ls_indexes = NULL;
1582
1583 ASSERT(ls != NULL);
1584 ASSERT(locit != NULL);
1585
1586 ls_indexes = vec_elt_at_index(lcm->locator_to_locator_sets,
1587 locit[0]);
1588 pool_put_index(lcm->locator_pool, locit[0]);
1589 vec_del1(ls->locator_indices, loc_id);
1590 vec_del1(ls_indexes[0], ls_index);
1591}
1592
1593int
1594vnet_lisp_add_del_locator (vnet_lisp_add_del_locator_set_args_t * a,
1595 locator_set_t * ls, u32 * ls_result)
1596{
1597 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
1598 locator_t * loc = NULL, *itloc = NULL;
1599 uword _p = (u32)~0, * p = &_p;
1600 u32 loc_index = ~0, ls_index = ~0, * locit = NULL, ** ls_indexes = NULL;
1601 u32 loc_id = ~0;
1602 int ret = 0;
1603
1604 ASSERT(a != NULL);
1605
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +02001606 if (vnet_lisp_enable_disable_status () == 0)
1607 {
1608 clib_warning ("LISP is disabled!");
1609 return VNET_API_ERROR_LISP_DISABLED;
1610 }
1611
Andrej Kozemcak6a2e4392016-05-26 12:20:08 +02001612 p = get_locator_set_index(a, p);
1613 if (!p)
1614 {
1615 clib_warning("locator-set %v doesn't exist", a->name);
1616 return VNET_API_ERROR_INVALID_ARGUMENT;
1617 }
1618
1619 if (ls == 0)
1620 {
1621 ls = pool_elt_at_index(lcm->locator_set_pool, p[0]);
1622 if (!ls)
1623 {
1624 clib_warning("locator-set %d to be overwritten doesn't exist!",
1625 p[0]);
1626 return VNET_API_ERROR_INVALID_ARGUMENT;
1627 }
1628 }
1629
1630 if (a->is_add)
1631 {
1632
1633 if (ls_result)
1634 ls_result[0] = p[0];
1635
1636 /* allocate locators */
1637 vec_foreach (itloc, a->locators)
1638 {
1639 ret = is_locator_in_locator_set(lcm, ls, itloc);
1640 if (0 != ret)
1641 {
1642 return ret;
1643 }
1644
1645 pool_get(lcm->locator_pool, loc);
1646 loc[0] = itloc[0];
1647 loc_index = loc - lcm->locator_pool;
1648
1649 vec_add1(ls->locator_indices, loc_index);
1650
1651 vec_validate (lcm->locator_to_locator_sets, loc_index);
1652 ls_indexes = vec_elt_at_index(lcm->locator_to_locator_sets,
1653 loc_index);
1654 vec_add1(ls_indexes[0], ls_index);
1655 }
1656 }
1657 else
1658 {
1659 ls_index = p[0];
1660
1661 itloc = a->locators;
1662 loc_id = 0;
1663 vec_foreach (locit, ls->locator_indices)
1664 {
1665 loc = pool_elt_at_index(lcm->locator_pool, locit[0]);
1666
1667 if (loc->local && loc->sw_if_index == itloc->sw_if_index)
1668 {
1669 remove_locator_from_locator_set(ls, locit,
1670 ls_index, loc_id);
1671 }
1672 if (0 == loc->local &&
1673 !gid_address_cmp(&loc->address, &itloc->address))
1674 {
1675 remove_locator_from_locator_set(ls, locit,
1676 ls_index, loc_id);
1677 }
1678
1679 loc_id++;
1680 }
1681 }
1682
1683 return 0;
1684}
1685
Florin Corase127a7e2016-02-18 22:20:01 +01001686int
1687vnet_lisp_add_del_locator_set (vnet_lisp_add_del_locator_set_args_t * a,
1688 u32 * ls_result)
1689{
1690 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
1691 locator_set_t * ls;
Florin Corase127a7e2016-02-18 22:20:01 +01001692 uword _p = (u32)~0, * p = &_p;
Andrej Kozemcak6a2e4392016-05-26 12:20:08 +02001693 u32 ls_index;
1694 u32 ** eid_indexes;
1695 int ret = 0;
Florin Corase127a7e2016-02-18 22:20:01 +01001696
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +02001697 if (vnet_lisp_enable_disable_status () == 0)
1698 {
1699 clib_warning ("LISP is disabled!");
1700 return VNET_API_ERROR_LISP_DISABLED;
1701 }
1702
Florin Corase127a7e2016-02-18 22:20:01 +01001703 if (a->is_add)
1704 {
Andrej Kozemcak6a2e4392016-05-26 12:20:08 +02001705 p = get_locator_set_index(a, p);
Florin Corase127a7e2016-02-18 22:20:01 +01001706
1707 /* overwrite */
1708 if (p && p[0] != (u32)~0)
1709 {
1710 ls = pool_elt_at_index(lcm->locator_set_pool, p[0]);
1711 if (!ls)
1712 {
1713 clib_warning("locator-set %d to be overwritten doesn't exist!",
1714 p[0]);
1715 return -1;
1716 }
1717
1718 /* clean locator to locator-set vectors and remove locators if
1719 * they're not part of another locator-set */
1720 clean_locator_to_locator_set (lcm, p[0]);
1721
1722 /* remove locator indices from locator set */
1723 vec_free(ls->locator_indices);
1724
1725 ls_index = p[0];
1726
1727 if (ls_result)
1728 ls_result[0] = p[0];
1729 }
1730 /* new locator-set */
1731 else
1732 {
1733 pool_get(lcm->locator_set_pool, ls);
Andrej Kozemcak6a2e4392016-05-26 12:20:08 +02001734 memset(ls, 0, sizeof(*ls));
Florin Corase127a7e2016-02-18 22:20:01 +01001735 ls_index = ls - lcm->locator_set_pool;
1736
1737 if (a->local)
1738 {
1739 ls->name = vec_dup(a->name);
1740
1741 if (!lcm->locator_set_index_by_name)
1742 lcm->locator_set_index_by_name = hash_create_vec(
1743 /* size */0, sizeof(ls->name[0]), sizeof(uword));
1744 hash_set_mem(lcm->locator_set_index_by_name, ls->name, ls_index);
1745
1746 /* mark as local locator-set */
1747 vec_add1(lcm->local_locator_set_indexes, ls_index);
1748 }
1749 ls->local = a->local;
1750 if (ls_result)
1751 ls_result[0] = ls_index;
1752 }
1753
Andrej Kozemcak6a2e4392016-05-26 12:20:08 +02001754 ret = vnet_lisp_add_del_locator(a, ls, NULL);
1755 if (0 != ret)
Florin Corase127a7e2016-02-18 22:20:01 +01001756 {
Andrej Kozemcak6a2e4392016-05-26 12:20:08 +02001757 return ret;
Florin Corase127a7e2016-02-18 22:20:01 +01001758 }
1759 }
1760 else
1761 {
Andrej Kozemcak6a2e4392016-05-26 12:20:08 +02001762 p = get_locator_set_index(a, p);
1763 if (!p)
Florin Corase127a7e2016-02-18 22:20:01 +01001764 {
Andrej Kozemcak6a2e4392016-05-26 12:20:08 +02001765 clib_warning("locator-set %v doesn't exists", a->name);
1766 return -1;
Florin Corase127a7e2016-02-18 22:20:01 +01001767 }
Florin Corase127a7e2016-02-18 22:20:01 +01001768
1769 ls = pool_elt_at_index(lcm->locator_set_pool, p[0]);
1770 if (!ls)
1771 {
1772 clib_warning("locator-set with index %d doesn't exists", p[0]);
1773 return -1;
1774 }
Florin Corase127a7e2016-02-18 22:20:01 +01001775
Andrej Kozemcakb6e4d392016-06-14 13:55:57 +02001776 if (lcm->mreq_itr_rlocs == p[0])
1777 {
1778 clib_warning ("Can't delete the locator-set used to constrain "
1779 "the itr-rlocs in map-requests!");
1780 return -1;
1781 }
1782
Andrej Kozemcakb92feb62016-03-31 13:51:42 +02001783 if (vec_len(lcm->locator_set_to_eids) != 0)
1784 {
1785 eid_indexes = vec_elt_at_index(lcm->locator_set_to_eids, p[0]);
1786 if (vec_len(eid_indexes[0]) != 0)
1787 {
1788 clib_warning ("Can't delete a locator that supports a mapping!");
1789 return -1;
1790 }
1791 }
1792
1793 /* clean locator to locator-sets data */
1794 clean_locator_to_locator_set (lcm, p[0]);
1795
1796 if (ls->local)
1797 {
1798 u32 it, lsi;
1799
1800 vec_foreach_index(it, lcm->local_locator_set_indexes)
1801 {
1802 lsi = vec_elt(lcm->local_locator_set_indexes, it);
1803 if (lsi == p[0])
1804 {
1805 vec_del1(lcm->local_locator_set_indexes, it);
1806 break;
1807 }
1808 }
1809 hash_unset_mem(lcm->locator_set_index_by_name, ls->name);
Andrej Kozemcakb92feb62016-03-31 13:51:42 +02001810 }
Andrej Kozemcak6a2e4392016-05-26 12:20:08 +02001811 vec_free(ls->name);
1812 vec_free(ls->locator_indices);
Andrej Kozemcakb92feb62016-03-31 13:51:42 +02001813 pool_put(lcm->locator_set_pool, ls);
1814 }
1815 return 0;
1816}
1817
Filip Tehlar46d4e362016-05-09 09:39:26 +02001818clib_error_t *
Florin Corasf727db92016-06-23 15:01:58 +02001819vnet_lisp_enable_disable (u8 is_enable)
Filip Tehlar46d4e362016-05-09 09:39:26 +02001820{
Florin Corasf727db92016-06-23 15:01:58 +02001821 u32 vni, table_id;
Filip Tehlar46d4e362016-05-09 09:39:26 +02001822 clib_error_t * error = 0;
1823 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
1824 vnet_lisp_gpe_enable_disable_args_t _a, * a = &_a;
1825
Florin Corasf727db92016-06-23 15:01:58 +02001826 a->is_en = is_enable;
Filip Tehlar46d4e362016-05-09 09:39:26 +02001827 error = vnet_lisp_gpe_enable_disable (a);
1828 if (error)
1829 {
1830 return clib_error_return (0, "failed to %s data-plane!",
1831 a->is_en ? "enable" : "disable");
1832 }
1833
Florin Corasf727db92016-06-23 15:01:58 +02001834 if (is_enable)
Filip Tehlar46d4e362016-05-09 09:39:26 +02001835 {
1836 /* enable all ifaces */
Florin Corasf727db92016-06-23 15:01:58 +02001837 hash_foreach(vni, table_id, lcm->table_id_by_vni, ({
1838 dp_add_del_iface(lcm, vni, 1);
1839 }));
Filip Tehlar46d4e362016-05-09 09:39:26 +02001840 }
1841 else
1842 {
Florin Corasf727db92016-06-23 15:01:58 +02001843 /* clear interface table */
1844 hash_free(lcm->dp_intf_by_vni);
1845 hash_free(lcm->fwd_entry_by_mapping_index);
1846 pool_free(lcm->fwd_entry_pool);
Filip Tehlar46d4e362016-05-09 09:39:26 +02001847 }
1848
1849 /* update global flag */
Florin Corasf727db92016-06-23 15:01:58 +02001850 lcm->is_enabled = is_enable;
Filip Tehlar46d4e362016-05-09 09:39:26 +02001851
1852 return 0;
1853}
1854
1855static clib_error_t *
1856lisp_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input,
Florin Corasf727db92016-06-23 15:01:58 +02001857 vlib_cli_command_t * cmd)
Filip Tehlar46d4e362016-05-09 09:39:26 +02001858{
1859 unformat_input_t _line_input, * line_input = &_line_input;
1860 u8 is_enabled = 0;
1861 u8 is_set = 0;
1862
1863 /* Get a line of input. */
1864 if (! unformat_user (input, unformat_line_input, line_input))
1865 return 0;
1866
1867 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1868 {
1869 if (unformat (line_input, "enable"))
1870 {
1871 is_set = 1;
1872 is_enabled = 1;
1873 }
1874 else if (unformat (line_input, "disable"))
1875 is_set = 1;
1876 else
1877 {
1878 return clib_error_return (0, "parse error: '%U'",
1879 format_unformat_error, line_input);
1880 }
1881 }
1882
1883 if (!is_set)
1884 return clib_error_return (0, "state not set");
1885
1886 return vnet_lisp_enable_disable (is_enabled);
1887}
1888
1889VLIB_CLI_COMMAND (lisp_cp_enable_disable_command) = {
1890 .path = "lisp",
1891 .short_help = "lisp [enable|disable]",
1892 .function = lisp_enable_disable_command_fn,
1893};
1894
1895u8
1896vnet_lisp_enable_disable_status (void)
1897{
1898 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
1899 return lcm->is_enabled;
1900}
1901
1902static u8 *
1903format_lisp_status (u8 * s, va_list * args)
1904{
1905 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
1906 return format (s, "%s", lcm->is_enabled ? "enabled" : "disabled");
1907}
1908
1909static clib_error_t *
1910lisp_show_status_command_fn (vlib_main_t * vm, unformat_input_t * input,
1911 vlib_cli_command_t * cmd)
1912{
1913 u8 * msg = 0;
1914 msg = format (msg, "feature: %U\ngpe: %U\n",
1915 format_lisp_status, format_vnet_lisp_gpe_status);
1916 vlib_cli_output (vm, "%v", msg);
1917 vec_free (msg);
1918 return 0;
1919}
1920
1921VLIB_CLI_COMMAND (lisp_show_status_command) = {
1922 .path = "show lisp status",
1923 .short_help = "show lisp status",
1924 .function = lisp_show_status_command_fn,
1925};
Filip Tehlar324112f2016-06-02 16:07:38 +02001926
1927static clib_error_t *
1928lisp_show_eid_table_map_command_fn (vlib_main_t * vm, unformat_input_t * input,
1929 vlib_cli_command_t * cmd)
1930{
1931 hash_pair_t * p;
1932 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
1933
1934 vlib_cli_output (vm, "%=10s%=10s", "VNI", "VRF");
1935 hash_foreach_pair (p, lcm->table_id_by_vni,
1936 {
1937 vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]);
1938 });
1939 return 0;
1940}
1941
1942VLIB_CLI_COMMAND (lisp_show_eid_table_map_command) = {
1943 .path = "show lisp eid-table map",
1944 .short_help = "show lisp eid-table vni to vrf mappings",
1945 .function = lisp_show_eid_table_map_command_fn,
1946};
1947
Florin Corase127a7e2016-02-18 22:20:01 +01001948static clib_error_t *
1949lisp_add_del_locator_set_command_fn (vlib_main_t * vm, unformat_input_t * input,
1950 vlib_cli_command_t * cmd)
1951{
1952 lisp_gpe_main_t * lgm = &lisp_gpe_main;
1953 vnet_main_t * vnm = lgm->vnet_main;
1954 unformat_input_t _line_input, * line_input = &_line_input;
1955 u8 is_add = 1;
1956 clib_error_t * error = 0;
1957 u8 * locator_set_name = 0;
1958 locator_t locator, * locators = 0;
1959 vnet_lisp_add_del_locator_set_args_t _a, * a = &_a;
1960 u32 ls_index = 0;
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +02001961 int rv = 0;
Florin Corase127a7e2016-02-18 22:20:01 +01001962
1963 memset(&locator, 0, sizeof(locator));
1964 memset(a, 0, sizeof(a[0]));
1965
1966 /* Get a line of input. */
1967 if (! unformat_user (input, unformat_line_input, line_input))
1968 return 0;
1969
1970 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1971 {
1972 if (unformat (line_input, "add %_%v%_", &locator_set_name))
1973 is_add = 1;
1974 else if (unformat (line_input, "del %_%v%_", &locator_set_name))
1975 is_add = 0;
1976 else if (unformat (line_input, "iface %U p %d w %d",
1977 unformat_vnet_sw_interface, vnm, &locator.sw_if_index,
1978 &locator.priority, &locator.weight))
1979 {
1980 locator.local = 1;
1981 vec_add1(locators, locator);
1982 }
1983 else
1984 {
1985 error = unformat_parse_error(line_input);
1986 goto done;
1987 }
1988 }
1989
1990 a->name = locator_set_name;
1991 a->locators = locators;
1992 a->is_add = is_add;
1993 a->local = 1;
1994
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +02001995 rv = vnet_lisp_add_del_locator_set(a, &ls_index);
1996 if (0 != rv)
1997 {
1998 error = clib_error_return(0, "failed to %s locator-set!",
1999 is_add ? "add" : "delete");
2000 }
Florin Corase127a7e2016-02-18 22:20:01 +01002001
2002 done:
2003 vec_free(locators);
Filip Tehlar53f09e32016-05-19 14:25:44 +02002004 if (locator_set_name)
2005 vec_free (locator_set_name);
Florin Corase127a7e2016-02-18 22:20:01 +01002006 return error;
2007}
2008
2009VLIB_CLI_COMMAND (lisp_cp_add_del_locator_set_command) = {
2010 .path = "lisp locator-set",
Andrej Kozemcak7511ae82016-06-20 10:08:20 +02002011 .short_help = "lisp locator-set add/del <name> [iface <iface-name> "
2012 "p <priority> w <weight>]",
Florin Corase127a7e2016-02-18 22:20:01 +01002013 .function = lisp_add_del_locator_set_command_fn,
2014};
2015
2016static clib_error_t *
Andrej Kozemcak7511ae82016-06-20 10:08:20 +02002017lisp_add_del_locator_in_set_command_fn (vlib_main_t * vm, unformat_input_t * input,
2018 vlib_cli_command_t * cmd)
2019{
2020 lisp_gpe_main_t * lgm = &lisp_gpe_main;
2021 vnet_main_t * vnm = lgm->vnet_main;
2022 unformat_input_t _line_input, * line_input = &_line_input;
2023 u8 is_add = 1;
2024 clib_error_t * error = 0;
2025 u8 * locator_set_name = 0;
2026 u8 locator_set_name_set = 0;
2027 locator_t locator, * locators = 0;
2028 vnet_lisp_add_del_locator_set_args_t _a, * a = &_a;
2029 u32 ls_index = 0;
2030
2031 memset(&locator, 0, sizeof(locator));
2032 memset(a, 0, sizeof(a[0]));
2033
2034 /* Get a line of input. */
2035 if (! unformat_user (input, unformat_line_input, line_input))
2036 return 0;
2037
2038 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2039 {
2040 if (unformat (line_input, "add"))
2041 is_add = 1;
2042 else if (unformat (line_input, "del"))
2043 is_add = 0;
2044 else if (unformat(line_input, "locator-set %_%v%_", &locator_set_name))
2045 locator_set_name_set = 1;
2046 else if (unformat (line_input, "iface %U p %d w %d",
2047 unformat_vnet_sw_interface, vnm, &locator.sw_if_index,
2048 &locator.priority, &locator.weight))
2049 {
2050 locator.local = 1;
2051 vec_add1(locators, locator);
2052 }
2053 else
2054 {
2055 error = unformat_parse_error(line_input);
2056 goto done;
2057 }
2058 }
2059
2060 if (!locator_set_name_set)
2061 {
2062 error = clib_error_return(0, "locator_set name not set!");
2063 goto done;
2064 }
2065
2066 a->name = locator_set_name;
2067 a->locators = locators;
2068 a->is_add = is_add;
2069 a->local = 1;
2070
2071 vnet_lisp_add_del_locator(a, 0, &ls_index);
2072
2073 done:
2074 vec_free(locators);
2075 vec_free (locator_set_name);
2076 return error;
2077}
2078
2079VLIB_CLI_COMMAND (lisp_cp_add_del_locator_in_set_command) = {
2080 .path = "lisp locator",
2081 .short_help = "lisp locator add/del locator-set <name> iface <iface-name> "
2082 "p <priority> w <weight>",
2083 .function = lisp_add_del_locator_in_set_command_fn,
2084};
2085
2086static clib_error_t *
Florin Corase127a7e2016-02-18 22:20:01 +01002087lisp_cp_show_locator_sets_command_fn (vlib_main_t * vm,
2088 unformat_input_t * input,
2089 vlib_cli_command_t * cmd)
2090{
2091 locator_set_t * lsit;
2092 locator_t * loc;
2093 u32 * locit;
2094 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
2095
2096 vlib_cli_output (vm, "%=20s%=16s%=16s%=16s", "Locator-set", "Locator",
2097 "Priority", "Weight");
2098 pool_foreach (lsit, lcm->locator_set_pool,
2099 ({
2100 u8 * msg = 0;
Andrej Kozemcak7511ae82016-06-20 10:08:20 +02002101 int next_line = 0;
2102 msg = format (msg, "%=16v", lsit->name);
Florin Corase127a7e2016-02-18 22:20:01 +01002103 vec_foreach (locit, lsit->locator_indices)
2104 {
Andrej Kozemcak7511ae82016-06-20 10:08:20 +02002105 if (next_line)
2106 {
2107 msg = format (msg, "%16s", " ");
2108 }
Florin Corase127a7e2016-02-18 22:20:01 +01002109 loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
2110 if (loc->local)
Andrej Kozemcak7511ae82016-06-20 10:08:20 +02002111 msg = format (msg, "%16d%16d%16d\n", loc->sw_if_index, loc->priority,
Florin Corase127a7e2016-02-18 22:20:01 +01002112 loc->weight);
2113 else
Andrej Kozemcak7511ae82016-06-20 10:08:20 +02002114 msg = format (msg, "%16U%16d%16d\n", format_ip_address,
Filip Tehlar4d5cabd2016-07-07 15:40:36 +02002115 &gid_address_ip(&loc->address), loc->priority,
Andrej Kozemcak7511ae82016-06-20 10:08:20 +02002116 loc->weight);
2117 next_line = 1;
Florin Corase127a7e2016-02-18 22:20:01 +01002118 }
2119 vlib_cli_output (vm, "%v", msg);
2120 vec_free (msg);
2121 }));
2122 return 0;
2123}
2124
2125VLIB_CLI_COMMAND (lisp_cp_show_locator_sets_command) = {
2126 .path = "show lisp locator-set",
2127 .short_help = "Shows locator-sets",
2128 .function = lisp_cp_show_locator_sets_command_fn,
2129};
2130
2131int
2132vnet_lisp_add_del_map_resolver (vnet_lisp_add_del_map_resolver_args_t * a)
2133{
2134 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
2135 ip_address_t * addr;
2136 u32 i;
2137
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +02002138 if (vnet_lisp_enable_disable_status () == 0)
2139 {
2140 clib_warning ("LISP is disabled!");
2141 return VNET_API_ERROR_LISP_DISABLED;
2142 }
2143
Florin Corase127a7e2016-02-18 22:20:01 +01002144 if (a->is_add)
2145 {
2146 vec_foreach(addr, lcm->map_resolvers)
2147 {
2148 if (!ip_address_cmp (addr, &a->address))
2149 {
2150 clib_warning("map-resolver %U already exists!", format_ip_address,
2151 &a->address);
2152 return -1;
2153 }
2154 }
2155 vec_add1(lcm->map_resolvers, a->address);
2156 }
2157 else
2158 {
2159 for (i = 0; i < vec_len(lcm->map_resolvers); i++)
2160 {
2161 addr = vec_elt_at_index(lcm->map_resolvers, i);
2162 if (!ip_address_cmp (addr, &a->address))
2163 {
2164 vec_delete(lcm->map_resolvers, 1, i);
2165 break;
2166 }
2167 }
2168 }
2169 return 0;
2170}
2171
2172static clib_error_t *
2173lisp_add_del_map_resolver_command_fn (vlib_main_t * vm,
Florin Corasf727db92016-06-23 15:01:58 +02002174 unformat_input_t * input,
2175 vlib_cli_command_t * cmd)
Florin Corase127a7e2016-02-18 22:20:01 +01002176{
2177 unformat_input_t _line_input, * line_input = &_line_input;
Florin Coras0f1c29c2016-07-26 12:12:17 +02002178 u8 is_add = 1, addr_set = 0;
Florin Corase127a7e2016-02-18 22:20:01 +01002179 ip_address_t ip_addr;
2180 clib_error_t * error = 0;
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +02002181 int rv = 0;
Florin Corase127a7e2016-02-18 22:20:01 +01002182 vnet_lisp_add_del_map_resolver_args_t _a, * a = &_a;
2183
2184 /* Get a line of input. */
2185 if (! unformat_user (input, unformat_line_input, line_input))
2186 return 0;
2187
2188 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2189 {
2190 if (unformat (line_input, "add"))
2191 is_add = 1;
2192 else if (unformat (line_input, "del"))
2193 is_add = 0;
2194 else if (unformat (line_input, "%U", unformat_ip_address, &ip_addr))
Florin Coras0f1c29c2016-07-26 12:12:17 +02002195 addr_set = 1;
Florin Corase127a7e2016-02-18 22:20:01 +01002196 else
2197 {
2198 error = unformat_parse_error(line_input);
2199 goto done;
2200 }
2201 }
Florin Coras0f1c29c2016-07-26 12:12:17 +02002202
2203 if (!addr_set)
2204 {
2205 error = clib_error_return(0, "Map-resolver address must be set!");
2206 goto done;
2207 }
2208
Florin Corase127a7e2016-02-18 22:20:01 +01002209 a->is_add = is_add;
2210 a->address = ip_addr;
Andrej Kozemcak8ebb2a12016-06-07 12:25:20 +02002211 rv = vnet_lisp_add_del_map_resolver (a);
2212 if (0 != rv)
2213 {
2214 error = clib_error_return(0, "failed to %s map-resolver!",
2215 is_add ? "add" : "delete");
2216 }
Florin Corase127a7e2016-02-18 22:20:01 +01002217
2218 done:
2219 return error;
2220}
2221
2222VLIB_CLI_COMMAND (lisp_add_del_map_resolver_command) = {
2223 .path = "lisp map-resolver",
2224 .short_help = "lisp map-resolver add/del <ip_address>",
2225 .function = lisp_add_del_map_resolver_command_fn,
2226};
2227
Andrej Kozemcakb6e4d392016-06-14 13:55:57 +02002228int
2229vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a)
2230{
2231 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
2232 uword * p = 0;
2233
Florin Corasf727db92016-06-23 15:01:58 +02002234 if (vnet_lisp_enable_disable_status () == 0)
2235 {
2236 clib_warning("LISP is disabled!");
2237 return VNET_API_ERROR_LISP_DISABLED;
2238 }
Andrej Kozemcakb6e4d392016-06-14 13:55:57 +02002239
2240 if (a->is_add)
2241 {
2242 p = hash_get_mem(lcm->locator_set_index_by_name, a->locator_set_name);
2243 if (!p)
2244 {
2245 clib_warning("locator-set %v doesn't exist", a->locator_set_name);
2246 return VNET_API_ERROR_INVALID_ARGUMENT;
2247 }
2248
2249 lcm->mreq_itr_rlocs = p[0];
2250 }
2251 else
2252 {
2253 lcm->mreq_itr_rlocs = ~0;
2254 }
2255
2256 return 0;
2257}
2258
2259static clib_error_t *
Florin Corasf727db92016-06-23 15:01:58 +02002260lisp_add_del_mreq_itr_rlocs_command_fn (vlib_main_t * vm,
2261 unformat_input_t * input,
2262 vlib_cli_command_t * cmd)
Andrej Kozemcakb6e4d392016-06-14 13:55:57 +02002263{
2264 unformat_input_t _line_input, * line_input = &_line_input;
2265 u8 is_add = 1;
2266 u8 * locator_set_name = 0;
2267 clib_error_t * error = 0;
2268 int rv = 0;
2269 vnet_lisp_add_del_mreq_itr_rloc_args_t _a, * a = &_a;
2270
2271 /* Get a line of input. */
2272 if (! unformat_user (input, unformat_line_input, line_input))
2273 return 0;
2274
2275 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2276 {
2277 if (unformat (line_input, "del"))
2278 is_add = 0;
2279 else if (unformat (line_input, "add %s", &locator_set_name))
2280 is_add = 1;
2281 else
2282 {
2283 error = unformat_parse_error(line_input);
2284 goto done;
2285 }
2286 }
2287
2288 a->is_add = is_add;
2289 a->locator_set_name = locator_set_name;
2290 rv = vnet_lisp_add_del_mreq_itr_rlocs (a);
2291 if (0 != rv)
2292 {
2293 error = clib_error_return(0, "failed to %s map-request itr-rlocs!",
2294 is_add ? "add" : "delete");
2295 }
2296
2297 vec_free(locator_set_name);
2298
2299 done:
2300 return error;
2301
2302}
2303
2304VLIB_CLI_COMMAND (lisp_add_del_map_request_command) = {
2305 .path = "lisp map-request itr-rlocs",
2306 .short_help = "lisp map-request itr-rlocs add/del <locator_set_name>",
2307 .function = lisp_add_del_mreq_itr_rlocs_command_fn,
2308};
2309
2310static clib_error_t *
2311lisp_show_mreq_itr_rlocs_command_fn (vlib_main_t * vm,
2312 unformat_input_t * input,
2313 vlib_cli_command_t * cmd)
2314{
2315 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
2316 locator_set_t * loc_set;
2317
2318 vlib_cli_output (vm, "%=20s", "itr-rlocs");
2319
2320 if (~0 == lcm->mreq_itr_rlocs)
2321 {
2322 return 0;
2323 }
2324
2325 loc_set = pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
2326
2327 vlib_cli_output (vm, "%=20s", loc_set->name);
2328
2329 return 0;
2330}
2331
2332VLIB_CLI_COMMAND (lisp_show_map_request_command) = {
2333 .path = "show lisp map-request itr-rlocs",
2334 .short_help = "Shows map-request itr-rlocs",
2335 .function = lisp_show_mreq_itr_rlocs_command_fn,
2336};
2337
Florin Corase127a7e2016-02-18 22:20:01 +01002338/* Statistics (not really errors) */
2339#define foreach_lisp_cp_lookup_error \
2340_(DROP, "drop") \
2341_(MAP_REQUESTS_SENT, "map-request sent")
2342
2343static char * lisp_cp_lookup_error_strings[] = {
2344#define _(sym,string) string,
2345 foreach_lisp_cp_lookup_error
2346#undef _
2347};
2348
2349typedef enum
2350{
2351#define _(sym,str) LISP_CP_LOOKUP_ERROR_##sym,
2352 foreach_lisp_cp_lookup_error
2353#undef _
2354 LISP_CP_LOOKUP_N_ERROR,
2355} lisp_cp_lookup_error_t;
2356
2357typedef enum
2358{
2359 LISP_CP_LOOKUP_NEXT_DROP,
2360 LISP_CP_LOOKUP_NEXT_IP4_LOOKUP,
2361 LISP_CP_LOOKUP_NEXT_IP6_LOOKUP,
2362 LISP_CP_LOOKUP_N_NEXT,
2363} lisp_cp_lookup_next_t;
2364
2365typedef struct
2366{
2367 gid_address_t dst_eid;
Andrej Kozemcak94e34762016-05-25 12:43:21 +02002368 ip_address_t map_resolver_ip;
Florin Corase127a7e2016-02-18 22:20:01 +01002369} lisp_cp_lookup_trace_t;
2370
2371u8 *
2372format_lisp_cp_lookup_trace (u8 * s, va_list * args)
2373{
2374 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
2375 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
2376 lisp_cp_lookup_trace_t * t = va_arg (*args, lisp_cp_lookup_trace_t *);
2377
2378 s = format (s, "LISP-CP-LOOKUP: map-resolver: %U destination eid %U",
Florin Coras02655bd2016-04-26 00:17:24 +02002379 format_ip_address, &t->map_resolver_ip, format_gid_address,
Florin Corase127a7e2016-02-18 22:20:01 +01002380 &t->dst_eid);
2381 return s;
2382}
2383
Florin Coras1c494842016-06-16 21:08:56 +02002384int
2385get_mr_and_local_iface_ip (lisp_cp_main_t * lcm, ip_address_t * mr_ip,
Florin Corasc2c90082016-06-13 18:37:15 +02002386 ip_address_t * sloc)
2387{
Florin Corasddfafb82016-05-13 18:09:56 +02002388 ip_address_t * mrit;
Florin Corase127a7e2016-02-18 22:20:01 +01002389
Florin Corasddfafb82016-05-13 18:09:56 +02002390 if (vec_len(lcm->map_resolvers) == 0)
Florin Corase127a7e2016-02-18 22:20:01 +01002391 {
Florin Corasddfafb82016-05-13 18:09:56 +02002392 clib_warning("No map-resolver configured");
Florin Coras1c494842016-06-16 21:08:56 +02002393 return 0;
Florin Corase127a7e2016-02-18 22:20:01 +01002394 }
2395
Florin Corasddfafb82016-05-13 18:09:56 +02002396 /* find the first mr ip we have a route to and the ip of the
2397 * iface that has a route to it */
2398 vec_foreach(mrit, lcm->map_resolvers)
Florin Corase127a7e2016-02-18 22:20:01 +01002399 {
Florin Coras1c494842016-06-16 21:08:56 +02002400 if (0 != ip_fib_get_first_egress_ip_for_dst (lcm, mrit, sloc)) {
Florin Corasddfafb82016-05-13 18:09:56 +02002401 ip_address_copy(mr_ip, mrit);
Florin Coras1c494842016-06-16 21:08:56 +02002402 return 1;
Florin Corasc2c90082016-06-13 18:37:15 +02002403 }
Florin Corasddfafb82016-05-13 18:09:56 +02002404 }
2405
2406 clib_warning("Can't find map-resolver and local interface ip!");
Florin Coras1c494842016-06-16 21:08:56 +02002407 return 0;
Florin Corasddfafb82016-05-13 18:09:56 +02002408}
Filip Tehlar254b0362016-04-07 10:04:34 +02002409
Filip Tehlarbeceab92016-04-20 17:21:55 +02002410static gid_address_t *
Filip Tehlar254b0362016-04-07 10:04:34 +02002411build_itr_rloc_list (lisp_cp_main_t * lcm, locator_set_t * loc_set)
2412{
Florin Coras1c494842016-06-16 21:08:56 +02002413 void * addr;
Filip Tehlar254b0362016-04-07 10:04:34 +02002414 u32 i;
2415 locator_t * loc;
2416 u32 * loc_indexp;
2417 ip_interface_address_t * ia = 0;
Filip Tehlarbeceab92016-04-20 17:21:55 +02002418 gid_address_t gid_data, * gid = &gid_data;
2419 gid_address_t * rlocs = 0;
2420 ip_prefix_t * ippref = &gid_address_ippref (gid);
2421 ip_address_t * rloc = &ip_prefix_addr (ippref);
Filip Tehlar254b0362016-04-07 10:04:34 +02002422
Filip Tehlar324112f2016-06-02 16:07:38 +02002423 memset (gid, 0, sizeof (gid[0]));
Filip Tehlarbeceab92016-04-20 17:21:55 +02002424 gid_address_type (gid) = GID_ADDR_IP_PREFIX;
Filip Tehlar254b0362016-04-07 10:04:34 +02002425 for (i = 0; i < vec_len(loc_set->locator_indices); i++)
2426 {
2427 loc_indexp = vec_elt_at_index(loc_set->locator_indices, i);
2428 loc = pool_elt_at_index (lcm->locator_pool, loc_indexp[0]);
2429
Filip Tehlar254b0362016-04-07 10:04:34 +02002430 /* Add ipv4 locators first TODO sort them */
2431 foreach_ip_interface_address (&lcm->im4->lookup_main, ia,
2432 loc->sw_if_index, 1 /* unnumbered */,
2433 ({
Florin Coras1c494842016-06-16 21:08:56 +02002434 addr = ip_interface_address_get_address (&lcm->im4->lookup_main, ia);
2435 ip_address_set (rloc, addr, IP4);
Florin Corasddfafb82016-05-13 18:09:56 +02002436 ip_prefix_len (ippref) = 32;
Filip Tehlarbeceab92016-04-20 17:21:55 +02002437 vec_add1 (rlocs, gid[0]);
Filip Tehlar254b0362016-04-07 10:04:34 +02002438 }));
2439
Filip Tehlar254b0362016-04-07 10:04:34 +02002440 /* Add ipv6 locators */
2441 foreach_ip_interface_address (&lcm->im6->lookup_main, ia,
2442 loc->sw_if_index, 1 /* unnumbered */,
2443 ({
Florin Coras1c494842016-06-16 21:08:56 +02002444 addr = ip_interface_address_get_address (&lcm->im6->lookup_main, ia);
2445 ip_address_set (rloc, addr, IP6);
Florin Corasddfafb82016-05-13 18:09:56 +02002446 ip_prefix_len (ippref) = 128;
Filip Tehlarbeceab92016-04-20 17:21:55 +02002447 vec_add1 (rlocs, gid[0]);
Filip Tehlar254b0362016-04-07 10:04:34 +02002448 }));
2449 }
2450 return rlocs;
2451}
2452
Florin Corase127a7e2016-02-18 22:20:01 +01002453static vlib_buffer_t *
2454build_encapsulated_map_request (vlib_main_t * vm, lisp_cp_main_t *lcm,
2455 gid_address_t * seid, gid_address_t * deid,
Florin Corasddfafb82016-05-13 18:09:56 +02002456 locator_set_t * loc_set, ip_address_t * mr_ip,
2457 ip_address_t * sloc, u8 is_smr_invoked,
Florin Corase127a7e2016-02-18 22:20:01 +01002458 u64 *nonce_res, u32 * bi_res)
2459{
2460 vlib_buffer_t * b;
2461 u32 bi;
Filip Tehlarbeceab92016-04-20 17:21:55 +02002462 gid_address_t * rlocs = 0;
Florin Corase127a7e2016-02-18 22:20:01 +01002463
2464 if (vlib_buffer_alloc (vm, &bi, 1) != 1)
2465 {
2466 clib_warning ("Can't allocate buffer for Map-Request!");
2467 return 0;
2468 }
2469
2470 b = vlib_get_buffer (vm, bi);
2471
2472 /* leave some space for the encap headers */
2473 vlib_buffer_make_headroom (b, MAX_LISP_MSG_ENCAP_LEN);
2474
Filip Tehlar254b0362016-04-07 10:04:34 +02002475 /* get rlocs */
2476 rlocs = build_itr_rloc_list (lcm, loc_set);
2477
Florin Corase127a7e2016-02-18 22:20:01 +01002478 /* put lisp msg */
Filip Tehlar254b0362016-04-07 10:04:34 +02002479 lisp_msg_put_mreq (lcm, b, seid, deid, rlocs, is_smr_invoked, nonce_res);
Florin Corase127a7e2016-02-18 22:20:01 +01002480
2481 /* push ecm: udp-ip-lisp */
2482 lisp_msg_push_ecm (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, seid, deid);
2483
Florin Corase127a7e2016-02-18 22:20:01 +01002484 /* push outer ip header */
Florin Corasddfafb82016-05-13 18:09:56 +02002485 pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, sloc,
Florin Corase127a7e2016-02-18 22:20:01 +01002486 mr_ip);
2487
2488 bi_res[0] = bi;
Filip Tehlar254b0362016-04-07 10:04:34 +02002489
Florin Coras1c494842016-06-16 21:08:56 +02002490 vec_free(rlocs);
Florin Corase127a7e2016-02-18 22:20:01 +01002491 return b;
2492}
2493
2494static void
2495send_encapsulated_map_request (vlib_main_t * vm, lisp_cp_main_t *lcm,
2496 gid_address_t * seid, gid_address_t * deid,
2497 u8 is_smr_invoked)
2498{
2499 u32 next_index, bi = 0, * to_next, map_index;
2500 vlib_buffer_t * b;
2501 vlib_frame_t * f;
2502 u64 nonce = 0;
2503 locator_set_t * loc_set;
2504 mapping_t * map;
2505 pending_map_request_t * pmr;
Florin Corasddfafb82016-05-13 18:09:56 +02002506 ip_address_t mr_ip, sloc;
Andrej Kozemcakb6e4d392016-06-14 13:55:57 +02002507 u32 ls_index;
Florin Corase127a7e2016-02-18 22:20:01 +01002508
2509 /* get locator-set for seid */
Filip Tehlar53f09e32016-05-19 14:25:44 +02002510 if (!lcm->lisp_pitr)
Florin Corase127a7e2016-02-18 22:20:01 +01002511 {
Filip Tehlar53f09e32016-05-19 14:25:44 +02002512 map_index = gid_dictionary_lookup (&lcm->mapping_index_by_gid, seid);
2513 if (map_index == ~0)
2514 {
2515 clib_warning("No local mapping found in eid-table for %U!",
2516 format_gid_address, seid);
2517 return;
2518 }
2519
2520 map = pool_elt_at_index (lcm->mapping_pool, map_index);
2521
2522 if (!map->local)
2523 {
2524 clib_warning("Mapping found for src eid %U is not marked as local!",
2525 format_gid_address, seid);
2526 return;
2527 }
Andrej Kozemcakb6e4d392016-06-14 13:55:57 +02002528 ls_index = map->locator_set_index;
Filip Tehlar53f09e32016-05-19 14:25:44 +02002529 }
2530 else
2531 {
2532 map_index = lcm->pitr_map_index;
2533 map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
Andrej Kozemcakb6e4d392016-06-14 13:55:57 +02002534 ls_index = map->locator_set_index;
Florin Corase127a7e2016-02-18 22:20:01 +01002535 }
2536
Andrej Kozemcakb6e4d392016-06-14 13:55:57 +02002537 /* overwrite locator set if map-request itr-rlocs configured */
2538 if (~0 != lcm->mreq_itr_rlocs)
2539 {
2540 ls_index = lcm->mreq_itr_rlocs;
2541 }
2542
2543 loc_set = pool_elt_at_index (lcm->locator_set_pool, ls_index);
Florin Corase127a7e2016-02-18 22:20:01 +01002544
Florin Coras1c494842016-06-16 21:08:56 +02002545 /* get local iface ip to use in map-request */
2546 if (0 == get_mr_and_local_iface_ip (lcm, &mr_ip, &sloc))
2547 return;
Florin Corasddfafb82016-05-13 18:09:56 +02002548
Florin Corase127a7e2016-02-18 22:20:01 +01002549 /* build the encapsulated map request */
Florin Corasddfafb82016-05-13 18:09:56 +02002550 b = build_encapsulated_map_request (vm, lcm, seid, deid, loc_set, &mr_ip,
2551 &sloc, is_smr_invoked, &nonce, &bi);
Florin Corase127a7e2016-02-18 22:20:01 +01002552
2553 if (!b)
2554 return;
2555
Florin Corasf727db92016-06-23 15:01:58 +02002556 /* set fib index to default and lookup node */
2557 vnet_buffer(b)->sw_if_index[VLIB_TX] = 0;
Florin Corasddfafb82016-05-13 18:09:56 +02002558 next_index = (ip_addr_version(&mr_ip) == IP4) ?
Florin Corase127a7e2016-02-18 22:20:01 +01002559 ip4_lookup_node.index : ip6_lookup_node.index;
2560
2561 f = vlib_get_frame_to_node (vm, next_index);
2562
2563 /* Enqueue the packet */
2564 to_next = vlib_frame_vector_args (f);
2565 to_next[0] = bi;
2566 f->n_vectors = 1;
2567 vlib_put_frame_to_node (vm, next_index, f);
2568
2569 /* add map-request to pending requests table */
2570 pool_get(lcm->pending_map_requests_pool, pmr);
2571 gid_address_copy (&pmr->src, seid);
2572 gid_address_copy (&pmr->dst, deid);
Florin Corase127a7e2016-02-18 22:20:01 +01002573 hash_set(lcm->pending_map_requests_by_nonce, nonce,
2574 pmr - lcm->pending_map_requests_pool);
2575}
2576
2577static void
2578get_src_and_dst (void *hdr, ip_address_t * src, ip_address_t *dst)
2579{
2580 ip4_header_t * ip4 = hdr;
2581 ip6_header_t * ip6;
2582
2583 if ((ip4->ip_version_and_header_length & 0xF0) == 0x40)
2584 {
Florin Corasc2c90082016-06-13 18:37:15 +02002585 ip_address_set(src, &ip4->src_address, IP4);
2586 ip_address_set(dst, &ip4->dst_address, IP4);
Florin Corase127a7e2016-02-18 22:20:01 +01002587 }
2588 else
2589 {
2590 ip6 = hdr;
Florin Corasc2c90082016-06-13 18:37:15 +02002591 ip_address_set(src, &ip6->src_address, IP6);
2592 ip_address_set(dst, &ip6->dst_address, IP6);
Florin Corase127a7e2016-02-18 22:20:01 +01002593 }
2594}
2595
Filip Tehlar324112f2016-06-02 16:07:38 +02002596static u32
2597lisp_get_vni_from_buffer (vlib_buffer_t * b, u8 version)
2598{
2599 uword * vnip;
2600 u32 vni = ~0, table_id = ~0, fib_index;
2601 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
2602
2603 if (version == IP4)
2604 {
2605 ip4_fib_t * fib;
2606 ip4_main_t * im4 = &ip4_main;
2607 fib_index = vec_elt (im4->fib_index_by_sw_if_index,
2608 vnet_buffer (b)->sw_if_index[VLIB_RX]);
2609 fib = find_ip4_fib_by_table_index_or_id (im4, fib_index,
2610 IP4_ROUTE_FLAG_FIB_INDEX);
2611 table_id = fib->table_id;
2612 }
2613 else
2614 {
2615 ip6_fib_t * fib;
2616 ip6_main_t * im6 = &ip6_main;
2617 fib_index = vec_elt (im6->fib_index_by_sw_if_index,
2618 vnet_buffer (b)->sw_if_index[VLIB_RX]);
2619 fib = find_ip6_fib_by_table_index_or_id (im6, fib_index,
2620 IP6_ROUTE_FLAG_FIB_INDEX);
2621 table_id = fib->table_id;
2622 }
2623
2624 vnip = hash_get (lcm->vni_by_table_id, table_id);
2625 if (vnip)
2626 vni = vnip[0];
2627 else
2628 clib_warning ("vrf %d is not mapped to any vni!", table_id);
2629
2630 return vni;
2631}
2632
Florin Corase127a7e2016-02-18 22:20:01 +01002633static uword
2634lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
2635 vlib_frame_t * from_frame)
2636{
Filip Tehlar215104e2016-05-10 16:58:29 +02002637 u32 * from, * to_next_drop, di, si;
Florin Corase127a7e2016-02-18 22:20:01 +01002638 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main();
2639 u32 pkts_mapped = 0;
2640 uword n_left_from, n_left_to_next_drop;
2641
2642 from = vlib_frame_vector_args (from_frame);
2643 n_left_from = from_frame->n_vectors;
2644
2645 while (n_left_from > 0)
2646 {
2647 vlib_get_next_frame (vm, node, LISP_CP_LOOKUP_NEXT_DROP,
2648 to_next_drop, n_left_to_next_drop);
2649
2650 while (n_left_from > 0 && n_left_to_next_drop > 0)
2651 {
Filip Tehlar324112f2016-06-02 16:07:38 +02002652 u32 pi0, vni;
Florin Corase127a7e2016-02-18 22:20:01 +01002653 vlib_buffer_t * p0;
2654 ip4_header_t * ip0;
2655 gid_address_t src, dst;
2656 ip_prefix_t * spref, * dpref;
2657
Filip Tehlarbeceab92016-04-20 17:21:55 +02002658 gid_address_type (&src) = GID_ADDR_IP_PREFIX;
Florin Corase127a7e2016-02-18 22:20:01 +01002659 spref = &gid_address_ippref(&src);
Filip Tehlarbeceab92016-04-20 17:21:55 +02002660 gid_address_type (&dst) = GID_ADDR_IP_PREFIX;
Florin Corase127a7e2016-02-18 22:20:01 +01002661 dpref = &gid_address_ippref(&dst);
2662
2663 pi0 = from[0];
2664 from += 1;
2665 n_left_from -= 1;
2666 to_next_drop[0] = pi0;
2667 to_next_drop += 1;
2668 n_left_to_next_drop -= 1;
2669
2670 p0 = vlib_get_buffer (vm, pi0);
2671 p0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
2672
2673 /* src/dst eid pair */
2674 ip0 = vlib_buffer_get_current (p0);
2675 get_src_and_dst (ip0, &ip_prefix_addr(spref), &ip_prefix_addr(dpref));
2676 ip_prefix_len(spref) = ip_address_max_len (ip_prefix_version(spref));
2677 ip_prefix_len(dpref) = ip_address_max_len (ip_prefix_version(dpref));
2678
Filip Tehlar324112f2016-06-02 16:07:38 +02002679 vni = lisp_get_vni_from_buffer (p0, ip_prefix_version (spref));
2680 gid_address_vni (&dst) = vni;
2681 gid_address_vni (&src) = vni;
2682
Filip Tehlar215104e2016-05-10 16:58:29 +02002683 /* if we have remote mapping for destination already in map-chache
2684 add forwarding tunnel directly. If not send a map-request */
2685 di = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst);
2686 if (~0 != di)
2687 {
Filip Tehlar53f09e32016-05-19 14:25:44 +02002688 mapping_t * m = vec_elt_at_index (lcm->mapping_pool, di);
2689 /* send a map-request also in case of negative mapping entry
2690 with corresponding action */
2691 if (m->action == ACTION_SEND_MAP_REQUEST)
Filip Tehlar215104e2016-05-10 16:58:29 +02002692 {
Filip Tehlar53f09e32016-05-19 14:25:44 +02002693 /* send map-request */
2694 send_encapsulated_map_request (vm, lcm, &src, &dst, 0);
2695 pkts_mapped++;
2696 }
2697 else
2698 {
2699 si = gid_dictionary_lookup (&lcm->mapping_index_by_gid,
2700 &src);
2701 if (~0 != si)
2702 {
Florin Corasf727db92016-06-23 15:01:58 +02002703 dp_add_fwd_entry (lcm, si, di);
Filip Tehlar53f09e32016-05-19 14:25:44 +02002704 }
Filip Tehlar215104e2016-05-10 16:58:29 +02002705 }
2706 }
2707 else
2708 {
2709 /* send map-request */
2710 send_encapsulated_map_request (vm, lcm, &src, &dst, 0);
2711 pkts_mapped++;
2712 }
Florin Corase127a7e2016-02-18 22:20:01 +01002713
2714 if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED))
2715 {
2716 lisp_cp_lookup_trace_t *tr = vlib_add_trace (vm, node, p0,
2717 sizeof(*tr));
Andrej Kozemcak94e34762016-05-25 12:43:21 +02002718
2719 memset(tr, 0, sizeof(*tr));
Florin Corase127a7e2016-02-18 22:20:01 +01002720 gid_address_copy (&tr->dst_eid, &dst);
Andrej Kozemcak94e34762016-05-25 12:43:21 +02002721 if (vec_len(lcm->map_resolvers) > 0)
2722 {
2723 clib_memcpy (&tr->map_resolver_ip,
2724 vec_elt_at_index(lcm->map_resolvers, 0),
2725 sizeof(ip_address_t));
2726 }
Florin Corase127a7e2016-02-18 22:20:01 +01002727 }
Filip Tehlar324112f2016-06-02 16:07:38 +02002728 gid_address_free (&dst);
2729 gid_address_free (&src);
Florin Corase127a7e2016-02-18 22:20:01 +01002730 }
2731
2732 vlib_put_next_frame (vm, node, LISP_CP_LOOKUP_NEXT_DROP, n_left_to_next_drop);
2733 }
2734 vlib_node_increment_counter (vm, node->node_index,
2735 LISP_CP_LOOKUP_ERROR_MAP_REQUESTS_SENT,
2736 pkts_mapped);
2737 return from_frame->n_vectors;
2738}
2739
2740VLIB_REGISTER_NODE (lisp_cp_lookup_node) = {
2741 .function = lisp_cp_lookup,
2742 .name = "lisp-cp-lookup",
2743 .vector_size = sizeof (u32),
2744 .format_trace = format_lisp_cp_lookup_trace,
2745 .type = VLIB_NODE_TYPE_INTERNAL,
2746
2747 .n_errors = LISP_CP_LOOKUP_N_ERROR,
2748 .error_strings = lisp_cp_lookup_error_strings,
2749
2750 .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
2751
2752 .next_nodes = {
2753 [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
2754 [LISP_CP_LOOKUP_NEXT_IP4_LOOKUP] = "ip4-lookup",
2755 [LISP_CP_LOOKUP_NEXT_IP6_LOOKUP] = "ip6-lookup",
2756 },
2757};
2758
2759/* lisp_cp_input statistics */
Florin Corasf727db92016-06-23 15:01:58 +02002760#define foreach_lisp_cp_input_error \
2761_(DROP, "drop") \
Florin Corase127a7e2016-02-18 22:20:01 +01002762_(MAP_REPLIES_RECEIVED, "map-replies received")
2763
2764static char * lisp_cp_input_error_strings[] = {
2765#define _(sym,string) string,
2766 foreach_lisp_cp_input_error
2767#undef _
2768};
2769
2770typedef enum
2771{
2772#define _(sym,str) LISP_CP_INPUT_ERROR_##sym,
2773 foreach_lisp_cp_input_error
2774#undef _
2775 LISP_CP_INPUT_N_ERROR,
2776} lisp_cp_input_error_t;
2777
2778typedef enum
2779{
2780 LISP_CP_INPUT_NEXT_DROP,
2781 LISP_CP_INPUT_N_NEXT,
2782} lisp_cp_input_next_t;
2783
2784typedef struct
2785{
2786 gid_address_t dst_eid;
2787 ip4_address_t map_resolver_ip;
2788} lisp_cp_input_trace_t;
2789
2790u8 *
2791format_lisp_cp_input_trace (u8 * s, va_list * args)
2792{
2793 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
2794 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
2795 CLIB_UNUSED(lisp_cp_input_trace_t * t) = va_arg (*args, lisp_cp_input_trace_t *);
2796
2797 s = format (s, "LISP-CP-INPUT: TODO");
2798 return s;
2799}
2800
Florin Corase127a7e2016-02-18 22:20:01 +01002801void
2802process_map_reply (lisp_cp_main_t * lcm, vlib_buffer_t * b)
2803{
Florin Coras71893ac2016-07-10 20:09:32 +02002804 u32 len = 0, i, ttl, dst_map_index = 0;
Florin Corase127a7e2016-02-18 22:20:01 +01002805 void * h;
Florin Corase127a7e2016-02-18 22:20:01 +01002806 pending_map_request_t * pmr;
2807 locator_t probed;
2808 map_reply_hdr_t * mrep_hdr;
2809 u64 nonce;
Florin Corasf727db92016-06-23 15:01:58 +02002810 gid_address_t deid;
Florin Corase127a7e2016-02-18 22:20:01 +01002811 uword * pmr_index;
Florin Corasf727db92016-06-23 15:01:58 +02002812 u8 authoritative, action;
2813 locator_t * locators = 0, * loc;
Florin Corase127a7e2016-02-18 22:20:01 +01002814
2815 mrep_hdr = vlib_buffer_get_current (b);
2816
2817 /* Check pending requests table and nonce */
2818 nonce = MREP_NONCE(mrep_hdr);
2819 pmr_index = hash_get(lcm->pending_map_requests_by_nonce, nonce);
2820 if (!pmr_index)
2821 {
2822 clib_warning("No pending map-request entry with nonce %lu!", nonce);
2823 return;
2824 }
2825 pmr = pool_elt_at_index(lcm->pending_map_requests_pool, pmr_index[0]);
2826
2827 vlib_buffer_pull (b, sizeof(*mrep_hdr));
2828
2829 for (i = 0; i < MREP_REC_COUNT(mrep_hdr); i++)
2830 {
Florin Corase127a7e2016-02-18 22:20:01 +01002831
2832 h = vlib_buffer_get_current (b);
Florin Corasf727db92016-06-23 15:01:58 +02002833 ttl = clib_net_to_host_u32 (MAP_REC_TTL(h));
2834 action = MAP_REC_ACTION(h);
2835 authoritative = MAP_REC_AUTH(h);
Florin Corase127a7e2016-02-18 22:20:01 +01002836
Florin Corasf727db92016-06-23 15:01:58 +02002837 len = lisp_msg_parse_mapping_record (b, &deid, &locators, &probed);
Florin Corase127a7e2016-02-18 22:20:01 +01002838 if (len == ~0)
2839 {
2840 clib_warning ("Failed to parse mapping record!");
Florin Corasf727db92016-06-23 15:01:58 +02002841 vec_foreach (loc, locators)
Filip Tehlarbeceab92016-04-20 17:21:55 +02002842 {
2843 locator_free (loc);
2844 }
Florin Corasf727db92016-06-23 15:01:58 +02002845 vec_free(locators);
Florin Corase127a7e2016-02-18 22:20:01 +01002846 return;
2847 }
2848
Florin Coras71893ac2016-07-10 20:09:32 +02002849 /* insert/update mappings cache */
2850 vnet_lisp_add_del_mapping (&deid, locators, action, authoritative, ttl, 1,
2851 &dst_map_index);
Florin Corase127a7e2016-02-18 22:20:01 +01002852
Florin Coras71893ac2016-07-10 20:09:32 +02002853 /* try to program forwarding only if mapping saved or updated*/
2854 if ((u32) ~0 != dst_map_index)
2855 lisp_add_del_adjacency (lcm, &pmr->src, &deid, 1);
Florin Corase127a7e2016-02-18 22:20:01 +01002856
Florin Corasf727db92016-06-23 15:01:58 +02002857 vec_free(locators);
Florin Corase127a7e2016-02-18 22:20:01 +01002858 }
2859
2860 /* remove pending map request entry */
2861 hash_unset(lcm->pending_map_requests_by_nonce, nonce);
2862 pool_put(lcm->pending_map_requests_pool, pmr);
2863}
2864
2865void
2866process_map_request (vlib_main_t * vm, lisp_cp_main_t * lcm, vlib_buffer_t * b)
2867{
2868 map_request_hdr_t * mreq_hdr;
2869 gid_address_t src, dst;
2870// u64 nonce;
2871 u32 i, len = 0;
Filip Tehlarbeceab92016-04-20 17:21:55 +02002872 gid_address_t * itr_rlocs = 0, * rloc;
Florin Corase127a7e2016-02-18 22:20:01 +01002873
2874 mreq_hdr = vlib_buffer_get_current (b);
2875 vlib_buffer_pull (b, sizeof(*mreq_hdr));
2876
2877// nonce = MREQ_NONCE(mreq_hdr);
2878
2879 if (!MREQ_SMR(mreq_hdr)) {
2880 clib_warning("Only SMR Map-Requests supported for now!");
2881 return;
2882 }
2883
2884 /* parse src eid */
2885 len = lisp_msg_parse_addr (b, &src);
2886 if (len == ~0)
2887 return;
2888
2889 /* for now we don't do anything with the itr's rlocs */
2890 len = lisp_msg_parse_itr_rlocs (b, &itr_rlocs, MREQ_ITR_RLOC_COUNT(mreq_hdr) + 1);
2891 if (len == ~0)
2892 return;
2893
Filip Tehlarbeceab92016-04-20 17:21:55 +02002894 /* TODO: RLOCs are currently unused, so free them for now */
2895 vec_foreach (rloc, itr_rlocs)
2896 {
2897 gid_address_free (rloc);
2898 }
2899
Florin Corase127a7e2016-02-18 22:20:01 +01002900 /* parse eid records and send SMR-invoked map-requests */
2901 for (i = 0; i < MREQ_REC_COUNT(mreq_hdr); i++)
2902 {
2903 memset(&dst, 0, sizeof(dst));
2904 len = lisp_msg_parse_eid_rec (b, &dst);
2905 if (len == ~0)
2906 {
2907 clib_warning("Can't parse map-request EID-record");
2908 return;
2909 }
2910 /* send SMR-invoked map-requests */
2911 send_encapsulated_map_request (vm, lcm, &dst, &src, /* invoked */ 1);
2912 }
2913}
2914
2915static uword
2916lisp_cp_input (vlib_main_t * vm, vlib_node_runtime_t * node,
2917 vlib_frame_t * from_frame)
2918{
2919 u32 n_left_from, * from, * to_next_drop;
2920 lisp_msg_type_e type;
2921 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
2922
2923 from = vlib_frame_vector_args (from_frame);
2924 n_left_from = from_frame->n_vectors;
2925
2926
2927 while (n_left_from > 0)
2928 {
2929 u32 n_left_to_next_drop;
2930
2931 vlib_get_next_frame (vm, node, LISP_CP_INPUT_NEXT_DROP,
2932 to_next_drop, n_left_to_next_drop);
2933 while (n_left_from > 0 && n_left_to_next_drop > 0)
2934 {
2935 u32 bi0;
2936 vlib_buffer_t * b0;
2937
2938 bi0 = from[0];
2939 from += 1;
2940 n_left_from -= 1;
2941 to_next_drop[0] = bi0;
2942 to_next_drop += 1;
2943 n_left_to_next_drop -= 1;
2944
2945 b0 = vlib_get_buffer (vm, bi0);
2946
2947 type = lisp_msg_type(vlib_buffer_get_current (b0));
2948 switch (type)
2949 {
2950 case LISP_MAP_REPLY:
2951 process_map_reply (lcm, b0);
2952 break;
2953 case LISP_MAP_REQUEST:
2954 process_map_request(vm, lcm, b0);
2955 break;
2956 default:
2957 clib_warning("Unsupported LISP message type %d", type);
2958 break;
2959 }
2960
2961 b0->error = node->errors[LISP_CP_INPUT_ERROR_DROP];
2962
2963 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
2964 {
2965
2966 }
2967 }
2968
2969 vlib_put_next_frame (vm, node, LISP_CP_INPUT_NEXT_DROP, n_left_to_next_drop);
2970 }
2971 return from_frame->n_vectors;
2972}
2973
2974VLIB_REGISTER_NODE (lisp_cp_input_node) = {
2975 .function = lisp_cp_input,
2976 .name = "lisp-cp-input",
2977 .vector_size = sizeof (u32),
2978 .format_trace = format_lisp_cp_input_trace,
2979 .type = VLIB_NODE_TYPE_INTERNAL,
2980
2981 .n_errors = LISP_CP_INPUT_N_ERROR,
2982 .error_strings = lisp_cp_input_error_strings,
2983
2984 .n_next_nodes = LISP_CP_INPUT_N_NEXT,
2985
2986 .next_nodes = {
2987 [LISP_CP_INPUT_NEXT_DROP] = "error-drop",
2988 },
2989};
2990
2991clib_error_t *
2992lisp_cp_init (vlib_main_t *vm)
2993{
2994 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
2995 clib_error_t * error = 0;
2996
2997 if ((error = vlib_call_init_function (vm, lisp_gpe_init)))
2998 return error;
2999
3000 lcm->im4 = &ip4_main;
3001 lcm->im6 = &ip6_main;
3002 lcm->vlib_main = vm;
3003 lcm->vnet_main = vnet_get_main();
Andrej Kozemcakb6e4d392016-06-14 13:55:57 +02003004 lcm->mreq_itr_rlocs = ~0;
Florin Corasf727db92016-06-23 15:01:58 +02003005 lcm->lisp_pitr = 0;
Florin Corase127a7e2016-02-18 22:20:01 +01003006
3007 gid_dictionary_init (&lcm->mapping_index_by_gid);
Florin Corase127a7e2016-02-18 22:20:01 +01003008
Florin Coras577c3552016-04-21 00:45:40 +02003009 /* default vrf mapped to vni 0 */
3010 hash_set(lcm->table_id_by_vni, 0, 0);
Filip Tehlar324112f2016-06-02 16:07:38 +02003011 hash_set(lcm->vni_by_table_id, 0, 0);
Florin Coras577c3552016-04-21 00:45:40 +02003012
Florin Corase127a7e2016-02-18 22:20:01 +01003013 udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp,
3014 lisp_cp_input_node.index, 1 /* is_ip4 */);
3015 udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp6,
3016 lisp_cp_input_node.index, 0 /* is_ip4 */);
3017
3018 return 0;
3019}
3020
3021VLIB_INIT_FUNCTION(lisp_cp_init);