blob: f6bd5440a6d2407f952074cdae0e210fb400a7ad [file] [log] [blame]
Pavel Kotucekabea9662016-12-21 15:50:08 +01001/*
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>
Filip Tehlar5fae99c2017-01-18 12:57:37 +010026#include <vnet/lisp-gpe/lisp_gpe_adjacency.h>
27#include <vnet/lisp-gpe/lisp_gpe_tunnel.h>
Pavel Kotucekabea9662016-12-21 15:50:08 +010028#include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
29#include <vnet/lisp-gpe/lisp_gpe_tenant.h>
30
31#include <vnet/vnet_msg_enum.h>
32
Filip Tehlar82786c42017-02-20 15:20:37 +010033#define vl_api_gpe_locator_pair_t_endian vl_noop_handler
34#define vl_api_gpe_locator_pair_t_print vl_noop_handler
35#define vl_api_gpe_add_del_fwd_entry_t_endian vl_noop_handler
36#define vl_api_gpe_add_del_fwd_entry_t_print vl_noop_handler
Filip Tehlarc3af7bf2017-01-13 14:13:09 +010037
Pavel Kotucekabea9662016-12-21 15:50:08 +010038#define vl_typedefs /* define message structures */
39#include <vnet/vnet_all_api_h.h>
40#undef vl_typedefs
41
42#define vl_endianfun /* define message structures */
43#include <vnet/vnet_all_api_h.h>
44#undef vl_endianfun
45
46/* instantiate all the print functions we know about */
47#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
48#define vl_printfun
49#include <vnet/vnet_all_api_h.h>
50#undef vl_printfun
51
52#include <vlibapi/api_helper_macros.h>
53
54#define foreach_vpe_api_msg \
Filip Tehlar82786c42017-02-20 15:20:37 +010055_(GPE_ADD_DEL_FWD_ENTRY, gpe_add_del_fwd_entry) \
56_(GPE_FWD_ENTRIES_GET, gpe_fwd_entries_get) \
57_(GPE_FWD_ENTRY_PATH_DUMP, gpe_fwd_entry_path_dump) \
58_(GPE_ENABLE_DISABLE, gpe_enable_disable) \
Filip Tehlar3e7b56932017-02-21 18:28:34 +010059_(GPE_ADD_DEL_IFACE, gpe_add_del_iface) \
60_(GPE_SET_ENCAP_MODE, gpe_set_encap_mode) \
61_(GPE_GET_ENCAP_MODE, gpe_get_encap_mode)
Pavel Kotucekabea9662016-12-21 15:50:08 +010062
63static locator_pair_t *
Filip Tehlar82786c42017-02-20 15:20:37 +010064unformat_gpe_loc_pairs (void *locs, u32 rloc_num)
Pavel Kotucekabea9662016-12-21 15:50:08 +010065{
66 u32 i;
Filip Tehlarc3af7bf2017-01-13 14:13:09 +010067 locator_pair_t *pairs = 0, pair, *p;
Filip Tehlar82786c42017-02-20 15:20:37 +010068 vl_api_gpe_locator_t *r;
Pavel Kotucekabea9662016-12-21 15:50:08 +010069
70 for (i = 0; i < rloc_num; i++)
71 {
72 /* local locator */
Filip Tehlar82786c42017-02-20 15:20:37 +010073 r = &((vl_api_gpe_locator_t *) locs)[i];
Filip Tehlarc3af7bf2017-01-13 14:13:09 +010074 memset (&pair, 0, sizeof (pair));
Pavel Kotucekabea9662016-12-21 15:50:08 +010075 ip_address_set (&pair.lcl_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
76
Pavel Kotucekabea9662016-12-21 15:50:08 +010077 pair.weight = r->weight;
Pavel Kotucekabea9662016-12-21 15:50:08 +010078 vec_add1 (pairs, pair);
79 }
Filip Tehlarc3af7bf2017-01-13 14:13:09 +010080
81 for (i = rloc_num; i < rloc_num * 2; i++)
82 {
83 /* remote locators */
Filip Tehlar82786c42017-02-20 15:20:37 +010084 r = &((vl_api_gpe_locator_t *) locs)[i];
Filip Tehlarc3af7bf2017-01-13 14:13:09 +010085 p = &pairs[i - rloc_num];
86 ip_address_set (&p->rmt_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
87 }
Pavel Kotucekabea9662016-12-21 15:50:08 +010088 return pairs;
89}
90
91static int
92unformat_lisp_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src,
93 u8 len)
94{
95 switch (type)
96 {
97 case 0: /* ipv4 */
98 gid_address_type (dst) = GID_ADDR_IP_PREFIX;
99 gid_address_ip_set (dst, src, IP4);
100 gid_address_ippref_len (dst) = len;
101 ip_prefix_normalize (&gid_address_ippref (dst));
102 break;
103 case 1: /* ipv6 */
104 gid_address_type (dst) = GID_ADDR_IP_PREFIX;
105 gid_address_ip_set (dst, src, IP6);
106 gid_address_ippref_len (dst) = len;
107 ip_prefix_normalize (&gid_address_ippref (dst));
108 break;
109 case 2: /* l2 mac */
110 gid_address_type (dst) = GID_ADDR_MAC;
111 clib_memcpy (&gid_address_mac (dst), src, 6);
112 break;
113 default:
114 /* unknown type */
115 return VNET_API_ERROR_INVALID_VALUE;
116 }
117
118 gid_address_vni (dst) = vni;
119
120 return 0;
121}
122
123static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100124 gpe_fwd_entry_path_dump_t_net_to_host
125 (vl_api_gpe_fwd_entry_path_dump_t * mp)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100126{
127 mp->fwd_entry_index = clib_net_to_host_u32 (mp->fwd_entry_index);
128}
129
130static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100131lisp_api_set_locator (vl_api_gpe_locator_t * loc,
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100132 const ip_address_t * addr, u8 weight)
133{
134 loc->weight = weight;
135 if (IP4 == ip_addr_version (addr))
136 {
137 loc->is_ip4 = 1;
138 memcpy (loc->addr, addr, 4);
139 }
140 else
141 {
142 loc->is_ip4 = 0;
143 memcpy (loc->addr, addr, 16);
144 }
145}
146
147static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100148 vl_api_gpe_fwd_entry_path_dump_t_handler
149 (vl_api_gpe_fwd_entry_path_dump_t * mp)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100150{
151 lisp_fwd_path_t *path;
Filip Tehlar82786c42017-02-20 15:20:37 +0100152 vl_api_gpe_fwd_entry_path_details_t *rmp = NULL;
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100153 lisp_gpe_main_t *lgm = &lisp_gpe_main;
154 unix_shared_memory_queue_t *q = NULL;
155 lisp_gpe_fwd_entry_t *lfe;
156
Filip Tehlar82786c42017-02-20 15:20:37 +0100157 gpe_fwd_entry_path_dump_t_net_to_host (mp);
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100158
159 q = vl_api_client_index_to_input_queue (mp->client_index);
160 if (q == 0)
161 return;
162
163 if (pool_is_free_index (lgm->lisp_fwd_entry_pool, mp->fwd_entry_index))
164 return;
165
166 lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, mp->fwd_entry_index);
167
168 if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE == lfe->type)
169 return;
170
171 vec_foreach (path, lfe->paths)
172 {
173 rmp = vl_msg_api_alloc (sizeof (*rmp));
174 memset (rmp, 0, sizeof (*rmp));
175 const lisp_gpe_tunnel_t *lgt;
176
177 rmp->_vl_msg_id =
Filip Tehlar82786c42017-02-20 15:20:37 +0100178 clib_host_to_net_u16 (VL_API_GPE_FWD_ENTRY_PATH_DETAILS);
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100179
180 const lisp_gpe_adjacency_t *ladj =
181 lisp_gpe_adjacency_get (path->lisp_adj);
182 lisp_api_set_locator (&rmp->rmt_loc, &ladj->remote_rloc, path->weight);
183 lgt = lisp_gpe_tunnel_get (ladj->tunnel_index);
184 lisp_api_set_locator (&rmp->lcl_loc, &lgt->key->lcl, path->weight);
185
186 rmp->context = mp->context;
187 vl_msg_api_send_shmem (q, (u8 *) & rmp);
188 }
189}
190
191static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100192gpe_fwd_entries_copy (vl_api_gpe_fwd_entry_t * dst,
193 lisp_api_gpe_fwd_entry_t * src)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100194{
195 lisp_api_gpe_fwd_entry_t *e;
196 u32 i = 0;
197
198 vec_foreach (e, src)
199 {
200 memset (dst, 0, sizeof (*dst));
201 dst[i].dp_table = src->dp_table;
202 dst[i].fwd_entry_index = src->fwd_entry_index;
203 switch (fid_addr_type (&e->leid))
204 {
205 case FID_ADDR_IP_PREF:
206 if (IP4 == ip_prefix_version (&fid_addr_ippref (&e->leid)))
207 {
208 memcpy (&dst[i].leid, &fid_addr_ippref (&e->leid), 4);
209 memcpy (&dst[i].reid, &fid_addr_ippref (&e->reid), 4);
210 dst[i].eid_type = 0;
211 }
212 else
213 {
214 memcpy (&dst[i].leid, &fid_addr_ippref (&e->leid), 16);
215 memcpy (&dst[i].reid, &fid_addr_ippref (&e->reid), 16);
216 dst[i].eid_type = 1;
217 }
218 dst[i].leid_prefix_len = ip_prefix_len (&fid_addr_ippref (&e->leid));
219 dst[i].reid_prefix_len = ip_prefix_len (&fid_addr_ippref (&e->reid));
220 break;
221 case FID_ADDR_MAC:
222 memcpy (&dst[i].leid, fid_addr_mac (&e->leid), 6);
223 memcpy (&dst[i].reid, fid_addr_mac (&e->reid), 6);
224 dst[i].eid_type = 2;
225 break;
226 default:
227 clib_warning ("unknown fid type %d!", fid_addr_type (&e->leid));
228 break;
229 }
230 i++;
231 }
232}
233
234static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100235gpe_fwd_entries_get_t_net_to_host (vl_api_gpe_fwd_entries_get_t * mp)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100236{
237 mp->vni = clib_net_to_host_u32 (mp->vni);
238}
239
240static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100241gpe_entry_t_host_to_net (vl_api_gpe_fwd_entry_t * e)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100242{
243 e->fwd_entry_index = clib_host_to_net_u32 (e->fwd_entry_index);
244 e->dp_table = clib_host_to_net_u32 (e->dp_table);
245}
246
247static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100248 gpe_fwd_entries_get_reply_t_host_to_net
249 (vl_api_gpe_fwd_entries_get_reply_t * mp)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100250{
251 u32 i;
Filip Tehlar82786c42017-02-20 15:20:37 +0100252 vl_api_gpe_fwd_entry_t *e;
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100253
254 for (i = 0; i < mp->count; i++)
255 {
256 e = &mp->entries[i];
Filip Tehlar82786c42017-02-20 15:20:37 +0100257 gpe_entry_t_host_to_net (e);
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100258 }
259 mp->count = clib_host_to_net_u32 (mp->count);
260}
261
262static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100263vl_api_gpe_fwd_entries_get_t_handler (vl_api_gpe_fwd_entries_get_t * mp)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100264{
265 lisp_api_gpe_fwd_entry_t *e;
Filip Tehlar82786c42017-02-20 15:20:37 +0100266 vl_api_gpe_fwd_entries_get_reply_t *rmp = 0;
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100267 u32 size = 0;
268 int rv = 0;
269
Filip Tehlar82786c42017-02-20 15:20:37 +0100270 gpe_fwd_entries_get_t_net_to_host (mp);
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100271
272 e = vnet_lisp_gpe_fwd_entries_get_by_vni (mp->vni);
Filip Tehlar82786c42017-02-20 15:20:37 +0100273 size = vec_len (e) * sizeof (vl_api_gpe_fwd_entry_t);
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100274
275 /* *INDENT-OFF* */
Filip Tehlar82786c42017-02-20 15:20:37 +0100276 REPLY_MACRO4 (VL_API_GPE_FWD_ENTRIES_GET_REPLY, size,
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100277 {
278 rmp->count = vec_len (e);
Filip Tehlar82786c42017-02-20 15:20:37 +0100279 gpe_fwd_entries_copy (rmp->entries, e);
280 gpe_fwd_entries_get_reply_t_host_to_net (rmp);
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100281 });
282 /* *INDENT-ON* */
283
284 vec_free (e);
285}
286
287static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100288gpe_add_del_fwd_entry_t_net_to_host (vl_api_gpe_add_del_fwd_entry_t * mp)
Filip Tehlarc3af7bf2017-01-13 14:13:09 +0100289{
290 mp->vni = clib_net_to_host_u32 (mp->vni);
291 mp->dp_table = clib_net_to_host_u32 (mp->dp_table);
292 mp->loc_num = clib_net_to_host_u32 (mp->loc_num);
293}
294
295static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100296vl_api_gpe_add_del_fwd_entry_t_handler (vl_api_gpe_add_del_fwd_entry_t * mp)
Pavel Kotucekabea9662016-12-21 15:50:08 +0100297{
Filip Tehlar82786c42017-02-20 15:20:37 +0100298 vl_api_gpe_add_del_fwd_entry_reply_t *rmp;
Pavel Kotucekabea9662016-12-21 15:50:08 +0100299 vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
300 locator_pair_t *pairs = 0;
301 int rv = 0;
302
Filip Tehlar82786c42017-02-20 15:20:37 +0100303 gpe_add_del_fwd_entry_t_net_to_host (mp);
Pavel Kotucekabea9662016-12-21 15:50:08 +0100304 memset (a, 0, sizeof (a[0]));
305
306 rv = unformat_lisp_eid_api (&a->rmt_eid, mp->vni, mp->eid_type,
307 mp->rmt_eid, mp->rmt_len);
308 rv |= unformat_lisp_eid_api (&a->lcl_eid, mp->vni, mp->eid_type,
309 mp->lcl_eid, mp->lcl_len);
310
Filip Tehlarc3af7bf2017-01-13 14:13:09 +0100311 if (mp->loc_num % 2 != 0)
312 {
313 rv = -1;
314 goto send_reply;
315 }
Filip Tehlar82786c42017-02-20 15:20:37 +0100316 pairs = unformat_gpe_loc_pairs (mp->locs, mp->loc_num / 2);
Pavel Kotucekabea9662016-12-21 15:50:08 +0100317
318 if (rv || 0 == pairs)
319 goto send_reply;
320
321 a->is_add = mp->is_add;
322 a->locator_pairs = pairs;
323 a->dp_table = mp->dp_table;
324 a->vni = mp->vni;
325 a->action = mp->action;
326
327 rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
328 vec_free (pairs);
329send_reply:
Filip Tehlar82786c42017-02-20 15:20:37 +0100330 REPLY_MACRO (VL_API_GPE_ADD_DEL_FWD_ENTRY_REPLY);
Pavel Kotucekabea9662016-12-21 15:50:08 +0100331}
332
333static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100334vl_api_gpe_enable_disable_t_handler (vl_api_gpe_enable_disable_t * mp)
Pavel Kotucekabea9662016-12-21 15:50:08 +0100335{
Filip Tehlar82786c42017-02-20 15:20:37 +0100336 vl_api_gpe_enable_disable_reply_t *rmp;
Pavel Kotucekabea9662016-12-21 15:50:08 +0100337 int rv = 0;
338 vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a;
339
340 a->is_en = mp->is_en;
341 vnet_lisp_gpe_enable_disable (a);
342
Filip Tehlar82786c42017-02-20 15:20:37 +0100343 REPLY_MACRO (VL_API_GPE_ENABLE_DISABLE_REPLY);
Pavel Kotucekabea9662016-12-21 15:50:08 +0100344}
345
346static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100347vl_api_gpe_add_del_iface_t_handler (vl_api_gpe_add_del_iface_t * mp)
Pavel Kotucekabea9662016-12-21 15:50:08 +0100348{
Filip Tehlar82786c42017-02-20 15:20:37 +0100349 vl_api_gpe_add_del_iface_reply_t *rmp;
Pavel Kotucekabea9662016-12-21 15:50:08 +0100350 int rv = 0;
351
352 if (mp->is_l2)
353 {
354 if (mp->is_add)
355 {
356 if (~0 ==
357 lisp_gpe_tenant_l2_iface_add_or_lock (mp->vni, mp->dp_table))
358 rv = 1;
359 }
360 else
361 lisp_gpe_tenant_l2_iface_unlock (mp->vni);
362 }
363 else
364 {
365 if (mp->is_add)
366 {
367 if (~0 ==
368 lisp_gpe_tenant_l3_iface_add_or_lock (mp->vni, mp->dp_table))
369 rv = 1;
370 }
371 else
372 lisp_gpe_tenant_l3_iface_unlock (mp->vni);
373 }
374
Filip Tehlar82786c42017-02-20 15:20:37 +0100375 REPLY_MACRO (VL_API_GPE_ADD_DEL_IFACE_REPLY);
Pavel Kotucekabea9662016-12-21 15:50:08 +0100376}
377
Filip Tehlar3e7b56932017-02-21 18:28:34 +0100378static void
379vl_api_gpe_set_encap_mode_t_handler (vl_api_gpe_set_encap_mode_t * mp)
380{
381 vl_api_gpe_set_encap_mode_reply_t *rmp;
382 int rv = 0;
383
384 rv = vnet_gpe_set_encap_mode (mp->mode);
385 REPLY_MACRO (VL_API_GPE_SET_ENCAP_MODE_REPLY);
386}
387
388static void
389vl_api_gpe_get_encap_mode_t_handler (vl_api_gpe_get_encap_mode_t * mp)
390{
391 vl_api_gpe_get_encap_mode_reply_t *rmp;
392 int rv = 0;
393
394 /* *INDENT-OFF* */
395 REPLY_MACRO2 (VL_API_GPE_GET_ENCAP_MODE_REPLY,
396 ({
397 rmp->encap_mode = vnet_gpe_get_encap_mode ();
398 }));
399 /* *INDENT-ON* */
400}
401
Pavel Kotucekabea9662016-12-21 15:50:08 +0100402/*
Filip Tehlar82786c42017-02-20 15:20:37 +0100403 * gpe_api_hookup
Pavel Kotucekabea9662016-12-21 15:50:08 +0100404 * Add vpe's API message handlers to the table.
405 * vlib has alread mapped shared memory and
406 * added the client registration handlers.
407 * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
408 */
409#define vl_msg_name_crc_list
410#include <vnet/vnet_all_api_h.h>
411#undef vl_msg_name_crc_list
412
413static void
414setup_message_id_table (api_main_t * am)
415{
416#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
417 foreach_vl_msg_name_crc_lisp_gpe;
418#undef _
419}
420
421static clib_error_t *
Filip Tehlar82786c42017-02-20 15:20:37 +0100422gpe_api_hookup (vlib_main_t * vm)
Pavel Kotucekabea9662016-12-21 15:50:08 +0100423{
424 api_main_t *am = &api_main;
425
426#define _(N,n) \
427 vl_msg_api_set_handlers(VL_API_##N, #n, \
428 vl_api_##n##_t_handler, \
429 vl_noop_handler, \
430 vl_api_##n##_t_endian, \
431 vl_api_##n##_t_print, \
432 sizeof(vl_api_##n##_t), 1);
433 foreach_vpe_api_msg;
434#undef _
435
436 /*
437 * Set up the (msg_name, crc, message-id) table
438 */
439 setup_message_id_table (am);
440
441 return 0;
442}
443
Filip Tehlar82786c42017-02-20 15:20:37 +0100444VLIB_API_INIT_FUNCTION (gpe_api_hookup);
Pavel Kotucekabea9662016-12-21 15:50:08 +0100445
446/*
447 * fd.io coding-style-patch-verification: ON
448 *
449 * Local Variables:
450 * eval: (c-set-style "gnu")
451 * End:
452 */