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