LISP: support for neighbor discovery
[vpp.git] / src / vnet / lisp-cp / one_cli.c
1 /*
2  * Copyright (c) 2017 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-gpe/lisp_gpe.h>
18
19 static clib_error_t *
20 lisp_show_adjacencies_command_fn (vlib_main_t * vm,
21                                   unformat_input_t * input,
22                                   vlib_cli_command_t * cmd)
23 {
24   lisp_adjacency_t *adjs, *adj;
25   vlib_cli_output (vm, "%s %40s\n", "leid", "reid");
26   unformat_input_t _line_input, *line_input = &_line_input;
27   u32 vni = ~0;
28
29   /* Get a line of input. */
30   if (!unformat_user (input, unformat_line_input, line_input))
31     return 0;
32
33   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
34     {
35       if (unformat (line_input, "vni %d", &vni))
36         ;
37       else
38         {
39           vlib_cli_output (vm, "parse error: '%U'",
40                            format_unformat_error, line_input);
41           unformat_free (line_input);
42           return 0;
43         }
44     }
45   unformat_free (line_input);
46
47   if (~0 == vni)
48     {
49       vlib_cli_output (vm, "error: no vni specified!");
50       return 0;
51     }
52
53   adjs = vnet_lisp_adjacencies_get_by_vni (vni);
54
55   vec_foreach (adj, adjs)
56   {
57     vlib_cli_output (vm, "%U %40U\n", format_gid_address, &adj->leid,
58                      format_gid_address, &adj->reid);
59   }
60   vec_free (adjs);
61
62   return 0;
63 }
64
65 /* *INDENT-OFF* */
66 VLIB_CLI_COMMAND (one_show_adjacencies_command) = {
67     .path = "show one adjacencies",
68     .short_help = "show one adjacencies",
69     .function = lisp_show_adjacencies_command_fn,
70 };
71 /* *INDENT-ON* */
72
73 static clib_error_t *
74 lisp_add_del_map_server_command_fn (vlib_main_t * vm,
75                                     unformat_input_t * input,
76                                     vlib_cli_command_t * cmd)
77 {
78   int rv = 0;
79   u8 is_add = 1, ip_set = 0;
80   ip_address_t ip;
81   unformat_input_t _line_input, *line_input = &_line_input;
82
83   /* Get a line of input. */
84   if (!unformat_user (input, unformat_line_input, line_input))
85     return 0;
86
87   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
88     {
89       if (unformat (line_input, "add"))
90         is_add = 1;
91       else if (unformat (line_input, "del"))
92         is_add = 0;
93       else if (unformat (line_input, "%U", unformat_ip_address, &ip))
94         ip_set = 1;
95       else
96         {
97           vlib_cli_output (vm, "parse error: '%U'",
98                            format_unformat_error, line_input);
99           unformat_free (line_input);
100           return 0;
101         }
102     }
103   unformat_free (line_input);
104
105   if (!ip_set)
106     {
107       vlib_cli_output (vm, "map-server ip address not set!");
108       return 0;
109     }
110
111   rv = vnet_lisp_add_del_map_server (&ip, is_add);
112   if (!rv)
113     vlib_cli_output (vm, "failed to %s map-server!",
114                      is_add ? "add" : "delete");
115
116   return 0;
117 }
118
119 /* *INDENT-OFF* */
120 VLIB_CLI_COMMAND (one_add_del_map_server_command) = {
121     .path = "one map-server",
122     .short_help = "one map-server add|del <ip>",
123     .function = lisp_add_del_map_server_command_fn,
124 };
125 /* *INDENT-ON* */
126
127
128 static clib_error_t *
129 lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
130                                    vlib_cli_command_t * cmd)
131 {
132   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
133   unformat_input_t _line_input, *line_input = &_line_input;
134   u8 is_add = 1;
135   gid_address_t eid;
136   gid_address_t *eids = 0;
137   clib_error_t *error = 0;
138   u8 *locator_set_name = 0;
139   u32 locator_set_index = 0, map_index = 0;
140   uword *p;
141   vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
142   int rv = 0;
143   u32 vni = 0;
144   u8 *key = 0;
145   u32 key_id = 0;
146
147   memset (&eid, 0, sizeof (eid));
148   memset (a, 0, sizeof (*a));
149
150   /* Get a line of input. */
151   if (!unformat_user (input, unformat_line_input, line_input))
152     return 0;
153
154   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
155     {
156       if (unformat (line_input, "add"))
157         is_add = 1;
158       else if (unformat (line_input, "del"))
159         is_add = 0;
160       else if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
161         ;
162       else if (unformat (line_input, "vni %d", &vni))
163         gid_address_vni (&eid) = vni;
164       else if (unformat (line_input, "secret-key %_%v%_", &key))
165         ;
166       else if (unformat (line_input, "key-id %U", unformat_hmac_key_id,
167                          &key_id))
168         ;
169       else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
170         {
171           p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
172           if (!p)
173             {
174               error = clib_error_return (0, "locator-set %s doesn't exist",
175                                          locator_set_name);
176               goto done;
177             }
178           locator_set_index = p[0];
179         }
180       else
181         {
182           error = unformat_parse_error (line_input);
183           goto done;
184         }
185     }
186   /* XXX treat batch configuration */
187
188   if (GID_ADDR_SRC_DST == gid_address_type (&eid))
189     {
190       error =
191         clib_error_return (0, "src/dst is not supported for local EIDs!");
192       goto done;
193     }
194
195   if (key && (0 == key_id))
196     {
197       vlib_cli_output (vm, "invalid key_id!");
198       goto done;
199     }
200
201   gid_address_copy (&a->eid, &eid);
202   a->is_add = is_add;
203   a->locator_set_index = locator_set_index;
204   a->local = 1;
205   a->key = key;
206   a->key_id = key_id;
207
208   rv = vnet_lisp_add_del_local_mapping (a, &map_index);
209   if (0 != rv)
210     {
211       error = clib_error_return (0, "failed to %s local mapping!",
212                                  is_add ? "add" : "delete");
213     }
214 done:
215   vec_free (eids);
216   if (locator_set_name)
217     vec_free (locator_set_name);
218   gid_address_free (&a->eid);
219   vec_free (a->key);
220   unformat_free (line_input);
221   return error;
222 }
223
224 /* *INDENT-OFF* */
225 VLIB_CLI_COMMAND (one_add_del_local_eid_command) = {
226     .path = "one eid-table",
227     .short_help = "one eid-table add/del [vni <vni>] eid <eid> "
228       "locator-set <locator-set> [key <secret-key> key-id sha1|sha256 ]",
229     .function = lisp_add_del_local_eid_command_fn,
230 };
231 /* *INDENT-ON* */
232
233 static clib_error_t *
234 lisp_eid_table_map_command_fn (vlib_main_t * vm,
235                                unformat_input_t * input,
236                                vlib_cli_command_t * cmd)
237 {
238   u8 is_add = 1, is_l2 = 0;
239   u32 vni = 0, dp_id = 0;
240   unformat_input_t _line_input, *line_input = &_line_input;
241   clib_error_t *error = NULL;
242
243   /* Get a line of input. */
244   if (!unformat_user (input, unformat_line_input, line_input))
245     return 0;
246
247   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
248     {
249       if (unformat (line_input, "del"))
250         is_add = 0;
251       else if (unformat (line_input, "vni %d", &vni))
252         ;
253       else if (unformat (line_input, "vrf %d", &dp_id))
254         ;
255       else if (unformat (line_input, "bd %d", &dp_id))
256         is_l2 = 1;
257       else
258         {
259           error = unformat_parse_error (line_input);
260           goto done;
261         }
262     }
263   vnet_lisp_eid_table_map (vni, dp_id, is_l2, is_add);
264
265 done:
266   unformat_free (line_input);
267
268   return error;
269 }
270
271 /* *INDENT-OFF* */
272 VLIB_CLI_COMMAND (one_eid_table_map_command) = {
273     .path = "one eid-table map",
274     .short_help = "one eid-table map [del] vni <vni> vrf <vrf> | bd <bdi>",
275     .function = lisp_eid_table_map_command_fn,
276 };
277 /* *INDENT-ON* */
278
279 static clib_error_t *
280 lisp_add_del_l2_arp_entry_command_fn (vlib_main_t * vm,
281                                       unformat_input_t * input,
282                                       vlib_cli_command_t * cmd)
283 {
284   unformat_input_t _line_input, *line_input = &_line_input;
285   clib_error_t *error = NULL;
286   int rc = 0;
287   u8 hw_addr[6], bd = 0;
288   ip4_address_t ip4;
289   u32 hw_addr_set = 0, ip_set = 0, is_add = 1;
290   gid_address_t _arp, *arp = &_arp;
291
292   memset (&ip4, 0, sizeof (ip4));
293   memset (hw_addr, 0, sizeof (hw_addr));
294   memset (arp, 0, sizeof (*arp));
295
296   if (!unformat_user (input, unformat_line_input, line_input))
297     return 0;
298
299   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
300     {
301       if (unformat (line_input, "mac %U", unformat_mac_address, hw_addr))
302         hw_addr_set = 1;
303       else if (unformat (line_input, "ip %U", unformat_ip4_address, &ip4))
304         ip_set = 1;
305       else if (unformat (line_input, "del"))
306         is_add = 0;
307       else if (unformat (line_input, "bd %d", &bd))
308         ;
309       else
310         {
311           error = clib_error_return (0, "parse error");
312           goto done;
313         }
314     }
315
316   if (!ip_set || (!hw_addr_set && is_add))
317     {
318       vlib_cli_output (vm, "expected IP and MAC addresses!");
319       return 0;
320     }
321
322   /* build GID address */
323   gid_address_arp_ip4 (arp) = ip4;
324   gid_address_arp_bd (arp) = bd;
325   gid_address_type (arp) = GID_ADDR_ARP;
326   rc = vnet_lisp_add_del_l2_arp_entry (arp, hw_addr, is_add);
327   if (rc)
328     clib_warning ("Failed to %s l2 arp entry!", is_add ? "add" : "delete");
329
330 done:
331   unformat_free (line_input);
332   return error;
333 }
334
335 /* *INDENT-OFF* */
336 VLIB_CLI_COMMAND (one_add_del_l2_arp_entry_command) = {
337     .path = "one l2 arp",
338     .short_help = "one l2 arp [del] bd <bd> mac <mac> ip <ipv4>",
339     .function = lisp_add_del_l2_arp_entry_command_fn,
340 };
341 /* *INDENT-ON* */
342
343 static clib_error_t *
344 lisp_show_l2_arp_entries_command_fn (vlib_main_t * vm,
345                                      unformat_input_t * input,
346                                      vlib_cli_command_t * cmd)
347 {
348   u32 *ht = vnet_lisp_l2_arp_bds_get ();
349   lisp_api_l2_arp_entry_t *entries, *e;
350   hash_pair_t *p;
351
352   /* *INDENT-OFF* */
353   hash_foreach_pair (p, ht,
354   ({
355     entries = vnet_lisp_l2_arp_entries_get_by_bd (p->key);
356     vlib_cli_output (vm, "Table: %d", p->key);
357
358     vec_foreach (e, entries)
359       {
360         vlib_cli_output (vm, "\t%U -> %U", format_ip4_address, &e->ip4,
361                          format_mac_address, e->mac);
362       }
363     vec_free (entries);
364   }));
365   /* *INDENT-ON* */
366
367   hash_free (ht);
368   return 0;
369 }
370
371 /* *INDENT-OFF* */
372 VLIB_CLI_COMMAND (one_show_l2_arp_entries_command) = {
373     .path = "show one l2 arp entries",
374     .short_help = "Show ONE L2 ARP entries",
375     .function = lisp_show_l2_arp_entries_command_fn,
376 };
377 /* *INDENT-ON* */
378
379 static clib_error_t *
380 lisp_show_ndp_entries_command_fn (vlib_main_t * vm,
381                                   unformat_input_t * input,
382                                   vlib_cli_command_t * cmd)
383 {
384   u32 *ht = vnet_lisp_ndp_bds_get ();
385   lisp_api_ndp_entry_t *entries, *e;
386   hash_pair_t *p;
387
388   /* *INDENT-OFF* */
389   hash_foreach_pair (p, ht,
390   ({
391     entries = vnet_lisp_ndp_entries_get_by_bd (p->key);
392     vlib_cli_output (vm, "Table: %d", p->key);
393
394     vec_foreach (e, entries)
395       {
396         vlib_cli_output (vm, "\t%U -> %U", format_ip6_address, &e->ip6,
397                          format_mac_address, e->mac);
398       }
399     vec_free (entries);
400   }));
401   /* *INDENT-ON* */
402
403   hash_free (ht);
404   return 0;
405 }
406
407 /* *INDENT-OFF* */
408 VLIB_CLI_COMMAND (one_show_ndp_entries_command) = {
409     .path = "show one ndp entries",
410     .short_help = "Show ONE NDP entries",
411     .function = lisp_show_ndp_entries_command_fn,
412 };
413 /* *INDENT-ON* */
414
415 /**
416  * Handler for add/del remote mapping CLI.
417  *
418  * @param vm vlib context
419  * @param input input from user
420  * @param cmd cmd
421  * @return pointer to clib error structure
422  */
423 static clib_error_t *
424 lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
425                                         unformat_input_t * input,
426                                         vlib_cli_command_t * cmd)
427 {
428   clib_error_t *error = 0;
429   unformat_input_t _line_input, *line_input = &_line_input;
430   u8 is_add = 1, del_all = 0;
431   locator_t rloc, *rlocs = 0, *curr_rloc = 0;
432   gid_address_t eid;
433   u8 eid_set = 0;
434   u32 vni, action = ~0, p, w;
435   int rv;
436
437   /* Get a line of input. */
438   if (!unformat_user (input, unformat_line_input, line_input))
439     return 0;
440
441   memset (&eid, 0, sizeof (eid));
442   memset (&rloc, 0, sizeof (rloc));
443
444   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
445     {
446       if (unformat (line_input, "del-all"))
447         del_all = 1;
448       else if (unformat (line_input, "del"))
449         is_add = 0;
450       else if (unformat (line_input, "add"))
451         ;
452       else if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
453         eid_set = 1;
454       else if (unformat (line_input, "vni %u", &vni))
455         {
456           gid_address_vni (&eid) = vni;
457         }
458       else if (unformat (line_input, "p %d w %d", &p, &w))
459         {
460           if (!curr_rloc)
461             {
462               clib_warning
463                 ("No RLOC configured for setting priority/weight!");
464               goto done;
465             }
466           curr_rloc->priority = p;
467           curr_rloc->weight = w;
468         }
469       else if (unformat (line_input, "rloc %U", unformat_ip_address,
470                          &gid_address_ip (&rloc.address)))
471         {
472           /* since rloc is stored in ip prefix we need to set prefix length */
473           ip_prefix_t *pref = &gid_address_ippref (&rloc.address);
474
475           u8 version = gid_address_ip_version (&rloc.address);
476           ip_prefix_len (pref) = ip_address_max_len (version);
477
478           vec_add1 (rlocs, rloc);
479           curr_rloc = &rlocs[vec_len (rlocs) - 1];
480         }
481       else if (unformat (line_input, "action %U",
482                          unformat_negative_mapping_action, &action))
483         ;
484       else
485         {
486           clib_warning ("parse error");
487           goto done;
488         }
489     }
490
491   if (!del_all && !eid_set)
492     {
493       clib_warning ("missing eid!");
494       goto done;
495     }
496
497   if (!del_all)
498     {
499       if (is_add && (~0 == action) && 0 == vec_len (rlocs))
500         {
501           clib_warning ("no action set for negative map-reply!");
502           goto done;
503         }
504     }
505   else
506     {
507       vnet_lisp_clear_all_remote_adjacencies ();
508       goto done;
509     }
510
511   /* if it's a delete, clean forwarding */
512   if (!is_add)
513     {
514       vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
515       memset (a, 0, sizeof (a[0]));
516       gid_address_copy (&a->reid, &eid);
517       if (vnet_lisp_add_del_adjacency (a))
518         {
519           clib_warning ("failed to delete adjacency!");
520           goto done;
521         }
522     }
523
524   /* add as static remote mapping, i.e., not authoritative and infinite
525    * ttl */
526   if (is_add)
527     {
528       vnet_lisp_add_del_mapping_args_t _map_args, *map_args = &_map_args;
529       memset (map_args, 0, sizeof (map_args[0]));
530       gid_address_copy (&map_args->eid, &eid);
531       map_args->action = action;
532       map_args->is_static = 1;
533       map_args->authoritative = 0;
534       map_args->ttl = ~0;
535       rv = vnet_lisp_add_mapping (map_args, rlocs, NULL, NULL);
536     }
537   else
538     rv = vnet_lisp_del_mapping (&eid, NULL);
539
540   if (rv)
541     clib_warning ("failed to %s remote mapping!", is_add ? "add" : "delete");
542
543 done:
544   vec_free (rlocs);
545   unformat_free (line_input);
546   return error;
547 }
548
549 /* *INDENT-OFF* */
550 VLIB_CLI_COMMAND (one_add_del_remote_mapping_command) = {
551   .path = "one remote-mapping",
552   .short_help =
553     "one remote-mapping add|del [del-all] vni <vni> "
554     "eid <est-eid> [action <no-action|natively-forward|"
555     "send-map-request|drop>] rloc <dst-locator> p <prio> w <weight> "
556     "[rloc <dst-locator> ... ]",
557   .function = lisp_add_del_remote_mapping_command_fn,
558 };
559 /* *INDENT-ON* */
560
561 /**
562  * Handler for add/del adjacency CLI.
563  */
564 static clib_error_t *
565 lisp_add_del_adjacency_command_fn (vlib_main_t * vm, unformat_input_t * input,
566                                    vlib_cli_command_t * cmd)
567 {
568   clib_error_t *error = 0;
569   unformat_input_t _line_input, *line_input = &_line_input;
570   vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
571   u8 is_add = 1;
572   ip_prefix_t *reid_ippref, *leid_ippref;
573   gid_address_t leid, reid;
574   u8 *dmac = gid_address_mac (&reid);
575   u8 *smac = gid_address_mac (&leid);
576   u8 reid_set = 0, leid_set = 0;
577   u32 vni;
578
579   /* Get a line of input. */
580   if (!unformat_user (input, unformat_line_input, line_input))
581     return 0;
582
583   memset (&reid, 0, sizeof (reid));
584   memset (&leid, 0, sizeof (leid));
585
586   leid_ippref = &gid_address_ippref (&leid);
587   reid_ippref = &gid_address_ippref (&reid);
588
589   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
590     {
591       if (unformat (line_input, "del"))
592         is_add = 0;
593       else if (unformat (line_input, "add"))
594         ;
595       else if (unformat (line_input, "reid %U",
596                          unformat_ip_prefix, reid_ippref))
597         {
598           gid_address_type (&reid) = GID_ADDR_IP_PREFIX;
599           reid_set = 1;
600         }
601       else if (unformat (line_input, "reid %U", unformat_mac_address, dmac))
602         {
603           gid_address_type (&reid) = GID_ADDR_MAC;
604           reid_set = 1;
605         }
606       else if (unformat (line_input, "vni %u", &vni))
607         {
608           gid_address_vni (&leid) = vni;
609           gid_address_vni (&reid) = vni;
610         }
611       else if (unformat (line_input, "leid %U",
612                          unformat_ip_prefix, leid_ippref))
613         {
614           gid_address_type (&leid) = GID_ADDR_IP_PREFIX;
615           leid_set = 1;
616         }
617       else if (unformat (line_input, "leid %U", unformat_mac_address, smac))
618         {
619           gid_address_type (&leid) = GID_ADDR_MAC;
620           leid_set = 1;
621         }
622       else
623         {
624           clib_warning ("parse error");
625           goto done;
626         }
627     }
628
629   if (!reid_set || !leid_set)
630     {
631       clib_warning ("missing remote or local eid!");
632       goto done;
633     }
634
635   if ((gid_address_type (&leid) != gid_address_type (&reid))
636       || (gid_address_type (&reid) == GID_ADDR_IP_PREFIX
637           && ip_prefix_version (reid_ippref)
638           != ip_prefix_version (leid_ippref)))
639     {
640       clib_warning ("remote and local EIDs are of different types!");
641       goto done;
642     }
643
644   memset (a, 0, sizeof (a[0]));
645   gid_address_copy (&a->leid, &leid);
646   gid_address_copy (&a->reid, &reid);
647   a->is_add = is_add;
648
649   if (vnet_lisp_add_del_adjacency (a))
650     clib_warning ("failed to %s adjacency!", is_add ? "add" : "delete");
651
652 done:
653   unformat_free (line_input);
654   return error;
655 }
656
657 /* *INDENT-OFF* */
658 VLIB_CLI_COMMAND (one_add_del_adjacency_command) = {
659     .path = "one adjacency",
660     .short_help = "one adjacency add|del vni <vni> reid <remote-eid> "
661       "leid <local-eid>",
662     .function = lisp_add_del_adjacency_command_fn,
663 };
664 /* *INDENT-ON* */
665
666
667 static clib_error_t *
668 lisp_map_request_mode_command_fn (vlib_main_t * vm,
669                                   unformat_input_t * input,
670                                   vlib_cli_command_t * cmd)
671 {
672   unformat_input_t _i, *i = &_i;
673   map_request_mode_t mr_mode = _MR_MODE_MAX;
674
675   /* Get a line of input. */
676   if (!unformat_user (input, unformat_line_input, i))
677     return 0;
678
679   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
680     {
681       if (unformat (i, "dst-only"))
682         mr_mode = MR_MODE_DST_ONLY;
683       else if (unformat (i, "src-dst"))
684         mr_mode = MR_MODE_SRC_DST;
685       else
686         {
687           clib_warning ("parse error '%U'", format_unformat_error, i);
688           goto done;
689         }
690     }
691
692   if (_MR_MODE_MAX == mr_mode)
693     {
694       clib_warning ("No map request mode entered!");
695       goto done;
696     }
697
698   vnet_lisp_set_map_request_mode (mr_mode);
699
700 done:
701   unformat_free (i);
702
703   return 0;
704 }
705
706 /* *INDENT-OFF* */
707 VLIB_CLI_COMMAND (one_map_request_mode_command) = {
708     .path = "one map-request mode",
709     .short_help = "one map-request mode dst-only|src-dst",
710     .function = lisp_map_request_mode_command_fn,
711 };
712 /* *INDENT-ON* */
713
714
715 static u8 *
716 format_lisp_map_request_mode (u8 * s, va_list * args)
717 {
718   u32 mode = va_arg (*args, u32);
719
720   switch (mode)
721     {
722     case 0:
723       return format (0, "dst-only");
724     case 1:
725       return format (0, "src-dst");
726     }
727   return 0;
728 }
729
730 static clib_error_t *
731 lisp_show_map_request_mode_command_fn (vlib_main_t * vm,
732                                        unformat_input_t * input,
733                                        vlib_cli_command_t * cmd)
734 {
735   vlib_cli_output (vm, "map-request mode: %U", format_lisp_map_request_mode,
736                    vnet_lisp_get_map_request_mode ());
737   return 0;
738 }
739
740 /* *INDENT-OFF* */
741 VLIB_CLI_COMMAND (one_show_map_request_mode_command) = {
742     .path = "show one map-request mode",
743     .short_help = "show one map-request mode",
744     .function = lisp_show_map_request_mode_command_fn,
745 };
746 /* *INDENT-ON* */
747
748 static clib_error_t *
749 lisp_show_map_resolvers_command_fn (vlib_main_t * vm,
750                                     unformat_input_t * input,
751                                     vlib_cli_command_t * cmd)
752 {
753   lisp_msmr_t *mr;
754   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
755
756   vec_foreach (mr, lcm->map_resolvers)
757   {
758     vlib_cli_output (vm, "%U", format_ip_address, &mr->address);
759   }
760   return 0;
761 }
762
763 /* *INDENT-OFF* */
764 VLIB_CLI_COMMAND (one_show_map_resolvers_command) = {
765     .path = "show one map-resolvers",
766     .short_help = "show one map-resolvers",
767     .function = lisp_show_map_resolvers_command_fn,
768 };
769 /* *INDENT-ON* */
770
771 static clib_error_t *
772 lisp_nsh_set_locator_set_command_fn (vlib_main_t * vm,
773                                      unformat_input_t * input,
774                                      vlib_cli_command_t * cmd)
775 {
776   u8 locator_name_set = 0;
777   u8 *locator_set_name = 0;
778   u8 is_add = 1;
779   unformat_input_t _line_input, *line_input = &_line_input;
780   clib_error_t *error = 0;
781   int rv = 0;
782
783   /* Get a line of input. */
784   if (!unformat_user (input, unformat_line_input, line_input))
785     return 0;
786
787   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
788     {
789       if (unformat (line_input, "ls %_%v%_", &locator_set_name))
790         locator_name_set = 1;
791       else if (unformat (line_input, "disable"))
792         is_add = 0;
793       else
794         {
795           error = clib_error_return (0, "parse error");
796           goto done;
797         }
798     }
799
800   if (!locator_name_set)
801     {
802       clib_warning ("No locator set specified!");
803       goto done;
804     }
805
806   rv = vnet_lisp_nsh_set_locator_set (locator_set_name, is_add);
807   if (0 != rv)
808     {
809       error = clib_error_return (0, "failed to %s NSH mapping!",
810                                  is_add ? "add" : "delete");
811     }
812
813 done:
814   vec_free (locator_set_name);
815   unformat_free (line_input);
816   return error;
817 }
818
819 /* *INDENT-OFF* */
820 VLIB_CLI_COMMAND (one_nsh_set_locator_set_command) = {
821     .path = "one nsh-mapping",
822     .short_help = "one nsh-mapping [del] ls <locator-set-name>",
823     .function = lisp_nsh_set_locator_set_command_fn,
824 };
825 /* *INDENT-ON* */
826
827 static clib_error_t *
828 lisp_map_register_fallback_threshold_show_command_fn (vlib_main_t * vm,
829                                                       unformat_input_t *
830                                                       input,
831                                                       vlib_cli_command_t *
832                                                       cmd)
833 {
834   u32 val = vnet_lisp_map_register_fallback_threshold_get ();
835   vlib_cli_output (vm, "map register fallback treshold value: %d", val);
836   return 0;
837 }
838
839 /* *INDENT-OFF* */
840 VLIB_CLI_COMMAND (one_map_register_fallback_threshold_show_command) = {
841     .path = "show one map-register fallback-threshold",
842     .short_help = "show one map-register fallback-threshold",
843     .function = lisp_map_register_fallback_threshold_show_command_fn,
844 };
845
846 /* *INDENT-ON* */
847
848 static clib_error_t *
849 lisp_map_register_fallback_threshold_command_fn (vlib_main_t * vm,
850                                                  unformat_input_t * input,
851                                                  vlib_cli_command_t * cmd)
852 {
853   unformat_input_t _line_input, *line_input = &_line_input;
854   clib_error_t *error = 0;
855   u32 val = 0;
856   int rv = 0;
857
858   /* Get a line of input. */
859   if (!unformat_user (input, unformat_line_input, line_input))
860     return 0;
861
862   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
863     {
864       if (unformat (line_input, "%d", &val))
865         ;
866       else
867         {
868           error = clib_error_return (0, "parse error");
869           goto done;
870         }
871     }
872
873   rv = vnet_lisp_map_register_fallback_threshold_set (val);
874   if (rv)
875     {
876       error = clib_error_return (0, "setting fallback threshold failed!");
877     }
878
879 done:
880   unformat_free (line_input);
881   return error;
882 }
883
884 /* *INDENT-OFF* */
885 VLIB_CLI_COMMAND (one_map_register_fallback_threshold_command) = {
886     .path = "one map-register fallback-threshold",
887     .short_help = "one map-register fallback-threshold <count>",
888     .function = lisp_map_register_fallback_threshold_command_fn,
889 };
890 /* *INDENT-ON* */
891
892 static clib_error_t *
893 lisp_pitr_set_locator_set_command_fn (vlib_main_t * vm,
894                                       unformat_input_t * input,
895                                       vlib_cli_command_t * cmd)
896 {
897   u8 locator_name_set = 0;
898   u8 *locator_set_name = 0;
899   u8 is_add = 1;
900   unformat_input_t _line_input, *line_input = &_line_input;
901   clib_error_t *error = 0;
902   int rv = 0;
903
904   /* Get a line of input. */
905   if (!unformat_user (input, unformat_line_input, line_input))
906     return 0;
907
908   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
909     {
910       if (unformat (line_input, "ls %_%v%_", &locator_set_name))
911         locator_name_set = 1;
912       else if (unformat (line_input, "disable"))
913         is_add = 0;
914       else
915         {
916           error = clib_error_return (0, "parse error");
917           goto done;
918         }
919     }
920
921   if (!locator_name_set)
922     {
923       clib_warning ("No locator set specified!");
924       goto done;
925     }
926   rv = vnet_lisp_pitr_set_locator_set (locator_set_name, is_add);
927   if (0 != rv)
928     {
929       error = clib_error_return (0, "failed to %s pitr!",
930                                  is_add ? "add" : "delete");
931     }
932
933 done:
934   if (locator_set_name)
935     vec_free (locator_set_name);
936   unformat_free (line_input);
937   return error;
938 }
939
940 /* *INDENT-OFF* */
941 VLIB_CLI_COMMAND (one_pitr_set_locator_set_command) = {
942     .path = "one pitr",
943     .short_help = "one pitr [disable] ls <locator-set-name>",
944     .function = lisp_pitr_set_locator_set_command_fn,
945 };
946 /* *INDENT-ON* */
947
948 static clib_error_t *
949 lisp_show_pitr_command_fn (vlib_main_t * vm,
950                            unformat_input_t * input, vlib_cli_command_t * cmd)
951 {
952   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
953   mapping_t *m;
954   locator_set_t *ls;
955   u8 *tmp_str = 0;
956
957   vlib_cli_output (vm, "%=20s%=16s",
958                    "pitr", lcm->lisp_pitr ? "locator-set" : "");
959
960   if (!lcm->lisp_pitr)
961     {
962       vlib_cli_output (vm, "%=20s", "disable");
963       return 0;
964     }
965
966   if (~0 == lcm->pitr_map_index)
967     {
968       tmp_str = format (0, "N/A");
969     }
970   else
971     {
972       m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
973       if (~0 != m->locator_set_index)
974         {
975           ls =
976             pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
977           tmp_str = format (0, "%s", ls->name);
978         }
979       else
980         {
981           tmp_str = format (0, "N/A");
982         }
983     }
984   vec_add1 (tmp_str, 0);
985
986   vlib_cli_output (vm, "%=20s%=16s", "enable", tmp_str);
987
988   vec_free (tmp_str);
989
990   return 0;
991 }
992
993 /* *INDENT-OFF* */
994 VLIB_CLI_COMMAND (one_show_pitr_command) = {
995     .path = "show one pitr",
996     .short_help = "Show pitr",
997     .function = lisp_show_pitr_command_fn,
998 };
999 /* *INDENT-ON* */
1000
1001 static u8 *
1002 format_eid_entry (u8 * s, va_list * args)
1003 {
1004   vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
1005   lisp_cp_main_t *lcm = va_arg (*args, lisp_cp_main_t *);
1006   mapping_t *mapit = va_arg (*args, mapping_t *);
1007   locator_set_t *ls = va_arg (*args, locator_set_t *);
1008   gid_address_t *gid = &mapit->eid;
1009   u32 ttl = mapit->ttl;
1010   u8 aut = mapit->authoritative;
1011   u32 *loc_index;
1012   u8 first_line = 1;
1013   u8 *loc;
1014
1015   u8 *type = ls->local ? format (0, "local(%s)", ls->name)
1016     : format (0, "remote");
1017
1018   if (vec_len (ls->locator_indices) == 0)
1019     {
1020       s = format (s, "%-35U%-20saction:%-30U%-20u%-u", format_gid_address,
1021                   gid, type, format_negative_mapping_action, mapit->action,
1022                   ttl, aut);
1023     }
1024   else
1025     {
1026       vec_foreach (loc_index, ls->locator_indices)
1027       {
1028         locator_t *l = pool_elt_at_index (lcm->locator_pool, loc_index[0]);
1029         if (l->local)
1030           loc = format (0, "%U", format_vnet_sw_if_index_name, vnm,
1031                         l->sw_if_index);
1032         else
1033           loc = format (0, "%U", format_ip_address,
1034                         &gid_address_ip (&l->address));
1035
1036         if (first_line)
1037           {
1038             s = format (s, "%-35U%-20s%-30v%-20u%-u\n", format_gid_address,
1039                         gid, type, loc, ttl, aut);
1040             first_line = 0;
1041           }
1042         else
1043           s = format (s, "%55s%v\n", "", loc);
1044       }
1045     }
1046   return s;
1047 }
1048
1049 static clib_error_t *
1050 lisp_show_eid_table_command_fn (vlib_main_t * vm,
1051                                 unformat_input_t * input,
1052                                 vlib_cli_command_t * cmd)
1053 {
1054   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1055   mapping_t *mapit;
1056   unformat_input_t _line_input, *line_input = &_line_input;
1057   u32 mi;
1058   gid_address_t eid;
1059   u8 print_all = 1;
1060   u8 filter = 0;
1061   clib_error_t *error = NULL;
1062
1063   memset (&eid, 0, sizeof (eid));
1064
1065   /* Get a line of input. */
1066   if (!unformat_user (input, unformat_line_input, line_input))
1067     return 0;
1068
1069   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1070     {
1071       if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
1072         print_all = 0;
1073       else if (unformat (line_input, "local"))
1074         filter = 1;
1075       else if (unformat (line_input, "remote"))
1076         filter = 2;
1077       else
1078         {
1079           error = clib_error_return (0, "parse error: '%U'",
1080                                      format_unformat_error, line_input);
1081           goto done;
1082         }
1083     }
1084
1085   vlib_cli_output (vm, "%-35s%-20s%-30s%-20s%-s",
1086                    "EID", "type", "locators", "ttl", "autoritative");
1087
1088   if (print_all)
1089     {
1090       /* *INDENT-OFF* */
1091       pool_foreach (mapit, lcm->mapping_pool,
1092       ({
1093         if (mapit->pitr_set || mapit->nsh_set)
1094           continue;
1095
1096         locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool,
1097                                                 mapit->locator_set_index);
1098         if (filter && !((1 == filter && ls->local) ||
1099           (2 == filter && !ls->local)))
1100           {
1101             continue;
1102           }
1103         vlib_cli_output (vm, "%U", format_eid_entry, lcm->vnet_main,
1104                          lcm, mapit, ls);
1105       }));
1106       /* *INDENT-ON* */
1107     }
1108   else
1109     {
1110       mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &eid);
1111       if ((u32) ~ 0 == mi)
1112         goto done;
1113
1114       mapit = pool_elt_at_index (lcm->mapping_pool, mi);
1115       locator_set_t *ls = pool_elt_at_index (lcm->locator_set_pool,
1116                                              mapit->locator_set_index);
1117
1118       if (filter && !((1 == filter && ls->local) ||
1119                       (2 == filter && !ls->local)))
1120         {
1121           goto done;
1122         }
1123
1124       vlib_cli_output (vm, "%U,", format_eid_entry, lcm->vnet_main,
1125                        lcm, mapit, ls);
1126     }
1127
1128 done:
1129   unformat_free (line_input);
1130
1131   return error;
1132 }
1133
1134 /* *INDENT-OFF* */
1135 VLIB_CLI_COMMAND (one_cp_show_eid_table_command) = {
1136     .path = "show one eid-table",
1137     .short_help = "Shows EID table",
1138     .function = lisp_show_eid_table_command_fn,
1139 };
1140 /* *INDENT-ON* */
1141
1142
1143 static clib_error_t *
1144 lisp_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input,
1145                                 vlib_cli_command_t * cmd)
1146 {
1147   unformat_input_t _line_input, *line_input = &_line_input;
1148   u8 is_enabled = 0;
1149   u8 is_set = 0;
1150   clib_error_t *error = NULL;
1151
1152   /* Get a line of input. */
1153   if (!unformat_user (input, unformat_line_input, line_input))
1154     return 0;
1155
1156   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1157     {
1158       if (unformat (line_input, "enable"))
1159         {
1160           is_set = 1;
1161           is_enabled = 1;
1162         }
1163       else if (unformat (line_input, "disable"))
1164         is_set = 1;
1165       else
1166         {
1167           error = clib_error_return (0, "parse error: '%U'",
1168                                      format_unformat_error, line_input);
1169           goto done;
1170         }
1171     }
1172
1173   if (!is_set)
1174     {
1175       error = clib_error_return (0, "state not set");
1176       goto done;
1177     }
1178
1179   vnet_lisp_enable_disable (is_enabled);
1180
1181 done:
1182   unformat_free (line_input);
1183
1184   return error;
1185 }
1186
1187 /* *INDENT-OFF* */
1188 VLIB_CLI_COMMAND (one_cp_enable_disable_command) = {
1189     .path = "one",
1190     .short_help = "one [enable|disable]",
1191     .function = lisp_enable_disable_command_fn,
1192 };
1193 /* *INDENT-ON* */
1194
1195 static clib_error_t *
1196 lisp_map_register_set_ttl_command_fn (vlib_main_t * vm,
1197                                       unformat_input_t * input,
1198                                       vlib_cli_command_t * cmd)
1199 {
1200   unformat_input_t _line_input, *line_input = &_line_input;
1201   u32 ttl = 0;
1202   u8 is_set = 0;
1203   clib_error_t *error = NULL;
1204
1205   /* Get a line of input. */
1206   if (!unformat_user (input, unformat_line_input, line_input))
1207     return 0;
1208
1209   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1210     {
1211       if (unformat (line_input, "%u", &ttl))
1212         is_set = 1;
1213       else
1214         {
1215           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1216                            line_input);
1217           goto done;
1218         }
1219     }
1220
1221   if (!is_set)
1222     {
1223       vlib_cli_output (vm, "expected integer value for TTL!");
1224       goto done;
1225     }
1226
1227   vnet_lisp_map_register_set_ttl (ttl);
1228
1229 done:
1230   unformat_free (line_input);
1231   return error;
1232 }
1233
1234 /* *INDENT-OFF* */
1235 VLIB_CLI_COMMAND (one_map_register_set_ttl_command) = {
1236     .path = "one map-register ttl",
1237     .short_help = "one map-register ttl",
1238     .function = lisp_map_register_set_ttl_command_fn,
1239 };
1240 /* *INDENT-ON* */
1241
1242 static clib_error_t *
1243 lisp_map_register_show_ttl_command_fn (vlib_main_t * vm,
1244                                        unformat_input_t * input,
1245                                        vlib_cli_command_t * cmd)
1246 {
1247   u32 ttl = vnet_lisp_map_register_get_ttl ();
1248
1249   vlib_cli_output (vm, "map-register TTL: %u", ttl);
1250   return 0;
1251 }
1252
1253 /* *INDENT-OFF* */
1254 VLIB_CLI_COMMAND (one_map_register_show_ttl_command) = {
1255     .path = "show one map-register ttl",
1256     .short_help = "show one map-register ttl",
1257     .function = lisp_map_register_show_ttl_command_fn,
1258 };
1259
1260 /* *INDENT-ON* */
1261
1262 static clib_error_t *
1263 lisp_map_register_enable_disable_command_fn (vlib_main_t * vm,
1264                                              unformat_input_t * input,
1265                                              vlib_cli_command_t * cmd)
1266 {
1267   unformat_input_t _line_input, *line_input = &_line_input;
1268   u8 is_enabled = 0;
1269   u8 is_set = 0;
1270   clib_error_t *error = NULL;
1271
1272   /* Get a line of input. */
1273   if (!unformat_user (input, unformat_line_input, line_input))
1274     return 0;
1275
1276   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1277     {
1278       if (unformat (line_input, "enable"))
1279         {
1280           is_set = 1;
1281           is_enabled = 1;
1282         }
1283       else if (unformat (line_input, "disable"))
1284         is_set = 1;
1285       else
1286         {
1287           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1288                            line_input);
1289           goto done;
1290         }
1291     }
1292
1293   if (!is_set)
1294     {
1295       vlib_cli_output (vm, "state not set!");
1296       goto done;
1297     }
1298
1299   vnet_lisp_map_register_enable_disable (is_enabled);
1300
1301 done:
1302   unformat_free (line_input);
1303
1304   return error;
1305 }
1306
1307 /* *INDENT-OFF* */
1308 VLIB_CLI_COMMAND (one_map_register_enable_disable_command) = {
1309     .path = "one map-register",
1310     .short_help = "one map-register [enable|disable]",
1311     .function = lisp_map_register_enable_disable_command_fn,
1312 };
1313 /* *INDENT-ON* */
1314
1315 static clib_error_t *
1316 lisp_rloc_probe_enable_disable_command_fn (vlib_main_t * vm,
1317                                            unformat_input_t * input,
1318                                            vlib_cli_command_t * cmd)
1319 {
1320   unformat_input_t _line_input, *line_input = &_line_input;
1321   u8 is_enabled = 0;
1322   u8 is_set = 0;
1323   clib_error_t *error = NULL;
1324
1325   /* Get a line of input. */
1326   if (!unformat_user (input, unformat_line_input, line_input))
1327     return 0;
1328
1329   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1330     {
1331       if (unformat (line_input, "enable"))
1332         {
1333           is_set = 1;
1334           is_enabled = 1;
1335         }
1336       else if (unformat (line_input, "disable"))
1337         is_set = 1;
1338       else
1339         {
1340           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1341                            line_input);
1342           goto done;
1343         }
1344     }
1345
1346   if (!is_set)
1347     {
1348       vlib_cli_output (vm, "state not set!");
1349       goto done;
1350     }
1351
1352   vnet_lisp_rloc_probe_enable_disable (is_enabled);
1353
1354 done:
1355   unformat_free (line_input);
1356
1357   return error;
1358 }
1359
1360 /* *INDENT-OFF* */
1361 VLIB_CLI_COMMAND (one_rloc_probe_enable_disable_command) = {
1362     .path = "one rloc-probe",
1363     .short_help = "one rloc-probe [enable|disable]",
1364     .function = lisp_rloc_probe_enable_disable_command_fn,
1365 };
1366 /* *INDENT-ON* */
1367
1368 static u8 *
1369 format_lisp_status (u8 * s, va_list * args)
1370 {
1371   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1372   return format (s, "%s", lcm->is_enabled ? "enabled" : "disabled");
1373 }
1374
1375 static clib_error_t *
1376 lisp_show_status_command_fn (vlib_main_t * vm, unformat_input_t * input,
1377                              vlib_cli_command_t * cmd)
1378 {
1379   u8 *msg = 0;
1380   msg = format (msg, "feature: %U\ngpe: %U\n",
1381                 format_lisp_status, format_vnet_lisp_gpe_status);
1382   vlib_cli_output (vm, "%v", msg);
1383   vec_free (msg);
1384   return 0;
1385 }
1386
1387 /* *INDENT-OFF* */
1388 VLIB_CLI_COMMAND (one_show_status_command) = {
1389     .path = "show one status",
1390     .short_help = "show one status",
1391     .function = lisp_show_status_command_fn,
1392 };
1393 /* *INDENT-ON* */
1394
1395 static clib_error_t *
1396 lisp_show_eid_table_map_command_fn (vlib_main_t * vm,
1397                                     unformat_input_t * input,
1398                                     vlib_cli_command_t * cmd)
1399 {
1400   hash_pair_t *p;
1401   unformat_input_t _line_input, *line_input = &_line_input;
1402   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1403   uword *vni_table = 0;
1404   u8 is_l2 = 0;
1405   clib_error_t *error = NULL;
1406
1407   /* Get a line of input. */
1408   if (!unformat_user (input, unformat_line_input, line_input))
1409     return 0;
1410
1411   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1412     {
1413       if (unformat (line_input, "l2"))
1414         {
1415           vni_table = lcm->bd_id_by_vni;
1416           is_l2 = 1;
1417         }
1418       else if (unformat (line_input, "l3"))
1419         {
1420           vni_table = lcm->table_id_by_vni;
1421           is_l2 = 0;
1422         }
1423       else
1424         {
1425           error = clib_error_return (0, "parse error: '%U'",
1426                                      format_unformat_error, line_input);
1427           goto done;
1428         }
1429     }
1430
1431   if (!vni_table)
1432     {
1433       vlib_cli_output (vm, "Error: expected l2|l3 param!\n");
1434       goto done;
1435     }
1436
1437   vlib_cli_output (vm, "%=10s%=10s", "VNI", is_l2 ? "BD" : "VRF");
1438
1439   /* *INDENT-OFF* */
1440   hash_foreach_pair (p, vni_table,
1441   ({
1442     vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]);
1443   }));
1444   /* *INDENT-ON* */
1445
1446 done:
1447   unformat_free (line_input);
1448
1449   return error;
1450 }
1451
1452 /* *INDENT-OFF* */
1453 VLIB_CLI_COMMAND (one_show_eid_table_map_command) = {
1454     .path = "show one eid-table map",
1455     .short_help = "show one eid-table l2|l3",
1456     .function = lisp_show_eid_table_map_command_fn,
1457 };
1458 /* *INDENT-ON* */
1459
1460
1461 static clib_error_t *
1462 lisp_add_del_locator_set_command_fn (vlib_main_t * vm,
1463                                      unformat_input_t * input,
1464                                      vlib_cli_command_t * cmd)
1465 {
1466   lisp_gpe_main_t *lgm = &lisp_gpe_main;
1467   vnet_main_t *vnm = lgm->vnet_main;
1468   unformat_input_t _line_input, *line_input = &_line_input;
1469   u8 is_add = 1;
1470   clib_error_t *error = 0;
1471   u8 *locator_set_name = 0;
1472   locator_t locator, *locators = 0;
1473   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
1474   u32 ls_index = 0;
1475   int rv = 0;
1476
1477   memset (&locator, 0, sizeof (locator));
1478   memset (a, 0, sizeof (a[0]));
1479
1480   /* Get a line of input. */
1481   if (!unformat_user (input, unformat_line_input, line_input))
1482     return 0;
1483
1484   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1485     {
1486       if (unformat (line_input, "add %_%v%_", &locator_set_name))
1487         is_add = 1;
1488       else if (unformat (line_input, "del %_%v%_", &locator_set_name))
1489         is_add = 0;
1490       else if (unformat (line_input, "iface %U p %d w %d",
1491                          unformat_vnet_sw_interface, vnm,
1492                          &locator.sw_if_index, &locator.priority,
1493                          &locator.weight))
1494         {
1495           locator.local = 1;
1496           vec_add1 (locators, locator);
1497         }
1498       else
1499         {
1500           error = unformat_parse_error (line_input);
1501           goto done;
1502         }
1503     }
1504
1505   a->name = locator_set_name;
1506   a->locators = locators;
1507   a->is_add = is_add;
1508   a->local = 1;
1509
1510   rv = vnet_lisp_add_del_locator_set (a, &ls_index);
1511   if (0 != rv)
1512     {
1513       error = clib_error_return (0, "failed to %s locator-set!",
1514                                  is_add ? "add" : "delete");
1515     }
1516
1517 done:
1518   vec_free (locators);
1519   if (locator_set_name)
1520     vec_free (locator_set_name);
1521   unformat_free (line_input);
1522   return error;
1523 }
1524
1525 /* *INDENT-OFF* */
1526 VLIB_CLI_COMMAND (one_cp_add_del_locator_set_command) = {
1527     .path = "one locator-set",
1528     .short_help = "one locator-set add/del <name> [iface <iface-name> "
1529         "p <priority> w <weight>]",
1530     .function = lisp_add_del_locator_set_command_fn,
1531 };
1532 /* *INDENT-ON* */
1533
1534 static clib_error_t *
1535 lisp_add_del_locator_in_set_command_fn (vlib_main_t * vm,
1536                                         unformat_input_t * input,
1537                                         vlib_cli_command_t * cmd)
1538 {
1539   lisp_gpe_main_t *lgm = &lisp_gpe_main;
1540   vnet_main_t *vnm = lgm->vnet_main;
1541   unformat_input_t _line_input, *line_input = &_line_input;
1542   u8 is_add = 1;
1543   clib_error_t *error = 0;
1544   u8 *locator_set_name = 0;
1545   u8 locator_set_name_set = 0;
1546   locator_t locator, *locators = 0;
1547   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
1548   u32 ls_index = 0;
1549
1550   memset (&locator, 0, sizeof (locator));
1551   memset (a, 0, sizeof (a[0]));
1552
1553   /* Get a line of input. */
1554   if (!unformat_user (input, unformat_line_input, line_input))
1555     return 0;
1556
1557   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1558     {
1559       if (unformat (line_input, "add"))
1560         is_add = 1;
1561       else if (unformat (line_input, "del"))
1562         is_add = 0;
1563       else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
1564         locator_set_name_set = 1;
1565       else if (unformat (line_input, "iface %U p %d w %d",
1566                          unformat_vnet_sw_interface, vnm,
1567                          &locator.sw_if_index, &locator.priority,
1568                          &locator.weight))
1569         {
1570           locator.local = 1;
1571           vec_add1 (locators, locator);
1572         }
1573       else
1574         {
1575           error = unformat_parse_error (line_input);
1576           goto done;
1577         }
1578     }
1579
1580   if (!locator_set_name_set)
1581     {
1582       error = clib_error_return (0, "locator_set name not set!");
1583       goto done;
1584     }
1585
1586   a->name = locator_set_name;
1587   a->locators = locators;
1588   a->is_add = is_add;
1589   a->local = 1;
1590
1591   vnet_lisp_add_del_locator (a, 0, &ls_index);
1592
1593 done:
1594   vec_free (locators);
1595   vec_free (locator_set_name);
1596   unformat_free (line_input);
1597   return error;
1598 }
1599
1600 /* *INDENT-OFF* */
1601 VLIB_CLI_COMMAND (one_cp_add_del_locator_in_set_command) = {
1602     .path = "one locator",
1603     .short_help = "one locator add/del locator-set <name> iface <iface-name> "
1604                   "p <priority> w <weight>",
1605     .function = lisp_add_del_locator_in_set_command_fn,
1606 };
1607 /* *INDENT-ON* */
1608
1609 static clib_error_t *
1610 lisp_cp_show_locator_sets_command_fn (vlib_main_t * vm,
1611                                       unformat_input_t * input,
1612                                       vlib_cli_command_t * cmd)
1613 {
1614   locator_set_t *lsit;
1615   locator_t *loc;
1616   u32 *locit;
1617   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1618
1619   vlib_cli_output (vm, "%s%=16s%=16s%=16s", "Locator-set", "Locator",
1620                    "Priority", "Weight");
1621
1622   /* *INDENT-OFF* */
1623   pool_foreach (lsit, lcm->locator_set_pool,
1624   ({
1625     u8 * msg = 0;
1626     int next_line = 0;
1627     if (lsit->local)
1628       {
1629         msg = format (msg, "%v", lsit->name);
1630       }
1631     else
1632       {
1633         msg = format (msg, "<%s-%d>", "remote", lsit - lcm->locator_set_pool);
1634       }
1635     vec_foreach (locit, lsit->locator_indices)
1636       {
1637         if (next_line)
1638           {
1639             msg = format (msg, "%16s", " ");
1640           }
1641         loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
1642         if (loc->local)
1643           msg = format (msg, "%16d%16d%16d\n", loc->sw_if_index, loc->priority,
1644                         loc->weight);
1645         else
1646           msg = format (msg, "%16U%16d%16d\n", format_ip_address,
1647                         &gid_address_ip(&loc->address), loc->priority,
1648                         loc->weight);
1649         next_line = 1;
1650       }
1651     vlib_cli_output (vm, "%v", msg);
1652     vec_free (msg);
1653   }));
1654   /* *INDENT-ON* */
1655   return 0;
1656 }
1657
1658 /* *INDENT-OFF* */
1659 VLIB_CLI_COMMAND (one_cp_show_locator_sets_command) = {
1660     .path = "show one locator-set",
1661     .short_help = "Shows locator-sets",
1662     .function = lisp_cp_show_locator_sets_command_fn,
1663 };
1664 /* *INDENT-ON* */
1665
1666
1667 static clib_error_t *
1668 lisp_add_del_map_resolver_command_fn (vlib_main_t * vm,
1669                                       unformat_input_t * input,
1670                                       vlib_cli_command_t * cmd)
1671 {
1672   unformat_input_t _line_input, *line_input = &_line_input;
1673   u8 is_add = 1, addr_set = 0;
1674   ip_address_t ip_addr;
1675   clib_error_t *error = 0;
1676   int rv = 0;
1677   vnet_lisp_add_del_map_resolver_args_t _a, *a = &_a;
1678
1679   /* Get a line of input. */
1680   if (!unformat_user (input, unformat_line_input, line_input))
1681     return 0;
1682
1683   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1684     {
1685       if (unformat (line_input, "add"))
1686         is_add = 1;
1687       else if (unformat (line_input, "del"))
1688         is_add = 0;
1689       else if (unformat (line_input, "%U", unformat_ip_address, &ip_addr))
1690         addr_set = 1;
1691       else
1692         {
1693           error = unformat_parse_error (line_input);
1694           goto done;
1695         }
1696     }
1697
1698   if (!addr_set)
1699     {
1700       error = clib_error_return (0, "Map-resolver address must be set!");
1701       goto done;
1702     }
1703
1704   a->is_add = is_add;
1705   a->address = ip_addr;
1706   rv = vnet_lisp_add_del_map_resolver (a);
1707   if (0 != rv)
1708     {
1709       error = clib_error_return (0, "failed to %s map-resolver!",
1710                                  is_add ? "add" : "delete");
1711     }
1712
1713 done:
1714   unformat_free (line_input);
1715   return error;
1716 }
1717
1718 /* *INDENT-OFF* */
1719 VLIB_CLI_COMMAND (one_add_del_map_resolver_command) = {
1720     .path = "one map-resolver",
1721     .short_help = "one map-resolver add/del <ip_address>",
1722     .function = lisp_add_del_map_resolver_command_fn,
1723 };
1724 /* *INDENT-ON* */
1725
1726
1727 static clib_error_t *
1728 lisp_add_del_mreq_itr_rlocs_command_fn (vlib_main_t * vm,
1729                                         unformat_input_t * input,
1730                                         vlib_cli_command_t * cmd)
1731 {
1732   unformat_input_t _line_input, *line_input = &_line_input;
1733   u8 is_add = 1;
1734   u8 *locator_set_name = 0;
1735   clib_error_t *error = 0;
1736   int rv = 0;
1737   vnet_lisp_add_del_mreq_itr_rloc_args_t _a, *a = &_a;
1738
1739   /* Get a line of input. */
1740   if (!unformat_user (input, unformat_line_input, line_input))
1741     return 0;
1742
1743   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1744     {
1745       if (unformat (line_input, "del"))
1746         is_add = 0;
1747       else if (unformat (line_input, "add %_%v%_", &locator_set_name))
1748         is_add = 1;
1749       else
1750         {
1751           error = unformat_parse_error (line_input);
1752           goto done;
1753         }
1754     }
1755
1756   a->is_add = is_add;
1757   a->locator_set_name = locator_set_name;
1758   rv = vnet_lisp_add_del_mreq_itr_rlocs (a);
1759   if (0 != rv)
1760     {
1761       error = clib_error_return (0, "failed to %s map-request itr-rlocs!",
1762                                  is_add ? "add" : "delete");
1763     }
1764
1765 done:
1766   vec_free (locator_set_name);
1767   unformat_free (line_input);
1768   return error;
1769
1770 }
1771
1772 /* *INDENT-OFF* */
1773 VLIB_CLI_COMMAND (one_add_del_map_request_command) = {
1774     .path = "one map-request itr-rlocs",
1775     .short_help = "one map-request itr-rlocs add/del <locator_set_name>",
1776     .function = lisp_add_del_mreq_itr_rlocs_command_fn,
1777 };
1778 /* *INDENT-ON* */
1779
1780 static clib_error_t *
1781 lisp_show_mreq_itr_rlocs_command_fn (vlib_main_t * vm,
1782                                      unformat_input_t * input,
1783                                      vlib_cli_command_t * cmd)
1784 {
1785   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1786   locator_set_t *loc_set;
1787
1788   vlib_cli_output (vm, "%=20s", "itr-rlocs");
1789
1790   if (~0 == lcm->mreq_itr_rlocs)
1791     {
1792       return 0;
1793     }
1794
1795   loc_set = pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
1796
1797   vlib_cli_output (vm, "%=20s", loc_set->name);
1798
1799   return 0;
1800 }
1801
1802 /* *INDENT-OFF* */
1803 VLIB_CLI_COMMAND (one_show_map_request_command) = {
1804     .path = "show one map-request itr-rlocs",
1805     .short_help = "Shows map-request itr-rlocs",
1806     .function = lisp_show_mreq_itr_rlocs_command_fn,
1807 };
1808 /* *INDENT-ON* */
1809
1810 static clib_error_t *
1811 lisp_use_petr_set_locator_set_command_fn (vlib_main_t * vm,
1812                                           unformat_input_t * input,
1813                                           vlib_cli_command_t * cmd)
1814 {
1815   u8 is_add = 1, ip_set = 0;
1816   unformat_input_t _line_input, *line_input = &_line_input;
1817   clib_error_t *error = 0;
1818   ip_address_t ip;
1819
1820   /* Get a line of input. */
1821   if (!unformat_user (input, unformat_line_input, line_input))
1822     return 0;
1823
1824   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1825     {
1826       if (unformat (line_input, "%U", unformat_ip_address, &ip))
1827         ip_set = 1;
1828       else if (unformat (line_input, "disable"))
1829         is_add = 0;
1830       else
1831         {
1832           error = clib_error_return (0, "parse error");
1833           goto done;
1834         }
1835     }
1836
1837   if (!ip_set)
1838     {
1839       clib_warning ("No petr IP specified!");
1840       goto done;
1841     }
1842
1843   if (vnet_lisp_use_petr (&ip, is_add))
1844     {
1845       error = clib_error_return (0, "failed to %s petr!",
1846                                  is_add ? "add" : "delete");
1847     }
1848
1849 done:
1850   unformat_free (line_input);
1851   return error;
1852 }
1853
1854 /* *INDENT-OFF* */
1855 VLIB_CLI_COMMAND (one_use_petr_set_locator_set_command) = {
1856     .path = "one use-petr",
1857     .short_help = "one use-petr [disable] <petr-ip>",
1858     .function = lisp_use_petr_set_locator_set_command_fn,
1859 };
1860
1861 static clib_error_t *
1862 lisp_show_petr_command_fn (vlib_main_t * vm,
1863                            unformat_input_t * input, vlib_cli_command_t * cmd)
1864 {
1865   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1866   mapping_t *m;
1867   locator_set_t *ls;
1868   locator_t *loc;
1869   u8 *tmp_str = 0;
1870   u8 use_petr = lcm->flags & LISP_FLAG_USE_PETR;
1871   vlib_cli_output (vm, "%=20s%=16s", "petr", use_petr ? "ip" : "");
1872
1873   if (!use_petr)
1874     {
1875       vlib_cli_output (vm, "%=20s", "disable");
1876       return 0;
1877     }
1878
1879   if (~0 == lcm->petr_map_index)
1880     {
1881       tmp_str = format (0, "N/A");
1882     }
1883   else
1884     {
1885       m = pool_elt_at_index (lcm->mapping_pool, lcm->petr_map_index);
1886       if (~0 != m->locator_set_index)
1887         {
1888           ls = pool_elt_at_index(lcm->locator_set_pool, m->locator_set_index);
1889           loc = pool_elt_at_index (lcm->locator_pool, ls->locator_indices[0]);
1890           tmp_str = format (0, "%U", format_ip_address, &loc->address);
1891         }
1892       else
1893         {
1894           tmp_str = format (0, "N/A");
1895         }
1896     }
1897   vec_add1 (tmp_str, 0);
1898
1899   vlib_cli_output (vm, "%=20s%=16s", "enable", tmp_str);
1900
1901   vec_free (tmp_str);
1902
1903   return 0;
1904 }
1905
1906 /* *INDENT-OFF* */
1907 VLIB_CLI_COMMAND (one_show_petr_command) = {
1908     .path = "show one petr",
1909     .short_help = "Show petr",
1910     .function = lisp_show_petr_command_fn,
1911 };
1912 /* *INDENT-ON* */
1913
1914 static clib_error_t *
1915 lisp_show_map_servers_command_fn (vlib_main_t * vm,
1916                                   unformat_input_t * input,
1917                                   vlib_cli_command_t * cmd)
1918 {
1919   lisp_msmr_t *ms;
1920   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1921
1922   vec_foreach (ms, lcm->map_servers)
1923   {
1924     vlib_cli_output (vm, "%U", format_ip_address, &ms->address);
1925   }
1926   return 0;
1927 }
1928
1929 /* *INDENT-OFF* */
1930 VLIB_CLI_COMMAND (one_show_map_servers_command) = {
1931     .path = "show one map-servers",
1932     .short_help = "show one map servers",
1933     .function = lisp_show_map_servers_command_fn,
1934 };
1935 /* *INDENT-ON* */
1936
1937 static clib_error_t *
1938 lisp_show_map_register_state_command_fn (vlib_main_t * vm,
1939                                          unformat_input_t * input,
1940                                          vlib_cli_command_t * cmd)
1941 {
1942   u8 *msg = 0;
1943   u8 is_enabled = vnet_lisp_map_register_state_get ();
1944
1945   msg = format (msg, "%s\n", is_enabled ? "enabled" : "disabled");
1946   vlib_cli_output (vm, "%v", msg);
1947   vec_free (msg);
1948   return 0;
1949 }
1950
1951 /* *INDENT-OFF* */
1952 VLIB_CLI_COMMAND (one_show_map_register_state_command) = {
1953     .path = "show one map-register state",
1954     .short_help = "show one map-register state",
1955     .function = lisp_show_map_register_state_command_fn,
1956 };
1957 /* *INDENT-ON* */
1958
1959 static clib_error_t *
1960 lisp_show_rloc_probe_state_command_fn (vlib_main_t * vm,
1961                                        unformat_input_t * input,
1962                                        vlib_cli_command_t * cmd)
1963 {
1964   u8 *msg = 0;
1965   u8 is_enabled = vnet_lisp_rloc_probe_state_get ();
1966
1967   msg = format (msg, "%s\n", is_enabled ? "enabled" : "disabled");
1968   vlib_cli_output (vm, "%v", msg);
1969   vec_free (msg);
1970   return 0;
1971 }
1972
1973 /* *INDENT-OFF* */
1974 VLIB_CLI_COMMAND (one_show_rloc_probe_state_command) = {
1975     .path = "show one rloc state",
1976     .short_help = "show one RLOC state",
1977     .function = lisp_show_rloc_probe_state_command_fn,
1978 };
1979 /* *INDENT-ON* */
1980
1981 static clib_error_t *
1982 lisp_show_stats_command_fn (vlib_main_t * vm,
1983                             unformat_input_t * input,
1984                             vlib_cli_command_t * cmd)
1985 {
1986   u8 is_enabled = vnet_lisp_stats_enable_disable_state ();
1987   vlib_cli_output (vm, "%s\n", is_enabled ? "enabled" : "disabled");
1988   return 0;
1989 }
1990
1991 /* *INDENT-OFF* */
1992 VLIB_CLI_COMMAND (one_show_stats_command) = {
1993     .path = "show one statistics status",
1994     .short_help = "show ONE statistics enable/disable status",
1995     .function = lisp_show_stats_command_fn,
1996 };
1997 /* *INDENT-ON* */
1998
1999 static clib_error_t *
2000 lisp_show_stats_details_command_fn (vlib_main_t * vm,
2001                                     unformat_input_t * input,
2002                                     vlib_cli_command_t * cmd)
2003 {
2004   lisp_api_stats_t *stat, *stats = vnet_lisp_get_stats ();
2005
2006   if (vec_len (stats) > 0)
2007     vlib_cli_output (vm,
2008                      "[src-EID, dst-EID] [loc-rloc, rmt-rloc] count bytes\n");
2009   else
2010     vlib_cli_output (vm, "No statistics found.\n");
2011
2012   vec_foreach (stat, stats)
2013   {
2014     vlib_cli_output (vm, "[%U, %U] [%U, %U] %7u %7u\n",
2015                      format_fid_address, &stat->seid,
2016                      format_fid_address, &stat->deid,
2017                      format_ip_address, &stat->loc_rloc,
2018                      format_ip_address, &stat->rmt_rloc,
2019                      stat->counters.packets, stat->counters.bytes);
2020   }
2021   vec_free (stats);
2022   return 0;
2023 }
2024
2025 /* *INDENT-OFF* */
2026 VLIB_CLI_COMMAND (one_show_stats_details_command) = {
2027     .path = "show one statistics details",
2028     .short_help = "show ONE statistics",
2029     .function = lisp_show_stats_details_command_fn,
2030 };
2031 /* *INDENT-ON* */
2032
2033 static clib_error_t *
2034 lisp_stats_enable_disable_command_fn (vlib_main_t * vm,
2035                                       unformat_input_t * input,
2036                                       vlib_cli_command_t * cmd)
2037 {
2038   unformat_input_t _line_input, *line_input = &_line_input;
2039   u8 enable = 0;
2040
2041   /* Get a line of input. */
2042   if (!unformat_user (input, unformat_line_input, line_input))
2043     return 0;
2044
2045   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2046     {
2047       if (unformat (line_input, "enable"))
2048         enable = 1;
2049       else if (unformat (line_input, "disable"))
2050         enable = 0;
2051       else
2052         {
2053           clib_warning ("Error: expected enable/disable!");
2054           goto done;
2055         }
2056     }
2057   vnet_lisp_stats_enable_disable (enable);
2058 done:
2059   unformat_free (line_input);
2060   return 0;
2061 }
2062
2063 /* *INDENT-OFF* */
2064 VLIB_CLI_COMMAND (one_stats_enable_disable_command) = {
2065     .path = "one statistics",
2066     .short_help = "enable/disable ONE statistics collecting",
2067     .function = lisp_stats_enable_disable_command_fn,
2068 };
2069 /* *INDENT-ON* */
2070
2071 static clib_error_t *
2072 lisp_stats_flush_command_fn (vlib_main_t * vm,
2073                              unformat_input_t * input,
2074                              vlib_cli_command_t * cmd)
2075 {
2076   vnet_lisp_flush_stats ();
2077   return 0;
2078 }
2079
2080 /* *INDENT-OFF* */
2081 VLIB_CLI_COMMAND (one_stats_flush_command) = {
2082     .path = "one statistics flush",
2083     .short_help = "Flush ONE statistics",
2084     .function = lisp_stats_flush_command_fn,
2085 };
2086 /* *INDENT-ON* */
2087
2088 /*
2089  * fd.io coding-style-patch-verification: ON
2090  *
2091  * Local Variables:
2092  * eval: (c-set-style "gnu")
2093  * End:
2094  */