vxlan: Fix L3 mode
[vpp.git] / src / vnet / vxlan / vxlan_api.c
1 /*
2  *------------------------------------------------------------------
3  * vxlan_api.c - vxlan 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/feature/feature.h>
26 #include <vnet/vxlan/vxlan.h>
27 #include <vnet/fib/fib_table.h>
28
29 #include <vnet/ip/ip_types_api.h>
30 #include <vnet/udp/udp_local.h>
31
32 #include <vnet/vnet_msg_enum.h>
33
34 #define vl_typedefs             /* define message structures */
35 #include <vnet/vnet_all_api_h.h>
36 #undef vl_typedefs
37
38 #define vl_endianfun            /* define message structures */
39 #include <vnet/vnet_all_api_h.h>
40 #undef vl_endianfun
41
42 /* instantiate all the print functions we know about */
43 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
44 #define vl_printfun
45 #include <vnet/vnet_all_api_h.h>
46 #undef vl_printfun
47
48 #include <vlibapi/api_helper_macros.h>
49
50 #define foreach_vpe_api_msg                                                   \
51   _ (SW_INTERFACE_SET_VXLAN_BYPASS, sw_interface_set_vxlan_bypass)            \
52   _ (VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel)                              \
53   _ (VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump)                                    \
54   _ (VXLAN_ADD_DEL_TUNNEL_V2, vxlan_add_del_tunnel_v2)                        \
55   _ (VXLAN_ADD_DEL_TUNNEL_V3, vxlan_add_del_tunnel_v3)                        \
56   _ (VXLAN_TUNNEL_V2_DUMP, vxlan_tunnel_v2_dump)                              \
57   _ (VXLAN_OFFLOAD_RX, vxlan_offload_rx)
58
59 static void
60 vl_api_vxlan_offload_rx_t_handler (vl_api_vxlan_offload_rx_t * mp)
61 {
62   vl_api_vxlan_offload_rx_reply_t *rmp;
63   int rv = 0;
64   u32 hw_if_index = ntohl (mp->hw_if_index);
65   u32 sw_if_index = ntohl (mp->sw_if_index);
66
67   if (!vnet_hw_interface_is_valid (vnet_get_main (), hw_if_index))
68     {
69       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
70       goto err;
71     }
72   VALIDATE_SW_IF_INDEX (mp);
73
74   u32 t_index = vnet_vxlan_get_tunnel_index (sw_if_index);
75   if (t_index == ~0)
76     {
77       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
78       goto err;
79     }
80
81   vxlan_main_t *vxm = &vxlan_main;
82   vxlan_tunnel_t *t = pool_elt_at_index (vxm->tunnels, t_index);
83   if (!ip46_address_is_ip4 (&t->dst))
84     {
85       rv = VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
86       goto err;
87     }
88
89   vnet_main_t *vnm = vnet_get_main ();
90   vnet_hw_interface_t *hw_if = vnet_get_hw_interface (vnm, hw_if_index);
91   ip4_main_t *im = &ip4_main;
92   u32 rx_fib_index =
93     vec_elt (im->fib_index_by_sw_if_index, hw_if->sw_if_index);
94
95   if (t->encap_fib_index != rx_fib_index)
96     {
97       rv = VNET_API_ERROR_NO_SUCH_FIB;
98       goto err;
99     }
100
101   if (vnet_vxlan_add_del_rx_flow (hw_if_index, t_index, mp->enable))
102     {
103       rv = VNET_API_ERROR_UNSPECIFIED;
104       goto err;
105     }
106   BAD_SW_IF_INDEX_LABEL;
107 err:
108
109   REPLY_MACRO (VL_API_VXLAN_OFFLOAD_RX_REPLY);
110 }
111
112 static void
113   vl_api_sw_interface_set_vxlan_bypass_t_handler
114   (vl_api_sw_interface_set_vxlan_bypass_t * mp)
115 {
116   vl_api_sw_interface_set_vxlan_bypass_reply_t *rmp;
117   int rv = 0;
118   u32 sw_if_index = ntohl (mp->sw_if_index);
119
120   VALIDATE_SW_IF_INDEX (mp);
121
122   vnet_int_vxlan_bypass_mode (sw_if_index, mp->is_ipv6, mp->enable);
123   BAD_SW_IF_INDEX_LABEL;
124
125   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VXLAN_BYPASS_REPLY);
126 }
127
128 static int
129 vxlan_add_del_tunnel_clean_input (vnet_vxlan_add_del_tunnel_args_t *a,
130                                   u32 encap_vrf_id)
131 {
132   a->is_ip6 = !ip46_address_is_ip4 (&a->src);
133
134   a->encap_fib_index = fib_table_find (fib_ip_proto (a->is_ip6), encap_vrf_id);
135   if (a->encap_fib_index == ~0)
136     {
137       return VNET_API_ERROR_NO_SUCH_FIB;
138     }
139
140   if (ip46_address_is_ip4 (&a->src) != ip46_address_is_ip4 (&a->dst))
141     {
142       return VNET_API_ERROR_INVALID_VALUE;
143     }
144
145   /* Check src & dst are different */
146   if (ip46_address_cmp (&a->dst, &a->src) == 0)
147     {
148       return VNET_API_ERROR_SAME_SRC_DST;
149     }
150   if (ip46_address_is_multicast (&a->dst) &&
151       !vnet_sw_if_index_is_api_valid (a->mcast_sw_if_index))
152     {
153       return VNET_API_ERROR_INVALID_SW_IF_INDEX;
154     }
155   return 0;
156 }
157
158 static void
159 vl_api_vxlan_add_del_tunnel_t_handler (vl_api_vxlan_add_del_tunnel_t *mp)
160 {
161   vl_api_vxlan_add_del_tunnel_reply_t *rmp;
162   u32 sw_if_index = ~0;
163   int rv = 0;
164
165   vnet_vxlan_add_del_tunnel_args_t a = {
166     .is_add = mp->is_add,
167     .instance = ntohl (mp->instance),
168     .mcast_sw_if_index = ntohl (mp->mcast_sw_if_index),
169     .decap_next_index = ntohl (mp->decap_next_index),
170     .vni = ntohl (mp->vni),
171   };
172   ip_address_decode (&mp->src_address, &a.src);
173   ip_address_decode (&mp->dst_address, &a.dst);
174
175   rv = vxlan_add_del_tunnel_clean_input (&a, ntohl (mp->encap_vrf_id));
176   if (rv)
177     goto out;
178   a.dst_port = a.is_ip6 ? UDP_DST_PORT_vxlan6 : UDP_DST_PORT_vxlan,
179   a.src_port = a.is_ip6 ? UDP_DST_PORT_vxlan6 : UDP_DST_PORT_vxlan,
180   rv = vnet_vxlan_add_del_tunnel (&a, &sw_if_index);
181
182 out:
183   REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
184   ({
185     rmp->sw_if_index = ntohl (sw_if_index);
186   }));
187 }
188
189 static void
190 vl_api_vxlan_add_del_tunnel_v2_t_handler (vl_api_vxlan_add_del_tunnel_v2_t *mp)
191 {
192   vl_api_vxlan_add_del_tunnel_v2_reply_t *rmp;
193   u32 sw_if_index = ~0;
194   int rv = 0;
195
196   vnet_vxlan_add_del_tunnel_args_t a = {
197     .is_add = mp->is_add,
198     .instance = ntohl (mp->instance),
199     .mcast_sw_if_index = ntohl (mp->mcast_sw_if_index),
200     .decap_next_index = ntohl (mp->decap_next_index),
201     .vni = ntohl (mp->vni),
202     .dst_port = ntohs (mp->dst_port),
203     .src_port = ntohs (mp->src_port),
204   };
205
206   ip_address_decode (&mp->src_address, &a.src);
207   ip_address_decode (&mp->dst_address, &a.dst);
208
209   rv = vxlan_add_del_tunnel_clean_input (&a, ntohl (mp->encap_vrf_id));
210   if (rv)
211     goto out;
212   rv = vnet_vxlan_add_del_tunnel (&a, &sw_if_index);
213 out:
214   REPLY_MACRO2 (VL_API_VXLAN_ADD_DEL_TUNNEL_V2_REPLY,
215                 ({ rmp->sw_if_index = ntohl (sw_if_index); }));
216 }
217
218 static void
219 vl_api_vxlan_add_del_tunnel_v3_t_handler (vl_api_vxlan_add_del_tunnel_v3_t *mp)
220 {
221   vl_api_vxlan_add_del_tunnel_v3_reply_t *rmp;
222   u32 sw_if_index = ~0;
223   int rv = 0;
224
225   vnet_vxlan_add_del_tunnel_args_t a = {
226     .is_add = mp->is_add,
227     .instance = ntohl (mp->instance),
228     .mcast_sw_if_index = ntohl (mp->mcast_sw_if_index),
229     .decap_next_index = ntohl (mp->decap_next_index),
230     .vni = ntohl (mp->vni),
231     .dst_port = ntohs (mp->dst_port),
232     .src_port = ntohs (mp->src_port),
233     .is_l3 = mp->is_l3,
234   };
235
236   ip_address_decode (&mp->src_address, &a.src);
237   ip_address_decode (&mp->dst_address, &a.dst);
238
239   rv = vxlan_add_del_tunnel_clean_input (&a, ntohl (mp->encap_vrf_id));
240   if (rv)
241     goto out;
242   rv = vnet_vxlan_add_del_tunnel (&a, &sw_if_index);
243 out:
244   REPLY_MACRO2 (VL_API_VXLAN_ADD_DEL_TUNNEL_V3_REPLY,
245                 ({ rmp->sw_if_index = ntohl (sw_if_index); }));
246 }
247
248 static void send_vxlan_tunnel_details
249   (vxlan_tunnel_t * t, vl_api_registration_t * reg, u32 context)
250 {
251   vl_api_vxlan_tunnel_details_t *rmp;
252   ip4_main_t *im4 = &ip4_main;
253   ip6_main_t *im6 = &ip6_main;
254
255   rmp = vl_msg_api_alloc (sizeof (*rmp));
256   clib_memset (rmp, 0, sizeof (*rmp));
257   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_TUNNEL_DETAILS);
258
259   ip_address_encode (&t->src, IP46_TYPE_ANY, &rmp->src_address);
260   ip_address_encode (&t->dst, IP46_TYPE_ANY, &rmp->dst_address);
261
262   if (ip46_address_is_ip4 (&t->dst))
263     rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
264   else
265     rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
266
267   rmp->instance = htonl (t->user_instance);
268   rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
269   rmp->vni = htonl (t->vni);
270   rmp->decap_next_index = htonl (t->decap_next_index);
271   rmp->sw_if_index = htonl (t->sw_if_index);
272   rmp->context = context;
273
274   vl_api_send_msg (reg, (u8 *) rmp);
275 }
276
277 static void vl_api_vxlan_tunnel_dump_t_handler
278   (vl_api_vxlan_tunnel_dump_t * mp)
279 {
280   vl_api_registration_t *reg;
281   vxlan_main_t *vxm = &vxlan_main;
282   vxlan_tunnel_t *t;
283   u32 sw_if_index;
284
285   reg = vl_api_client_index_to_registration (mp->client_index);
286   if (!reg)
287     return;
288
289   sw_if_index = ntohl (mp->sw_if_index);
290
291   if (~0 == sw_if_index)
292     {
293       pool_foreach (t, vxm->tunnels)
294         send_vxlan_tunnel_details(t, reg, mp->context);
295     }
296   else
297     {
298       if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
299           (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
300         {
301           return;
302         }
303       t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
304       send_vxlan_tunnel_details (t, reg, mp->context);
305     }
306 }
307
308 static void
309 send_vxlan_tunnel_v2_details (vxlan_tunnel_t *t, vl_api_registration_t *reg,
310                               u32 context)
311 {
312   vl_api_vxlan_tunnel_v2_details_t *rmp;
313   ip4_main_t *im4 = &ip4_main;
314   ip6_main_t *im6 = &ip6_main;
315
316   rmp = vl_msg_api_alloc (sizeof (*rmp));
317   clib_memset (rmp, 0, sizeof (*rmp));
318   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_TUNNEL_V2_DETAILS);
319
320   ip_address_encode (&t->src, IP46_TYPE_ANY, &rmp->src_address);
321   ip_address_encode (&t->dst, IP46_TYPE_ANY, &rmp->dst_address);
322   rmp->src_port = htons (t->src_port);
323   rmp->dst_port = htons (t->dst_port);
324
325   if (ip46_address_is_ip4 (&t->dst))
326     rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
327   else
328     rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
329
330   rmp->instance = htonl (t->user_instance);
331   rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
332   rmp->vni = htonl (t->vni);
333   rmp->decap_next_index = htonl (t->decap_next_index);
334   rmp->sw_if_index = htonl (t->sw_if_index);
335   rmp->context = context;
336
337   vl_api_send_msg (reg, (u8 *) rmp);
338 }
339
340 static void
341 vl_api_vxlan_tunnel_v2_dump_t_handler (vl_api_vxlan_tunnel_v2_dump_t *mp)
342 {
343   vl_api_registration_t *reg;
344   vxlan_main_t *vxm = &vxlan_main;
345   vxlan_tunnel_t *t;
346   u32 sw_if_index;
347
348   reg = vl_api_client_index_to_registration (mp->client_index);
349   if (!reg)
350     return;
351
352   sw_if_index = ntohl (mp->sw_if_index);
353
354   if (~0 == sw_if_index)
355     {
356       pool_foreach (t, vxm->tunnels)
357         send_vxlan_tunnel_v2_details (t, reg, mp->context);
358     }
359   else
360     {
361       if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
362           (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
363         {
364           return;
365         }
366       t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
367       send_vxlan_tunnel_v2_details (t, reg, mp->context);
368     }
369 }
370
371 /*
372  * vpe_api_hookup
373  * Add vpe's API message handlers to the table.
374  * vlib has already mapped shared memory and
375  * added the client registration handlers.
376  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
377  */
378 #define vl_msg_name_crc_list
379 #include <vnet/vnet_all_api_h.h>
380 #undef vl_msg_name_crc_list
381
382 static void
383 setup_message_id_table (api_main_t * am)
384 {
385 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
386   foreach_vl_msg_name_crc_vxlan;
387 #undef _
388 }
389
390 static clib_error_t *
391 vxlan_api_hookup (vlib_main_t * vm)
392 {
393   api_main_t *am = vlibapi_get_main ();
394
395 #define _(N,n)                                                  \
396     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
397                            vl_api_##n##_t_handler,              \
398                            vl_noop_handler,                     \
399                            vl_api_##n##_t_endian,               \
400                            vl_api_##n##_t_print,                \
401                            sizeof(vl_api_##n##_t), 1);
402   foreach_vpe_api_msg;
403 #undef _
404
405   am->api_trace_cfg[VL_API_VXLAN_ADD_DEL_TUNNEL].size += 16 * sizeof (u32);
406
407   /*
408    * Set up the (msg_name, crc, message-id) table
409    */
410   setup_message_id_table (am);
411
412   return 0;
413 }
414
415 VLIB_API_INIT_FUNCTION (vxlan_api_hookup);
416
417 /*
418  * fd.io coding-style-patch-verification: ON
419  *
420  * Local Variables:
421  * eval: (c-set-style "gnu")
422  * End:
423  */