LISP: L2 ARP handling
[vpp.git] / src / vnet / lisp-cp / one_api.c
1 /*
2  *------------------------------------------------------------------
3  * one_api.c - Overlay Network Engine API
4  *
5  * Copyright (c) 2016-2017 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19
20 #include <vnet/vnet.h>
21 #include <vlibmemory/api.h>
22
23 #include <vnet/interface.h>
24 #include <vnet/api_errno.h>
25 #include <vnet/lisp-cp/control.h>
26 #include <vnet/lisp-gpe/lisp_gpe.h>
27
28 #include <vnet/vnet_msg_enum.h>
29
30 #define vl_api_one_remote_locator_t_endian vl_noop_handler
31 #define vl_api_one_remote_locator_t_print vl_noop_handler
32 #define vl_api_one_local_locator_t_endian vl_noop_handler
33 #define vl_api_one_local_locator_t_print vl_noop_handler
34
35 #define vl_api_one_add_del_locator_set_t_endian vl_noop_handler
36 #define vl_api_one_add_del_locator_set_t_print vl_noop_handler
37 #define vl_api_one_add_del_remote_mapping_t_endian vl_noop_handler
38 #define vl_api_one_add_del_remote_mapping_t_print vl_noop_handler
39
40 #define vl_api_one_add_del_locator_set_t_endian vl_noop_handler
41 #define vl_api_one_add_del_locator_set_t_print vl_noop_handler
42 #define vl_api_one_add_del_remote_mapping_t_endian vl_noop_handler
43 #define vl_api_one_add_del_remote_mapping_t_print vl_noop_handler
44
45 #define vl_api_one_l2_arp_entry_t_endian vl_noop_handler
46 #define vl_api_one_l2_arp_entry_t_print vl_noop_handler
47 #define vl_api_one_add_del_l2_arp_entry vl_noop_handler
48 #define vl_api_one_l2_arp_bd_get vl_noop_handler
49
50 #define vl_typedefs             /* define message structures */
51 #include <vnet/vnet_all_api_h.h>
52 #undef vl_typedefs
53
54 #define vl_endianfun            /* define message structures */
55 #include <vnet/vnet_all_api_h.h>
56 #undef vl_endianfun
57
58 /* instantiate all the print functions we know about */
59 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
60 #define vl_printfun
61 #include <vnet/vnet_all_api_h.h>
62 #undef vl_printfun
63
64 #include <vlibapi/api_helper_macros.h>
65
66 #define REPLY_DETAILS(t, body)                                  \
67 do {                                                            \
68     unix_shared_memory_queue_t * q;                             \
69     rv = vl_msg_api_pd_handler (mp, rv);                        \
70     q = vl_api_client_index_to_input_queue (mp->client_index);  \
71     if (!q)                                                     \
72         return;                                                 \
73                                                                 \
74     rmp = vl_msg_api_alloc (sizeof (*rmp));                     \
75     rmp->_vl_msg_id = ntohs((t));                               \
76     rmp->context = mp->context;                                 \
77     do {body;} while (0);                                       \
78     vl_msg_api_send_shmem (q, (u8 *)&rmp);                      \
79 } while(0);
80
81 #define foreach_vpe_api_msg                             \
82 _(ONE_ADD_DEL_LOCATOR_SET, one_add_del_locator_set)                     \
83 _(ONE_ADD_DEL_LOCATOR, one_add_del_locator)                             \
84 _(ONE_ADD_DEL_LOCAL_EID, one_add_del_local_eid)                         \
85 _(ONE_ADD_DEL_MAP_RESOLVER, one_add_del_map_resolver)                   \
86 _(ONE_ADD_DEL_MAP_SERVER, one_add_del_map_server)                       \
87 _(ONE_ENABLE_DISABLE, one_enable_disable)                               \
88 _(ONE_RLOC_PROBE_ENABLE_DISABLE, one_rloc_probe_enable_disable)         \
89 _(ONE_MAP_REGISTER_ENABLE_DISABLE, one_map_register_enable_disable)     \
90 _(ONE_ADD_DEL_REMOTE_MAPPING, one_add_del_remote_mapping)               \
91 _(ONE_ADD_DEL_ADJACENCY, one_add_del_adjacency)                         \
92 _(ONE_PITR_SET_LOCATOR_SET, one_pitr_set_locator_set)                   \
93 _(ONE_MAP_REQUEST_MODE, one_map_request_mode)                           \
94 _(ONE_EID_TABLE_ADD_DEL_MAP, one_eid_table_add_del_map)                 \
95 _(ONE_LOCATOR_SET_DUMP, one_locator_set_dump)                           \
96 _(ONE_LOCATOR_DUMP, one_locator_dump)                                   \
97 _(ONE_EID_TABLE_DUMP, one_eid_table_dump)                               \
98 _(ONE_MAP_RESOLVER_DUMP, one_map_resolver_dump)                         \
99 _(ONE_MAP_SERVER_DUMP, one_map_server_dump)                             \
100 _(ONE_EID_TABLE_MAP_DUMP, one_eid_table_map_dump)                       \
101 _(ONE_EID_TABLE_VNI_DUMP, one_eid_table_vni_dump)                       \
102 _(ONE_ADJACENCIES_GET, one_adjacencies_get)                             \
103 _(SHOW_ONE_RLOC_PROBE_STATE, show_one_rloc_probe_state)                 \
104 _(SHOW_ONE_MAP_REGISTER_STATE, show_one_map_register_state)             \
105 _(SHOW_ONE_STATUS, show_one_status)                                     \
106 _(ONE_ADD_DEL_MAP_REQUEST_ITR_RLOCS,                                    \
107   one_add_del_map_request_itr_rlocs)                                    \
108 _(ONE_GET_MAP_REQUEST_ITR_RLOCS, one_get_map_request_itr_rlocs)         \
109 _(SHOW_ONE_PITR, show_one_pitr)                                         \
110 _(SHOW_ONE_MAP_REQUEST_MODE, show_one_map_request_mode)                 \
111 _(ONE_USE_PETR, one_use_petr)                                           \
112 _(SHOW_ONE_USE_PETR, show_one_use_petr)                                 \
113 _(SHOW_ONE_STATS_ENABLE_DISABLE, show_one_stats_enable_disable)         \
114 _(ONE_STATS_ENABLE_DISABLE, one_stats_enable_disable)                   \
115 _(ONE_STATS_DUMP, one_stats_dump)                                       \
116 _(ONE_STATS_FLUSH, one_stats_flush)                                     \
117 _(ONE_L2_ARP_BD_GET, one_l2_arp_bd_get)                                 \
118 _(ONE_L2_ARP_ENTRIES_GET, one_l2_arp_entries_get)                       \
119 _(ONE_ADD_DEL_L2_ARP_ENTRY, one_add_del_l2_arp_entry)                   \
120
121
122 static locator_t *
123 unformat_one_locs (vl_api_one_remote_locator_t * rmt_locs, u32 rloc_num)
124 {
125   u32 i;
126   locator_t *locs = 0, loc;
127   vl_api_one_remote_locator_t *r;
128
129   for (i = 0; i < rloc_num; i++)
130     {
131       /* remote locators */
132       r = &rmt_locs[i];
133       memset (&loc, 0, sizeof (loc));
134       gid_address_ip_set (&loc.address, &r->addr, r->is_ip4 ? IP4 : IP6);
135
136       loc.priority = r->priority;
137       loc.weight = r->weight;
138
139       vec_add1 (locs, loc);
140     }
141   return locs;
142 }
143
144 static void
145 vl_api_one_add_del_locator_set_t_handler (vl_api_one_add_del_locator_set_t *
146                                           mp)
147 {
148   vl_api_one_add_del_locator_set_reply_t *rmp;
149   int rv = 0;
150   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
151   locator_t locator;
152   vl_api_one_local_locator_t *ls_loc;
153   u32 ls_index = ~0, locator_num;
154   u8 *locator_name = NULL;
155   int i;
156
157   memset (a, 0, sizeof (a[0]));
158
159   locator_name = format (0, "%s", mp->locator_set_name);
160
161   a->name = locator_name;
162   a->is_add = mp->is_add;
163   a->local = 1;
164   locator_num = clib_net_to_host_u32 (mp->locator_num);
165
166   memset (&locator, 0, sizeof (locator));
167   for (i = 0; i < locator_num; i++)
168     {
169       ls_loc = &mp->locators[i];
170       VALIDATE_SW_IF_INDEX (ls_loc);
171
172       locator.sw_if_index = htonl (ls_loc->sw_if_index);
173       locator.priority = ls_loc->priority;
174       locator.weight = ls_loc->weight;
175       locator.local = 1;
176       vec_add1 (a->locators, locator);
177     }
178
179   rv = vnet_lisp_add_del_locator_set (a, &ls_index);
180
181   BAD_SW_IF_INDEX_LABEL;
182
183   vec_free (locator_name);
184   vec_free (a->locators);
185
186   /* *INDENT-OFF* */
187   REPLY_MACRO2 (VL_API_ONE_ADD_DEL_LOCATOR_SET_REPLY,
188   ({
189     rmp->ls_index = clib_host_to_net_u32 (ls_index);
190   }));
191   /* *INDENT-ON* */
192 }
193
194 static void
195 vl_api_one_add_del_locator_t_handler (vl_api_one_add_del_locator_t * mp)
196 {
197   vl_api_one_add_del_locator_reply_t *rmp;
198   int rv = 0;
199   locator_t locator, *locators = NULL;
200   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
201   u32 ls_index = ~0;
202   u8 *locator_name = NULL;
203
204   memset (&locator, 0, sizeof (locator));
205   memset (a, 0, sizeof (a[0]));
206
207   locator.sw_if_index = ntohl (mp->sw_if_index);
208   locator.priority = mp->priority;
209   locator.weight = mp->weight;
210   locator.local = 1;
211   vec_add1 (locators, locator);
212
213   locator_name = format (0, "%s", mp->locator_set_name);
214
215   a->name = locator_name;
216   a->locators = locators;
217   a->is_add = mp->is_add;
218   a->local = 1;
219
220   rv = vnet_lisp_add_del_locator (a, NULL, &ls_index);
221
222   vec_free (locators);
223   vec_free (locator_name);
224
225   REPLY_MACRO (VL_API_ONE_ADD_DEL_LOCATOR_REPLY);
226 }
227
228 static int
229 unformat_one_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src,
230                       u8 len)
231 {
232   switch (type)
233     {
234     case 0:                     /* ipv4 */
235       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
236       gid_address_ip_set (dst, src, IP4);
237       gid_address_ippref_len (dst) = len;
238       ip_prefix_normalize (&gid_address_ippref (dst));
239       break;
240     case 1:                     /* ipv6 */
241       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
242       gid_address_ip_set (dst, src, IP6);
243       gid_address_ippref_len (dst) = len;
244       ip_prefix_normalize (&gid_address_ippref (dst));
245       break;
246     case 2:                     /* l2 mac */
247       gid_address_type (dst) = GID_ADDR_MAC;
248       clib_memcpy (&gid_address_mac (dst), src, 6);
249       break;
250     default:
251       /* unknown type */
252       return VNET_API_ERROR_INVALID_VALUE;
253     }
254
255   gid_address_vni (dst) = vni;
256
257   return 0;
258 }
259
260 static void
261 vl_api_one_add_del_local_eid_t_handler (vl_api_one_add_del_local_eid_t * mp)
262 {
263   vl_api_one_add_del_local_eid_reply_t *rmp;
264   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
265   int rv = 0;
266   gid_address_t _eid, *eid = &_eid;
267   uword *p = NULL;
268   u32 locator_set_index = ~0, map_index = ~0;
269   vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
270   u8 *name = NULL, *key = NULL;
271   memset (a, 0, sizeof (a[0]));
272   memset (eid, 0, sizeof (eid[0]));
273
274   rv = unformat_one_eid_api (eid, clib_net_to_host_u32 (mp->vni),
275                              mp->eid_type, mp->eid, mp->prefix_len);
276   if (rv)
277     goto out;
278
279   name = format (0, "%s", mp->locator_set_name);
280   p = hash_get_mem (lcm->locator_set_index_by_name, name);
281   if (!p)
282     {
283       rv = VNET_API_ERROR_INVALID_VALUE;
284       goto out;
285     }
286   locator_set_index = p[0];
287
288   if (*mp->key)
289     key = format (0, "%s", mp->key);
290
291   /* XXX treat batch configuration */
292   a->is_add = mp->is_add;
293   gid_address_copy (&a->eid, eid);
294   a->locator_set_index = locator_set_index;
295   a->local = 1;
296   a->key = key;
297   a->key_id = clib_net_to_host_u16 (mp->key_id);
298
299   rv = vnet_lisp_add_del_local_mapping (a, &map_index);
300
301 out:
302   vec_free (name);
303   vec_free (key);
304   gid_address_free (&a->eid);
305
306   REPLY_MACRO (VL_API_ONE_ADD_DEL_LOCAL_EID_REPLY);
307 }
308
309 static void
310   vl_api_one_eid_table_add_del_map_t_handler
311   (vl_api_one_eid_table_add_del_map_t * mp)
312 {
313   vl_api_one_eid_table_add_del_map_reply_t *rmp;
314   int rv = 0;
315   rv = vnet_lisp_eid_table_map (clib_net_to_host_u32 (mp->vni),
316                                 clib_net_to_host_u32 (mp->dp_table),
317                                 mp->is_l2, mp->is_add);
318 REPLY_MACRO (VL_API_ONE_EID_TABLE_ADD_DEL_MAP_REPLY)}
319
320 static void
321 vl_api_one_add_del_map_server_t_handler (vl_api_one_add_del_map_server_t * mp)
322 {
323   vl_api_one_add_del_map_server_reply_t *rmp;
324   int rv = 0;
325   ip_address_t addr;
326
327   memset (&addr, 0, sizeof (addr));
328
329   ip_address_set (&addr, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
330   rv = vnet_lisp_add_del_map_server (&addr, mp->is_add);
331
332   REPLY_MACRO (VL_API_ONE_ADD_DEL_MAP_SERVER_REPLY);
333 }
334
335 static void
336 vl_api_one_add_del_map_resolver_t_handler (vl_api_one_add_del_map_resolver_t
337                                            * mp)
338 {
339   vl_api_one_add_del_map_resolver_reply_t *rmp;
340   int rv = 0;
341   vnet_lisp_add_del_map_resolver_args_t _a, *a = &_a;
342
343   memset (a, 0, sizeof (a[0]));
344
345   a->is_add = mp->is_add;
346   ip_address_set (&a->address, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
347
348   rv = vnet_lisp_add_del_map_resolver (a);
349
350   REPLY_MACRO (VL_API_ONE_ADD_DEL_MAP_RESOLVER_REPLY);
351 }
352
353 static void
354   vl_api_one_map_register_enable_disable_t_handler
355   (vl_api_one_map_register_enable_disable_t * mp)
356 {
357   vl_api_one_map_register_enable_disable_reply_t *rmp;
358   int rv = 0;
359
360   vnet_lisp_map_register_enable_disable (mp->is_enabled);
361   REPLY_MACRO (VL_API_ONE_ENABLE_DISABLE_REPLY);
362 }
363
364 static void
365   vl_api_one_rloc_probe_enable_disable_t_handler
366   (vl_api_one_rloc_probe_enable_disable_t * mp)
367 {
368   vl_api_one_rloc_probe_enable_disable_reply_t *rmp;
369   int rv = 0;
370
371   vnet_lisp_rloc_probe_enable_disable (mp->is_enabled);
372   REPLY_MACRO (VL_API_ONE_ENABLE_DISABLE_REPLY);
373 }
374
375 static void
376 vl_api_one_enable_disable_t_handler (vl_api_one_enable_disable_t * mp)
377 {
378   vl_api_one_enable_disable_reply_t *rmp;
379   int rv = 0;
380
381   vnet_lisp_enable_disable (mp->is_en);
382   REPLY_MACRO (VL_API_ONE_ENABLE_DISABLE_REPLY);
383 }
384
385 static void
386   vl_api_show_one_map_request_mode_t_handler
387   (vl_api_show_one_map_request_mode_t * mp)
388 {
389   int rv = 0;
390   vl_api_show_one_map_request_mode_reply_t *rmp;
391
392   /* *INDENT-OFF* */
393   REPLY_MACRO2(VL_API_SHOW_ONE_MAP_REQUEST_MODE_REPLY,
394   ({
395     rmp->mode = vnet_lisp_get_map_request_mode ();
396   }));
397   /* *INDENT-ON* */
398 }
399
400 static void
401 vl_api_one_map_request_mode_t_handler (vl_api_one_map_request_mode_t * mp)
402 {
403   vl_api_one_map_request_mode_reply_t *rmp;
404   int rv = 0;
405
406   rv = vnet_lisp_set_map_request_mode (mp->mode);
407
408   REPLY_MACRO (VL_API_ONE_MAP_REQUEST_MODE_REPLY);
409 }
410
411 static void
412 vl_api_one_pitr_set_locator_set_t_handler (vl_api_one_pitr_set_locator_set_t
413                                            * mp)
414 {
415   vl_api_one_pitr_set_locator_set_reply_t *rmp;
416   int rv = 0;
417   u8 *ls_name = 0;
418
419   ls_name = format (0, "%s", mp->ls_name);
420   rv = vnet_lisp_pitr_set_locator_set (ls_name, mp->is_add);
421   vec_free (ls_name);
422
423   REPLY_MACRO (VL_API_ONE_PITR_SET_LOCATOR_SET_REPLY);
424 }
425
426 static void
427 vl_api_one_use_petr_t_handler (vl_api_one_use_petr_t * mp)
428 {
429   vl_api_one_use_petr_reply_t *rmp;
430   int rv = 0;
431   ip_address_t addr;
432
433   ip_address_set (&addr, &mp->address, mp->is_ip4 ? IP4 : IP6);
434   rv = vnet_lisp_use_petr (&addr, mp->is_add);
435
436   REPLY_MACRO (VL_API_ONE_USE_PETR_REPLY);
437 }
438
439 static void
440 vl_api_show_one_use_petr_t_handler (vl_api_show_one_use_petr_t * mp)
441 {
442   unix_shared_memory_queue_t *q = NULL;
443   vl_api_show_one_use_petr_reply_t *rmp = NULL;
444   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
445   mapping_t *m;
446   locator_set_t *ls = 0;
447   int rv = 0;
448   locator_t *loc = 0;
449   u8 status = 0;
450   gid_address_t addr;
451
452   q = vl_api_client_index_to_input_queue (mp->client_index);
453   if (q == 0)
454     {
455       return;
456     }
457
458   memset (&addr, 0, sizeof (addr));
459   status = lcm->flags & LISP_FLAG_USE_PETR;
460   if (status)
461     {
462       m = pool_elt_at_index (lcm->mapping_pool, lcm->petr_map_index);
463       if (~0 != m->locator_set_index)
464         {
465           ls =
466             pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
467           loc = pool_elt_at_index (lcm->locator_pool, ls->locator_indices[0]);
468           gid_address_copy (&addr, &loc->address);
469         }
470     }
471
472   /* *INDENT-OFF* */
473   REPLY_MACRO2 (VL_API_SHOW_ONE_USE_PETR_REPLY,
474   {
475     rmp->status = status;
476     ip_address_t *ip = &gid_address_ip (&addr);
477     switch (ip_addr_version (ip))
478       {
479       case IP4:
480         clib_memcpy (rmp->address, &ip_addr_v4 (ip),
481                      sizeof (ip_addr_v4 (ip)));
482         break;
483
484       case IP6:
485         clib_memcpy (rmp->address, &ip_addr_v6 (ip),
486                      sizeof (ip_addr_v6 (ip)));
487         break;
488
489       default:
490         ASSERT (0);
491       }
492     rmp->is_ip4 = (gid_address_ip_version (&addr) == IP4);
493   });
494   /* *INDENT-ON* */
495 }
496
497 static void
498   vl_api_one_add_del_map_request_itr_rlocs_t_handler
499   (vl_api_one_add_del_map_request_itr_rlocs_t * mp)
500 {
501   vl_api_one_add_del_map_request_itr_rlocs_reply_t *rmp;
502   int rv = 0;
503   u8 *locator_set_name = NULL;
504   vnet_lisp_add_del_mreq_itr_rloc_args_t _a, *a = &_a;
505
506   locator_set_name = format (0, "%s", mp->locator_set_name);
507
508   a->is_add = mp->is_add;
509   a->locator_set_name = locator_set_name;
510
511   rv = vnet_lisp_add_del_mreq_itr_rlocs (a);
512
513   vec_free (locator_set_name);
514
515   REPLY_MACRO (VL_API_ONE_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY);
516 }
517
518 static void
519   vl_api_one_add_del_remote_mapping_t_handler
520   (vl_api_one_add_del_remote_mapping_t * mp)
521 {
522   locator_t *rlocs = 0;
523   vl_api_one_add_del_remote_mapping_reply_t *rmp;
524   int rv = 0;
525   gid_address_t _eid, *eid = &_eid;
526   u32 rloc_num = clib_net_to_host_u32 (mp->rloc_num);
527
528   memset (eid, 0, sizeof (eid[0]));
529
530   rv = unformat_one_eid_api (eid, clib_net_to_host_u32 (mp->vni),
531                              mp->eid_type, mp->eid, mp->eid_len);
532   if (rv)
533     goto send_reply;
534
535   rlocs = unformat_one_locs (mp->rlocs, rloc_num);
536
537   if (!mp->is_add)
538     {
539       vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
540       gid_address_copy (&a->reid, eid);
541       a->is_add = 0;
542       rv = vnet_lisp_add_del_adjacency (a);
543       if (rv)
544         {
545           goto out;
546         }
547     }
548
549   /* NOTE: for now this works as a static remote mapping, i.e.,
550    * not authoritative and ttl infinite. */
551   rv = vnet_lisp_add_del_mapping (eid, rlocs, mp->action, 0, ~0,
552                                   mp->is_add, 1 /* is_static */ , 0);
553
554   if (mp->del_all)
555     vnet_lisp_clear_all_remote_adjacencies ();
556
557 out:
558   vec_free (rlocs);
559 send_reply:
560   REPLY_MACRO (VL_API_ONE_ADD_DEL_REMOTE_MAPPING_REPLY);
561 }
562
563 static void
564 vl_api_one_add_del_adjacency_t_handler (vl_api_one_add_del_adjacency_t * mp)
565 {
566   vl_api_one_add_del_adjacency_reply_t *rmp;
567   vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
568
569   int rv = 0;
570   memset (a, 0, sizeof (a[0]));
571
572   rv = unformat_one_eid_api (&a->leid, clib_net_to_host_u32 (mp->vni),
573                              mp->eid_type, mp->leid, mp->leid_len);
574   rv |= unformat_one_eid_api (&a->reid, clib_net_to_host_u32 (mp->vni),
575                               mp->eid_type, mp->reid, mp->reid_len);
576
577   if (rv)
578     goto send_reply;
579
580   a->is_add = mp->is_add;
581   rv = vnet_lisp_add_del_adjacency (a);
582
583 send_reply:
584   REPLY_MACRO (VL_API_ONE_ADD_DEL_ADJACENCY_REPLY);
585 }
586
587 static void
588 send_one_locator_details (lisp_cp_main_t * lcm,
589                           locator_t * loc,
590                           unix_shared_memory_queue_t * q, u32 context)
591 {
592   vl_api_one_locator_details_t *rmp;
593
594   rmp = vl_msg_api_alloc (sizeof (*rmp));
595   memset (rmp, 0, sizeof (*rmp));
596   rmp->_vl_msg_id = ntohs (VL_API_ONE_LOCATOR_DETAILS);
597   rmp->context = context;
598
599   rmp->local = loc->local;
600   if (loc->local)
601     {
602       rmp->sw_if_index = ntohl (loc->sw_if_index);
603     }
604   else
605     {
606       rmp->is_ipv6 = gid_address_ip_version (&loc->address);
607       ip_address_copy_addr (rmp->ip_address, &gid_address_ip (&loc->address));
608     }
609   rmp->priority = loc->priority;
610   rmp->weight = loc->weight;
611
612   vl_msg_api_send_shmem (q, (u8 *) & rmp);
613 }
614
615 static void
616 vl_api_one_locator_dump_t_handler (vl_api_one_locator_dump_t * mp)
617 {
618   u8 *ls_name = 0;
619   unix_shared_memory_queue_t *q = 0;
620   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
621   locator_set_t *lsit = 0;
622   locator_t *loc = 0;
623   u32 ls_index = ~0, *locit = 0;
624   uword *p = 0;
625
626   q = vl_api_client_index_to_input_queue (mp->client_index);
627   if (q == 0)
628     {
629       return;
630     }
631
632   if (mp->is_index_set)
633     ls_index = htonl (mp->ls_index);
634   else
635     {
636       /* make sure we get a proper C-string */
637       mp->ls_name[sizeof (mp->ls_name) - 1] = 0;
638       ls_name = format (0, "%s", mp->ls_name);
639       p = hash_get_mem (lcm->locator_set_index_by_name, ls_name);
640       if (!p)
641         goto out;
642       ls_index = p[0];
643     }
644
645   if (pool_is_free_index (lcm->locator_set_pool, ls_index))
646     return;
647
648   lsit = pool_elt_at_index (lcm->locator_set_pool, ls_index);
649
650   vec_foreach (locit, lsit->locator_indices)
651   {
652     loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
653     send_one_locator_details (lcm, loc, q, mp->context);
654   };
655 out:
656   vec_free (ls_name);
657 }
658
659 static void
660 send_one_locator_set_details (lisp_cp_main_t * lcm,
661                               locator_set_t * lsit,
662                               unix_shared_memory_queue_t * q,
663                               u32 context, u32 ls_index)
664 {
665   vl_api_one_locator_set_details_t *rmp;
666   u8 *str = 0;
667
668   rmp = vl_msg_api_alloc (sizeof (*rmp));
669   memset (rmp, 0, sizeof (*rmp));
670   rmp->_vl_msg_id = ntohs (VL_API_ONE_LOCATOR_SET_DETAILS);
671   rmp->context = context;
672
673   rmp->ls_index = htonl (ls_index);
674   if (lsit->local)
675     {
676       ASSERT (lsit->name != NULL);
677       strncpy ((char *) rmp->ls_name, (char *) lsit->name,
678                vec_len (lsit->name));
679     }
680   else
681     {
682       str = format (0, "<remote-%d>", ls_index);
683       strncpy ((char *) rmp->ls_name, (char *) str, vec_len (str));
684       vec_free (str);
685     }
686
687   vl_msg_api_send_shmem (q, (u8 *) & rmp);
688 }
689
690 static void
691 vl_api_one_locator_set_dump_t_handler (vl_api_one_locator_set_dump_t * mp)
692 {
693   unix_shared_memory_queue_t *q = NULL;
694   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
695   locator_set_t *lsit = NULL;
696   u8 filter;
697
698   q = vl_api_client_index_to_input_queue (mp->client_index);
699   if (q == 0)
700     {
701       return;
702     }
703
704   filter = mp->filter;
705   /* *INDENT-OFF* */
706   pool_foreach (lsit, lcm->locator_set_pool,
707   ({
708     if (filter && !((1 == filter && lsit->local) ||
709                     (2 == filter && !lsit->local)))
710       {
711         continue;
712       }
713     send_one_locator_set_details (lcm, lsit, q, mp->context,
714                                    lsit - lcm->locator_set_pool);
715   }));
716   /* *INDENT-ON* */
717 }
718
719 static void
720 one_fid_put_api (u8 * dst, fid_address_t * src, u8 * prefix_length)
721 {
722   ASSERT (prefix_length);
723   ip_prefix_t *ippref = &fid_addr_ippref (src);
724
725   switch (fid_addr_type (src))
726     {
727     case FID_ADDR_IP_PREF:
728       if (ip_prefix_version (ippref) == IP4)
729         clib_memcpy (dst, &ip_prefix_v4 (ippref), 4);
730       else
731         clib_memcpy (dst, &ip_prefix_v6 (ippref), 16);
732       prefix_length[0] = ip_prefix_len (ippref);
733       break;
734
735     case FID_ADDR_MAC:
736       prefix_length[0] = 0;
737       clib_memcpy (dst, fid_addr_mac (src), 6);
738       break;
739
740     default:
741       clib_warning ("Unknown FID type %d!", fid_addr_type (src));
742       break;
743     }
744 }
745
746 static u8
747 fid_type_to_api_type (fid_address_t * fid)
748 {
749   ip_prefix_t *ippref;
750
751   switch (fid_addr_type (fid))
752     {
753     case FID_ADDR_IP_PREF:
754       ippref = &fid_addr_ippref (fid);
755       if (ip_prefix_version (ippref) == IP4)
756         return 0;
757       else if (ip_prefix_version (ippref) == IP6)
758         return 1;
759       else
760         return ~0;
761
762     case FID_ADDR_MAC:
763       return 2;
764     case FID_ADDR_NSH:
765       return 3;
766     }
767
768   return ~0;
769 }
770
771 static void
772 send_one_eid_table_details (mapping_t * mapit,
773                             unix_shared_memory_queue_t * q,
774                             u32 context, u8 filter)
775 {
776   fid_address_t *fid;
777   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
778   locator_set_t *ls = 0;
779   vl_api_one_eid_table_details_t *rmp = NULL;
780   gid_address_t *gid = NULL;
781   u8 *mac = 0;
782   ip_prefix_t *ip_prefix = NULL;
783
784   if (mapit->pitr_set)
785     return;
786
787   switch (filter)
788     {
789     case 0:                     /* all mappings */
790       break;
791
792     case 1:                     /* local only */
793       if (!mapit->local)
794         return;
795       break;
796     case 2:                     /* remote only */
797       if (mapit->local)
798         return;
799       break;
800     default:
801       clib_warning ("Filter error, unknown filter: %d", filter);
802       return;
803     }
804
805   gid = &mapit->eid;
806   ip_prefix = &gid_address_ippref (gid);
807   mac = gid_address_mac (gid);
808
809   rmp = vl_msg_api_alloc (sizeof (*rmp));
810   memset (rmp, 0, sizeof (*rmp));
811   rmp->_vl_msg_id = ntohs (VL_API_ONE_EID_TABLE_DETAILS);
812
813   ls = pool_elt_at_index (lcm->locator_set_pool, mapit->locator_set_index);
814   if (vec_len (ls->locator_indices) == 0)
815     rmp->locator_set_index = ~0;
816   else
817     rmp->locator_set_index = clib_host_to_net_u32 (mapit->locator_set_index);
818
819   rmp->is_local = mapit->local;
820   rmp->ttl = clib_host_to_net_u32 (mapit->ttl);
821   rmp->action = mapit->action;
822   rmp->authoritative = mapit->authoritative;
823
824   switch (gid_address_type (gid))
825     {
826     case GID_ADDR_SRC_DST:
827       rmp->is_src_dst = 1;
828       fid = &gid_address_sd_src (gid);
829       rmp->eid_type = fid_type_to_api_type (fid);
830       one_fid_put_api (rmp->seid, &gid_address_sd_src (gid),
831                        &rmp->seid_prefix_len);
832       one_fid_put_api (rmp->eid, &gid_address_sd_dst (gid),
833                        &rmp->eid_prefix_len);
834       break;
835     case GID_ADDR_IP_PREFIX:
836       rmp->eid_prefix_len = ip_prefix_len (ip_prefix);
837       if (ip_prefix_version (ip_prefix) == IP4)
838         {
839           rmp->eid_type = 0;    /* ipv4 type */
840           clib_memcpy (rmp->eid, &ip_prefix_v4 (ip_prefix),
841                        sizeof (ip_prefix_v4 (ip_prefix)));
842         }
843       else
844         {
845           rmp->eid_type = 1;    /* ipv6 type */
846           clib_memcpy (rmp->eid, &ip_prefix_v6 (ip_prefix),
847                        sizeof (ip_prefix_v6 (ip_prefix)));
848         }
849       break;
850     case GID_ADDR_MAC:
851       rmp->eid_type = 2;        /* l2 mac type */
852       clib_memcpy (rmp->eid, mac, 6);
853       break;
854     default:
855       ASSERT (0);
856     }
857   rmp->context = context;
858   rmp->vni = clib_host_to_net_u32 (gid_address_vni (gid));
859   rmp->key_id = clib_host_to_net_u16 (mapit->key_id);
860   memcpy (rmp->key, mapit->key, vec_len (mapit->key));
861   vl_msg_api_send_shmem (q, (u8 *) & rmp);
862 }
863
864 static void
865 vl_api_one_eid_table_dump_t_handler (vl_api_one_eid_table_dump_t * mp)
866 {
867   u32 mi;
868   unix_shared_memory_queue_t *q = NULL;
869   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
870   mapping_t *mapit = NULL;
871   gid_address_t _eid, *eid = &_eid;
872
873   q = vl_api_client_index_to_input_queue (mp->client_index);
874   if (q == 0)
875     {
876       return;
877     }
878
879   if (mp->eid_set)
880     {
881       memset (eid, 0, sizeof (*eid));
882
883       unformat_one_eid_api (eid, clib_net_to_host_u32 (mp->vni),
884                             mp->eid_type, mp->eid, mp->prefix_length);
885
886       mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
887       if ((u32) ~ 0 == mi)
888         return;
889
890       mapit = pool_elt_at_index (lcm->mapping_pool, mi);
891       send_one_eid_table_details (mapit, q, mp->context,
892                                   0 /* ignore filter */ );
893     }
894   else
895     {
896       /* *INDENT-OFF* */
897       pool_foreach (mapit, lcm->mapping_pool,
898       ({
899         send_one_eid_table_details(mapit, q, mp->context,
900                                     mp->filter);
901       }));
902       /* *INDENT-ON* */
903     }
904 }
905
906 static void
907 send_one_map_server_details (ip_address_t * ip,
908                              unix_shared_memory_queue_t * q, u32 context)
909 {
910   vl_api_one_map_server_details_t *rmp = NULL;
911
912   rmp = vl_msg_api_alloc (sizeof (*rmp));
913   memset (rmp, 0, sizeof (*rmp));
914   rmp->_vl_msg_id = ntohs (VL_API_ONE_MAP_SERVER_DETAILS);
915
916   switch (ip_addr_version (ip))
917     {
918     case IP4:
919       rmp->is_ipv6 = 0;
920       clib_memcpy (rmp->ip_address, &ip_addr_v4 (ip),
921                    sizeof (ip_addr_v4 (ip)));
922       break;
923
924     case IP6:
925       rmp->is_ipv6 = 1;
926       clib_memcpy (rmp->ip_address, &ip_addr_v6 (ip),
927                    sizeof (ip_addr_v6 (ip)));
928       break;
929
930     default:
931       ASSERT (0);
932     }
933   rmp->context = context;
934
935   vl_msg_api_send_shmem (q, (u8 *) & rmp);
936 }
937
938 static void
939 vl_api_one_map_server_dump_t_handler (vl_api_one_map_server_dump_t * mp)
940 {
941   unix_shared_memory_queue_t *q = NULL;
942   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
943   lisp_msmr_t *mr;
944
945   q = vl_api_client_index_to_input_queue (mp->client_index);
946   if (q == 0)
947     {
948       return;
949     }
950
951   vec_foreach (mr, lcm->map_servers)
952   {
953     send_one_map_server_details (&mr->address, q, mp->context);
954   }
955 }
956
957 static void
958 send_one_map_resolver_details (ip_address_t * ip,
959                                unix_shared_memory_queue_t * q, u32 context)
960 {
961   vl_api_one_map_resolver_details_t *rmp = NULL;
962
963   rmp = vl_msg_api_alloc (sizeof (*rmp));
964   memset (rmp, 0, sizeof (*rmp));
965   rmp->_vl_msg_id = ntohs (VL_API_ONE_MAP_RESOLVER_DETAILS);
966
967   switch (ip_addr_version (ip))
968     {
969     case IP4:
970       rmp->is_ipv6 = 0;
971       clib_memcpy (rmp->ip_address, &ip_addr_v4 (ip),
972                    sizeof (ip_addr_v4 (ip)));
973       break;
974
975     case IP6:
976       rmp->is_ipv6 = 1;
977       clib_memcpy (rmp->ip_address, &ip_addr_v6 (ip),
978                    sizeof (ip_addr_v6 (ip)));
979       break;
980
981     default:
982       ASSERT (0);
983     }
984   rmp->context = context;
985
986   vl_msg_api_send_shmem (q, (u8 *) & rmp);
987 }
988
989 static void
990 vl_api_one_map_resolver_dump_t_handler (vl_api_one_map_resolver_dump_t * mp)
991 {
992   unix_shared_memory_queue_t *q = NULL;
993   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
994   lisp_msmr_t *mr;
995
996   q = vl_api_client_index_to_input_queue (mp->client_index);
997   if (q == 0)
998     {
999       return;
1000     }
1001
1002   vec_foreach (mr, lcm->map_resolvers)
1003   {
1004     send_one_map_resolver_details (&mr->address, q, mp->context);
1005   }
1006 }
1007
1008 static void
1009 send_eid_table_map_pair (hash_pair_t * p,
1010                          unix_shared_memory_queue_t * q, u32 context)
1011 {
1012   vl_api_one_eid_table_map_details_t *rmp = NULL;
1013
1014   rmp = vl_msg_api_alloc (sizeof (*rmp));
1015   memset (rmp, 0, sizeof (*rmp));
1016   rmp->_vl_msg_id = ntohs (VL_API_ONE_EID_TABLE_MAP_DETAILS);
1017
1018   rmp->vni = clib_host_to_net_u32 (p->key);
1019   rmp->dp_table = clib_host_to_net_u32 (p->value[0]);
1020   rmp->context = context;
1021   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1022 }
1023
1024 static void
1025 vl_api_one_eid_table_map_dump_t_handler (vl_api_one_eid_table_map_dump_t * mp)
1026 {
1027   unix_shared_memory_queue_t *q = NULL;
1028   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1029   hash_pair_t *p;
1030   uword *vni_table = 0;
1031
1032   q = vl_api_client_index_to_input_queue (mp->client_index);
1033   if (q == 0)
1034     {
1035       return;
1036     }
1037
1038   if (mp->is_l2)
1039     {
1040       vni_table = lcm->bd_id_by_vni;
1041     }
1042   else
1043     {
1044       vni_table = lcm->table_id_by_vni;
1045     }
1046
1047   /* *INDENT-OFF* */
1048   hash_foreach_pair (p, vni_table,
1049   ({
1050     send_eid_table_map_pair (p, q, mp->context);
1051   }));
1052   /* *INDENT-ON* */
1053 }
1054
1055 static void
1056 send_eid_table_vni (u32 vni, unix_shared_memory_queue_t * q, u32 context)
1057 {
1058   vl_api_one_eid_table_vni_details_t *rmp = 0;
1059
1060   rmp = vl_msg_api_alloc (sizeof (*rmp));
1061   memset (rmp, 0, sizeof (*rmp));
1062   rmp->_vl_msg_id = ntohs (VL_API_ONE_EID_TABLE_VNI_DETAILS);
1063   rmp->context = context;
1064   rmp->vni = clib_host_to_net_u32 (vni);
1065   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1066 }
1067
1068 static void
1069 one_adjacency_copy (vl_api_one_adjacency_t * dst, lisp_adjacency_t * adjs)
1070 {
1071   lisp_adjacency_t *adj;
1072   vl_api_one_adjacency_t a;
1073   u32 i, n = vec_len (adjs);
1074
1075   for (i = 0; i < n; i++)
1076     {
1077       adj = vec_elt_at_index (adjs, i);
1078       memset (&a, 0, sizeof (a));
1079
1080       switch (gid_address_type (&adj->reid))
1081         {
1082         case GID_ADDR_IP_PREFIX:
1083           a.reid_prefix_len = gid_address_ippref_len (&adj->reid);
1084           a.leid_prefix_len = gid_address_ippref_len (&adj->leid);
1085           if (gid_address_ip_version (&adj->reid) == IP4)
1086             {
1087               a.eid_type = 0;   /* ipv4 type */
1088               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 4);
1089               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 4);
1090             }
1091           else
1092             {
1093               a.eid_type = 1;   /* ipv6 type */
1094               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 16);
1095               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 16);
1096             }
1097           break;
1098         case GID_ADDR_MAC:
1099           a.eid_type = 2;       /* l2 mac type */
1100           mac_copy (a.reid, gid_address_mac (&adj->reid));
1101           mac_copy (a.leid, gid_address_mac (&adj->leid));
1102           break;
1103         default:
1104           ASSERT (0);
1105         }
1106       dst[i] = a;
1107     }
1108 }
1109
1110 static void
1111   vl_api_show_one_rloc_probe_state_t_handler
1112   (vl_api_show_one_rloc_probe_state_t * mp)
1113 {
1114   vl_api_show_one_rloc_probe_state_reply_t *rmp = 0;
1115   int rv = 0;
1116
1117   /* *INDENT-OFF* */
1118   REPLY_MACRO2 (VL_API_SHOW_ONE_RLOC_PROBE_STATE_REPLY,
1119   {
1120     rmp->is_enabled = vnet_lisp_rloc_probe_state_get ();
1121   });
1122   /* *INDENT-ON* */
1123 }
1124
1125 static void
1126   vl_api_show_one_map_register_state_t_handler
1127   (vl_api_show_one_map_register_state_t * mp)
1128 {
1129   vl_api_show_one_map_register_state_reply_t *rmp = 0;
1130   int rv = 0;
1131
1132   /* *INDENT-OFF* */
1133   REPLY_MACRO2 (VL_API_SHOW_ONE_MAP_REGISTER_STATE_REPLY,
1134   {
1135     rmp->is_enabled = vnet_lisp_map_register_state_get ();
1136   });
1137   /* *INDENT-ON* */
1138 }
1139
1140 static void
1141 vl_api_one_adjacencies_get_t_handler (vl_api_one_adjacencies_get_t * mp)
1142 {
1143   vl_api_one_adjacencies_get_reply_t *rmp = 0;
1144   lisp_adjacency_t *adjs = 0;
1145   int rv = 0;
1146   u32 size = ~0;
1147   u32 vni = clib_net_to_host_u32 (mp->vni);
1148
1149   adjs = vnet_lisp_adjacencies_get_by_vni (vni);
1150   size = vec_len (adjs) * sizeof (vl_api_one_adjacency_t);
1151
1152   /* *INDENT-OFF* */
1153   REPLY_MACRO4 (VL_API_ONE_ADJACENCIES_GET_REPLY, size,
1154   {
1155     rmp->count = clib_host_to_net_u32 (vec_len (adjs));
1156     one_adjacency_copy (rmp->adjacencies, adjs);
1157   });
1158   /* *INDENT-ON* */
1159
1160   vec_free (adjs);
1161 }
1162
1163 static void
1164 vl_api_one_eid_table_vni_dump_t_handler (vl_api_one_eid_table_vni_dump_t * mp)
1165 {
1166   hash_pair_t *p;
1167   u32 *vnis = 0;
1168   unix_shared_memory_queue_t *q = 0;
1169   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1170
1171   q = vl_api_client_index_to_input_queue (mp->client_index);
1172   if (q == 0)
1173     {
1174       return;
1175     }
1176
1177   /* *INDENT-OFF* */
1178   hash_foreach_pair (p, lcm->table_id_by_vni,
1179   ({
1180     hash_set (vnis, p->key, 0);
1181   }));
1182
1183   hash_foreach_pair (p, lcm->bd_id_by_vni,
1184   ({
1185     hash_set (vnis, p->key, 0);
1186   }));
1187
1188   hash_foreach_pair (p, vnis,
1189   ({
1190     send_eid_table_vni (p->key, q, mp->context);
1191   }));
1192   /* *INDENT-ON* */
1193
1194   hash_free (vnis);
1195 }
1196
1197 static void
1198 vl_api_show_one_status_t_handler (vl_api_show_one_status_t * mp)
1199 {
1200   unix_shared_memory_queue_t *q = NULL;
1201   vl_api_show_one_status_reply_t *rmp = NULL;
1202   int rv = 0;
1203
1204   q = vl_api_client_index_to_input_queue (mp->client_index);
1205   if (q == 0)
1206     {
1207       return;
1208     }
1209
1210   /* *INDENT-OFF* */
1211   REPLY_MACRO2(VL_API_SHOW_ONE_STATUS_REPLY,
1212   ({
1213     rmp->gpe_status = vnet_lisp_gpe_enable_disable_status ();
1214     rmp->feature_status = vnet_lisp_enable_disable_status ();
1215   }));
1216   /* *INDENT-ON* */
1217 }
1218
1219 static void
1220   vl_api_one_get_map_request_itr_rlocs_t_handler
1221   (vl_api_one_get_map_request_itr_rlocs_t * mp)
1222 {
1223   unix_shared_memory_queue_t *q = NULL;
1224   vl_api_one_get_map_request_itr_rlocs_reply_t *rmp = NULL;
1225   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1226   locator_set_t *loc_set = 0;
1227   u8 *tmp_str = 0;
1228   int rv = 0;
1229
1230   q = vl_api_client_index_to_input_queue (mp->client_index);
1231   if (q == 0)
1232     {
1233       return;
1234     }
1235
1236   if (~0 == lcm->mreq_itr_rlocs)
1237     {
1238       tmp_str = format (0, " ");
1239     }
1240   else
1241     {
1242       loc_set =
1243         pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
1244       tmp_str = format (0, "%s", loc_set->name);
1245     }
1246
1247   /* *INDENT-OFF* */
1248   REPLY_MACRO2(VL_API_ONE_GET_MAP_REQUEST_ITR_RLOCS_REPLY,
1249   ({
1250     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
1251             ARRAY_LEN(rmp->locator_set_name) - 1);
1252   }));
1253   /* *INDENT-ON* */
1254
1255   vec_free (tmp_str);
1256 }
1257
1258 static void
1259 vl_api_show_one_pitr_t_handler (vl_api_show_one_pitr_t * mp)
1260 {
1261   unix_shared_memory_queue_t *q = NULL;
1262   vl_api_show_one_pitr_reply_t *rmp = NULL;
1263   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1264   mapping_t *m;
1265   locator_set_t *ls = 0;
1266   u8 *tmp_str = 0;
1267   int rv = 0;
1268
1269   q = vl_api_client_index_to_input_queue (mp->client_index);
1270   if (q == 0)
1271     {
1272       return;
1273     }
1274
1275   if (!lcm->lisp_pitr)
1276     {
1277       tmp_str = format (0, "N/A");
1278     }
1279   else
1280     {
1281       m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
1282       if (~0 != m->locator_set_index)
1283         {
1284           ls =
1285             pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
1286           tmp_str = format (0, "%s", ls->name);
1287         }
1288       else
1289         {
1290           tmp_str = format (0, "N/A");
1291         }
1292     }
1293   vec_add1 (tmp_str, 0);
1294
1295   /* *INDENT-OFF* */
1296   REPLY_MACRO2(VL_API_SHOW_ONE_PITR_REPLY,
1297   ({
1298     rmp->status = lcm->lisp_pitr;
1299     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
1300             ARRAY_LEN(rmp->locator_set_name) - 1);
1301   }));
1302   /* *INDENT-ON* */
1303 }
1304
1305 static void
1306   vl_api_show_one_stats_enable_disable_t_handler
1307   (vl_api_show_one_stats_enable_disable_t * mp)
1308 {
1309   vl_api_show_one_stats_enable_disable_reply_t *rmp = NULL;
1310   vnet_api_error_t rv = 0;
1311
1312   /* *INDENT-OFF* */
1313   REPLY_MACRO2 (VL_API_SHOW_ONE_STATS_ENABLE_DISABLE_REPLY,
1314   ({
1315     rmp->is_en = vnet_lisp_stats_enable_disable_state ();
1316   }));
1317   /* *INDENT-ON* */
1318 }
1319
1320 static void
1321   vl_api_one_stats_enable_disable_t_handler
1322   (vl_api_one_stats_enable_disable_t * mp)
1323 {
1324   vl_api_one_enable_disable_reply_t *rmp = NULL;
1325
1326   vnet_api_error_t rv = vnet_lisp_stats_enable_disable (mp->is_en);
1327   REPLY_MACRO (VL_API_ONE_ENABLE_DISABLE_REPLY);
1328 }
1329
1330 static void
1331 lisp_fid_addr_to_api (fid_address_t * fid, u8 * dst, u8 * api_eid_type,
1332                       u8 * prefix_length)
1333 {
1334   switch (fid_addr_type (fid))
1335     {
1336     case FID_ADDR_IP_PREF:
1337       *prefix_length = fid_addr_prefix_length (fid);
1338       if (fid_addr_ip_version (fid) == IP4)
1339         {
1340           *api_eid_type = 0;    /* ipv4 type */
1341           clib_memcpy (dst, &fid_addr_ippref (fid), 4);
1342         }
1343       else
1344         {
1345           *api_eid_type = 1;    /* ipv6 type */
1346           clib_memcpy (dst, &fid_addr_ippref (fid), 16);
1347         }
1348       break;
1349     case FID_ADDR_MAC:
1350       *api_eid_type = 2;        /* l2 mac type */
1351       mac_copy (dst, fid_addr_mac (fid));
1352       break;
1353     default:
1354       ASSERT (0);
1355     }
1356 }
1357
1358 static void
1359 vl_api_one_stats_flush_t_handler (vl_api_one_stats_flush_t * mp)
1360 {
1361   vl_api_one_stats_flush_reply_t *rmp;
1362   u8 rv;
1363
1364   rv = vnet_lisp_flush_stats ();
1365   REPLY_MACRO (VL_API_ONE_STATS_FLUSH_REPLY);
1366 }
1367
1368 static void
1369 vl_api_one_stats_dump_t_handler (vl_api_one_stats_dump_t * mp)
1370 {
1371   vl_api_one_stats_details_t *rmp;
1372   lisp_api_stats_t *stats, *stat;
1373   u8 rv = 0;
1374
1375   stats = vnet_lisp_get_stats ();
1376   vec_foreach (stat, stats)
1377   {
1378       /* *INDENT-OFF* */
1379       REPLY_DETAILS (VL_API_ONE_STATS_DETAILS,
1380       ({
1381         lisp_fid_addr_to_api (&stat->deid, rmp->deid, &rmp->eid_type,
1382                               &rmp->deid_pref_len);
1383         lisp_fid_addr_to_api (&stat->seid, rmp->seid, &rmp->eid_type,
1384                               &rmp->seid_pref_len);
1385         rmp->vni = clib_host_to_net_u32 (stat->vni);
1386
1387         rmp->is_ip4 = ip_addr_version (&stat->rmt_rloc) == IP4 ? 1 : 0;
1388         ip_address_copy_addr (rmp->rloc, &stat->rmt_rloc);
1389         ip_address_copy_addr (rmp->lloc, &stat->loc_rloc);
1390
1391         rmp->pkt_count = clib_host_to_net_u32 (stat->counters.packets);
1392         rmp->bytes = clib_host_to_net_u32 (stat->counters.bytes);
1393       }));
1394       /* *INDENT-ON* */
1395   }
1396 }
1397
1398 static void
1399   vl_api_one_add_del_l2_arp_entry_t_handler
1400   (vl_api_one_add_del_l2_arp_entry_t * mp)
1401 {
1402   vl_api_one_add_del_l2_arp_entry_reply_t *rmp;
1403   int rv = 0;
1404   gid_address_t _arp, *arp = &_arp;
1405   memset (arp, 0, sizeof (*arp));
1406
1407   gid_address_type (arp) = GID_ADDR_ARP;
1408   gid_address_arp_bd (arp) = clib_net_to_host_u32 (mp->bd);
1409
1410   /* vpp keeps ip4 addresses in network byte order */
1411   clib_memcpy (&gid_address_arp_ip4 (arp), &mp->ip4, 4);
1412
1413   rv = vnet_lisp_add_del_l2_arp_entry (arp, mp->mac, mp->is_add);
1414
1415   REPLY_MACRO (VL_API_ONE_ADD_DEL_L2_ARP_ENTRY_REPLY);
1416 }
1417
1418 static void
1419 vl_api_one_l2_arp_bd_get_t_handler (vl_api_one_l2_arp_bd_get_t * mp)
1420 {
1421   vl_api_one_l2_arp_bd_get_reply_t *rmp;
1422   int rv = 0;
1423   u32 i = 0;
1424   hash_pair_t *p;
1425
1426   u32 *bds = vnet_lisp_l2_arp_bds_get ();
1427   u32 size = hash_elts (bds) * sizeof (u32);
1428
1429   /* *INDENT-OFF* */
1430   REPLY_MACRO4 (VL_API_ONE_L2_ARP_BD_GET_REPLY, size,
1431   {
1432     rmp->count = clib_host_to_net_u32 (hash_elts (bds));
1433     hash_foreach_pair (p, bds,
1434     ({
1435       rmp->bridge_domains[i++] = clib_host_to_net_u32 (p->key);
1436     }));
1437   });
1438   /* *INDENT-ON* */
1439
1440   hash_free (bds);
1441 }
1442
1443 static void
1444 vl_api_one_l2_arp_entries_get_t_handler (vl_api_one_l2_arp_entries_get_t * mp)
1445 {
1446   vl_api_one_l2_arp_entries_get_reply_t *rmp;
1447   lisp_api_l2_arp_entry_t *entries = 0, *e;
1448   u32 i = 0;
1449   int rv = 0;
1450
1451   u32 bd = clib_net_to_host_u32 (mp->bd);
1452
1453   entries = vnet_lisp_l2_arp_entries_get_by_bd (bd);
1454   u32 size = vec_len (entries) * sizeof (u32);
1455
1456   /* *INDENT-OFF* */
1457   REPLY_MACRO4 (VL_API_ONE_L2_ARP_ENTRIES_GET_REPLY, size,
1458   {
1459     rmp->count = clib_host_to_net_u32 (vec_len (entries));
1460     vec_foreach (e, entries)
1461       {
1462         mac_copy (rmp->entries[i].mac, e->mac);
1463         rmp->entries[i].ip4 = e->ip4;
1464         i++;
1465       }
1466   });
1467   /* *INDENT-ON* */
1468
1469   vec_free (entries);
1470 }
1471
1472 /*
1473  * one_api_hookup
1474  * Add vpe's API message handlers to the table.
1475  * vlib has alread mapped shared memory and
1476  * added the client registration handlers.
1477  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
1478  */
1479 #define vl_msg_name_crc_list
1480 #include <vnet/vnet_all_api_h.h>
1481 #undef vl_msg_name_crc_list
1482
1483 static void
1484 setup_message_id_table (api_main_t * am)
1485 {
1486 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
1487   foreach_vl_msg_name_crc_one;
1488 #undef _
1489 }
1490
1491 static clib_error_t *
1492 one_api_hookup (vlib_main_t * vm)
1493 {
1494   api_main_t *am = &api_main;
1495
1496 #define _(N,n)                                                  \
1497     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
1498                            vl_api_##n##_t_handler,              \
1499                            vl_noop_handler,                     \
1500                            vl_api_##n##_t_endian,               \
1501                            vl_api_##n##_t_print,                \
1502                            sizeof(vl_api_##n##_t), 1);
1503   foreach_vpe_api_msg;
1504 #undef _
1505
1506   /*
1507    * Set up the (msg_name, crc, message-id) table
1508    */
1509   setup_message_id_table (am);
1510
1511   return 0;
1512 }
1513
1514 VLIB_API_INIT_FUNCTION (one_api_hookup);
1515
1516 /*
1517  * fd.io coding-style-patch-verification: ON
1518  *
1519  * Local Variables:
1520  * eval: (c-set-style "gnu")
1521  * End:
1522  */