Add Overlay Network Engine API
[vpp.git] / src / vnet / lisp-cp / lisp_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           return 0;
42         }
43     }
44
45   if (~0 == vni)
46     {
47       vlib_cli_output (vm, "error: no vni specified!");
48       return 0;
49     }
50
51   adjs = vnet_lisp_adjacencies_get_by_vni (vni);
52
53   vec_foreach (adj, adjs)
54   {
55     vlib_cli_output (vm, "%U %40U\n", format_gid_address, &adj->leid,
56                      format_gid_address, &adj->reid);
57   }
58   vec_free (adjs);
59
60   return 0;
61 }
62
63 /* *INDENT-OFF* */
64 VLIB_CLI_COMMAND (lisp_show_adjacencies_command) = {
65     .path = "show lisp adjacencies",
66     .short_help = "show lisp adjacencies",
67     .function = lisp_show_adjacencies_command_fn,
68 };
69 /* *INDENT-ON* */
70
71 static clib_error_t *
72 lisp_add_del_map_server_command_fn (vlib_main_t * vm,
73                                     unformat_input_t * input,
74                                     vlib_cli_command_t * cmd)
75 {
76   int rv = 0;
77   u8 is_add = 1, ip_set = 0;
78   ip_address_t ip;
79   unformat_input_t _line_input, *line_input = &_line_input;
80
81   /* Get a line of input. */
82   if (!unformat_user (input, unformat_line_input, line_input))
83     return 0;
84
85   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
86     {
87       if (unformat (line_input, "add"))
88         is_add = 1;
89       else if (unformat (line_input, "del"))
90         is_add = 0;
91       else if (unformat (line_input, "%U", unformat_ip_address, &ip))
92         ip_set = 1;
93       else
94         {
95           vlib_cli_output (vm, "parse error: '%U'",
96                            format_unformat_error, line_input);
97           return 0;
98         }
99     }
100
101   if (!ip_set)
102     {
103       vlib_cli_output (vm, "map-server ip address not set!");
104       return 0;
105     }
106
107   rv = vnet_lisp_add_del_map_server (&ip, is_add);
108   if (!rv)
109     vlib_cli_output (vm, "failed to %s map-server!",
110                      is_add ? "add" : "delete");
111
112   return 0;
113 }
114
115 /* *INDENT-OFF* */
116 VLIB_CLI_COMMAND (lisp_add_del_map_server_command) = {
117     .path = "lisp map-server",
118     .short_help = "lisp map-server add|del <ip>",
119     .function = lisp_add_del_map_server_command_fn,
120 };
121 /* *INDENT-ON* */
122
123
124 static clib_error_t *
125 lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
126                                    vlib_cli_command_t * cmd)
127 {
128   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
129   unformat_input_t _line_input, *line_input = &_line_input;
130   u8 is_add = 1;
131   gid_address_t eid;
132   gid_address_t *eids = 0;
133   clib_error_t *error = 0;
134   u8 *locator_set_name = 0;
135   u32 locator_set_index = 0, map_index = 0;
136   uword *p;
137   vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
138   int rv = 0;
139   u32 vni = 0;
140   u8 *key = 0;
141   u32 key_id = 0;
142
143   memset (&eid, 0, sizeof (eid));
144   memset (a, 0, sizeof (*a));
145
146   /* Get a line of input. */
147   if (!unformat_user (input, unformat_line_input, line_input))
148     return 0;
149
150   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
151     {
152       if (unformat (line_input, "add"))
153         is_add = 1;
154       else if (unformat (line_input, "del"))
155         is_add = 0;
156       else if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
157         ;
158       else if (unformat (line_input, "vni %d", &vni))
159         gid_address_vni (&eid) = vni;
160       else if (unformat (line_input, "secret-key %_%v%_", &key))
161         ;
162       else if (unformat (line_input, "key-id %U", unformat_hmac_key_id,
163                          &key_id))
164         ;
165       else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
166         {
167           p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
168           if (!p)
169             {
170               error = clib_error_return (0, "locator-set %s doesn't exist",
171                                          locator_set_name);
172               goto done;
173             }
174           locator_set_index = p[0];
175         }
176       else
177         {
178           error = unformat_parse_error (line_input);
179           goto done;
180         }
181     }
182   /* XXX treat batch configuration */
183
184   if (GID_ADDR_SRC_DST == gid_address_type (&eid))
185     {
186       error =
187         clib_error_return (0, "src/dst is not supported for local EIDs!");
188       goto done;
189     }
190
191   if (key && (0 == key_id))
192     {
193       vlib_cli_output (vm, "invalid key_id!");
194       return 0;
195     }
196
197   gid_address_copy (&a->eid, &eid);
198   a->is_add = is_add;
199   a->locator_set_index = locator_set_index;
200   a->local = 1;
201   a->key = key;
202   a->key_id = key_id;
203
204   rv = vnet_lisp_add_del_local_mapping (a, &map_index);
205   if (0 != rv)
206     {
207       error = clib_error_return (0, "failed to %s local mapping!",
208                                  is_add ? "add" : "delete");
209     }
210 done:
211   vec_free (eids);
212   if (locator_set_name)
213     vec_free (locator_set_name);
214   gid_address_free (&a->eid);
215   vec_free (a->key);
216   return error;
217 }
218
219 /* *INDENT-OFF* */
220 VLIB_CLI_COMMAND (lisp_add_del_local_eid_command) = {
221     .path = "lisp eid-table",
222     .short_help = "lisp eid-table add/del [vni <vni>] eid <eid> "
223       "locator-set <locator-set> [key <secret-key> key-id sha1|sha256 ]",
224     .function = lisp_add_del_local_eid_command_fn,
225 };
226 /* *INDENT-ON* */
227
228 static clib_error_t *
229 lisp_eid_table_map_command_fn (vlib_main_t * vm,
230                                unformat_input_t * input,
231                                vlib_cli_command_t * cmd)
232 {
233   u8 is_add = 1, is_l2 = 0;
234   u32 vni = 0, dp_id = 0;
235   unformat_input_t _line_input, *line_input = &_line_input;
236
237   /* Get a line of input. */
238   if (!unformat_user (input, unformat_line_input, line_input))
239     return 0;
240
241   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
242     {
243       if (unformat (line_input, "del"))
244         is_add = 0;
245       else if (unformat (line_input, "vni %d", &vni))
246         ;
247       else if (unformat (line_input, "vrf %d", &dp_id))
248         ;
249       else if (unformat (line_input, "bd %d", &dp_id))
250         is_l2 = 1;
251       else
252         {
253           return unformat_parse_error (line_input);
254         }
255     }
256   vnet_lisp_eid_table_map (vni, dp_id, is_l2, is_add);
257   return 0;
258 }
259
260 /* *INDENT-OFF* */
261 VLIB_CLI_COMMAND (lisp_eid_table_map_command) = {
262     .path = "lisp eid-table map",
263     .short_help = "lisp eid-table map [del] vni <vni> vrf <vrf> | bd <bdi>",
264     .function = lisp_eid_table_map_command_fn,
265 };
266 /* *INDENT-ON* */
267
268 /**
269  * Handler for add/del remote mapping CLI.
270  *
271  * @param vm vlib context
272  * @param input input from user
273  * @param cmd cmd
274  * @return pointer to clib error structure
275  */
276 static clib_error_t *
277 lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
278                                         unformat_input_t * input,
279                                         vlib_cli_command_t * cmd)
280 {
281   clib_error_t *error = 0;
282   unformat_input_t _line_input, *line_input = &_line_input;
283   u8 is_add = 1, del_all = 0;
284   locator_t rloc, *rlocs = 0, *curr_rloc = 0;
285   gid_address_t eid;
286   u8 eid_set = 0;
287   u32 vni, action = ~0, p, w;
288   int rv;
289
290   /* Get a line of input. */
291   if (!unformat_user (input, unformat_line_input, line_input))
292     return 0;
293
294   memset (&eid, 0, sizeof (eid));
295   memset (&rloc, 0, sizeof (rloc));
296
297   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
298     {
299       if (unformat (line_input, "del-all"))
300         del_all = 1;
301       else if (unformat (line_input, "del"))
302         is_add = 0;
303       else if (unformat (line_input, "add"))
304         ;
305       else if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
306         eid_set = 1;
307       else if (unformat (line_input, "vni %u", &vni))
308         {
309           gid_address_vni (&eid) = vni;
310         }
311       else if (unformat (line_input, "p %d w %d", &p, &w))
312         {
313           if (!curr_rloc)
314             {
315               clib_warning
316                 ("No RLOC configured for setting priority/weight!");
317               goto done;
318             }
319           curr_rloc->priority = p;
320           curr_rloc->weight = w;
321         }
322       else if (unformat (line_input, "rloc %U", unformat_ip_address,
323                          &gid_address_ip (&rloc.address)))
324         {
325           /* since rloc is stored in ip prefix we need to set prefix length */
326           ip_prefix_t *pref = &gid_address_ippref (&rloc.address);
327
328           u8 version = gid_address_ip_version (&rloc.address);
329           ip_prefix_len (pref) = ip_address_max_len (version);
330
331           vec_add1 (rlocs, rloc);
332           curr_rloc = &rlocs[vec_len (rlocs) - 1];
333         }
334       else if (unformat (line_input, "action %U",
335                          unformat_negative_mapping_action, &action))
336         ;
337       else
338         {
339           clib_warning ("parse error");
340           goto done;
341         }
342     }
343
344   if (!eid_set)
345     {
346       clib_warning ("missing eid!");
347       goto done;
348     }
349
350   if (!del_all)
351     {
352       if (is_add && (~0 == action) && 0 == vec_len (rlocs))
353         {
354           clib_warning ("no action set for negative map-reply!");
355           goto done;
356         }
357     }
358   else
359     {
360       vnet_lisp_clear_all_remote_adjacencies ();
361       goto done;
362     }
363
364   /* TODO build src/dst with seid */
365
366   /* if it's a delete, clean forwarding */
367   if (!is_add)
368     {
369       vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
370       memset (a, 0, sizeof (a[0]));
371       gid_address_copy (&a->reid, &eid);
372       if (vnet_lisp_add_del_adjacency (a))
373         {
374           clib_warning ("failed to delete adjacency!");
375           goto done;
376         }
377     }
378
379   /* add as static remote mapping, i.e., not authoritative and infinite
380    * ttl */
381   rv = vnet_lisp_add_del_mapping (&eid, rlocs, action, 0, ~0, is_add,
382                                   1 /* is_static */ , 0);
383
384   if (rv)
385     clib_warning ("failed to %s remote mapping!", is_add ? "add" : "delete");
386
387 done:
388   vec_free (rlocs);
389   unformat_free (line_input);
390   return error;
391 }
392
393 VLIB_CLI_COMMAND (lisp_add_del_remote_mapping_command) =
394 {
395 .path = "lisp remote-mapping",.short_help =
396     "lisp remote-mapping add|del [del-all] vni <vni> "
397     "eid <est-eid> [action <no-action|natively-forward|"
398     "send-map-request|drop>] rloc <dst-locator> p <prio> w <weight> "
399     "[rloc <dst-locator> ... ]",.function =
400     lisp_add_del_remote_mapping_command_fn,};
401
402 /**
403  * Handler for add/del adjacency CLI.
404  */
405 static clib_error_t *
406 lisp_add_del_adjacency_command_fn (vlib_main_t * vm, unformat_input_t * input,
407                                    vlib_cli_command_t * cmd)
408 {
409   clib_error_t *error = 0;
410   unformat_input_t _line_input, *line_input = &_line_input;
411   vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
412   u8 is_add = 1;
413   ip_prefix_t *reid_ippref, *leid_ippref;
414   gid_address_t leid, reid;
415   u8 *dmac = gid_address_mac (&reid);
416   u8 *smac = gid_address_mac (&leid);
417   u8 reid_set = 0, leid_set = 0;
418   u32 vni;
419
420   /* Get a line of input. */
421   if (!unformat_user (input, unformat_line_input, line_input))
422     return 0;
423
424   memset (&reid, 0, sizeof (reid));
425   memset (&leid, 0, sizeof (leid));
426
427   leid_ippref = &gid_address_ippref (&leid);
428   reid_ippref = &gid_address_ippref (&reid);
429
430   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
431     {
432       if (unformat (line_input, "del"))
433         is_add = 0;
434       else if (unformat (line_input, "add"))
435         ;
436       else if (unformat (line_input, "reid %U",
437                          unformat_ip_prefix, reid_ippref))
438         {
439           gid_address_type (&reid) = GID_ADDR_IP_PREFIX;
440           reid_set = 1;
441         }
442       else if (unformat (line_input, "reid %U", unformat_mac_address, dmac))
443         {
444           gid_address_type (&reid) = GID_ADDR_MAC;
445           reid_set = 1;
446         }
447       else if (unformat (line_input, "vni %u", &vni))
448         {
449           gid_address_vni (&leid) = vni;
450           gid_address_vni (&reid) = vni;
451         }
452       else if (unformat (line_input, "leid %U",
453                          unformat_ip_prefix, leid_ippref))
454         {
455           gid_address_type (&leid) = GID_ADDR_IP_PREFIX;
456           leid_set = 1;
457         }
458       else if (unformat (line_input, "leid %U", unformat_mac_address, smac))
459         {
460           gid_address_type (&leid) = GID_ADDR_MAC;
461           leid_set = 1;
462         }
463       else
464         {
465           clib_warning ("parse error");
466           goto done;
467         }
468     }
469
470   if (!reid_set || !leid_set)
471     {
472       clib_warning ("missing remote or local eid!");
473       goto done;
474     }
475
476   if ((gid_address_type (&leid) != gid_address_type (&reid))
477       || (gid_address_type (&reid) == GID_ADDR_IP_PREFIX
478           && ip_prefix_version (reid_ippref)
479           != ip_prefix_version (leid_ippref)))
480     {
481       clib_warning ("remote and local EIDs are of different types!");
482       return error;
483     }
484
485   memset (a, 0, sizeof (a[0]));
486   gid_address_copy (&a->leid, &leid);
487   gid_address_copy (&a->reid, &reid);
488   a->is_add = is_add;
489
490   if (vnet_lisp_add_del_adjacency (a))
491     clib_warning ("failed to %s adjacency!", is_add ? "add" : "delete");
492
493 done:
494   unformat_free (line_input);
495   return error;
496 }
497
498 /* *INDENT-OFF* */
499 VLIB_CLI_COMMAND (lisp_add_del_adjacency_command) = {
500     .path = "lisp adjacency",
501     .short_help = "lisp adjacency add|del vni <vni> reid <remote-eid> "
502       "leid <local-eid>",
503     .function = lisp_add_del_adjacency_command_fn,
504 };
505 /* *INDENT-ON* */
506
507
508 static clib_error_t *
509 lisp_map_request_mode_command_fn (vlib_main_t * vm,
510                                   unformat_input_t * input,
511                                   vlib_cli_command_t * cmd)
512 {
513   unformat_input_t _i, *i = &_i;
514   map_request_mode_t mr_mode = _MR_MODE_MAX;
515
516   /* Get a line of input. */
517   if (!unformat_user (input, unformat_line_input, i))
518     return 0;
519
520   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
521     {
522       if (unformat (i, "dst-only"))
523         mr_mode = MR_MODE_DST_ONLY;
524       else if (unformat (i, "src-dst"))
525         mr_mode = MR_MODE_SRC_DST;
526       else
527         {
528           clib_warning ("parse error '%U'", format_unformat_error, i);
529           goto done;
530         }
531     }
532
533   if (_MR_MODE_MAX == mr_mode)
534     {
535       clib_warning ("No LISP map request mode entered!");
536       return 0;
537     }
538
539   vnet_lisp_set_map_request_mode (mr_mode);
540 done:
541   return 0;
542 }
543
544 /* *INDENT-OFF* */
545 VLIB_CLI_COMMAND (lisp_map_request_mode_command) = {
546     .path = "lisp map-request mode",
547     .short_help = "lisp map-request mode dst-only|src-dst",
548     .function = lisp_map_request_mode_command_fn,
549 };
550 /* *INDENT-ON* */
551
552
553 static u8 *
554 format_lisp_map_request_mode (u8 * s, va_list * args)
555 {
556   u32 mode = va_arg (*args, u32);
557
558   switch (mode)
559     {
560     case 0:
561       return format (0, "dst-only");
562     case 1:
563       return format (0, "src-dst");
564     }
565   return 0;
566 }
567
568 static clib_error_t *
569 lisp_show_map_request_mode_command_fn (vlib_main_t * vm,
570                                        unformat_input_t * input,
571                                        vlib_cli_command_t * cmd)
572 {
573   vlib_cli_output (vm, "map-request mode: %U", format_lisp_map_request_mode,
574                    vnet_lisp_get_map_request_mode ());
575   return 0;
576 }
577
578 /* *INDENT-OFF* */
579 VLIB_CLI_COMMAND (lisp_show_map_request_mode_command) = {
580     .path = "show lisp map-request mode",
581     .short_help = "show lisp map-request mode",
582     .function = lisp_show_map_request_mode_command_fn,
583 };
584 /* *INDENT-ON* */
585
586 static clib_error_t *
587 lisp_show_map_resolvers_command_fn (vlib_main_t * vm,
588                                     unformat_input_t * input,
589                                     vlib_cli_command_t * cmd)
590 {
591   lisp_msmr_t *mr;
592   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
593
594   vec_foreach (mr, lcm->map_resolvers)
595   {
596     vlib_cli_output (vm, "%U", format_ip_address, &mr->address);
597   }
598   return 0;
599 }
600
601 /* *INDENT-OFF* */
602 VLIB_CLI_COMMAND (lisp_show_map_resolvers_command) = {
603     .path = "show lisp map-resolvers",
604     .short_help = "show lisp map-resolvers",
605     .function = lisp_show_map_resolvers_command_fn,
606 };
607 /* *INDENT-ON* */
608
609
610 static clib_error_t *
611 lisp_pitr_set_locator_set_command_fn (vlib_main_t * vm,
612                                       unformat_input_t * input,
613                                       vlib_cli_command_t * cmd)
614 {
615   u8 locator_name_set = 0;
616   u8 *locator_set_name = 0;
617   u8 is_add = 1;
618   unformat_input_t _line_input, *line_input = &_line_input;
619   clib_error_t *error = 0;
620   int rv = 0;
621
622   /* Get a line of input. */
623   if (!unformat_user (input, unformat_line_input, line_input))
624     return 0;
625
626   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
627     {
628       if (unformat (line_input, "ls %_%v%_", &locator_set_name))
629         locator_name_set = 1;
630       else if (unformat (line_input, "disable"))
631         is_add = 0;
632       else
633         return clib_error_return (0, "parse error");
634     }
635
636   if (!locator_name_set)
637     {
638       clib_warning ("No locator set specified!");
639       goto done;
640     }
641   rv = vnet_lisp_pitr_set_locator_set (locator_set_name, is_add);
642   if (0 != rv)
643     {
644       error = clib_error_return (0, "failed to %s pitr!",
645                                  is_add ? "add" : "delete");
646     }
647
648 done:
649   if (locator_set_name)
650     vec_free (locator_set_name);
651   return error;
652 }
653
654 /* *INDENT-OFF* */
655 VLIB_CLI_COMMAND (lisp_pitr_set_locator_set_command) = {
656     .path = "lisp pitr",
657     .short_help = "lisp pitr [disable] ls <locator-set-name>",
658     .function = lisp_pitr_set_locator_set_command_fn,
659 };
660 /* *INDENT-ON* */
661
662 static clib_error_t *
663 lisp_show_pitr_command_fn (vlib_main_t * vm,
664                            unformat_input_t * input, vlib_cli_command_t * cmd)
665 {
666   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
667   mapping_t *m;
668   locator_set_t *ls;
669   u8 *tmp_str = 0;
670
671   vlib_cli_output (vm, "%=20s%=16s",
672                    "pitr", lcm->lisp_pitr ? "locator-set" : "");
673
674   if (!lcm->lisp_pitr)
675     {
676       vlib_cli_output (vm, "%=20s", "disable");
677       return 0;
678     }
679
680   if (~0 == lcm->pitr_map_index)
681     {
682       tmp_str = format (0, "N/A");
683     }
684   else
685     {
686       m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
687       if (~0 != m->locator_set_index)
688         {
689           ls =
690             pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
691           tmp_str = format (0, "%s", ls->name);
692         }
693       else
694         {
695           tmp_str = format (0, "N/A");
696         }
697     }
698   vec_add1 (tmp_str, 0);
699
700   vlib_cli_output (vm, "%=20s%=16s", "enable", tmp_str);
701
702   vec_free (tmp_str);
703
704   return 0;
705 }
706
707 /* *INDENT-OFF* */
708 VLIB_CLI_COMMAND (lisp_show_pitr_command) = {
709     .path = "show lisp pitr",
710     .short_help = "Show pitr",
711     .function = lisp_show_pitr_command_fn,
712 };
713 /* *INDENT-ON* */
714
715 static u8 *
716 format_eid_entry (u8 * s, va_list * args)
717 {
718   vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
719   lisp_cp_main_t *lcm = va_arg (*args, lisp_cp_main_t *);
720   mapping_t *mapit = va_arg (*args, mapping_t *);
721   locator_set_t *ls = va_arg (*args, locator_set_t *);
722   gid_address_t *gid = &mapit->eid;
723   u32 ttl = mapit->ttl;
724   u8 aut = mapit->authoritative;
725   u32 *loc_index;
726   u8 first_line = 1;
727   u8 *loc;
728
729   u8 *type = ls->local ? format (0, "local(%s)", ls->name)
730     : format (0, "remote");
731
732   if (vec_len (ls->locator_indices) == 0)
733     {
734       s = format (s, "%-35U%-30s%-20u%-u", format_gid_address, gid,
735                   type, ttl, aut);
736     }
737   else
738     {
739       vec_foreach (loc_index, ls->locator_indices)
740       {
741         locator_t *l = pool_elt_at_index (lcm->locator_pool, loc_index[0]);
742         if (l->local)
743           loc = format (0, "%U", format_vnet_sw_if_index_name, vnm,
744                         l->sw_if_index);
745         else
746           loc = format (0, "%U", format_ip_address,
747                         &gid_address_ip (&l->address));
748
749         if (first_line)
750           {
751             s = format (s, "%-35U%-20s%-30v%-20u%-u\n", format_gid_address,
752                         gid, type, loc, ttl, aut);
753             first_line = 0;
754           }
755         else
756           s = format (s, "%55s%v\n", "", loc);
757       }
758     }
759   return s;
760 }
761
762 static clib_error_t *
763 lisp_show_eid_table_command_fn (vlib_main_t * vm,
764                                 unformat_input_t * input,
765                                 vlib_cli_command_t * cmd)
766 {
767   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
768   mapping_t *mapit;
769   unformat_input_t _line_input, *line_input = &_line_input;
770   u32 mi;
771   gid_address_t eid;
772   u8 print_all = 1;
773   u8 filter = 0;
774
775   memset (&eid, 0, sizeof (eid));
776
777   /* Get a line of input. */
778   if (!unformat_user (input, unformat_line_input, line_input))
779     return 0;
780
781   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
782     {
783       if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
784         print_all = 0;
785       else if (unformat (line_input, "local"))
786         filter = 1;
787       else if (unformat (line_input, "remote"))
788         filter = 2;
789       else
790         return clib_error_return (0, "parse error: '%U'",
791                                   format_unformat_error, line_input);
792     }
793
794   vlib_cli_output (vm, "%-35s%-20s%-30s%-20s%-s",
795                    "EID", "type", "locators", "ttl", "autoritative");
796
797   if (print_all)
798     {
799       /* *INDENT-OFF* */
800       pool_foreach (mapit, lcm->mapping_pool,
801       ({
802         if (mapit->pitr_set)
803           continue;
804
805         locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool,
806                                                 mapit->locator_set_index);
807         if (filter && !((1 == filter && ls->local) ||
808           (2 == filter && !ls->local)))
809           {
810             continue;
811           }
812         vlib_cli_output (vm, "%U", format_eid_entry, lcm->vnet_main,
813                          lcm, mapit, ls);
814       }));
815       /* *INDENT-ON* */
816     }
817   else
818     {
819       mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &eid);
820       if ((u32) ~ 0 == mi)
821         return 0;
822
823       mapit = pool_elt_at_index (lcm->mapping_pool, mi);
824       locator_set_t *ls = pool_elt_at_index (lcm->locator_set_pool,
825                                              mapit->locator_set_index);
826
827       if (filter && !((1 == filter && ls->local) ||
828                       (2 == filter && !ls->local)))
829         {
830           return 0;
831         }
832
833       vlib_cli_output (vm, "%U,", format_eid_entry, lcm->vnet_main,
834                        lcm, mapit, ls);
835     }
836
837   return 0;
838 }
839
840 /* *INDENT-OFF* */
841 VLIB_CLI_COMMAND (lisp_cp_show_eid_table_command) = {
842     .path = "show lisp eid-table",
843     .short_help = "Shows EID table",
844     .function = lisp_show_eid_table_command_fn,
845 };
846 /* *INDENT-ON* */
847
848
849 static clib_error_t *
850 lisp_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input,
851                                 vlib_cli_command_t * cmd)
852 {
853   unformat_input_t _line_input, *line_input = &_line_input;
854   u8 is_enabled = 0;
855   u8 is_set = 0;
856
857   /* Get a line of input. */
858   if (!unformat_user (input, unformat_line_input, line_input))
859     return 0;
860
861   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
862     {
863       if (unformat (line_input, "enable"))
864         {
865           is_set = 1;
866           is_enabled = 1;
867         }
868       else if (unformat (line_input, "disable"))
869         is_set = 1;
870       else
871         {
872           return clib_error_return (0, "parse error: '%U'",
873                                     format_unformat_error, line_input);
874         }
875     }
876
877   if (!is_set)
878     return clib_error_return (0, "state not set");
879
880   vnet_lisp_enable_disable (is_enabled);
881   return 0;
882 }
883
884 /* *INDENT-OFF* */
885 VLIB_CLI_COMMAND (lisp_cp_enable_disable_command) = {
886     .path = "lisp",
887     .short_help = "lisp [enable|disable]",
888     .function = lisp_enable_disable_command_fn,
889 };
890 /* *INDENT-ON* */
891
892 static clib_error_t *
893 lisp_map_register_enable_disable_command_fn (vlib_main_t * vm,
894                                              unformat_input_t * input,
895                                              vlib_cli_command_t * cmd)
896 {
897   unformat_input_t _line_input, *line_input = &_line_input;
898   u8 is_enabled = 0;
899   u8 is_set = 0;
900
901   /* Get a line of input. */
902   if (!unformat_user (input, unformat_line_input, line_input))
903     return 0;
904
905   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
906     {
907       if (unformat (line_input, "enable"))
908         {
909           is_set = 1;
910           is_enabled = 1;
911         }
912       else if (unformat (line_input, "disable"))
913         is_set = 1;
914       else
915         {
916           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
917                            line_input);
918           return 0;
919         }
920     }
921
922   if (!is_set)
923     {
924       vlib_cli_output (vm, "state not set!");
925       return 0;
926     }
927
928   vnet_lisp_map_register_enable_disable (is_enabled);
929   return 0;
930 }
931
932 /* *INDENT-OFF* */
933 VLIB_CLI_COMMAND (lisp_map_register_enable_disable_command) = {
934     .path = "lisp map-register",
935     .short_help = "lisp map-register [enable|disable]",
936     .function = lisp_map_register_enable_disable_command_fn,
937 };
938 /* *INDENT-ON* */
939
940 static clib_error_t *
941 lisp_rloc_probe_enable_disable_command_fn (vlib_main_t * vm,
942                                            unformat_input_t * input,
943                                            vlib_cli_command_t * cmd)
944 {
945   unformat_input_t _line_input, *line_input = &_line_input;
946   u8 is_enabled = 0;
947   u8 is_set = 0;
948
949   /* Get a line of input. */
950   if (!unformat_user (input, unformat_line_input, line_input))
951     return 0;
952
953   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
954     {
955       if (unformat (line_input, "enable"))
956         {
957           is_set = 1;
958           is_enabled = 1;
959         }
960       else if (unformat (line_input, "disable"))
961         is_set = 1;
962       else
963         {
964           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
965                            line_input);
966           return 0;
967         }
968     }
969
970   if (!is_set)
971     {
972       vlib_cli_output (vm, "state not set!");
973       return 0;
974     }
975
976   vnet_lisp_rloc_probe_enable_disable (is_enabled);
977   return 0;
978 }
979
980 /* *INDENT-OFF* */
981 VLIB_CLI_COMMAND (lisp_rloc_probe_enable_disable_command) = {
982     .path = "lisp rloc-probe",
983     .short_help = "lisp rloc-probe [enable|disable]",
984     .function = lisp_rloc_probe_enable_disable_command_fn,
985 };
986 /* *INDENT-ON* */
987
988 static u8 *
989 format_lisp_status (u8 * s, va_list * args)
990 {
991   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
992   return format (s, "%s", lcm->is_enabled ? "enabled" : "disabled");
993 }
994
995 static clib_error_t *
996 lisp_show_status_command_fn (vlib_main_t * vm, unformat_input_t * input,
997                              vlib_cli_command_t * cmd)
998 {
999   u8 *msg = 0;
1000   msg = format (msg, "feature: %U\ngpe: %U\n",
1001                 format_lisp_status, format_vnet_lisp_gpe_status);
1002   vlib_cli_output (vm, "%v", msg);
1003   vec_free (msg);
1004   return 0;
1005 }
1006
1007 /* *INDENT-OFF* */
1008 VLIB_CLI_COMMAND (lisp_show_status_command) = {
1009     .path = "show lisp status",
1010     .short_help = "show lisp status",
1011     .function = lisp_show_status_command_fn,
1012 };
1013 /* *INDENT-ON* */
1014
1015 static clib_error_t *
1016 lisp_show_eid_table_map_command_fn (vlib_main_t * vm,
1017                                     unformat_input_t * input,
1018                                     vlib_cli_command_t * cmd)
1019 {
1020   hash_pair_t *p;
1021   unformat_input_t _line_input, *line_input = &_line_input;
1022   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1023   uword *vni_table = 0;
1024   u8 is_l2 = 0;
1025
1026   /* Get a line of input. */
1027   if (!unformat_user (input, unformat_line_input, line_input))
1028     return 0;
1029
1030   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1031     {
1032       if (unformat (line_input, "l2"))
1033         {
1034           vni_table = lcm->bd_id_by_vni;
1035           is_l2 = 1;
1036         }
1037       else if (unformat (line_input, "l3"))
1038         {
1039           vni_table = lcm->table_id_by_vni;
1040           is_l2 = 0;
1041         }
1042       else
1043         return clib_error_return (0, "parse error: '%U'",
1044                                   format_unformat_error, line_input);
1045     }
1046
1047   if (!vni_table)
1048     {
1049       vlib_cli_output (vm, "Error: expected l2|l3 param!\n");
1050       return 0;
1051     }
1052
1053   vlib_cli_output (vm, "%=10s%=10s", "VNI", is_l2 ? "BD" : "VRF");
1054
1055   /* *INDENT-OFF* */
1056   hash_foreach_pair (p, vni_table,
1057   ({
1058     vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]);
1059   }));
1060   /* *INDENT-ON* */
1061
1062   return 0;
1063 }
1064
1065 /* *INDENT-OFF* */
1066 VLIB_CLI_COMMAND (lisp_show_eid_table_map_command) = {
1067     .path = "show lisp eid-table map",
1068     .short_help = "show lisp eid-table l2|l3",
1069     .function = lisp_show_eid_table_map_command_fn,
1070 };
1071 /* *INDENT-ON* */
1072
1073
1074 static clib_error_t *
1075 lisp_add_del_locator_set_command_fn (vlib_main_t * vm,
1076                                      unformat_input_t * input,
1077                                      vlib_cli_command_t * cmd)
1078 {
1079   lisp_gpe_main_t *lgm = &lisp_gpe_main;
1080   vnet_main_t *vnm = lgm->vnet_main;
1081   unformat_input_t _line_input, *line_input = &_line_input;
1082   u8 is_add = 1;
1083   clib_error_t *error = 0;
1084   u8 *locator_set_name = 0;
1085   locator_t locator, *locators = 0;
1086   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
1087   u32 ls_index = 0;
1088   int rv = 0;
1089
1090   memset (&locator, 0, sizeof (locator));
1091   memset (a, 0, sizeof (a[0]));
1092
1093   /* Get a line of input. */
1094   if (!unformat_user (input, unformat_line_input, line_input))
1095     return 0;
1096
1097   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1098     {
1099       if (unformat (line_input, "add %_%v%_", &locator_set_name))
1100         is_add = 1;
1101       else if (unformat (line_input, "del %_%v%_", &locator_set_name))
1102         is_add = 0;
1103       else if (unformat (line_input, "iface %U p %d w %d",
1104                          unformat_vnet_sw_interface, vnm,
1105                          &locator.sw_if_index, &locator.priority,
1106                          &locator.weight))
1107         {
1108           locator.local = 1;
1109           vec_add1 (locators, locator);
1110         }
1111       else
1112         {
1113           error = unformat_parse_error (line_input);
1114           goto done;
1115         }
1116     }
1117
1118   a->name = locator_set_name;
1119   a->locators = locators;
1120   a->is_add = is_add;
1121   a->local = 1;
1122
1123   rv = vnet_lisp_add_del_locator_set (a, &ls_index);
1124   if (0 != rv)
1125     {
1126       error = clib_error_return (0, "failed to %s locator-set!",
1127                                  is_add ? "add" : "delete");
1128     }
1129
1130 done:
1131   vec_free (locators);
1132   if (locator_set_name)
1133     vec_free (locator_set_name);
1134   return error;
1135 }
1136
1137 /* *INDENT-OFF* */
1138 VLIB_CLI_COMMAND (lisp_cp_add_del_locator_set_command) = {
1139     .path = "lisp locator-set",
1140     .short_help = "lisp locator-set add/del <name> [iface <iface-name> "
1141         "p <priority> w <weight>]",
1142     .function = lisp_add_del_locator_set_command_fn,
1143 };
1144 /* *INDENT-ON* */
1145
1146 static clib_error_t *
1147 lisp_add_del_locator_in_set_command_fn (vlib_main_t * vm,
1148                                         unformat_input_t * input,
1149                                         vlib_cli_command_t * cmd)
1150 {
1151   lisp_gpe_main_t *lgm = &lisp_gpe_main;
1152   vnet_main_t *vnm = lgm->vnet_main;
1153   unformat_input_t _line_input, *line_input = &_line_input;
1154   u8 is_add = 1;
1155   clib_error_t *error = 0;
1156   u8 *locator_set_name = 0;
1157   u8 locator_set_name_set = 0;
1158   locator_t locator, *locators = 0;
1159   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
1160   u32 ls_index = 0;
1161
1162   memset (&locator, 0, sizeof (locator));
1163   memset (a, 0, sizeof (a[0]));
1164
1165   /* Get a line of input. */
1166   if (!unformat_user (input, unformat_line_input, line_input))
1167     return 0;
1168
1169   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1170     {
1171       if (unformat (line_input, "add"))
1172         is_add = 1;
1173       else if (unformat (line_input, "del"))
1174         is_add = 0;
1175       else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
1176         locator_set_name_set = 1;
1177       else if (unformat (line_input, "iface %U p %d w %d",
1178                          unformat_vnet_sw_interface, vnm,
1179                          &locator.sw_if_index, &locator.priority,
1180                          &locator.weight))
1181         {
1182           locator.local = 1;
1183           vec_add1 (locators, locator);
1184         }
1185       else
1186         {
1187           error = unformat_parse_error (line_input);
1188           goto done;
1189         }
1190     }
1191
1192   if (!locator_set_name_set)
1193     {
1194       error = clib_error_return (0, "locator_set name not set!");
1195       goto done;
1196     }
1197
1198   a->name = locator_set_name;
1199   a->locators = locators;
1200   a->is_add = is_add;
1201   a->local = 1;
1202
1203   vnet_lisp_add_del_locator (a, 0, &ls_index);
1204
1205 done:
1206   vec_free (locators);
1207   vec_free (locator_set_name);
1208   return error;
1209 }
1210
1211 /* *INDENT-OFF* */
1212 VLIB_CLI_COMMAND (lisp_cp_add_del_locator_in_set_command) = {
1213     .path = "lisp locator",
1214     .short_help = "lisp locator add/del locator-set <name> iface <iface-name> "
1215                   "p <priority> w <weight>",
1216     .function = lisp_add_del_locator_in_set_command_fn,
1217 };
1218 /* *INDENT-ON* */
1219
1220 static clib_error_t *
1221 lisp_cp_show_locator_sets_command_fn (vlib_main_t * vm,
1222                                       unformat_input_t * input,
1223                                       vlib_cli_command_t * cmd)
1224 {
1225   locator_set_t *lsit;
1226   locator_t *loc;
1227   u32 *locit;
1228   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1229
1230   vlib_cli_output (vm, "%s%=16s%=16s%=16s", "Locator-set", "Locator",
1231                    "Priority", "Weight");
1232
1233   /* *INDENT-OFF* */
1234   pool_foreach (lsit, lcm->locator_set_pool,
1235   ({
1236     u8 * msg = 0;
1237     int next_line = 0;
1238     if (lsit->local)
1239       {
1240         msg = format (msg, "%v", lsit->name);
1241       }
1242     else
1243       {
1244         msg = format (msg, "<%s-%d>", "remote", lsit - lcm->locator_set_pool);
1245       }
1246     vec_foreach (locit, lsit->locator_indices)
1247       {
1248         if (next_line)
1249           {
1250             msg = format (msg, "%16s", " ");
1251           }
1252         loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
1253         if (loc->local)
1254           msg = format (msg, "%16d%16d%16d\n", loc->sw_if_index, loc->priority,
1255                         loc->weight);
1256         else
1257           msg = format (msg, "%16U%16d%16d\n", format_ip_address,
1258                         &gid_address_ip(&loc->address), loc->priority,
1259                         loc->weight);
1260         next_line = 1;
1261       }
1262     vlib_cli_output (vm, "%v", msg);
1263     vec_free (msg);
1264   }));
1265   /* *INDENT-ON* */
1266   return 0;
1267 }
1268
1269 /* *INDENT-OFF* */
1270 VLIB_CLI_COMMAND (lisp_cp_show_locator_sets_command) = {
1271     .path = "show lisp locator-set",
1272     .short_help = "Shows locator-sets",
1273     .function = lisp_cp_show_locator_sets_command_fn,
1274 };
1275 /* *INDENT-ON* */
1276
1277
1278 static clib_error_t *
1279 lisp_add_del_map_resolver_command_fn (vlib_main_t * vm,
1280                                       unformat_input_t * input,
1281                                       vlib_cli_command_t * cmd)
1282 {
1283   unformat_input_t _line_input, *line_input = &_line_input;
1284   u8 is_add = 1, addr_set = 0;
1285   ip_address_t ip_addr;
1286   clib_error_t *error = 0;
1287   int rv = 0;
1288   vnet_lisp_add_del_map_resolver_args_t _a, *a = &_a;
1289
1290   /* Get a line of input. */
1291   if (!unformat_user (input, unformat_line_input, line_input))
1292     return 0;
1293
1294   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1295     {
1296       if (unformat (line_input, "add"))
1297         is_add = 1;
1298       else if (unformat (line_input, "del"))
1299         is_add = 0;
1300       else if (unformat (line_input, "%U", unformat_ip_address, &ip_addr))
1301         addr_set = 1;
1302       else
1303         {
1304           error = unformat_parse_error (line_input);
1305           goto done;
1306         }
1307     }
1308
1309   if (!addr_set)
1310     {
1311       error = clib_error_return (0, "Map-resolver address must be set!");
1312       goto done;
1313     }
1314
1315   a->is_add = is_add;
1316   a->address = ip_addr;
1317   rv = vnet_lisp_add_del_map_resolver (a);
1318   if (0 != rv)
1319     {
1320       error = clib_error_return (0, "failed to %s map-resolver!",
1321                                  is_add ? "add" : "delete");
1322     }
1323
1324 done:
1325   return error;
1326 }
1327
1328 /* *INDENT-OFF* */
1329 VLIB_CLI_COMMAND (lisp_add_del_map_resolver_command) = {
1330     .path = "lisp map-resolver",
1331     .short_help = "lisp map-resolver add/del <ip_address>",
1332     .function = lisp_add_del_map_resolver_command_fn,
1333 };
1334 /* *INDENT-ON* */
1335
1336
1337 static clib_error_t *
1338 lisp_add_del_mreq_itr_rlocs_command_fn (vlib_main_t * vm,
1339                                         unformat_input_t * input,
1340                                         vlib_cli_command_t * cmd)
1341 {
1342   unformat_input_t _line_input, *line_input = &_line_input;
1343   u8 is_add = 1;
1344   u8 *locator_set_name = 0;
1345   clib_error_t *error = 0;
1346   int rv = 0;
1347   vnet_lisp_add_del_mreq_itr_rloc_args_t _a, *a = &_a;
1348
1349   /* Get a line of input. */
1350   if (!unformat_user (input, unformat_line_input, line_input))
1351     return 0;
1352
1353   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1354     {
1355       if (unformat (line_input, "del"))
1356         is_add = 0;
1357       else if (unformat (line_input, "add %_%v%_", &locator_set_name))
1358         is_add = 1;
1359       else
1360         {
1361           error = unformat_parse_error (line_input);
1362           goto done;
1363         }
1364     }
1365
1366   a->is_add = is_add;
1367   a->locator_set_name = locator_set_name;
1368   rv = vnet_lisp_add_del_mreq_itr_rlocs (a);
1369   if (0 != rv)
1370     {
1371       error = clib_error_return (0, "failed to %s map-request itr-rlocs!",
1372                                  is_add ? "add" : "delete");
1373     }
1374
1375   vec_free (locator_set_name);
1376
1377 done:
1378   return error;
1379
1380 }
1381
1382 /* *INDENT-OFF* */
1383 VLIB_CLI_COMMAND (lisp_add_del_map_request_command) = {
1384     .path = "lisp map-request itr-rlocs",
1385     .short_help = "lisp map-request itr-rlocs add/del <locator_set_name>",
1386     .function = lisp_add_del_mreq_itr_rlocs_command_fn,
1387 };
1388 /* *INDENT-ON* */
1389
1390 static clib_error_t *
1391 lisp_show_mreq_itr_rlocs_command_fn (vlib_main_t * vm,
1392                                      unformat_input_t * input,
1393                                      vlib_cli_command_t * cmd)
1394 {
1395   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1396   locator_set_t *loc_set;
1397
1398   vlib_cli_output (vm, "%=20s", "itr-rlocs");
1399
1400   if (~0 == lcm->mreq_itr_rlocs)
1401     {
1402       return 0;
1403     }
1404
1405   loc_set = pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
1406
1407   vlib_cli_output (vm, "%=20s", loc_set->name);
1408
1409   return 0;
1410 }
1411
1412 /* *INDENT-OFF* */
1413 VLIB_CLI_COMMAND (lisp_show_map_request_command) = {
1414     .path = "show lisp map-request itr-rlocs",
1415     .short_help = "Shows map-request itr-rlocs",
1416     .function = lisp_show_mreq_itr_rlocs_command_fn,
1417 };
1418 /* *INDENT-ON* */
1419
1420 static clib_error_t *
1421 lisp_use_petr_set_locator_set_command_fn (vlib_main_t * vm,
1422                                           unformat_input_t * input,
1423                                           vlib_cli_command_t * cmd)
1424 {
1425   u8 is_add = 1, ip_set = 0;
1426   unformat_input_t _line_input, *line_input = &_line_input;
1427   clib_error_t *error = 0;
1428   ip_address_t ip;
1429
1430   /* Get a line of input. */
1431   if (!unformat_user (input, unformat_line_input, line_input))
1432     return 0;
1433
1434   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1435     {
1436       if (unformat (line_input, "%U", unformat_ip_address, &ip))
1437         ip_set = 1;
1438       else if (unformat (line_input, "disable"))
1439         is_add = 0;
1440       else
1441         return clib_error_return (0, "parse error");
1442     }
1443
1444   if (!ip_set)
1445     {
1446       clib_warning ("No petr IP specified!");
1447       goto done;
1448     }
1449
1450   if (vnet_lisp_use_petr (&ip, is_add))
1451     {
1452       error = clib_error_return (0, "failed to %s petr!",
1453                                  is_add ? "add" : "delete");
1454     }
1455
1456 done:
1457   return error;
1458 }
1459
1460 /* *INDENT-OFF* */
1461 VLIB_CLI_COMMAND (lisp_use_petr_set_locator_set_command) = {
1462     .path = "lisp use-petr",
1463     .short_help = "lisp use-petr [disable] <petr-ip>",
1464     .function = lisp_use_petr_set_locator_set_command_fn,
1465 };
1466
1467 static clib_error_t *
1468 lisp_show_petr_command_fn (vlib_main_t * vm,
1469                            unformat_input_t * input, vlib_cli_command_t * cmd)
1470 {
1471   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1472   mapping_t *m;
1473   locator_set_t *ls;
1474   locator_t *loc;
1475   u8 *tmp_str = 0;
1476   u8 use_petr = lcm->flags & LISP_FLAG_USE_PETR;
1477   vlib_cli_output (vm, "%=20s%=16s", "petr", use_petr ? "ip" : "");
1478
1479   if (!use_petr)
1480     {
1481       vlib_cli_output (vm, "%=20s", "disable");
1482       return 0;
1483     }
1484
1485   if (~0 == lcm->petr_map_index)
1486     {
1487       tmp_str = format (0, "N/A");
1488     }
1489   else
1490     {
1491       m = pool_elt_at_index (lcm->mapping_pool, lcm->petr_map_index);
1492       if (~0 != m->locator_set_index)
1493         {
1494           ls = pool_elt_at_index(lcm->locator_set_pool, m->locator_set_index);
1495           loc = pool_elt_at_index (lcm->locator_pool, ls->locator_indices[0]);
1496           tmp_str = format (0, "%U", format_ip_address, &loc->address);
1497         }
1498       else
1499         {
1500           tmp_str = format (0, "N/A");
1501         }
1502     }
1503   vec_add1 (tmp_str, 0);
1504
1505   vlib_cli_output (vm, "%=20s%=16s", "enable", tmp_str);
1506
1507   vec_free (tmp_str);
1508
1509   return 0;
1510 }
1511
1512 /* *INDENT-OFF* */
1513 VLIB_CLI_COMMAND (lisp_show_petr_command) = {
1514     .path = "show lisp petr",
1515     .short_help = "Show petr",
1516     .function = lisp_show_petr_command_fn,
1517 };
1518 /* *INDENT-ON* */
1519
1520 /*
1521  * fd.io coding-style-patch-verification: ON
1522  *
1523  * Local Variables:
1524  * eval: (c-set-style "gnu")
1525  * End:
1526  */