api: refactor vlibmemory
[vpp.git] / src / plugins / ioam / lib-vxlan-gpe / vxlan_gpe_api.c
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  *------------------------------------------------------------------
17  * vxlan_gpe_api.c - iOAM VxLAN-GPE related APIs to create
18  *               and maintain profiles
19  *------------------------------------------------------------------
20  */
21
22 #include <vnet/vnet.h>
23 #include <vnet/plugin/plugin.h>
24 #include <ioam/lib-vxlan-gpe/vxlan_gpe_ioam.h>
25
26 #include <vlibapi/api.h>
27 #include <vlibmemory/api.h>
28
29
30 /* define message IDs */
31 #include <ioam/lib-vxlan-gpe/vxlan_gpe_msg_enum.h>
32
33 /* define message structures */
34 #define vl_typedefs
35 #include <ioam/lib-vxlan-gpe/vxlan_gpe_all_api_h.h>
36 #undef vl_typedefs
37
38 /* define generated endian-swappers */
39 #define vl_endianfun
40 #include <ioam/lib-vxlan-gpe/vxlan_gpe_all_api_h.h>
41 #undef vl_endianfun
42
43 /* instantiate all the print functions we know about */
44 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
45 #define vl_printfun
46 #include <ioam/lib-vxlan-gpe/vxlan_gpe_all_api_h.h>
47 #undef vl_printfun
48
49 /* Get the API version number */
50 #define vl_api_version(n,v) static u32 api_version=(v);
51 #include <ioam/lib-vxlan-gpe/vxlan_gpe_all_api_h.h>
52 #undef vl_api_version
53
54 /*
55  * A handy macro to set up a message reply.
56  * Assumes that the following variables are available:
57  * mp - pointer to request message
58  * rmp - pointer to reply message type
59  * rv - return value
60  */
61
62 #define VXLAN_GPE_REPLY_MACRO(t)                                \
63 do {                                                            \
64     svm_queue_t * q =                            \
65     vl_api_client_index_to_input_queue (mp->client_index);      \
66     if (!q)                                                     \
67         return;                                                 \
68                                                                 \
69     rmp = vl_msg_api_alloc (sizeof (*rmp));                     \
70     rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base);               \
71     rmp->context = mp->context;                                 \
72     rmp->retval = ntohl(rv);                                    \
73                                                                 \
74     vl_msg_api_send_shmem (q, (u8 *)&rmp);                      \
75 } while(0);
76
77 /* *INDENT-OFF* */
78 #define VXLAN_GPE_REPLY_MACRO2(t, body)                         \
79 do {                                                            \
80     svm_queue_t * q;                             \
81     rv = vl_msg_api_pd_handler (mp, rv);                        \
82     q = vl_api_client_index_to_input_queue (mp->client_index);  \
83     if (!q)                                                     \
84         return;                                                 \
85                                                                 \
86     rmp = vl_msg_api_alloc (sizeof (*rmp));                     \
87     rmp->_vl_msg_id = ntohs((t));                               \
88     rmp->context = mp->context;                                 \
89     rmp->retval = ntohl(rv);                                    \
90     do {body;} while (0);                                       \
91     vl_msg_api_send_shmem (q, (u8 *)&rmp);                      \
92 } while(0);
93 /* *INDENT-ON* */
94
95 /* List of message types that this plugin understands */
96
97 #define foreach_vxlan_gpe_plugin_api_msg                               \
98 _(VXLAN_GPE_IOAM_ENABLE, vxlan_gpe_ioam_enable)                        \
99 _(VXLAN_GPE_IOAM_DISABLE, vxlan_gpe_ioam_disable)                      \
100 _(VXLAN_GPE_IOAM_VNI_ENABLE, vxlan_gpe_ioam_vni_enable)                \
101 _(VXLAN_GPE_IOAM_VNI_DISABLE, vxlan_gpe_ioam_vni_disable)              \
102 _(VXLAN_GPE_IOAM_TRANSIT_ENABLE, vxlan_gpe_ioam_transit_enable)        \
103 _(VXLAN_GPE_IOAM_TRANSIT_DISABLE, vxlan_gpe_ioam_transit_disable)      \
104
105
106 static void vl_api_vxlan_gpe_ioam_enable_t_handler
107   (vl_api_vxlan_gpe_ioam_enable_t * mp)
108 {
109   int rv = 0;
110   vl_api_vxlan_gpe_ioam_enable_reply_t *rmp;
111   clib_error_t *error;
112   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
113
114   /* Ignoring the profile id as currently a single profile
115    * is supported */
116   error =
117     vxlan_gpe_ioam_enable (mp->trace_enable, mp->pow_enable, mp->trace_ppc);
118   if (error)
119     {
120       clib_error_report (error);
121       rv = clib_error_get_code (error);
122     }
123
124   VXLAN_GPE_REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_ENABLE_REPLY);
125 }
126
127 static void vl_api_vxlan_gpe_ioam_disable_t_handler
128   (vl_api_vxlan_gpe_ioam_disable_t * mp)
129 {
130   int rv = 0;
131   vl_api_vxlan_gpe_ioam_disable_reply_t *rmp;
132   clib_error_t *error;
133   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
134
135   /* Ignoring the profile id as currently a single profile
136    * is supported */
137   error = vxlan_gpe_ioam_disable (0, 0, 0);
138   if (error)
139     {
140       clib_error_report (error);
141       rv = clib_error_get_code (error);
142     }
143
144   VXLAN_GPE_REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_DISABLE_REPLY);
145 }
146
147 static void vl_api_vxlan_gpe_ioam_vni_enable_t_handler
148   (vl_api_vxlan_gpe_ioam_vni_enable_t * mp)
149 {
150   int rv = 0;
151   vl_api_vxlan_gpe_ioam_vni_enable_reply_t *rmp;
152   clib_error_t *error;
153   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
154   vxlan4_gpe_tunnel_key_t key4;
155   uword *p = NULL;
156   vxlan_gpe_main_t *gm = &vxlan_gpe_main;
157   vxlan_gpe_tunnel_t *t = 0;
158   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
159   u32 vni;
160
161
162   if (!mp->is_ipv6)
163     {
164       clib_memcpy (&key4.local, &mp->local, sizeof (key4.local));
165       clib_memcpy (&key4.remote, &mp->remote, sizeof (key4.remote));
166       vni = clib_net_to_host_u32 (mp->vni);
167       key4.vni = clib_host_to_net_u32 (vni << 8);
168       key4.pad = 0;
169
170       p = hash_get_mem (gm->vxlan4_gpe_tunnel_by_key, &key4);
171     }
172   else
173     {
174       return;
175     }
176
177   if (!p)
178     return;
179
180   t = pool_elt_at_index (gm->tunnels, p[0]);
181
182   error = vxlan_gpe_ioam_set (t, hm->has_trace_option,
183                               hm->has_pot_option,
184                               hm->has_ppc_option, mp->is_ipv6);
185
186
187   if (error)
188     {
189       clib_error_report (error);
190       rv = clib_error_get_code (error);
191     }
192
193   VXLAN_GPE_REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_VNI_ENABLE_REPLY);
194 }
195
196
197 static void vl_api_vxlan_gpe_ioam_vni_disable_t_handler
198   (vl_api_vxlan_gpe_ioam_vni_disable_t * mp)
199 {
200   int rv = 0;
201   vl_api_vxlan_gpe_ioam_vni_enable_reply_t *rmp;
202   clib_error_t *error;
203   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
204   vxlan4_gpe_tunnel_key_t key4;
205   uword *p = NULL;
206   vxlan_gpe_main_t *gm = &vxlan_gpe_main;
207   vxlan_gpe_tunnel_t *t = 0;
208   u32 vni;
209
210
211   if (!mp->is_ipv6)
212     {
213       clib_memcpy (&key4.local, &mp->local, sizeof (key4.local));
214       clib_memcpy (&key4.remote, &mp->remote, sizeof (key4.remote));
215       vni = clib_net_to_host_u32 (mp->vni);
216       key4.vni = clib_host_to_net_u32 (vni << 8);
217       key4.pad = 0;
218
219       p = hash_get_mem (gm->vxlan4_gpe_tunnel_by_key, &key4);
220     }
221   else
222     {
223       return;
224     }
225
226   if (!p)
227     return;
228
229   t = pool_elt_at_index (gm->tunnels, p[0]);
230
231   error = vxlan_gpe_ioam_clear (t, 0, 0, 0, 0);
232
233
234   if (error)
235     {
236       clib_error_report (error);
237       rv = clib_error_get_code (error);
238     }
239
240
241   VXLAN_GPE_REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_VNI_DISABLE_REPLY);
242 }
243
244 static void vl_api_vxlan_gpe_ioam_transit_enable_t_handler
245   (vl_api_vxlan_gpe_ioam_transit_enable_t * mp)
246 {
247   int rv = 0;
248   vl_api_vxlan_gpe_ioam_transit_enable_reply_t *rmp;
249   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
250   ip46_address_t dst_addr;
251
252   memset (&dst_addr.ip4, 0, sizeof (dst_addr.ip4));
253   if (!mp->is_ipv6)
254     {
255       clib_memcpy (&dst_addr.ip4, &mp->dst_addr, sizeof (dst_addr.ip4));
256     }
257   rv = vxlan_gpe_enable_disable_ioam_for_dest (sm->vlib_main,
258                                                dst_addr,
259                                                ntohl (mp->outer_fib_index),
260                                                mp->is_ipv6 ? 0 : 1,
261                                                1 /* is_add */ );
262
263   VXLAN_GPE_REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_TRANSIT_ENABLE_REPLY);
264 }
265
266 static void vl_api_vxlan_gpe_ioam_transit_disable_t_handler
267   (vl_api_vxlan_gpe_ioam_transit_disable_t * mp)
268 {
269   int rv = 0;
270   vl_api_vxlan_gpe_ioam_transit_disable_reply_t *rmp;
271   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
272   ip46_address_t dst_addr;
273
274   memset (&dst_addr.ip4, 0, sizeof (dst_addr.ip4));
275   if (!mp->is_ipv6)
276     {
277       clib_memcpy (&dst_addr.ip4, &mp->dst_addr, sizeof (dst_addr.ip4));
278     }
279
280   rv = vxlan_gpe_ioam_disable_for_dest (sm->vlib_main,
281                                         dst_addr,
282                                         ntohl (mp->outer_fib_index),
283                                         mp->is_ipv6 ? 0 : 1);
284   VXLAN_GPE_REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_TRANSIT_DISABLE_REPLY);
285 }
286
287 /* Set up the API message handling tables */
288 static clib_error_t *
289 vxlan_gpe_plugin_api_hookup (vlib_main_t * vm)
290 {
291   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
292 #define _(N,n)                                                  \
293     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
294                            #n,                                  \
295                            vl_api_##n##_t_handler,              \
296                            vl_noop_handler,                     \
297                            vl_api_##n##_t_endian,               \
298                            vl_api_##n##_t_print,                \
299                            sizeof(vl_api_##n##_t), 1);
300   foreach_vxlan_gpe_plugin_api_msg;
301 #undef _
302
303   return 0;
304 }
305
306 #define vl_msg_name_crc_list
307 #include <ioam/lib-vxlan-gpe/vxlan_gpe_all_api_h.h>
308 #undef vl_msg_name_crc_list
309
310 static void
311 setup_message_id_table (vxlan_gpe_ioam_main_t * sm, api_main_t * am)
312 {
313 #define _(id,n,crc) \
314   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
315   foreach_vl_msg_name_crc_ioam_vxlan_gpe;
316 #undef _
317 }
318
319 static clib_error_t *
320 vxlan_gpe_init (vlib_main_t * vm)
321 {
322   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
323   clib_error_t *error = 0;
324   u8 *name;
325   u32 encap_node_index = vxlan_gpe_encap_ioam_v4_node.index;
326   u32 decap_node_index = vxlan_gpe_decap_ioam_v4_node.index;
327   vlib_node_t *vxlan_gpe_encap_node = NULL;
328   vlib_node_t *vxlan_gpe_decap_node = NULL;
329   uword next_node = 0;
330
331   sm->vlib_main = vm;
332   sm->vnet_main = vnet_get_main ();
333   sm->unix_time_0 = (u32) time (0);     /* Store starting time */
334   sm->vlib_time_0 = vlib_time_now (vm);
335
336   name = format (0, "ioam_vxlan_gpe_%08x%c", api_version, 0);
337
338   /* Ask for a correctly-sized block of API message decode slots */
339   sm->msg_id_base = vl_msg_api_get_msg_ids
340     ((char *) name, VL_MSG_FIRST_AVAILABLE);
341
342   error = vxlan_gpe_plugin_api_hookup (vm);
343
344   /* Add our API messages to the global name_crc hash table */
345   setup_message_id_table (sm, &api_main);
346
347   /* Hook the ioam-encap node to vxlan-gpe-encap */
348   vxlan_gpe_encap_node = vlib_get_node_by_name (vm, (u8 *) "vxlan-gpe-encap");
349   sm->encap_v4_next_node =
350     vlib_node_add_next (vm, vxlan_gpe_encap_node->index, encap_node_index);
351
352   vxlan_gpe_decap_node =
353     vlib_get_node_by_name (vm, (u8 *) "vxlan4-gpe-input");
354   next_node =
355     vlib_node_add_next (vm, vxlan_gpe_decap_node->index, decap_node_index);
356   vxlan_gpe_register_decap_protocol (VXLAN_GPE_PROTOCOL_IOAM, next_node);
357
358   vec_new (vxlan_gpe_ioam_sw_interface_t, pool_elts (sm->sw_interfaces));
359   sm->dst_by_ip4 = hash_create_mem (0, sizeof (fib_prefix_t), sizeof (uword));
360
361   sm->dst_by_ip6 = hash_create_mem (0, sizeof (fib_prefix_t), sizeof (uword));
362
363   vxlan_gpe_ioam_interface_init ();
364   vec_free (name);
365
366   return error;
367 }
368
369 VLIB_INIT_FUNCTION (vxlan_gpe_init);
370
371 /*
372  * fd.io coding-style-patch-verification: ON
373  *
374  * Local Variables:
375  * eval: (c-set-style "gnu")
376  * End:
377  */