vxlan-gbp: Mark APIs as in-progress
[vpp.git] / src / vnet / lisp-gpe / lisp_gpe_api.c
1 /*
2  *------------------------------------------------------------------
3  * lisp_gpe_api.c - lisp_gpe 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-gpe/lisp_gpe.h>
26 #include <vnet/lisp-gpe/lisp_gpe_adjacency.h>
27 #include <vnet/lisp-gpe/lisp_gpe_tunnel.h>
28 #include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
29 #include <vnet/lisp-gpe/lisp_gpe_tenant.h>
30 #include <vnet/fib/fib_table.h>
31 #include <vnet/vnet_msg_enum.h>
32 #include <vnet/ip/ip_types_api.h>
33 #include <vnet/ethernet/ethernet_types_api.h>
34 #include <vnet/lisp-gpe/lisp_types_api.h>
35
36 #define vl_api_gpe_locator_pair_t_endian vl_noop_handler
37 #define vl_api_gpe_locator_pair_t_print vl_noop_handler
38 #define vl_api_gpe_add_del_fwd_entry_t_endian vl_noop_handler
39 #define vl_api_gpe_add_del_fwd_entry_t_print vl_noop_handler
40
41 #define vl_typedefs             /* define message structures */
42 #include <vnet/vnet_all_api_h.h>
43 #undef vl_typedefs
44
45 #define vl_endianfun            /* define message structures */
46 #include <vnet/vnet_all_api_h.h>
47 #undef vl_endianfun
48
49 /* instantiate all the print functions we know about */
50 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
51 #define vl_printfun
52 #include <vnet/vnet_all_api_h.h>
53 #undef vl_printfun
54
55 #include <vlibapi/api_helper_macros.h>
56
57 #define foreach_vpe_api_msg                                     \
58 _(GPE_ADD_DEL_FWD_ENTRY, gpe_add_del_fwd_entry)                 \
59 _(GPE_FWD_ENTRIES_GET, gpe_fwd_entries_get)                     \
60 _(GPE_FWD_ENTRY_PATH_DUMP, gpe_fwd_entry_path_dump)             \
61 _(GPE_ENABLE_DISABLE, gpe_enable_disable)                       \
62 _(GPE_ADD_DEL_IFACE, gpe_add_del_iface)                         \
63 _(GPE_FWD_ENTRY_VNIS_GET, gpe_fwd_entry_vnis_get)               \
64 _(GPE_SET_ENCAP_MODE, gpe_set_encap_mode)                       \
65 _(GPE_GET_ENCAP_MODE, gpe_get_encap_mode)                       \
66 _(GPE_ADD_DEL_NATIVE_FWD_RPATH, gpe_add_del_native_fwd_rpath)   \
67 _(GPE_NATIVE_FWD_RPATHS_GET, gpe_native_fwd_rpaths_get)
68
69 static locator_pair_t *
70 unformat_gpe_loc_pairs (void *locs, u32 rloc_num)
71 {
72   u32 i;
73   locator_pair_t *pairs = 0, pair, *p;
74   vl_api_gpe_locator_t *r;
75
76   for (i = 0; i < rloc_num; i++)
77     {
78       /* local locator */
79       r = &((vl_api_gpe_locator_t *) locs)[i];
80       clib_memset (&pair, 0, sizeof (pair));
81       ip_address_decode2 (&r->addr, &pair.lcl_loc);
82
83       pair.weight = r->weight;
84       vec_add1 (pairs, pair);
85     }
86
87   for (i = rloc_num; i < rloc_num * 2; i++)
88     {
89       /* remote locators */
90       r = &((vl_api_gpe_locator_t *) locs)[i];
91       p = &pairs[i - rloc_num];
92       ip_address_decode2 (&r->addr, &p->rmt_loc);
93     }
94   return pairs;
95 }
96
97 static void
98   gpe_fwd_entry_path_dump_t_net_to_host
99   (vl_api_gpe_fwd_entry_path_dump_t * mp)
100 {
101   mp->fwd_entry_index = clib_net_to_host_u32 (mp->fwd_entry_index);
102 }
103
104 static void
105 lisp_api_set_locator (vl_api_gpe_locator_t * loc,
106                       const ip_address_t * addr, u8 weight)
107 {
108   loc->weight = weight;
109   ip_address_encode2 (addr, &loc->addr);
110 }
111
112 static void
113   vl_api_gpe_fwd_entry_path_dump_t_handler
114   (vl_api_gpe_fwd_entry_path_dump_t * mp)
115 {
116   lisp_fwd_path_t *path;
117   vl_api_gpe_fwd_entry_path_details_t *rmp = NULL;
118   lisp_gpe_main_t *lgm = &lisp_gpe_main;
119   vl_api_registration_t *reg;
120   lisp_gpe_fwd_entry_t *lfe;
121
122   gpe_fwd_entry_path_dump_t_net_to_host (mp);
123
124   reg = vl_api_client_index_to_registration (mp->client_index);
125   if (!reg)
126     return;
127
128   if (pool_is_free_index (lgm->lisp_fwd_entry_pool, mp->fwd_entry_index))
129     return;
130
131   lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, mp->fwd_entry_index);
132
133   if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE == lfe->type)
134     return;
135
136   vec_foreach (path, lfe->paths)
137   {
138     rmp = vl_msg_api_alloc (sizeof (*rmp));
139     clib_memset (rmp, 0, sizeof (*rmp));
140     const lisp_gpe_tunnel_t *lgt;
141
142     rmp->_vl_msg_id =
143       clib_host_to_net_u16 (VL_API_GPE_FWD_ENTRY_PATH_DETAILS);
144
145     const lisp_gpe_adjacency_t *ladj =
146       lisp_gpe_adjacency_get (path->lisp_adj);
147     lisp_api_set_locator (&rmp->rmt_loc, &ladj->remote_rloc, path->weight);
148     lgt = lisp_gpe_tunnel_get (ladj->tunnel_index);
149     lisp_api_set_locator (&rmp->lcl_loc, &lgt->key->lcl, path->weight);
150
151     rmp->context = mp->context;
152     vl_api_send_msg (reg, (u8 *) rmp);
153   }
154 }
155
156 static void
157 gpe_fwd_entries_copy (vl_api_gpe_fwd_entry_t * dst,
158                       lisp_api_gpe_fwd_entry_t * src)
159 {
160   lisp_api_gpe_fwd_entry_t *e;
161   u32 i = 0;
162
163   vec_foreach (e, src)
164   {
165     clib_memset (&dst[i], 0, sizeof (*dst));
166     dst[i].dp_table = e->dp_table;
167     dst[i].fwd_entry_index = e->fwd_entry_index;
168     dst[i].vni = e->vni;
169     dst[i].action = e->action;
170     switch (fid_addr_type (&e->leid))
171       {
172       case FID_ADDR_IP_PREF:
173         dst[i].leid.type = EID_TYPE_API_PREFIX;
174         dst[i].reid.type = EID_TYPE_API_PREFIX;
175         ip_prefix_encode2 (&fid_addr_ippref (&e->leid),
176                            &dst[i].leid.address.prefix);
177         ip_prefix_encode2 (&fid_addr_ippref (&e->reid),
178                            &dst[i].reid.address.prefix);
179         break;
180       case FID_ADDR_MAC:
181         mac_address_encode ((mac_address_t *) fid_addr_mac (&e->leid),
182                             dst[i].leid.address.mac);
183         mac_address_encode ((mac_address_t *) fid_addr_mac (&e->reid),
184                             dst[i].reid.address.mac);
185         dst[i].leid.type = EID_TYPE_API_MAC;
186         dst[i].reid.type = EID_TYPE_API_MAC;
187         break;
188       default:
189         clib_warning ("unknown fid type %d!", fid_addr_type (&e->leid));
190         break;
191       }
192     i++;
193   }
194 }
195
196 static void
197 gpe_fwd_entries_get_t_net_to_host (vl_api_gpe_fwd_entries_get_t * mp)
198 {
199   mp->vni = clib_net_to_host_u32 (mp->vni);
200 }
201
202 static void
203 gpe_entry_t_host_to_net (vl_api_gpe_fwd_entry_t * e)
204 {
205   e->fwd_entry_index = clib_host_to_net_u32 (e->fwd_entry_index);
206   e->dp_table = clib_host_to_net_u32 (e->dp_table);
207   e->vni = clib_host_to_net_u32 (e->vni);
208 }
209
210 static void
211   gpe_fwd_entries_get_reply_t_host_to_net
212   (vl_api_gpe_fwd_entries_get_reply_t * mp)
213 {
214   u32 i;
215   vl_api_gpe_fwd_entry_t *e;
216
217   for (i = 0; i < mp->count; i++)
218     {
219       e = &mp->entries[i];
220       gpe_entry_t_host_to_net (e);
221     }
222   mp->count = clib_host_to_net_u32 (mp->count);
223 }
224
225 static void
226 vl_api_gpe_fwd_entry_vnis_get_t_handler (vl_api_gpe_fwd_entry_vnis_get_t * mp)
227 {
228   vl_api_gpe_fwd_entry_vnis_get_reply_t *rmp = 0;
229   hash_pair_t *p;
230   u32 i = 0;
231   int rv = 0;
232
233   u32 *vnis = vnet_lisp_gpe_get_fwd_entry_vnis ();
234   u32 size = hash_elts (vnis) * sizeof (u32);
235
236   /* *INDENT-OFF* */
237   REPLY_MACRO4 (VL_API_GPE_FWD_ENTRY_VNIS_GET_REPLY, size,
238   {
239     rmp->count = clib_host_to_net_u32 (hash_elts (vnis));
240     hash_foreach_pair (p, vnis,
241     ({
242       rmp->vnis[i++] = clib_host_to_net_u32 (p->key);
243     }));
244   });
245   /* *INDENT-ON* */
246
247   hash_free (vnis);
248 }
249
250 static void
251 vl_api_gpe_fwd_entries_get_t_handler (vl_api_gpe_fwd_entries_get_t * mp)
252 {
253   lisp_api_gpe_fwd_entry_t *e;
254   vl_api_gpe_fwd_entries_get_reply_t *rmp = 0;
255   u32 size = 0;
256   int rv = 0;
257
258   gpe_fwd_entries_get_t_net_to_host (mp);
259
260   e = vnet_lisp_gpe_fwd_entries_get_by_vni (mp->vni);
261   size = vec_len (e) * sizeof (vl_api_gpe_fwd_entry_t);
262
263   /* *INDENT-OFF* */
264   REPLY_MACRO4 (VL_API_GPE_FWD_ENTRIES_GET_REPLY, size,
265   {
266     rmp->count = vec_len (e);
267     gpe_fwd_entries_copy (rmp->entries, e);
268     gpe_fwd_entries_get_reply_t_host_to_net (rmp);
269   });
270   /* *INDENT-ON* */
271
272   vec_free (e);
273 }
274
275 static void
276 gpe_add_del_fwd_entry_t_net_to_host (vl_api_gpe_add_del_fwd_entry_t * mp)
277 {
278   mp->vni = clib_net_to_host_u32 (mp->vni);
279   mp->dp_table = clib_net_to_host_u32 (mp->dp_table);
280   mp->loc_num = clib_net_to_host_u32 (mp->loc_num);
281 }
282
283 static void
284 vl_api_gpe_add_del_fwd_entry_t_handler (vl_api_gpe_add_del_fwd_entry_t * mp)
285 {
286   vl_api_gpe_add_del_fwd_entry_reply_t *rmp;
287   vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
288   locator_pair_t *pairs = 0;
289   int rv = 0;
290
291   gpe_add_del_fwd_entry_t_net_to_host (mp);
292   clib_memset (a, 0, sizeof (a[0]));
293
294   rv = unformat_lisp_eid_api (&a->rmt_eid, mp->vni, &mp->rmt_eid);
295   rv |= unformat_lisp_eid_api (&a->lcl_eid, mp->vni, &mp->lcl_eid);
296
297   if (mp->loc_num % 2 != 0)
298     {
299       rv = -1;
300       goto send_reply;
301     }
302   pairs = unformat_gpe_loc_pairs (mp->locs, mp->loc_num / 2);
303
304   if (rv)
305     goto send_reply;
306
307   a->is_add = mp->is_add;
308   a->locator_pairs = pairs;
309   a->dp_table = mp->dp_table;
310   a->vni = mp->vni;
311   a->action = mp->action;
312   if (mp->loc_num == 0)
313     a->is_negative = 1;
314
315   rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
316   vec_free (pairs);
317 send_reply:
318   /* *INDENT-OFF* */
319   REPLY_MACRO2 (VL_API_GPE_ADD_DEL_FWD_ENTRY_REPLY,
320   {
321     rmp->fwd_entry_index = clib_host_to_net_u32 (a->fwd_entry_index);
322   });
323   /* *INDENT-ON* */
324 }
325
326 static void
327 vl_api_gpe_enable_disable_t_handler (vl_api_gpe_enable_disable_t * mp)
328 {
329   vl_api_gpe_enable_disable_reply_t *rmp;
330   int rv = 0;
331   vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a;
332
333   a->is_en = mp->is_enable;
334   vnet_lisp_gpe_enable_disable (a);
335
336   REPLY_MACRO (VL_API_GPE_ENABLE_DISABLE_REPLY);
337 }
338
339 static void
340 vl_api_gpe_add_del_iface_t_handler (vl_api_gpe_add_del_iface_t * mp)
341 {
342   vl_api_gpe_add_del_iface_reply_t *rmp;
343   int rv = 0;
344   u32 vni, dp_table;
345
346   vni = clib_net_to_host_u32 (mp->vni);
347   dp_table = clib_net_to_host_u32 (mp->dp_table);
348
349   if (mp->is_l2)
350     {
351       if (mp->is_add)
352         {
353           if (~0 == lisp_gpe_tenant_l2_iface_add_or_lock (vni, dp_table))
354             rv = 1;
355         }
356       else
357         lisp_gpe_tenant_l2_iface_unlock (vni);
358     }
359   else
360     {
361       if (mp->is_add)
362         {
363           if (~0 == lisp_gpe_tenant_l3_iface_add_or_lock (vni, dp_table, 1))
364             rv = 1;
365         }
366       else
367         lisp_gpe_tenant_l3_iface_unlock (vni);
368     }
369
370   REPLY_MACRO (VL_API_GPE_ADD_DEL_IFACE_REPLY);
371 }
372
373 static void
374 vl_api_gpe_set_encap_mode_t_handler (vl_api_gpe_set_encap_mode_t * mp)
375 {
376   vl_api_gpe_set_encap_mode_reply_t *rmp;
377   int rv = 0;
378
379   rv = vnet_gpe_set_encap_mode (mp->is_vxlan);
380   REPLY_MACRO (VL_API_GPE_SET_ENCAP_MODE_REPLY);
381 }
382
383 static void
384 vl_api_gpe_get_encap_mode_t_handler (vl_api_gpe_get_encap_mode_t * mp)
385 {
386   vl_api_gpe_get_encap_mode_reply_t *rmp;
387   int rv = 0;
388
389   /* *INDENT-OFF* */
390   REPLY_MACRO2 (VL_API_GPE_GET_ENCAP_MODE_REPLY,
391   ({
392     rmp->encap_mode = vnet_gpe_get_encap_mode ();
393   }));
394   /* *INDENT-ON* */
395 }
396
397 static void
398   vl_api_gpe_add_del_native_fwd_rpath_t_handler
399   (vl_api_gpe_add_del_native_fwd_rpath_t * mp)
400 {
401   vl_api_gpe_add_del_native_fwd_rpath_reply_t *rmp;
402   vnet_gpe_native_fwd_rpath_args_t _a, *a = &_a;
403   int rv = 0;
404
405   clib_memset (a, 0, sizeof (a[0]));
406
407   if (mp->nh_addr.af)
408     clib_memcpy (&a->rpath.frp_addr.ip6, mp->nh_addr.un.ip6,
409                  sizeof (ip6_address_t));
410   else
411     clib_memcpy (&a->rpath.frp_addr.ip4, mp->nh_addr.un.ip4,
412                  sizeof (ip4_address_t));
413
414   a->is_add = mp->is_add;
415   a->rpath.frp_proto = mp->nh_addr.af ? DPO_PROTO_IP6 : DPO_PROTO_IP4;
416   a->rpath.frp_fib_index =
417     fib_table_find (dpo_proto_to_fib (a->rpath.frp_proto),
418                     clib_net_to_host_u32 (mp->table_id));
419   if (~0 == a->rpath.frp_fib_index)
420     {
421       rv = VNET_API_ERROR_INVALID_VALUE;
422       goto done;
423     }
424
425   a->rpath.frp_sw_if_index = clib_net_to_host_u32 (mp->nh_sw_if_index);
426   a->rpath.frp_weight = 1;
427
428   rv = vnet_gpe_add_del_native_fwd_rpath (a);
429 done:
430   REPLY_MACRO (VL_API_GPE_ADD_DEL_NATIVE_FWD_RPATH_REPLY);
431 }
432
433 static void
434 gpe_native_fwd_rpaths_copy (vl_api_gpe_native_fwd_rpath_t * dst,
435                             fib_route_path_t * src)
436 {
437   fib_route_path_t *e;
438   fib_table_t *table;
439   u32 i = 0;
440
441   vec_foreach (e, src)
442   {
443     clib_memset (&dst[i], 0, sizeof (*dst));
444     table = fib_table_get (e->frp_fib_index, dpo_proto_to_fib (e->frp_proto));
445     dst[i].fib_index = table->ft_table_id;
446     dst[i].nh_sw_if_index = e->frp_sw_if_index;
447     ip_address_encode (&e->frp_addr, IP46_TYPE_ANY, &dst[i].nh_addr);
448     i++;
449   }
450 }
451
452 static void
453 gpe_native_fwd_rpath_t_host_to_net (vl_api_gpe_native_fwd_rpath_t * e)
454 {
455   e->fib_index = clib_host_to_net_u32 (e->fib_index);
456   e->nh_sw_if_index = clib_host_to_net_u32 (e->nh_sw_if_index);
457 }
458
459 static void
460   gpe_native_fwd_rpaths_get_reply_t_host_to_net
461   (vl_api_gpe_native_fwd_rpaths_get_reply_t * mp)
462 {
463   u32 i;
464   vl_api_gpe_native_fwd_rpath_t *e;
465
466   for (i = 0; i < mp->count; i++)
467     {
468       e = &mp->entries[i];
469       gpe_native_fwd_rpath_t_host_to_net (e);
470     }
471   mp->count = clib_host_to_net_u32 (mp->count);
472 }
473
474 static void
475 vl_api_gpe_native_fwd_rpaths_get_t_handler (vl_api_gpe_native_fwd_rpaths_get_t
476                                             * mp)
477 {
478   lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
479   vl_api_gpe_native_fwd_rpaths_get_reply_t *rmp;
480   u32 size = 0;
481   int rv = 0;
482
483   u8 rpath_index = mp->is_ip4 ? 1 : 0;
484
485   size = vec_len (lgm->native_fwd_rpath[rpath_index])
486     * sizeof (vl_api_gpe_native_fwd_rpath_t);
487
488   /* *INDENT-OFF* */
489   REPLY_MACRO4 (VL_API_GPE_NATIVE_FWD_RPATHS_GET_REPLY, size,
490   {
491     rmp->count = vec_len (lgm->native_fwd_rpath[rpath_index]);
492     gpe_native_fwd_rpaths_copy (rmp->entries,
493                                 lgm->native_fwd_rpath[rpath_index]);
494     gpe_native_fwd_rpaths_get_reply_t_host_to_net (rmp);
495   });
496   /* *INDENT-ON* */
497 }
498
499 /*
500  * gpe_api_hookup
501  * Add vpe's API message handlers to the table.
502  * vlib has already mapped shared memory and
503  * added the client registration handlers.
504  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
505  */
506 #define vl_msg_name_crc_list
507 #include <vnet/vnet_all_api_h.h>
508 #undef vl_msg_name_crc_list
509
510 static void
511 setup_message_id_table (api_main_t * am)
512 {
513 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
514   foreach_vl_msg_name_crc_lisp_gpe;
515 #undef _
516 }
517
518 static clib_error_t *
519 gpe_api_hookup (vlib_main_t * vm)
520 {
521   api_main_t *am = vlibapi_get_main ();
522
523 #define _(N,n)                                                  \
524     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
525                            vl_api_##n##_t_handler,              \
526                            vl_noop_handler,                     \
527                            vl_api_##n##_t_endian,               \
528                            vl_api_##n##_t_print,                \
529                            sizeof(vl_api_##n##_t), 1);
530   foreach_vpe_api_msg;
531 #undef _
532
533   /*
534    * Set up the (msg_name, crc, message-id) table
535    */
536   setup_message_id_table (am);
537
538   return 0;
539 }
540
541 VLIB_API_INIT_FUNCTION (gpe_api_hookup);
542
543 /*
544  * fd.io coding-style-patch-verification: ON
545  *
546  * Local Variables:
547  * eval: (c-set-style "gnu")
548  * End:
549  */