blob: f026e8b08e8bf677931695149096d1f18af9e724 [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>
Florin Corasa4e63e52017-06-07 21:50:57 -070030#include <vnet/fib/fib_table.h>
Pavel Kotucekabea9662016-12-21 15:50:08 +010031#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
Florin Corasa4e63e52017-06-07 21:50:57 -070054#define foreach_vpe_api_msg \
55_(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) \
59_(GPE_ADD_DEL_IFACE, gpe_add_del_iface) \
60_(GPE_FWD_ENTRY_VNIS_GET, gpe_fwd_entry_vnis_get) \
61_(GPE_SET_ENCAP_MODE, gpe_set_encap_mode) \
62_(GPE_GET_ENCAP_MODE, gpe_get_encap_mode) \
63_(GPE_ADD_DEL_NATIVE_FWD_RPATH, gpe_add_del_native_fwd_rpath) \
64_(GPE_NATIVE_FWD_RPATHS_GET, gpe_native_fwd_rpaths_get)
Pavel Kotucekabea9662016-12-21 15:50:08 +010065
66static locator_pair_t *
Filip Tehlar82786c42017-02-20 15:20:37 +010067unformat_gpe_loc_pairs (void *locs, u32 rloc_num)
Pavel Kotucekabea9662016-12-21 15:50:08 +010068{
69 u32 i;
Filip Tehlarc3af7bf2017-01-13 14:13:09 +010070 locator_pair_t *pairs = 0, pair, *p;
Filip Tehlar82786c42017-02-20 15:20:37 +010071 vl_api_gpe_locator_t *r;
Pavel Kotucekabea9662016-12-21 15:50:08 +010072
73 for (i = 0; i < rloc_num; i++)
74 {
75 /* local locator */
Filip Tehlar82786c42017-02-20 15:20:37 +010076 r = &((vl_api_gpe_locator_t *) locs)[i];
Filip Tehlarc3af7bf2017-01-13 14:13:09 +010077 memset (&pair, 0, sizeof (pair));
Pavel Kotucekabea9662016-12-21 15:50:08 +010078 ip_address_set (&pair.lcl_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
79
Pavel Kotucekabea9662016-12-21 15:50:08 +010080 pair.weight = r->weight;
Pavel Kotucekabea9662016-12-21 15:50:08 +010081 vec_add1 (pairs, pair);
82 }
Filip Tehlarc3af7bf2017-01-13 14:13:09 +010083
84 for (i = rloc_num; i < rloc_num * 2; i++)
85 {
86 /* remote locators */
Filip Tehlar82786c42017-02-20 15:20:37 +010087 r = &((vl_api_gpe_locator_t *) locs)[i];
Filip Tehlarc3af7bf2017-01-13 14:13:09 +010088 p = &pairs[i - rloc_num];
89 ip_address_set (&p->rmt_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
90 }
Pavel Kotucekabea9662016-12-21 15:50:08 +010091 return pairs;
92}
93
94static int
95unformat_lisp_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src,
96 u8 len)
97{
98 switch (type)
99 {
100 case 0: /* ipv4 */
101 gid_address_type (dst) = GID_ADDR_IP_PREFIX;
102 gid_address_ip_set (dst, src, IP4);
103 gid_address_ippref_len (dst) = len;
104 ip_prefix_normalize (&gid_address_ippref (dst));
105 break;
106 case 1: /* ipv6 */
107 gid_address_type (dst) = GID_ADDR_IP_PREFIX;
108 gid_address_ip_set (dst, src, IP6);
109 gid_address_ippref_len (dst) = len;
110 ip_prefix_normalize (&gid_address_ippref (dst));
111 break;
112 case 2: /* l2 mac */
113 gid_address_type (dst) = GID_ADDR_MAC;
114 clib_memcpy (&gid_address_mac (dst), src, 6);
115 break;
116 default:
117 /* unknown type */
118 return VNET_API_ERROR_INVALID_VALUE;
119 }
120
121 gid_address_vni (dst) = vni;
122
123 return 0;
124}
125
126static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100127 gpe_fwd_entry_path_dump_t_net_to_host
128 (vl_api_gpe_fwd_entry_path_dump_t * mp)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100129{
130 mp->fwd_entry_index = clib_net_to_host_u32 (mp->fwd_entry_index);
131}
132
133static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100134lisp_api_set_locator (vl_api_gpe_locator_t * loc,
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100135 const ip_address_t * addr, u8 weight)
136{
137 loc->weight = weight;
138 if (IP4 == ip_addr_version (addr))
139 {
140 loc->is_ip4 = 1;
141 memcpy (loc->addr, addr, 4);
142 }
143 else
144 {
145 loc->is_ip4 = 0;
146 memcpy (loc->addr, addr, 16);
147 }
148}
149
150static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100151 vl_api_gpe_fwd_entry_path_dump_t_handler
152 (vl_api_gpe_fwd_entry_path_dump_t * mp)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100153{
154 lisp_fwd_path_t *path;
Filip Tehlar82786c42017-02-20 15:20:37 +0100155 vl_api_gpe_fwd_entry_path_details_t *rmp = NULL;
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100156 lisp_gpe_main_t *lgm = &lisp_gpe_main;
157 unix_shared_memory_queue_t *q = NULL;
158 lisp_gpe_fwd_entry_t *lfe;
159
Filip Tehlar82786c42017-02-20 15:20:37 +0100160 gpe_fwd_entry_path_dump_t_net_to_host (mp);
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100161
162 q = vl_api_client_index_to_input_queue (mp->client_index);
163 if (q == 0)
164 return;
165
166 if (pool_is_free_index (lgm->lisp_fwd_entry_pool, mp->fwd_entry_index))
167 return;
168
169 lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, mp->fwd_entry_index);
170
171 if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE == lfe->type)
172 return;
173
174 vec_foreach (path, lfe->paths)
175 {
176 rmp = vl_msg_api_alloc (sizeof (*rmp));
177 memset (rmp, 0, sizeof (*rmp));
178 const lisp_gpe_tunnel_t *lgt;
179
180 rmp->_vl_msg_id =
Filip Tehlar82786c42017-02-20 15:20:37 +0100181 clib_host_to_net_u16 (VL_API_GPE_FWD_ENTRY_PATH_DETAILS);
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100182
183 const lisp_gpe_adjacency_t *ladj =
184 lisp_gpe_adjacency_get (path->lisp_adj);
185 lisp_api_set_locator (&rmp->rmt_loc, &ladj->remote_rloc, path->weight);
186 lgt = lisp_gpe_tunnel_get (ladj->tunnel_index);
187 lisp_api_set_locator (&rmp->lcl_loc, &lgt->key->lcl, path->weight);
188
189 rmp->context = mp->context;
190 vl_msg_api_send_shmem (q, (u8 *) & rmp);
191 }
192}
193
194static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100195gpe_fwd_entries_copy (vl_api_gpe_fwd_entry_t * dst,
196 lisp_api_gpe_fwd_entry_t * src)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100197{
198 lisp_api_gpe_fwd_entry_t *e;
199 u32 i = 0;
200
201 vec_foreach (e, src)
202 {
Filip Tehlar719aef42017-06-05 09:50:38 +0200203 memset (&dst[i], 0, sizeof (*dst));
204 dst[i].dp_table = e->dp_table;
205 dst[i].fwd_entry_index = e->fwd_entry_index;
206 dst[i].vni = e->vni;
207 dst[i].action = e->action;
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100208 switch (fid_addr_type (&e->leid))
209 {
210 case FID_ADDR_IP_PREF:
211 if (IP4 == ip_prefix_version (&fid_addr_ippref (&e->leid)))
212 {
213 memcpy (&dst[i].leid, &fid_addr_ippref (&e->leid), 4);
214 memcpy (&dst[i].reid, &fid_addr_ippref (&e->reid), 4);
215 dst[i].eid_type = 0;
216 }
217 else
218 {
219 memcpy (&dst[i].leid, &fid_addr_ippref (&e->leid), 16);
220 memcpy (&dst[i].reid, &fid_addr_ippref (&e->reid), 16);
221 dst[i].eid_type = 1;
222 }
223 dst[i].leid_prefix_len = ip_prefix_len (&fid_addr_ippref (&e->leid));
224 dst[i].reid_prefix_len = ip_prefix_len (&fid_addr_ippref (&e->reid));
225 break;
226 case FID_ADDR_MAC:
227 memcpy (&dst[i].leid, fid_addr_mac (&e->leid), 6);
228 memcpy (&dst[i].reid, fid_addr_mac (&e->reid), 6);
229 dst[i].eid_type = 2;
230 break;
231 default:
232 clib_warning ("unknown fid type %d!", fid_addr_type (&e->leid));
233 break;
234 }
235 i++;
236 }
237}
238
239static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100240gpe_fwd_entries_get_t_net_to_host (vl_api_gpe_fwd_entries_get_t * mp)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100241{
242 mp->vni = clib_net_to_host_u32 (mp->vni);
243}
244
245static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100246gpe_entry_t_host_to_net (vl_api_gpe_fwd_entry_t * e)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100247{
248 e->fwd_entry_index = clib_host_to_net_u32 (e->fwd_entry_index);
249 e->dp_table = clib_host_to_net_u32 (e->dp_table);
Filip Tehlar0eb874e2017-05-18 14:23:32 +0200250 e->vni = clib_host_to_net_u32 (e->vni);
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100251}
252
253static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100254 gpe_fwd_entries_get_reply_t_host_to_net
255 (vl_api_gpe_fwd_entries_get_reply_t * mp)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100256{
257 u32 i;
Filip Tehlar82786c42017-02-20 15:20:37 +0100258 vl_api_gpe_fwd_entry_t *e;
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100259
260 for (i = 0; i < mp->count; i++)
261 {
262 e = &mp->entries[i];
Filip Tehlar82786c42017-02-20 15:20:37 +0100263 gpe_entry_t_host_to_net (e);
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100264 }
265 mp->count = clib_host_to_net_u32 (mp->count);
266}
267
268static void
Filip Tehlar0eb874e2017-05-18 14:23:32 +0200269vl_api_gpe_fwd_entry_vnis_get_t_handler (vl_api_gpe_fwd_entry_vnis_get_t * mp)
270{
271 vl_api_gpe_fwd_entry_vnis_get_reply_t *rmp = 0;
272 hash_pair_t *p;
273 u32 i = 0;
274 int rv = 0;
275
276 u32 *vnis = vnet_lisp_gpe_get_fwd_entry_vnis ();
277 u32 size = hash_elts (vnis) * sizeof (u32);
278
279 /* *INDENT-OFF* */
280 REPLY_MACRO4 (VL_API_GPE_FWD_ENTRY_VNIS_GET_REPLY, size,
281 {
282 rmp->count = clib_host_to_net_u32 (hash_elts (vnis));
283 hash_foreach_pair (p, vnis,
284 ({
285 rmp->vnis[i++] = clib_host_to_net_u32 (p->key);
286 }));
287 });
288 /* *INDENT-ON* */
289
290 hash_free (vnis);
291}
292
293static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100294vl_api_gpe_fwd_entries_get_t_handler (vl_api_gpe_fwd_entries_get_t * mp)
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100295{
296 lisp_api_gpe_fwd_entry_t *e;
Filip Tehlar82786c42017-02-20 15:20:37 +0100297 vl_api_gpe_fwd_entries_get_reply_t *rmp = 0;
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100298 u32 size = 0;
299 int rv = 0;
300
Filip Tehlar82786c42017-02-20 15:20:37 +0100301 gpe_fwd_entries_get_t_net_to_host (mp);
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100302
303 e = vnet_lisp_gpe_fwd_entries_get_by_vni (mp->vni);
Filip Tehlar82786c42017-02-20 15:20:37 +0100304 size = vec_len (e) * sizeof (vl_api_gpe_fwd_entry_t);
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100305
306 /* *INDENT-OFF* */
Filip Tehlar82786c42017-02-20 15:20:37 +0100307 REPLY_MACRO4 (VL_API_GPE_FWD_ENTRIES_GET_REPLY, size,
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100308 {
309 rmp->count = vec_len (e);
Filip Tehlar82786c42017-02-20 15:20:37 +0100310 gpe_fwd_entries_copy (rmp->entries, e);
311 gpe_fwd_entries_get_reply_t_host_to_net (rmp);
Filip Tehlar5fae99c2017-01-18 12:57:37 +0100312 });
313 /* *INDENT-ON* */
314
315 vec_free (e);
316}
317
318static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100319gpe_add_del_fwd_entry_t_net_to_host (vl_api_gpe_add_del_fwd_entry_t * mp)
Filip Tehlarc3af7bf2017-01-13 14:13:09 +0100320{
321 mp->vni = clib_net_to_host_u32 (mp->vni);
322 mp->dp_table = clib_net_to_host_u32 (mp->dp_table);
323 mp->loc_num = clib_net_to_host_u32 (mp->loc_num);
324}
325
326static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100327vl_api_gpe_add_del_fwd_entry_t_handler (vl_api_gpe_add_del_fwd_entry_t * mp)
Pavel Kotucekabea9662016-12-21 15:50:08 +0100328{
Filip Tehlar82786c42017-02-20 15:20:37 +0100329 vl_api_gpe_add_del_fwd_entry_reply_t *rmp;
Pavel Kotucekabea9662016-12-21 15:50:08 +0100330 vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
331 locator_pair_t *pairs = 0;
332 int rv = 0;
333
Filip Tehlar82786c42017-02-20 15:20:37 +0100334 gpe_add_del_fwd_entry_t_net_to_host (mp);
Pavel Kotucekabea9662016-12-21 15:50:08 +0100335 memset (a, 0, sizeof (a[0]));
336
337 rv = unformat_lisp_eid_api (&a->rmt_eid, mp->vni, mp->eid_type,
338 mp->rmt_eid, mp->rmt_len);
339 rv |= unformat_lisp_eid_api (&a->lcl_eid, mp->vni, mp->eid_type,
340 mp->lcl_eid, mp->lcl_len);
341
Filip Tehlarc3af7bf2017-01-13 14:13:09 +0100342 if (mp->loc_num % 2 != 0)
343 {
344 rv = -1;
345 goto send_reply;
346 }
Filip Tehlar82786c42017-02-20 15:20:37 +0100347 pairs = unformat_gpe_loc_pairs (mp->locs, mp->loc_num / 2);
Pavel Kotucekabea9662016-12-21 15:50:08 +0100348
Filip Tehlar0eb874e2017-05-18 14:23:32 +0200349 if (rv)
Pavel Kotucekabea9662016-12-21 15:50:08 +0100350 goto send_reply;
351
352 a->is_add = mp->is_add;
353 a->locator_pairs = pairs;
354 a->dp_table = mp->dp_table;
355 a->vni = mp->vni;
356 a->action = mp->action;
Filip Tehlar0eb874e2017-05-18 14:23:32 +0200357 if (mp->loc_num == 0)
358 a->is_negative = 1;
Pavel Kotucekabea9662016-12-21 15:50:08 +0100359
360 rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
361 vec_free (pairs);
362send_reply:
Filip Tehlar560274d2017-06-05 13:40:13 +0200363 /* *INDENT-OFF* */
364 REPLY_MACRO2 (VL_API_GPE_ADD_DEL_FWD_ENTRY_REPLY,
365 {
366 rmp->fwd_entry_index = clib_host_to_net_u32 (a->fwd_entry_index);
367 });
368 /* *INDENT-ON* */
Pavel Kotucekabea9662016-12-21 15:50:08 +0100369}
370
371static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100372vl_api_gpe_enable_disable_t_handler (vl_api_gpe_enable_disable_t * mp)
Pavel Kotucekabea9662016-12-21 15:50:08 +0100373{
Filip Tehlar82786c42017-02-20 15:20:37 +0100374 vl_api_gpe_enable_disable_reply_t *rmp;
Pavel Kotucekabea9662016-12-21 15:50:08 +0100375 int rv = 0;
376 vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a;
377
378 a->is_en = mp->is_en;
379 vnet_lisp_gpe_enable_disable (a);
380
Filip Tehlar82786c42017-02-20 15:20:37 +0100381 REPLY_MACRO (VL_API_GPE_ENABLE_DISABLE_REPLY);
Pavel Kotucekabea9662016-12-21 15:50:08 +0100382}
383
384static void
Filip Tehlar82786c42017-02-20 15:20:37 +0100385vl_api_gpe_add_del_iface_t_handler (vl_api_gpe_add_del_iface_t * mp)
Pavel Kotucekabea9662016-12-21 15:50:08 +0100386{
Filip Tehlar82786c42017-02-20 15:20:37 +0100387 vl_api_gpe_add_del_iface_reply_t *rmp;
Pavel Kotucekabea9662016-12-21 15:50:08 +0100388 int rv = 0;
389
390 if (mp->is_l2)
391 {
392 if (mp->is_add)
393 {
394 if (~0 ==
395 lisp_gpe_tenant_l2_iface_add_or_lock (mp->vni, mp->dp_table))
396 rv = 1;
397 }
398 else
399 lisp_gpe_tenant_l2_iface_unlock (mp->vni);
400 }
401 else
402 {
403 if (mp->is_add)
404 {
405 if (~0 ==
406 lisp_gpe_tenant_l3_iface_add_or_lock (mp->vni, mp->dp_table))
407 rv = 1;
408 }
409 else
410 lisp_gpe_tenant_l3_iface_unlock (mp->vni);
411 }
412
Filip Tehlar82786c42017-02-20 15:20:37 +0100413 REPLY_MACRO (VL_API_GPE_ADD_DEL_IFACE_REPLY);
Pavel Kotucekabea9662016-12-21 15:50:08 +0100414}
415
Filip Tehlar3e7b56932017-02-21 18:28:34 +0100416static void
417vl_api_gpe_set_encap_mode_t_handler (vl_api_gpe_set_encap_mode_t * mp)
418{
419 vl_api_gpe_set_encap_mode_reply_t *rmp;
420 int rv = 0;
421
422 rv = vnet_gpe_set_encap_mode (mp->mode);
423 REPLY_MACRO (VL_API_GPE_SET_ENCAP_MODE_REPLY);
424}
425
426static void
427vl_api_gpe_get_encap_mode_t_handler (vl_api_gpe_get_encap_mode_t * mp)
428{
429 vl_api_gpe_get_encap_mode_reply_t *rmp;
430 int rv = 0;
431
432 /* *INDENT-OFF* */
433 REPLY_MACRO2 (VL_API_GPE_GET_ENCAP_MODE_REPLY,
434 ({
435 rmp->encap_mode = vnet_gpe_get_encap_mode ();
436 }));
437 /* *INDENT-ON* */
438}
439
Florin Corasa4e63e52017-06-07 21:50:57 -0700440static void
441 vl_api_gpe_add_del_native_fwd_rpath_t_handler
442 (vl_api_gpe_add_del_native_fwd_rpath_t * mp)
443{
Filip Tehlarb4243aa2017-06-14 14:39:42 +0200444 vl_api_gpe_add_del_native_fwd_rpath_reply_t *rmp;
Florin Corasa4e63e52017-06-07 21:50:57 -0700445 vnet_gpe_native_fwd_rpath_args_t _a, *a = &_a;
446 int rv = 0;
447
448 memset (a, 0, sizeof (a[0]));
449
450 if (mp->is_ip4)
Filip Tehlarb4243aa2017-06-14 14:39:42 +0200451 clib_memcpy (&a->rpath.frp_addr.ip4, mp->nh_addr, sizeof (ip4_address_t));
Florin Corasa4e63e52017-06-07 21:50:57 -0700452 else
Filip Tehlarb4243aa2017-06-14 14:39:42 +0200453 clib_memcpy (&a->rpath.frp_addr.ip6, mp->nh_addr, sizeof (ip6_address_t));
Florin Corasa4e63e52017-06-07 21:50:57 -0700454
455 a->is_add = mp->is_add;
456 a->rpath.frp_proto = mp->is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
457 a->rpath.frp_fib_index = fib_table_find (a->rpath.frp_proto,
458 clib_net_to_host_u32
459 (mp->table_id));
Filip Tehlarb4243aa2017-06-14 14:39:42 +0200460 if (~0 == a->rpath.frp_fib_index)
461 {
462 rv = VNET_API_ERROR_INVALID_VALUE;
463 goto done;
464 }
465
Florin Corasa4e63e52017-06-07 21:50:57 -0700466 a->rpath.frp_sw_if_index = clib_net_to_host_u32 (mp->nh_sw_if_index);
467 a->rpath.frp_weight = 1;
468
469 rv = vnet_gpe_add_del_native_fwd_rpath (a);
Filip Tehlarb4243aa2017-06-14 14:39:42 +0200470done:
Florin Corasa4e63e52017-06-07 21:50:57 -0700471 REPLY_MACRO (VL_API_GPE_ADD_DEL_NATIVE_FWD_RPATH_REPLY);
472}
473
474static void
475gpe_native_fwd_rpaths_copy (vl_api_gpe_native_fwd_rpath_t * dst,
Florin Coras27b390e2017-06-09 10:22:22 -0700476 fib_route_path_t * src, u8 is_ip4)
Florin Corasa4e63e52017-06-07 21:50:57 -0700477{
478 fib_route_path_t *e;
479 u32 i = 0;
480
481 vec_foreach (e, src)
482 {
483 memset (&dst[i], 0, sizeof (*dst));
Florin Coras27b390e2017-06-09 10:22:22 -0700484 dst[i].fib_index = e->frp_fib_index;
485 dst[i].nh_sw_if_index = e->frp_sw_if_index;
486 dst[i].is_ip4 = is_ip4;
Filip Tehlarb4243aa2017-06-14 14:39:42 +0200487 if (is_ip4)
488 clib_memcpy (&dst[i].nh_addr, &e->frp_addr.ip4, sizeof (ip4_address_t));
489 else
490 clib_memcpy (&dst[i].nh_addr, &e->frp_addr.ip6, sizeof (ip6_address_t));
491 i++;
Florin Corasa4e63e52017-06-07 21:50:57 -0700492 }
493}
494
495static void
496gpe_native_fwd_rpath_t_host_to_net (vl_api_gpe_native_fwd_rpath_t * e)
497{
498 e->fib_index = clib_host_to_net_u32 (e->fib_index);
499 e->nh_sw_if_index = clib_host_to_net_u32 (e->nh_sw_if_index);
500}
501
502static void
503 gpe_native_fwd_rpaths_get_reply_t_host_to_net
504 (vl_api_gpe_native_fwd_rpaths_get_reply_t * mp)
505{
506 u32 i;
507 vl_api_gpe_native_fwd_rpath_t *e;
508
509 for (i = 0; i < mp->count; i++)
510 {
511 e = &mp->entries[i];
512 gpe_native_fwd_rpath_t_host_to_net (e);
513 }
514 mp->count = clib_host_to_net_u32 (mp->count);
515}
516
517static void
518vl_api_gpe_native_fwd_rpaths_get_t_handler (vl_api_gpe_native_fwd_rpaths_get_t
519 * mp)
520{
521 lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
522 vl_api_gpe_native_fwd_rpaths_get_reply_t *rmp;
523 u32 size = 0;
524 int rv = 0;
525
Filip Tehlarb4243aa2017-06-14 14:39:42 +0200526 u8 rpath_index = mp->is_ip4 ? 0 : 1;
527
528 size = vec_len (lgm->native_fwd_rpath[rpath_index])
Florin Corasa4e63e52017-06-07 21:50:57 -0700529 * sizeof (vl_api_gpe_native_fwd_rpath_t);
530
531 /* *INDENT-OFF* */
532 REPLY_MACRO4 (VL_API_GPE_NATIVE_FWD_RPATHS_GET_REPLY, size,
533 {
Filip Tehlarb4243aa2017-06-14 14:39:42 +0200534 rmp->count = vec_len (lgm->native_fwd_rpath[rpath_index]);
Florin Corasa4e63e52017-06-07 21:50:57 -0700535 gpe_native_fwd_rpaths_copy (rmp->entries,
Filip Tehlarb4243aa2017-06-14 14:39:42 +0200536 lgm->native_fwd_rpath[rpath_index],
Florin Coras27b390e2017-06-09 10:22:22 -0700537 mp->is_ip4);
Florin Corasa4e63e52017-06-07 21:50:57 -0700538 gpe_native_fwd_rpaths_get_reply_t_host_to_net (rmp);
539 });
540 /* *INDENT-ON* */
541}
542
Pavel Kotucekabea9662016-12-21 15:50:08 +0100543/*
Filip Tehlar82786c42017-02-20 15:20:37 +0100544 * gpe_api_hookup
Pavel Kotucekabea9662016-12-21 15:50:08 +0100545 * Add vpe's API message handlers to the table.
546 * vlib has alread mapped shared memory and
547 * added the client registration handlers.
548 * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
549 */
550#define vl_msg_name_crc_list
551#include <vnet/vnet_all_api_h.h>
552#undef vl_msg_name_crc_list
553
554static void
555setup_message_id_table (api_main_t * am)
556{
557#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
558 foreach_vl_msg_name_crc_lisp_gpe;
559#undef _
560}
561
562static clib_error_t *
Filip Tehlar82786c42017-02-20 15:20:37 +0100563gpe_api_hookup (vlib_main_t * vm)
Pavel Kotucekabea9662016-12-21 15:50:08 +0100564{
565 api_main_t *am = &api_main;
566
567#define _(N,n) \
568 vl_msg_api_set_handlers(VL_API_##N, #n, \
569 vl_api_##n##_t_handler, \
570 vl_noop_handler, \
571 vl_api_##n##_t_endian, \
572 vl_api_##n##_t_print, \
573 sizeof(vl_api_##n##_t), 1);
574 foreach_vpe_api_msg;
575#undef _
576
577 /*
578 * Set up the (msg_name, crc, message-id) table
579 */
580 setup_message_id_table (am);
581
582 return 0;
583}
584
Filip Tehlar82786c42017-02-20 15:20:37 +0100585VLIB_API_INIT_FUNCTION (gpe_api_hookup);
Pavel Kotucekabea9662016-12-21 15:50:08 +0100586
587/*
588 * fd.io coding-style-patch-verification: ON
589 *
590 * Local Variables:
591 * eval: (c-set-style "gnu")
592 * End:
593 */