API: Fix shared memory only action handlers.
[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 #include <vlibapi/api_helper_macros.h>
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 /* List of message types that this plugin understands */
55
56 #define foreach_vxlan_gpe_plugin_api_msg                               \
57 _(VXLAN_GPE_IOAM_ENABLE, vxlan_gpe_ioam_enable)                        \
58 _(VXLAN_GPE_IOAM_DISABLE, vxlan_gpe_ioam_disable)                      \
59 _(VXLAN_GPE_IOAM_VNI_ENABLE, vxlan_gpe_ioam_vni_enable)                \
60 _(VXLAN_GPE_IOAM_VNI_DISABLE, vxlan_gpe_ioam_vni_disable)              \
61 _(VXLAN_GPE_IOAM_TRANSIT_ENABLE, vxlan_gpe_ioam_transit_enable)        \
62 _(VXLAN_GPE_IOAM_TRANSIT_DISABLE, vxlan_gpe_ioam_transit_disable)      \
63
64
65 static void vl_api_vxlan_gpe_ioam_enable_t_handler
66   (vl_api_vxlan_gpe_ioam_enable_t * mp)
67 {
68   int rv = 0;
69   vl_api_vxlan_gpe_ioam_enable_reply_t *rmp;
70   clib_error_t *error;
71
72   /* Ignoring the profile id as currently a single profile
73    * is supported */
74   error =
75     vxlan_gpe_ioam_enable (mp->trace_enable, mp->pow_enable, mp->trace_ppc);
76   if (error)
77     {
78       clib_error_report (error);
79       rv = clib_error_get_code (error);
80     }
81
82   REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_ENABLE_REPLY);
83 }
84
85 static void vl_api_vxlan_gpe_ioam_disable_t_handler
86   (vl_api_vxlan_gpe_ioam_disable_t * mp)
87 {
88   int rv = 0;
89   vl_api_vxlan_gpe_ioam_disable_reply_t *rmp;
90   clib_error_t *error;
91
92   /* Ignoring the profile id as currently a single profile
93    * is supported */
94   error = vxlan_gpe_ioam_disable (0, 0, 0);
95   if (error)
96     {
97       clib_error_report (error);
98       rv = clib_error_get_code (error);
99     }
100
101   REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_DISABLE_REPLY);
102 }
103
104 static void vl_api_vxlan_gpe_ioam_vni_enable_t_handler
105   (vl_api_vxlan_gpe_ioam_vni_enable_t * mp)
106 {
107   int rv = 0;
108   vl_api_vxlan_gpe_ioam_vni_enable_reply_t *rmp;
109   clib_error_t *error;
110   vxlan4_gpe_tunnel_key_t key4;
111   uword *p = NULL;
112   vxlan_gpe_main_t *gm = &vxlan_gpe_main;
113   vxlan_gpe_tunnel_t *t = 0;
114   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
115   u32 vni;
116
117
118   if (!mp->is_ipv6)
119     {
120       clib_memcpy (&key4.local, &mp->local, sizeof (key4.local));
121       clib_memcpy (&key4.remote, &mp->remote, sizeof (key4.remote));
122       vni = clib_net_to_host_u32 (mp->vni);
123       key4.vni = clib_host_to_net_u32 (vni << 8);
124       key4.pad = 0;
125
126       p = hash_get_mem (gm->vxlan4_gpe_tunnel_by_key, &key4);
127     }
128   else
129     {
130       return;
131     }
132
133   if (!p)
134     return;
135
136   t = pool_elt_at_index (gm->tunnels, p[0]);
137
138   error = vxlan_gpe_ioam_set (t, hm->has_trace_option,
139                               hm->has_pot_option,
140                               hm->has_ppc_option, mp->is_ipv6);
141
142
143   if (error)
144     {
145       clib_error_report (error);
146       rv = clib_error_get_code (error);
147     }
148
149   REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_VNI_ENABLE_REPLY);
150 }
151
152
153 static void vl_api_vxlan_gpe_ioam_vni_disable_t_handler
154   (vl_api_vxlan_gpe_ioam_vni_disable_t * mp)
155 {
156   int rv = 0;
157   vl_api_vxlan_gpe_ioam_vni_enable_reply_t *rmp;
158   clib_error_t *error;
159   vxlan4_gpe_tunnel_key_t key4;
160   uword *p = NULL;
161   vxlan_gpe_main_t *gm = &vxlan_gpe_main;
162   vxlan_gpe_tunnel_t *t = 0;
163   u32 vni;
164
165
166   if (!mp->is_ipv6)
167     {
168       clib_memcpy (&key4.local, &mp->local, sizeof (key4.local));
169       clib_memcpy (&key4.remote, &mp->remote, sizeof (key4.remote));
170       vni = clib_net_to_host_u32 (mp->vni);
171       key4.vni = clib_host_to_net_u32 (vni << 8);
172       key4.pad = 0;
173
174       p = hash_get_mem (gm->vxlan4_gpe_tunnel_by_key, &key4);
175     }
176   else
177     {
178       return;
179     }
180
181   if (!p)
182     return;
183
184   t = pool_elt_at_index (gm->tunnels, p[0]);
185
186   error = vxlan_gpe_ioam_clear (t, 0, 0, 0, 0);
187
188
189   if (error)
190     {
191       clib_error_report (error);
192       rv = clib_error_get_code (error);
193     }
194
195
196   REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_VNI_DISABLE_REPLY);
197 }
198
199 static void vl_api_vxlan_gpe_ioam_transit_enable_t_handler
200   (vl_api_vxlan_gpe_ioam_transit_enable_t * mp)
201 {
202   int rv = 0;
203   vl_api_vxlan_gpe_ioam_transit_enable_reply_t *rmp;
204   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
205   ip46_address_t dst_addr;
206
207   clib_memset (&dst_addr.ip4, 0, sizeof (dst_addr.ip4));
208   if (!mp->is_ipv6)
209     {
210       clib_memcpy (&dst_addr.ip4, &mp->dst_addr, sizeof (dst_addr.ip4));
211     }
212   rv = vxlan_gpe_enable_disable_ioam_for_dest (sm->vlib_main,
213                                                dst_addr,
214                                                ntohl (mp->outer_fib_index),
215                                                mp->is_ipv6 ? 0 : 1,
216                                                1 /* is_add */ );
217
218   REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_TRANSIT_ENABLE_REPLY);
219 }
220
221 static void vl_api_vxlan_gpe_ioam_transit_disable_t_handler
222   (vl_api_vxlan_gpe_ioam_transit_disable_t * mp)
223 {
224   int rv = 0;
225   vl_api_vxlan_gpe_ioam_transit_disable_reply_t *rmp;
226   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
227   ip46_address_t dst_addr;
228
229   clib_memset (&dst_addr.ip4, 0, sizeof (dst_addr.ip4));
230   if (!mp->is_ipv6)
231     {
232       clib_memcpy (&dst_addr.ip4, &mp->dst_addr, sizeof (dst_addr.ip4));
233     }
234
235   rv = vxlan_gpe_ioam_disable_for_dest (sm->vlib_main,
236                                         dst_addr,
237                                         ntohl (mp->outer_fib_index),
238                                         mp->is_ipv6 ? 0 : 1);
239   REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_TRANSIT_DISABLE_REPLY);
240 }
241
242 /* Set up the API message handling tables */
243 static clib_error_t *
244 vxlan_gpe_plugin_api_hookup (vlib_main_t * vm)
245 {
246   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
247 #define _(N,n)                                                  \
248     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
249                            #n,                                  \
250                            vl_api_##n##_t_handler,              \
251                            vl_noop_handler,                     \
252                            vl_api_##n##_t_endian,               \
253                            vl_api_##n##_t_print,                \
254                            sizeof(vl_api_##n##_t), 1);
255   foreach_vxlan_gpe_plugin_api_msg;
256 #undef _
257
258   return 0;
259 }
260
261 #define vl_msg_name_crc_list
262 #include <ioam/lib-vxlan-gpe/vxlan_gpe_all_api_h.h>
263 #undef vl_msg_name_crc_list
264
265 static void
266 setup_message_id_table (vxlan_gpe_ioam_main_t * sm, api_main_t * am)
267 {
268 #define _(id,n,crc) \
269   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
270   foreach_vl_msg_name_crc_ioam_vxlan_gpe;
271 #undef _
272 }
273
274 static clib_error_t *
275 vxlan_gpe_init (vlib_main_t * vm)
276 {
277   vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
278   clib_error_t *error = 0;
279   u8 *name;
280   u32 encap_node_index = vxlan_gpe_encap_ioam_v4_node.index;
281   u32 decap_node_index = vxlan_gpe_decap_ioam_v4_node.index;
282   vlib_node_t *vxlan_gpe_encap_node = NULL;
283   vlib_node_t *vxlan_gpe_decap_node = NULL;
284   uword next_node = 0;
285
286   sm->vlib_main = vm;
287   sm->vnet_main = vnet_get_main ();
288   sm->unix_time_0 = (u32) time (0);     /* Store starting time */
289   sm->vlib_time_0 = vlib_time_now (vm);
290
291   name = format (0, "ioam_vxlan_gpe_%08x%c", api_version, 0);
292
293   /* Ask for a correctly-sized block of API message decode slots */
294   sm->msg_id_base = vl_msg_api_get_msg_ids
295     ((char *) name, VL_MSG_FIRST_AVAILABLE);
296
297   error = vxlan_gpe_plugin_api_hookup (vm);
298
299   /* Add our API messages to the global name_crc hash table */
300   setup_message_id_table (sm, &api_main);
301
302   /* Hook the ioam-encap node to vxlan-gpe-encap */
303   vxlan_gpe_encap_node = vlib_get_node_by_name (vm, (u8 *) "vxlan-gpe-encap");
304   sm->encap_v4_next_node =
305     vlib_node_add_next (vm, vxlan_gpe_encap_node->index, encap_node_index);
306
307   vxlan_gpe_decap_node =
308     vlib_get_node_by_name (vm, (u8 *) "vxlan4-gpe-input");
309   next_node =
310     vlib_node_add_next (vm, vxlan_gpe_decap_node->index, decap_node_index);
311   vxlan_gpe_register_decap_protocol (VXLAN_GPE_PROTOCOL_IOAM, next_node);
312
313   vec_new (vxlan_gpe_ioam_sw_interface_t, pool_elts (sm->sw_interfaces));
314   sm->dst_by_ip4 = hash_create_mem (0, sizeof (fib_prefix_t), sizeof (uword));
315
316   sm->dst_by_ip6 = hash_create_mem (0, sizeof (fib_prefix_t), sizeof (uword));
317
318   vxlan_gpe_ioam_interface_init ();
319   vec_free (name);
320
321   return error;
322 }
323
324 VLIB_INIT_FUNCTION (vxlan_gpe_init);
325
326 /*
327  * fd.io coding-style-patch-verification: ON
328  *
329  * Local Variables:
330  * eval: (c-set-style "gnu")
331  * End:
332  */