d3fc4627c5f823222db8c37feb9190d4cafaed73
[vpp.git] / vnet / vnet / lisp-cp / lisp_api.c
1 /*
2  *------------------------------------------------------------------
3  * lisp_api.c - lisp api
4  *
5  * Copyright (c) 2016 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_typedefs             /* define message structures */
31 #include <vnet/vnet_all_api_h.h>
32 #undef vl_typedefs
33
34 #define vl_endianfun            /* define message structures */
35 #include <vnet/vnet_all_api_h.h>
36 #undef vl_endianfun
37
38 /* instantiate all the print functions we know about */
39 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
40 #define vl_printfun
41 #include <vnet/vnet_all_api_h.h>
42 #undef vl_printfun
43
44 #include <vlibapi/api_helper_macros.h>
45
46 #define foreach_vpe_api_msg                             \
47 _(LISP_ADD_DEL_LOCATOR_SET, lisp_add_del_locator_set)                   \
48 _(LISP_ADD_DEL_LOCATOR, lisp_add_del_locator)                           \
49 _(LISP_ADD_DEL_LOCAL_EID, lisp_add_del_local_eid)                       \
50 _(LISP_ADD_DEL_MAP_RESOLVER, lisp_add_del_map_resolver)                 \
51 _(LISP_ADD_DEL_MAP_SERVER, lisp_add_del_map_server)                     \
52 _(LISP_ENABLE_DISABLE, lisp_enable_disable)                             \
53 _(LISP_RLOC_PROBE_ENABLE_DISABLE, lisp_rloc_probe_enable_disable)       \
54 _(LISP_MAP_REGISTER_ENABLE_DISABLE, lisp_map_register_enable_disable)   \
55 _(LISP_ADD_DEL_REMOTE_MAPPING, lisp_add_del_remote_mapping)             \
56 _(LISP_ADD_DEL_ADJACENCY, lisp_add_del_adjacency)                       \
57 _(LISP_PITR_SET_LOCATOR_SET, lisp_pitr_set_locator_set)                 \
58 _(LISP_MAP_REQUEST_MODE, lisp_map_request_mode)                         \
59 _(LISP_EID_TABLE_ADD_DEL_MAP, lisp_eid_table_add_del_map)               \
60 _(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump)                         \
61 _(LISP_LOCATOR_DUMP, lisp_locator_dump)                                 \
62 _(LISP_EID_TABLE_DUMP, lisp_eid_table_dump)                             \
63 _(LISP_MAP_RESOLVER_DUMP, lisp_map_resolver_dump)                       \
64 _(LISP_MAP_SERVER_DUMP, lisp_map_server_dump)                           \
65 _(LISP_EID_TABLE_MAP_DUMP, lisp_eid_table_map_dump)                     \
66 _(LISP_EID_TABLE_VNI_DUMP, lisp_eid_table_vni_dump)                     \
67 _(LISP_ADJACENCIES_GET, lisp_adjacencies_get)                           \
68 _(SHOW_LISP_RLOC_PROBE_STATE, show_lisp_rloc_probe_state)               \
69 _(SHOW_LISP_MAP_REGISTER_STATE, show_lisp_map_register_state)           \
70 _(SHOW_LISP_STATUS, show_lisp_status)                                   \
71 _(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS,                                   \
72   lisp_add_del_map_request_itr_rlocs)                                   \
73 _(LISP_GET_MAP_REQUEST_ITR_RLOCS, lisp_get_map_request_itr_rlocs)       \
74 _(SHOW_LISP_PITR, show_lisp_pitr)                                       \
75 _(SHOW_LISP_MAP_REQUEST_MODE, show_lisp_map_request_mode)               \
76
77 /** Used for transferring locators via VPP API */
78 /* *INDENT-OFF* */
79 typedef CLIB_PACKED (struct {
80   u8 is_ip4; /**< is locator an IPv4 address */
81   u8 priority; /**< locator priority */
82   u8 weight; /**< locator weight */
83   u8 addr[16]; /**< IPv4/IPv6 address */
84 }) rloc_t;
85 /* *INDENT-ON* */
86
87 /** Used for transferring locators via VPP API */
88 /* *INDENT-OFF* */
89 typedef CLIB_PACKED (struct {
90   u32 sw_if_index; /**< locator sw_if_index */
91   u8 priority; /**< locator priority */
92   u8 weight; /**< locator weight */
93 }) ls_locator_t;
94 /* *INDENT-ON* */
95
96 static locator_t *
97 unformat_lisp_locs (void *rmt_locs, u32 rloc_num)
98 {
99   u32 i;
100   locator_t *locs = 0, loc;
101   rloc_t *r;
102
103   for (i = 0; i < rloc_num; i++)
104     {
105       /* remote locators */
106       r = &((rloc_t *) rmt_locs)[i];
107       memset (&loc, 0, sizeof (loc));
108       gid_address_ip_set (&loc.address, &r->addr, r->is_ip4 ? IP4 : IP6);
109
110       loc.priority = r->priority;
111       loc.weight = r->weight;
112
113       vec_add1 (locs, loc);
114     }
115   return locs;
116 }
117
118 static void
119 vl_api_lisp_add_del_locator_set_t_handler (vl_api_lisp_add_del_locator_set_t *
120                                            mp)
121 {
122   vl_api_lisp_add_del_locator_set_reply_t *rmp;
123   int rv = 0;
124   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
125   locator_t locator;
126   ls_locator_t *ls_loc;
127   u32 ls_index = ~0, locator_num;
128   u8 *locator_name = NULL;
129   int i;
130
131   memset (a, 0, sizeof (a[0]));
132
133   locator_name = format (0, "%s", mp->locator_set_name);
134
135   a->name = locator_name;
136   a->is_add = mp->is_add;
137   a->local = 1;
138   locator_num = clib_net_to_host_u32 (mp->locator_num);
139
140   memset (&locator, 0, sizeof (locator));
141   for (i = 0; i < locator_num; i++)
142     {
143       ls_loc = &((ls_locator_t *) mp->locators)[i];
144       VALIDATE_SW_IF_INDEX (ls_loc);
145
146       locator.sw_if_index = htonl (ls_loc->sw_if_index);
147       locator.priority = ls_loc->priority;
148       locator.weight = ls_loc->weight;
149       locator.local = 1;
150       vec_add1 (a->locators, locator);
151     }
152
153   rv = vnet_lisp_add_del_locator_set (a, &ls_index);
154
155   BAD_SW_IF_INDEX_LABEL;
156
157   vec_free (locator_name);
158   vec_free (a->locators);
159
160   /* *INDENT-OFF* */
161   REPLY_MACRO2 (VL_API_LISP_ADD_DEL_LOCATOR_SET_REPLY,
162   ({
163     rmp->ls_index = clib_host_to_net_u32 (ls_index);
164   }));
165   /* *INDENT-ON* */
166 }
167
168 static void
169 vl_api_lisp_add_del_locator_t_handler (vl_api_lisp_add_del_locator_t * mp)
170 {
171   vl_api_lisp_add_del_locator_reply_t *rmp;
172   int rv = 0;
173   locator_t locator, *locators = NULL;
174   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
175   u32 ls_index = ~0;
176   u8 *locator_name = NULL;
177
178   memset (&locator, 0, sizeof (locator));
179   memset (a, 0, sizeof (a[0]));
180
181   locator.sw_if_index = ntohl (mp->sw_if_index);
182   locator.priority = mp->priority;
183   locator.weight = mp->weight;
184   locator.local = 1;
185   vec_add1 (locators, locator);
186
187   locator_name = format (0, "%s", mp->locator_set_name);
188
189   a->name = locator_name;
190   a->locators = locators;
191   a->is_add = mp->is_add;
192   a->local = 1;
193
194   rv = vnet_lisp_add_del_locator (a, NULL, &ls_index);
195
196   vec_free (locators);
197   vec_free (locator_name);
198
199   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCATOR_REPLY);
200 }
201
202 static int
203 unformat_lisp_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src,
204                        u8 len)
205 {
206   switch (type)
207     {
208     case 0:                     /* ipv4 */
209       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
210       gid_address_ip_set (dst, src, IP4);
211       gid_address_ippref_len (dst) = len;
212       ip_prefix_normalize (&gid_address_ippref (dst));
213       break;
214     case 1:                     /* ipv6 */
215       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
216       gid_address_ip_set (dst, src, IP6);
217       gid_address_ippref_len (dst) = len;
218       ip_prefix_normalize (&gid_address_ippref (dst));
219       break;
220     case 2:                     /* l2 mac */
221       gid_address_type (dst) = GID_ADDR_MAC;
222       clib_memcpy (&gid_address_mac (dst), src, 6);
223       break;
224     default:
225       /* unknown type */
226       return VNET_API_ERROR_INVALID_VALUE;
227     }
228
229   gid_address_vni (dst) = vni;
230
231   return 0;
232 }
233
234 static void
235 vl_api_lisp_add_del_local_eid_t_handler (vl_api_lisp_add_del_local_eid_t * mp)
236 {
237   vl_api_lisp_add_del_local_eid_reply_t *rmp;
238   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
239   int rv = 0;
240   gid_address_t _eid, *eid = &_eid;
241   uword *p = NULL;
242   u32 locator_set_index = ~0, map_index = ~0;
243   vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
244   u8 *name = NULL, *key = NULL;
245   memset (a, 0, sizeof (a[0]));
246   memset (eid, 0, sizeof (eid[0]));
247
248   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
249                               mp->eid_type, mp->eid, mp->prefix_len);
250   if (rv)
251     goto out;
252
253   name = format (0, "%s", mp->locator_set_name);
254   p = hash_get_mem (lcm->locator_set_index_by_name, name);
255   if (!p)
256     {
257       rv = VNET_API_ERROR_INVALID_VALUE;
258       goto out;
259     }
260   locator_set_index = p[0];
261
262   if (*mp->key)
263     key = format (0, "%s", mp->key);
264
265   /* XXX treat batch configuration */
266   a->is_add = mp->is_add;
267   gid_address_copy (&a->eid, eid);
268   a->locator_set_index = locator_set_index;
269   a->local = 1;
270   a->key = key;
271   a->key_id = clib_net_to_host_u16 (mp->key_id);
272
273   rv = vnet_lisp_add_del_local_mapping (a, &map_index);
274
275 out:
276   vec_free (name);
277   vec_free (key);
278   gid_address_free (&a->eid);
279
280   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCAL_EID_REPLY);
281 }
282
283 static void
284   vl_api_lisp_eid_table_add_del_map_t_handler
285   (vl_api_lisp_eid_table_add_del_map_t * mp)
286 {
287   vl_api_lisp_eid_table_add_del_map_reply_t *rmp;
288   int rv = 0;
289   rv = vnet_lisp_eid_table_map (clib_net_to_host_u32 (mp->vni),
290                                 clib_net_to_host_u32 (mp->dp_table),
291                                 mp->is_l2, mp->is_add);
292 REPLY_MACRO (VL_API_LISP_EID_TABLE_ADD_DEL_MAP_REPLY)}
293
294 static void
295 vl_api_lisp_add_del_map_server_t_handler (vl_api_lisp_add_del_map_server_t
296                                           * mp)
297 {
298   vl_api_lisp_add_del_map_server_reply_t *rmp;
299   int rv = 0;
300   ip_address_t addr;
301
302   memset (&addr, 0, sizeof (addr));
303
304   ip_address_set (&addr, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
305   rv = vnet_lisp_add_del_map_server (&addr, mp->is_add);
306
307   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_SERVER_REPLY);
308 }
309
310 static void
311 vl_api_lisp_add_del_map_resolver_t_handler (vl_api_lisp_add_del_map_resolver_t
312                                             * mp)
313 {
314   vl_api_lisp_add_del_map_resolver_reply_t *rmp;
315   int rv = 0;
316   vnet_lisp_add_del_map_resolver_args_t _a, *a = &_a;
317
318   memset (a, 0, sizeof (a[0]));
319
320   a->is_add = mp->is_add;
321   ip_address_set (&a->address, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
322
323   rv = vnet_lisp_add_del_map_resolver (a);
324
325   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_RESOLVER_REPLY);
326 }
327
328 static void
329   vl_api_lisp_map_register_enable_disable_t_handler
330   (vl_api_lisp_map_register_enable_disable_t * mp)
331 {
332   vl_api_lisp_map_register_enable_disable_reply_t *rmp;
333   int rv = 0;
334
335   vnet_lisp_map_register_enable_disable (mp->is_enabled);
336   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
337 }
338
339 static void
340   vl_api_lisp_rloc_probe_enable_disable_t_handler
341   (vl_api_lisp_rloc_probe_enable_disable_t * mp)
342 {
343   vl_api_lisp_rloc_probe_enable_disable_reply_t *rmp;
344   int rv = 0;
345
346   vnet_lisp_rloc_probe_enable_disable (mp->is_enabled);
347   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
348 }
349
350 static void
351 vl_api_lisp_enable_disable_t_handler (vl_api_lisp_enable_disable_t * mp)
352 {
353   vl_api_lisp_enable_disable_reply_t *rmp;
354   int rv = 0;
355
356   vnet_lisp_enable_disable (mp->is_en);
357   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
358 }
359
360 static void
361   vl_api_show_lisp_map_request_mode_t_handler
362   (vl_api_show_lisp_map_request_mode_t * mp)
363 {
364   int rv = 0;
365   vl_api_show_lisp_map_request_mode_reply_t *rmp;
366
367   /* *INDENT-OFF* */
368   REPLY_MACRO2(VL_API_SHOW_LISP_MAP_REQUEST_MODE_REPLY,
369   ({
370     rmp->mode = vnet_lisp_get_map_request_mode ();
371   }));
372   /* *INDENT-ON* */
373 }
374
375 static void
376 vl_api_lisp_map_request_mode_t_handler (vl_api_lisp_map_request_mode_t * mp)
377 {
378   vl_api_lisp_map_request_mode_reply_t *rmp;
379   int rv = 0;
380
381   rv = vnet_lisp_set_map_request_mode (mp->mode);
382
383   REPLY_MACRO (VL_API_LISP_MAP_REQUEST_MODE_REPLY);
384 }
385
386 static void
387 vl_api_lisp_pitr_set_locator_set_t_handler (vl_api_lisp_pitr_set_locator_set_t
388                                             * mp)
389 {
390   vl_api_lisp_pitr_set_locator_set_reply_t *rmp;
391   int rv = 0;
392   u8 *ls_name = 0;
393
394   ls_name = format (0, "%s", mp->ls_name);
395   rv = vnet_lisp_pitr_set_locator_set (ls_name, mp->is_add);
396   vec_free (ls_name);
397
398   REPLY_MACRO (VL_API_LISP_PITR_SET_LOCATOR_SET_REPLY);
399 }
400
401 static void
402   vl_api_lisp_add_del_map_request_itr_rlocs_t_handler
403   (vl_api_lisp_add_del_map_request_itr_rlocs_t * mp)
404 {
405   vl_api_lisp_add_del_map_request_itr_rlocs_reply_t *rmp;
406   int rv = 0;
407   u8 *locator_set_name = NULL;
408   vnet_lisp_add_del_mreq_itr_rloc_args_t _a, *a = &_a;
409
410   locator_set_name = format (0, "%s", mp->locator_set_name);
411
412   a->is_add = mp->is_add;
413   a->locator_set_name = locator_set_name;
414
415   rv = vnet_lisp_add_del_mreq_itr_rlocs (a);
416
417   vec_free (locator_set_name);
418
419   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY);
420 }
421
422 static void
423   vl_api_lisp_add_del_remote_mapping_t_handler
424   (vl_api_lisp_add_del_remote_mapping_t * mp)
425 {
426   locator_t *rlocs = 0;
427   vl_api_lisp_add_del_remote_mapping_reply_t *rmp;
428   int rv = 0;
429   gid_address_t _eid, *eid = &_eid;
430   u32 rloc_num = clib_net_to_host_u32 (mp->rloc_num);
431
432   memset (eid, 0, sizeof (eid[0]));
433
434   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
435                               mp->eid_type, mp->eid, mp->eid_len);
436   if (rv)
437     goto send_reply;
438
439   rlocs = unformat_lisp_locs (mp->rlocs, rloc_num);
440
441   if (!mp->is_add)
442     {
443       vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
444       gid_address_copy (&a->reid, eid);
445       a->is_add = 0;
446       rv = vnet_lisp_add_del_adjacency (a);
447       if (rv)
448         {
449           goto out;
450         }
451     }
452
453   /* NOTE: for now this works as a static remote mapping, i.e.,
454    * not authoritative and ttl infinite. */
455   rv = vnet_lisp_add_del_mapping (eid, rlocs, mp->action, 0, ~0,
456                                   mp->is_add, 1 /* is_static */ , 0);
457
458   if (mp->del_all)
459     vnet_lisp_clear_all_remote_adjacencies ();
460
461 out:
462   vec_free (rlocs);
463 send_reply:
464   REPLY_MACRO (VL_API_LISP_ADD_DEL_REMOTE_MAPPING_REPLY);
465 }
466
467 static void
468 vl_api_lisp_add_del_adjacency_t_handler (vl_api_lisp_add_del_adjacency_t * mp)
469 {
470   vl_api_lisp_add_del_adjacency_reply_t *rmp;
471   vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
472
473   int rv = 0;
474   memset (a, 0, sizeof (a[0]));
475
476   rv = unformat_lisp_eid_api (&a->leid, clib_net_to_host_u32 (mp->vni),
477                               mp->eid_type, mp->leid, mp->leid_len);
478   rv |= unformat_lisp_eid_api (&a->reid, clib_net_to_host_u32 (mp->vni),
479                                mp->eid_type, mp->reid, mp->reid_len);
480
481   if (rv)
482     goto send_reply;
483
484   a->is_add = mp->is_add;
485   rv = vnet_lisp_add_del_adjacency (a);
486
487 send_reply:
488   REPLY_MACRO (VL_API_LISP_ADD_DEL_ADJACENCY_REPLY);
489 }
490
491 static void
492 send_lisp_locator_details (lisp_cp_main_t * lcm,
493                            locator_t * loc,
494                            unix_shared_memory_queue_t * q, u32 context)
495 {
496   vl_api_lisp_locator_details_t *rmp;
497
498   rmp = vl_msg_api_alloc (sizeof (*rmp));
499   memset (rmp, 0, sizeof (*rmp));
500   rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_DETAILS);
501   rmp->context = context;
502
503   rmp->local = loc->local;
504   if (loc->local)
505     {
506       rmp->sw_if_index = ntohl (loc->sw_if_index);
507     }
508   else
509     {
510       rmp->is_ipv6 = gid_address_ip_version (&loc->address);
511       ip_address_copy_addr (rmp->ip_address, &gid_address_ip (&loc->address));
512     }
513   rmp->priority = loc->priority;
514   rmp->weight = loc->weight;
515
516   vl_msg_api_send_shmem (q, (u8 *) & rmp);
517 }
518
519 static void
520 vl_api_lisp_locator_dump_t_handler (vl_api_lisp_locator_dump_t * mp)
521 {
522   u8 *ls_name = 0;
523   unix_shared_memory_queue_t *q = 0;
524   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
525   locator_set_t *lsit = 0;
526   locator_t *loc = 0;
527   u32 ls_index = ~0, *locit = 0;
528   uword *p = 0;
529
530   q = vl_api_client_index_to_input_queue (mp->client_index);
531   if (q == 0)
532     {
533       return;
534     }
535
536   if (mp->is_index_set)
537     ls_index = htonl (mp->ls_index);
538   else
539     {
540       /* make sure we get a proper C-string */
541       mp->ls_name[sizeof (mp->ls_name) - 1] = 0;
542       ls_name = format (0, "%s", mp->ls_name);
543       p = hash_get_mem (lcm->locator_set_index_by_name, ls_name);
544       if (!p)
545         goto out;
546       ls_index = p[0];
547     }
548
549   if (pool_is_free_index (lcm->locator_set_pool, ls_index))
550     return;
551
552   lsit = pool_elt_at_index (lcm->locator_set_pool, ls_index);
553
554   vec_foreach (locit, lsit->locator_indices)
555   {
556     loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
557     send_lisp_locator_details (lcm, loc, q, mp->context);
558   };
559 out:
560   vec_free (ls_name);
561 }
562
563 static void
564 send_lisp_locator_set_details (lisp_cp_main_t * lcm,
565                                locator_set_t * lsit,
566                                unix_shared_memory_queue_t * q,
567                                u32 context, u32 ls_index)
568 {
569   vl_api_lisp_locator_set_details_t *rmp;
570   u8 *str = 0;
571
572   rmp = vl_msg_api_alloc (sizeof (*rmp));
573   memset (rmp, 0, sizeof (*rmp));
574   rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_SET_DETAILS);
575   rmp->context = context;
576
577   rmp->ls_index = htonl (ls_index);
578   if (lsit->local)
579     {
580       ASSERT (lsit->name != NULL);
581       strncpy ((char *) rmp->ls_name, (char *) lsit->name,
582                vec_len (lsit->name));
583     }
584   else
585     {
586       str = format (0, "<remote-%d>", ls_index);
587       strncpy ((char *) rmp->ls_name, (char *) str, vec_len (str));
588       vec_free (str);
589     }
590
591   vl_msg_api_send_shmem (q, (u8 *) & rmp);
592 }
593
594 static void
595 vl_api_lisp_locator_set_dump_t_handler (vl_api_lisp_locator_set_dump_t * mp)
596 {
597   unix_shared_memory_queue_t *q = NULL;
598   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
599   locator_set_t *lsit = NULL;
600   u8 filter;
601
602   q = vl_api_client_index_to_input_queue (mp->client_index);
603   if (q == 0)
604     {
605       return;
606     }
607
608   filter = mp->filter;
609   /* *INDENT-OFF* */
610   pool_foreach (lsit, lcm->locator_set_pool,
611   ({
612     if (filter && !((1 == filter && lsit->local) ||
613                     (2 == filter && !lsit->local)))
614       {
615         continue;
616       }
617     send_lisp_locator_set_details (lcm, lsit, q, mp->context,
618                                    lsit - lcm->locator_set_pool);
619   }));
620   /* *INDENT-ON* */
621 }
622
623 static void
624 lisp_fid_put_api (u8 * dst, fid_address_t * src, u8 * prefix_length)
625 {
626   ASSERT (prefix_length);
627   ip_prefix_t *ippref = &fid_addr_ippref (src);
628
629   switch (fid_addr_type (src))
630     {
631     case FID_ADDR_IP_PREF:
632       if (ip_prefix_version (ippref) == IP4)
633         clib_memcpy (dst, &ip_prefix_v4 (ippref), 4);
634       else
635         clib_memcpy (dst, &ip_prefix_v6 (ippref), 16);
636       prefix_length[0] = ip_prefix_len (ippref);
637       break;
638
639     case FID_ADDR_MAC:
640       prefix_length[0] = 0;
641       clib_memcpy (dst, fid_addr_mac (src), 6);
642       break;
643
644     default:
645       clib_warning ("Unknown FID type %d!", fid_addr_type (src));
646       break;
647     }
648 }
649
650 static u8
651 fid_type_to_api_type (fid_address_t * fid)
652 {
653   ip_prefix_t *ippref;
654
655   switch (fid_addr_type (fid))
656     {
657     case FID_ADDR_IP_PREF:
658       ippref = &fid_addr_ippref (fid);
659       if (ip_prefix_version (ippref) == IP4)
660         return 0;
661       else if (ip_prefix_version (ippref) == IP6)
662         return 1;
663       else
664         return ~0;
665
666     case FID_ADDR_MAC:
667       return 2;
668     }
669
670   return ~0;
671 }
672
673 static void
674 send_lisp_eid_table_details (mapping_t * mapit,
675                              unix_shared_memory_queue_t * q,
676                              u32 context, u8 filter)
677 {
678   fid_address_t *fid;
679   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
680   locator_set_t *ls = 0;
681   vl_api_lisp_eid_table_details_t *rmp = NULL;
682   gid_address_t *gid = NULL;
683   u8 *mac = 0;
684   ip_prefix_t *ip_prefix = NULL;
685
686   switch (filter)
687     {
688     case 0:                     /* all mappings */
689       break;
690
691     case 1:                     /* local only */
692       if (!mapit->local)
693         return;
694       break;
695     case 2:                     /* remote only */
696       if (mapit->local)
697         return;
698       break;
699     default:
700       clib_warning ("Filter error, unknown filter: %d", filter);
701       return;
702     }
703
704   gid = &mapit->eid;
705   ip_prefix = &gid_address_ippref (gid);
706   mac = gid_address_mac (gid);
707
708   rmp = vl_msg_api_alloc (sizeof (*rmp));
709   memset (rmp, 0, sizeof (*rmp));
710   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_DETAILS);
711
712   ls = pool_elt_at_index (lcm->locator_set_pool, mapit->locator_set_index);
713   if (vec_len (ls->locator_indices) == 0)
714     rmp->locator_set_index = ~0;
715   else
716     rmp->locator_set_index = clib_host_to_net_u32 (mapit->locator_set_index);
717
718   rmp->is_local = mapit->local;
719   rmp->ttl = clib_host_to_net_u32 (mapit->ttl);
720   rmp->action = mapit->action;
721   rmp->authoritative = mapit->authoritative;
722
723   switch (gid_address_type (gid))
724     {
725     case GID_ADDR_SRC_DST:
726       rmp->is_src_dst = 1;
727       fid = &gid_address_sd_src (gid);
728       rmp->eid_type = fid_type_to_api_type (fid);
729       lisp_fid_put_api (rmp->seid, &gid_address_sd_src (gid),
730                         &rmp->seid_prefix_len);
731       lisp_fid_put_api (rmp->eid, &gid_address_sd_dst (gid),
732                         &rmp->eid_prefix_len);
733       break;
734     case GID_ADDR_IP_PREFIX:
735       rmp->eid_prefix_len = ip_prefix_len (ip_prefix);
736       if (ip_prefix_version (ip_prefix) == IP4)
737         {
738           rmp->eid_type = 0;    /* ipv4 type */
739           clib_memcpy (rmp->eid, &ip_prefix_v4 (ip_prefix),
740                        sizeof (ip_prefix_v4 (ip_prefix)));
741         }
742       else
743         {
744           rmp->eid_type = 1;    /* ipv6 type */
745           clib_memcpy (rmp->eid, &ip_prefix_v6 (ip_prefix),
746                        sizeof (ip_prefix_v6 (ip_prefix)));
747         }
748       break;
749     case GID_ADDR_MAC:
750       rmp->eid_type = 2;        /* l2 mac type */
751       clib_memcpy (rmp->eid, mac, 6);
752       break;
753     default:
754       ASSERT (0);
755     }
756   rmp->context = context;
757   rmp->vni = clib_host_to_net_u32 (gid_address_vni (gid));
758   rmp->key_id = clib_host_to_net_u16 (mapit->key_id);
759   memcpy (rmp->key, mapit->key, vec_len (mapit->key));
760   vl_msg_api_send_shmem (q, (u8 *) & rmp);
761 }
762
763 static void
764 vl_api_lisp_eid_table_dump_t_handler (vl_api_lisp_eid_table_dump_t * mp)
765 {
766   u32 mi;
767   unix_shared_memory_queue_t *q = NULL;
768   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
769   mapping_t *mapit = NULL;
770   gid_address_t _eid, *eid = &_eid;
771
772   q = vl_api_client_index_to_input_queue (mp->client_index);
773   if (q == 0)
774     {
775       return;
776     }
777
778   if (mp->eid_set)
779     {
780       memset (eid, 0, sizeof (*eid));
781
782       unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
783                              mp->eid_type, mp->eid, mp->prefix_length);
784
785       mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
786       if ((u32) ~ 0 == mi)
787         return;
788
789       mapit = pool_elt_at_index (lcm->mapping_pool, mi);
790       send_lisp_eid_table_details (mapit, q, mp->context,
791                                    0 /* ignore filter */ );
792     }
793   else
794     {
795       /* *INDENT-OFF* */
796       pool_foreach (mapit, lcm->mapping_pool,
797       ({
798         send_lisp_eid_table_details(mapit, q, mp->context,
799                                     mp->filter);
800       }));
801       /* *INDENT-ON* */
802     }
803 }
804
805 static void
806 send_lisp_map_server_details (ip_address_t * ip,
807                               unix_shared_memory_queue_t * q, u32 context)
808 {
809   vl_api_lisp_map_server_details_t *rmp = NULL;
810
811   rmp = vl_msg_api_alloc (sizeof (*rmp));
812   memset (rmp, 0, sizeof (*rmp));
813   rmp->_vl_msg_id = ntohs (VL_API_LISP_MAP_SERVER_DETAILS);
814
815   switch (ip_addr_version (ip))
816     {
817     case IP4:
818       rmp->is_ipv6 = 0;
819       clib_memcpy (rmp->ip_address, &ip_addr_v4 (ip),
820                    sizeof (ip_addr_v4 (ip)));
821       break;
822
823     case IP6:
824       rmp->is_ipv6 = 1;
825       clib_memcpy (rmp->ip_address, &ip_addr_v6 (ip),
826                    sizeof (ip_addr_v6 (ip)));
827       break;
828
829     default:
830       ASSERT (0);
831     }
832   rmp->context = context;
833
834   vl_msg_api_send_shmem (q, (u8 *) & rmp);
835 }
836
837 static void
838 vl_api_lisp_map_server_dump_t_handler (vl_api_lisp_map_server_dump_t * mp)
839 {
840   unix_shared_memory_queue_t *q = NULL;
841   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
842   lisp_msmr_t *mr;
843
844   q = vl_api_client_index_to_input_queue (mp->client_index);
845   if (q == 0)
846     {
847       return;
848     }
849
850   vec_foreach (mr, lcm->map_servers)
851   {
852     send_lisp_map_server_details (&mr->address, q, mp->context);
853   }
854 }
855
856 static void
857 send_lisp_map_resolver_details (ip_address_t * ip,
858                                 unix_shared_memory_queue_t * q, u32 context)
859 {
860   vl_api_lisp_map_resolver_details_t *rmp = NULL;
861
862   rmp = vl_msg_api_alloc (sizeof (*rmp));
863   memset (rmp, 0, sizeof (*rmp));
864   rmp->_vl_msg_id = ntohs (VL_API_LISP_MAP_RESOLVER_DETAILS);
865
866   switch (ip_addr_version (ip))
867     {
868     case IP4:
869       rmp->is_ipv6 = 0;
870       clib_memcpy (rmp->ip_address, &ip_addr_v4 (ip),
871                    sizeof (ip_addr_v4 (ip)));
872       break;
873
874     case IP6:
875       rmp->is_ipv6 = 1;
876       clib_memcpy (rmp->ip_address, &ip_addr_v6 (ip),
877                    sizeof (ip_addr_v6 (ip)));
878       break;
879
880     default:
881       ASSERT (0);
882     }
883   rmp->context = context;
884
885   vl_msg_api_send_shmem (q, (u8 *) & rmp);
886 }
887
888 static void
889 vl_api_lisp_map_resolver_dump_t_handler (vl_api_lisp_map_resolver_dump_t * mp)
890 {
891   unix_shared_memory_queue_t *q = NULL;
892   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
893   lisp_msmr_t *mr;
894
895   q = vl_api_client_index_to_input_queue (mp->client_index);
896   if (q == 0)
897     {
898       return;
899     }
900
901   vec_foreach (mr, lcm->map_resolvers)
902   {
903     send_lisp_map_resolver_details (&mr->address, q, mp->context);
904   }
905 }
906
907 static void
908 send_eid_table_map_pair (hash_pair_t * p,
909                          unix_shared_memory_queue_t * q, u32 context)
910 {
911   vl_api_lisp_eid_table_map_details_t *rmp = NULL;
912
913   rmp = vl_msg_api_alloc (sizeof (*rmp));
914   memset (rmp, 0, sizeof (*rmp));
915   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_MAP_DETAILS);
916
917   rmp->vni = clib_host_to_net_u32 (p->key);
918   rmp->dp_table = clib_host_to_net_u32 (p->value[0]);
919   rmp->context = context;
920   vl_msg_api_send_shmem (q, (u8 *) & rmp);
921 }
922
923 static void
924 vl_api_lisp_eid_table_map_dump_t_handler (vl_api_lisp_eid_table_map_dump_t *
925                                           mp)
926 {
927   unix_shared_memory_queue_t *q = NULL;
928   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
929   hash_pair_t *p;
930   uword *vni_table = 0;
931
932   q = vl_api_client_index_to_input_queue (mp->client_index);
933   if (q == 0)
934     {
935       return;
936     }
937
938   if (mp->is_l2)
939     {
940       vni_table = lcm->bd_id_by_vni;
941     }
942   else
943     {
944       vni_table = lcm->table_id_by_vni;
945     }
946
947   /* *INDENT-OFF* */
948   hash_foreach_pair (p, vni_table,
949   ({
950     send_eid_table_map_pair (p, q, mp->context);
951   }));
952   /* *INDENT-ON* */
953 }
954
955 static void
956 send_eid_table_vni (u32 vni, unix_shared_memory_queue_t * q, u32 context)
957 {
958   vl_api_lisp_eid_table_vni_details_t *rmp = 0;
959
960   rmp = vl_msg_api_alloc (sizeof (*rmp));
961   memset (rmp, 0, sizeof (*rmp));
962   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_VNI_DETAILS);
963   rmp->context = context;
964   rmp->vni = clib_host_to_net_u32 (vni);
965   vl_msg_api_send_shmem (q, (u8 *) & rmp);
966 }
967
968 static void
969 lisp_adjacency_copy (vl_api_lisp_adjacency_t * dst, lisp_adjacency_t * adjs)
970 {
971   lisp_adjacency_t *adj;
972   vl_api_lisp_adjacency_t a;
973   u32 i, n = vec_len (adjs);
974
975   for (i = 0; i < n; i++)
976     {
977       adj = vec_elt_at_index (adjs, i);
978       memset (&a, 0, sizeof (a));
979
980       switch (gid_address_type (&adj->reid))
981         {
982         case GID_ADDR_IP_PREFIX:
983           a.reid_prefix_len = gid_address_ippref_len (&adj->reid);
984           a.leid_prefix_len = gid_address_ippref_len (&adj->leid);
985           if (gid_address_ip_version (&adj->reid) == IP4)
986             {
987               a.eid_type = 0;   /* ipv4 type */
988               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 4);
989               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 4);
990             }
991           else
992             {
993               a.eid_type = 1;   /* ipv6 type */
994               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 16);
995               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 16);
996             }
997           break;
998         case GID_ADDR_MAC:
999           a.eid_type = 2;       /* l2 mac type */
1000           mac_copy (a.reid, gid_address_mac (&adj->reid));
1001           mac_copy (a.leid, gid_address_mac (&adj->leid));
1002           break;
1003         default:
1004           ASSERT (0);
1005         }
1006       dst[i] = a;
1007     }
1008 }
1009
1010 static void
1011   vl_api_show_lisp_rloc_probe_state_t_handler
1012   (vl_api_show_lisp_rloc_probe_state_t * mp)
1013 {
1014   vl_api_show_lisp_rloc_probe_state_reply_t *rmp = 0;
1015   int rv = 0;
1016
1017   /* *INDENT-OFF* */
1018   REPLY_MACRO2 (VL_API_SHOW_LISP_RLOC_PROBE_STATE_REPLY,
1019   {
1020     rmp->is_enabled = vnet_lisp_rloc_probe_state_get ();
1021   });
1022   /* *INDENT-ON* */
1023 }
1024
1025 static void
1026   vl_api_show_lisp_map_register_state_t_handler
1027   (vl_api_show_lisp_map_register_state_t * mp)
1028 {
1029   vl_api_show_lisp_map_register_state_reply_t *rmp = 0;
1030   int rv = 0;
1031
1032   /* *INDENT-OFF* */
1033   REPLY_MACRO2 (VL_API_SHOW_LISP_MAP_REGISTER_STATE_REPLY,
1034   {
1035     rmp->is_enabled = vnet_lisp_map_register_state_get ();
1036   });
1037   /* *INDENT-ON* */
1038 }
1039
1040 static void
1041 vl_api_lisp_adjacencies_get_t_handler (vl_api_lisp_adjacencies_get_t * mp)
1042 {
1043   vl_api_lisp_adjacencies_get_reply_t *rmp = 0;
1044   lisp_adjacency_t *adjs = 0;
1045   int rv = 0;
1046   vl_api_lisp_adjacency_t a;
1047   u32 size = ~0;
1048   u32 vni = clib_net_to_host_u32 (mp->vni);
1049
1050   adjs = vnet_lisp_adjacencies_get_by_vni (vni);
1051   size = vec_len (adjs) * sizeof (a);
1052
1053   /* *INDENT-OFF* */
1054   REPLY_MACRO4 (VL_API_LISP_ADJACENCIES_GET_REPLY, size,
1055   {
1056     rmp->count = clib_host_to_net_u32 (vec_len (adjs));
1057     lisp_adjacency_copy (rmp->adjacencies, adjs);
1058   });
1059   /* *INDENT-ON* */
1060
1061   vec_free (adjs);
1062 }
1063
1064 static void
1065 vl_api_lisp_eid_table_vni_dump_t_handler (vl_api_lisp_eid_table_vni_dump_t *
1066                                           mp)
1067 {
1068   hash_pair_t *p;
1069   u32 *vnis = 0;
1070   unix_shared_memory_queue_t *q = 0;
1071   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1072
1073   q = vl_api_client_index_to_input_queue (mp->client_index);
1074   if (q == 0)
1075     {
1076       return;
1077     }
1078
1079   /* *INDENT-OFF* */
1080   hash_foreach_pair (p, lcm->table_id_by_vni,
1081   ({
1082     hash_set (vnis, p->key, 0);
1083   }));
1084
1085   hash_foreach_pair (p, lcm->bd_id_by_vni,
1086   ({
1087     hash_set (vnis, p->key, 0);
1088   }));
1089
1090   hash_foreach_pair (p, vnis,
1091   ({
1092     send_eid_table_vni (p->key, q, mp->context);
1093   }));
1094   /* *INDENT-ON* */
1095
1096   hash_free (vnis);
1097 }
1098
1099 static void
1100 vl_api_show_lisp_status_t_handler (vl_api_show_lisp_status_t * mp)
1101 {
1102   unix_shared_memory_queue_t *q = NULL;
1103   vl_api_show_lisp_status_reply_t *rmp = NULL;
1104   int rv = 0;
1105
1106   q = vl_api_client_index_to_input_queue (mp->client_index);
1107   if (q == 0)
1108     {
1109       return;
1110     }
1111
1112   /* *INDENT-OFF* */
1113   REPLY_MACRO2(VL_API_SHOW_LISP_STATUS_REPLY,
1114   ({
1115     rmp->gpe_status = vnet_lisp_gpe_enable_disable_status ();
1116     rmp->feature_status = vnet_lisp_enable_disable_status ();
1117   }));
1118   /* *INDENT-ON* */
1119 }
1120
1121 static void
1122   vl_api_lisp_get_map_request_itr_rlocs_t_handler
1123   (vl_api_lisp_get_map_request_itr_rlocs_t * mp)
1124 {
1125   unix_shared_memory_queue_t *q = NULL;
1126   vl_api_lisp_get_map_request_itr_rlocs_reply_t *rmp = NULL;
1127   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1128   locator_set_t *loc_set = 0;
1129   u8 *tmp_str = 0;
1130   int rv = 0;
1131
1132   q = vl_api_client_index_to_input_queue (mp->client_index);
1133   if (q == 0)
1134     {
1135       return;
1136     }
1137
1138   if (~0 == lcm->mreq_itr_rlocs)
1139     {
1140       tmp_str = format (0, " ");
1141     }
1142   else
1143     {
1144       loc_set =
1145         pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
1146       tmp_str = format (0, "%s", loc_set->name);
1147     }
1148
1149   /* *INDENT-OFF* */
1150   REPLY_MACRO2(VL_API_LISP_GET_MAP_REQUEST_ITR_RLOCS_REPLY,
1151   ({
1152     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
1153             ARRAY_LEN(rmp->locator_set_name) - 1);
1154   }));
1155   /* *INDENT-ON* */
1156
1157   vec_free (tmp_str);
1158 }
1159
1160 static void
1161 vl_api_show_lisp_pitr_t_handler (vl_api_show_lisp_pitr_t * mp)
1162 {
1163   unix_shared_memory_queue_t *q = NULL;
1164   vl_api_show_lisp_pitr_reply_t *rmp = NULL;
1165   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1166   mapping_t *m;
1167   locator_set_t *ls = 0;
1168   u8 *tmp_str = 0;
1169   int rv = 0;
1170
1171   q = vl_api_client_index_to_input_queue (mp->client_index);
1172   if (q == 0)
1173     {
1174       return;
1175     }
1176
1177   if (!lcm->lisp_pitr)
1178     {
1179       tmp_str = format (0, "N/A");
1180     }
1181   else
1182     {
1183       m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
1184       if (~0 != m->locator_set_index)
1185         {
1186           ls =
1187             pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
1188           tmp_str = format (0, "%s", ls->name);
1189         }
1190       else
1191         {
1192           tmp_str = format (0, "N/A");
1193         }
1194     }
1195   vec_add1 (tmp_str, 0);
1196
1197   /* *INDENT-OFF* */
1198   REPLY_MACRO2(VL_API_SHOW_LISP_PITR_REPLY,
1199   ({
1200     rmp->status = lcm->lisp_pitr;
1201     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
1202             ARRAY_LEN(rmp->locator_set_name) - 1);
1203   }));
1204   /* *INDENT-ON* */
1205 }
1206
1207 /*
1208  * lisp_api_hookup
1209  * Add vpe's API message handlers to the table.
1210  * vlib has alread mapped shared memory and
1211  * added the client registration handlers.
1212  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
1213  */
1214 #define vl_msg_name_crc_list
1215 #include <vnet/vnet_all_api_h.h>
1216 #undef vl_msg_name_crc_list
1217
1218 static void
1219 setup_message_id_table (api_main_t * am)
1220 {
1221 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
1222   foreach_vl_msg_name_crc_lisp;
1223 #undef _
1224 }
1225
1226 static clib_error_t *
1227 lisp_api_hookup (vlib_main_t * vm)
1228 {
1229   api_main_t *am = &api_main;
1230
1231 #define _(N,n)                                                  \
1232     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
1233                            vl_api_##n##_t_handler,              \
1234                            vl_noop_handler,                     \
1235                            vl_api_##n##_t_endian,               \
1236                            vl_api_##n##_t_print,                \
1237                            sizeof(vl_api_##n##_t), 1);
1238   foreach_vpe_api_msg;
1239 #undef _
1240
1241   /*
1242    * Set up the (msg_name, crc, message-id) table
1243    */
1244   setup_message_id_table (am);
1245
1246   return 0;
1247 }
1248
1249 VLIB_API_INIT_FUNCTION (lisp_api_hookup);
1250
1251 /*
1252  * fd.io coding-style-patch-verification: ON
1253  *
1254  * Local Variables:
1255  * eval: (c-set-style "gnu")
1256  * End:
1257  */