api: vat2 and json autogeneration for api messages
[vpp.git] / src / plugins / map / map_api.c
1 /*
2  *------------------------------------------------------------------
3  * map_api.c - vnet map 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/ip/ip_types_api.h>
21 #include <map/map.h>
22 #include <map/map.api_enum.h>
23 #include <map/map.api_types.h>
24 #include <vnet/ip/ip.h>
25 #include <vnet/ip/reass/ip4_sv_reass.h>
26 #include <vnet/ip/reass/ip6_sv_reass.h>
27 #include <vnet/ip/reass/ip6_full_reass.h>
28 #include <vnet/fib/fib_table.h>
29 #include <vlibmemory/api.h>
30
31 #define REPLY_MSG_ID_BASE mm->msg_id_base
32 #include <vlibapi/api_helper_macros.h>
33
34 static void
35 vl_api_map_add_domain_t_handler (vl_api_map_add_domain_t * mp)
36 {
37   map_main_t *mm = &map_main;
38   vl_api_map_add_domain_reply_t *rmp;
39   int rv = 0;
40   u32 index;
41   u8 flags = 0;
42
43   mp->tag[ARRAY_LEN (mp->tag) - 1] = '\0';
44   rv =
45     map_create_domain ((ip4_address_t *) & mp->ip4_prefix.address,
46                        mp->ip4_prefix.len,
47                        (ip6_address_t *) & mp->ip6_prefix.address,
48                        mp->ip6_prefix.len,
49                        (ip6_address_t *) & mp->ip6_src.address,
50                        mp->ip6_src.len, mp->ea_bits_len, mp->psid_offset,
51                        mp->psid_length, &index, mp->mtu, flags, mp->tag);
52
53   /* *INDENT-OFF* */
54   REPLY_MACRO2_END(VL_API_MAP_ADD_DOMAIN_REPLY,
55   ({
56     rmp->index = index;
57   }));
58
59   /* *INDENT-ON* */
60 }
61
62 static void
63 vl_api_map_del_domain_t_handler (vl_api_map_del_domain_t * mp)
64 {
65   map_main_t *mm = &map_main;
66   vl_api_map_del_domain_reply_t *rmp;
67   int rv = 0;
68
69   rv = map_delete_domain (ntohl (mp->index));
70
71   REPLY_MACRO (VL_API_MAP_DEL_DOMAIN_REPLY);
72 }
73
74 static void
75 vl_api_map_add_del_rule_t_handler (vl_api_map_add_del_rule_t * mp)
76 {
77   map_main_t *mm = &map_main;
78   vl_api_map_del_domain_reply_t *rmp;
79   int rv = 0;
80
81   rv =
82     map_add_del_psid (ntohl (mp->index), ntohs (mp->psid),
83                       (ip6_address_t *) & mp->ip6_dst, mp->is_add);
84
85   REPLY_MACRO (VL_API_MAP_ADD_DEL_RULE_REPLY);
86 }
87
88 static void
89 send_domain_details (u32 map_domain_index, vl_api_registration_t * rp,
90                      u32 context)
91 {
92   map_main_t *mm = &map_main;
93   vl_api_map_domain_details_t *rmp;
94   map_domain_t *d = pool_elt_at_index (mm->domains, map_domain_index);
95
96   /* Make sure every field is initiated (or don't skip the clib_memset()) */
97   map_domain_extra_t *de =
98     vec_elt_at_index (mm->domain_extras, map_domain_index);
99   int tag_len = clib_min (ARRAY_LEN (rmp->tag), vec_len (de->tag) + 1);
100
101   /* *INDENT-OFF* */
102   REPLY_MACRO_DETAILS4(VL_API_MAP_DOMAIN_DETAILS, rp, context,
103   ({
104     rmp->domain_index = htonl (map_domain_index);
105     clib_memcpy (&rmp->ip6_prefix.address, &d->ip6_prefix,
106                  sizeof (rmp->ip6_prefix.address));
107     clib_memcpy (&rmp->ip4_prefix.address, &d->ip4_prefix,
108                  sizeof (rmp->ip4_prefix.address));
109     clib_memcpy (&rmp->ip6_src.address, &d->ip6_src,
110                  sizeof (rmp->ip6_src.address));
111     rmp->ip6_prefix.len = d->ip6_prefix_len;
112     rmp->ip4_prefix.len = d->ip4_prefix_len;
113     rmp->ip6_src.len = d->ip6_src_len;
114     rmp->ea_bits_len = d->ea_bits_len;
115     rmp->psid_offset = d->psid_offset;
116     rmp->psid_length = d->psid_length;
117     rmp->flags = d->flags;
118     rmp->mtu = htons (d->mtu);
119     memcpy (rmp->tag, de->tag, tag_len - 1);
120     rmp->tag[tag_len - 1] = '\0';
121   }));
122   /* *INDENT-ON* */
123 }
124
125 static void
126 vl_api_map_domain_dump_t_handler (vl_api_map_domain_dump_t * mp)
127 {
128   map_main_t *mm = &map_main;
129   int i;
130   vl_api_registration_t *reg;
131
132   if (pool_elts (mm->domains) == 0)
133     return;
134
135   reg = vl_api_client_index_to_registration (mp->client_index);
136   if (!reg)
137     return;
138
139   /* *INDENT-OFF* */
140   pool_foreach_index(i, mm->domains,
141   ({
142     send_domain_details(i, reg, mp->context);
143   }));
144   /* *INDENT-ON* */
145 }
146
147 static void
148 vl_api_map_domains_get_t_handler (vl_api_map_domains_get_t * mp)
149 {
150   map_main_t *mm = &map_main;
151   vl_api_map_domains_get_reply_t *rmp;
152
153   i32 rv = 0;
154
155   if (pool_elts (mm->domains) == 0)
156     {
157       REPLY_MACRO (VL_API_MAP_DOMAINS_GET_REPLY);
158       return;
159     }
160
161   /* *INDENT-OFF* */
162   REPLY_AND_DETAILS_MACRO (VL_API_MAP_DOMAINS_GET_REPLY, mm->domains,
163   ({
164     send_domain_details (cursor, rp, mp->context);
165   }));
166   /* *INDENT-ON* */
167 }
168
169 static void
170 vl_api_map_rule_dump_t_handler (vl_api_map_rule_dump_t * mp)
171 {
172   vl_api_registration_t *reg;
173   u16 i;
174   ip6_address_t dst;
175   vl_api_map_rule_details_t *rmp;
176   map_main_t *mm = &map_main;
177   u32 domain_index = ntohl (mp->domain_index);
178   map_domain_t *d;
179
180   if (pool_elts (mm->domains) == 0)
181     return;
182
183   d = pool_elt_at_index (mm->domains, domain_index);
184   if (!d || !d->rules)
185     {
186       return;
187     }
188
189   reg = vl_api_client_index_to_registration (mp->client_index);
190   if (!reg)
191     return;
192
193   for (i = 0; i < (0x1 << d->psid_length); i++)
194     {
195       dst = d->rules[i];
196       if (dst.as_u64[0] == 0 && dst.as_u64[1] == 0)
197         {
198           continue;
199         }
200       rmp = vl_msg_api_alloc (sizeof (*rmp));
201       clib_memset (rmp, 0, sizeof (*rmp));
202       rmp->_vl_msg_id = ntohs (VL_API_MAP_RULE_DETAILS + mm->msg_id_base);
203       rmp->psid = htons (i);
204       clib_memcpy (&rmp->ip6_dst, &dst, sizeof (rmp->ip6_dst));
205       rmp->context = mp->context;
206       vl_api_send_msg (reg, (u8 *) rmp);
207     }
208 }
209
210 static void
211 vl_api_map_summary_stats_t_handler (vl_api_map_summary_stats_t * mp)
212 {
213   vl_api_map_summary_stats_reply_t *rmp;
214   vlib_combined_counter_main_t *cm;
215   vlib_counter_t v;
216   int i, which;
217   u64 total_pkts[VLIB_N_RX_TX];
218   u64 total_bytes[VLIB_N_RX_TX];
219   map_main_t *mm = &map_main;
220   vl_api_registration_t *reg;
221
222   reg = vl_api_client_index_to_registration (mp->client_index);
223   if (!reg)
224     return;
225
226   rmp = vl_msg_api_alloc (sizeof (*rmp));
227   rmp->_vl_msg_id = htons (VL_API_MAP_SUMMARY_STATS_REPLY + mm->msg_id_base);
228   rmp->context = mp->context;
229   rmp->retval = 0;
230
231   if (pool_elts (mm->domains) == 0)
232     {
233       rmp->retval = -1;
234       goto out;
235     }
236
237   clib_memset (total_pkts, 0, sizeof (total_pkts));
238   clib_memset (total_bytes, 0, sizeof (total_bytes));
239
240   map_domain_counter_lock (mm);
241   vec_foreach (cm, mm->domain_counters)
242   {
243     which = cm - mm->domain_counters;
244
245     for (i = 0; i < vlib_combined_counter_n_counters (cm); i++)
246       {
247         vlib_get_combined_counter (cm, i, &v);
248         total_pkts[which] += v.packets;
249         total_bytes[which] += v.bytes;
250       }
251   }
252
253   map_domain_counter_unlock (mm);
254
255   /* Note: in network byte order! */
256   rmp->total_pkts[MAP_DOMAIN_COUNTER_RX] =
257     clib_host_to_net_u64 (total_pkts[MAP_DOMAIN_COUNTER_RX]);
258   rmp->total_bytes[MAP_DOMAIN_COUNTER_RX] =
259     clib_host_to_net_u64 (total_bytes[MAP_DOMAIN_COUNTER_RX]);
260   rmp->total_pkts[MAP_DOMAIN_COUNTER_TX] =
261     clib_host_to_net_u64 (total_pkts[MAP_DOMAIN_COUNTER_TX]);
262   rmp->total_bytes[MAP_DOMAIN_COUNTER_TX] =
263     clib_host_to_net_u64 (total_bytes[MAP_DOMAIN_COUNTER_TX]);
264   rmp->total_bindings = clib_host_to_net_u64 (pool_elts (mm->domains));
265   rmp->total_ip4_fragments = 0; // Not yet implemented. Should be a simple counter.
266   rmp->total_security_check[MAP_DOMAIN_COUNTER_TX] =
267     clib_host_to_net_u64 (map_error_counter_get
268                           (ip4_map_node.index, MAP_ERROR_ENCAP_SEC_CHECK));
269   rmp->total_security_check[MAP_DOMAIN_COUNTER_RX] =
270     clib_host_to_net_u64 (map_error_counter_get
271                           (ip4_map_node.index, MAP_ERROR_DECAP_SEC_CHECK));
272
273 out:
274   vl_api_send_msg (reg, (u8 *) rmp);
275 }
276
277
278 int
279 map_param_set_fragmentation (bool inner, bool ignore_df)
280 {
281   map_main_t *mm = &map_main;
282
283   mm->frag_inner = ! !inner;
284   mm->frag_ignore_df = ! !ignore_df;
285
286   return 0;
287 }
288
289 static void
290   vl_api_map_param_set_fragmentation_t_handler
291   (vl_api_map_param_set_fragmentation_t * mp)
292 {
293   map_main_t *mm = &map_main;
294   vl_api_map_param_set_fragmentation_reply_t *rmp;
295   int rv = 0;
296
297   rv = map_param_set_fragmentation (mp->inner, mp->ignore_df);
298
299   REPLY_MACRO (VL_API_MAP_PARAM_SET_FRAGMENTATION_REPLY);
300 }
301
302
303 int
304 map_param_set_icmp (ip4_address_t * icmp_src_address)
305 {
306   map_main_t *mm = &map_main;
307
308   if (icmp_src_address == 0)
309     return -1;
310
311   mm->icmp4_src_address = *icmp_src_address;
312
313   return 0;
314 }
315
316
317 static void
318 vl_api_map_param_set_icmp_t_handler (vl_api_map_param_set_icmp_t * mp)
319 {
320   map_main_t *mm = &map_main;
321   vl_api_map_param_set_icmp_reply_t *rmp;
322   int rv;
323
324   rv = map_param_set_icmp ((ip4_address_t *) & mp->ip4_err_relay_src);
325
326   REPLY_MACRO (VL_API_MAP_PARAM_SET_ICMP_REPLY);
327 }
328
329
330 int
331 map_param_set_icmp6 (u8 enable_unreachable)
332 {
333   map_main_t *mm = &map_main;
334
335   mm->icmp6_enabled = ! !enable_unreachable;
336
337   return 0;
338 }
339
340 static void
341 vl_api_map_param_set_icmp6_t_handler (vl_api_map_param_set_icmp6_t * mp)
342 {
343   map_main_t *mm = &map_main;
344   vl_api_map_param_set_icmp6_reply_t *rmp;
345   int rv;
346
347   rv = map_param_set_icmp6 (mp->enable_unreachable);
348
349   REPLY_MACRO (VL_API_MAP_PARAM_SET_ICMP6_REPLY);
350 }
351
352
353 static void
354   vl_api_map_param_add_del_pre_resolve_t_handler
355   (vl_api_map_param_add_del_pre_resolve_t * mp)
356 {
357   map_main_t *mm = &map_main;
358   vl_api_map_param_add_del_pre_resolve_reply_t *rmp;
359   int rv = 0;
360
361   map_pre_resolve ((ip4_address_t *) & mp->ip4_nh_address,
362                    (ip6_address_t *) & mp->ip6_nh_address, !mp->is_add);
363
364   REPLY_MACRO (VL_API_MAP_PARAM_ADD_DEL_PRE_RESOLVE_REPLY);
365 }
366
367 int
368 map_param_set_security_check (bool enable, bool fragments)
369 {
370   map_main_t *mm = &map_main;
371
372   mm->sec_check = ! !enable;
373   mm->sec_check_frag = ! !fragments;
374
375   return 0;
376 }
377
378 static void
379   vl_api_map_param_set_security_check_t_handler
380   (vl_api_map_param_set_security_check_t * mp)
381 {
382   map_main_t *mm = &map_main;
383   vl_api_map_param_set_security_check_reply_t *rmp;
384   int rv;
385
386   rv = map_param_set_security_check (mp->enable, mp->fragments);
387
388   REPLY_MACRO (VL_API_MAP_PARAM_SET_SECURITY_CHECK_REPLY);
389 }
390
391
392 int
393 map_param_set_traffic_class (bool copy, u8 tc)
394 {
395   map_main_t *mm = &map_main;
396
397   mm->tc_copy = ! !copy;
398   mm->tc = tc;
399
400   return 0;
401 }
402
403 static void
404   vl_api_map_param_set_traffic_class_t_handler
405   (vl_api_map_param_set_traffic_class_t * mp)
406 {
407   map_main_t *mm = &map_main;
408   vl_api_map_param_set_traffic_class_reply_t *rmp;
409   int rv;
410
411   rv = map_param_set_traffic_class (mp->copy, mp->tc_class);
412
413   REPLY_MACRO (VL_API_MAP_PARAM_SET_TRAFFIC_CLASS_REPLY);
414 }
415
416
417 int
418 map_param_set_tcp (u16 tcp_mss)
419 {
420   map_main_t *mm = &map_main;
421
422   mm->tcp_mss = tcp_mss;
423
424   return 0;
425 }
426
427
428 static void
429 vl_api_map_param_set_tcp_t_handler (vl_api_map_param_set_tcp_t * mp)
430 {
431   map_main_t *mm = &map_main;
432   vl_api_map_param_set_tcp_reply_t *rmp;
433   int rv = 0;
434
435   map_param_set_tcp (ntohs (mp->tcp_mss));
436   REPLY_MACRO (VL_API_MAP_PARAM_SET_TCP_REPLY);
437 }
438
439
440 static void
441 vl_api_map_param_get_t_handler (vl_api_map_param_get_t * mp)
442 {
443   map_main_t *mm = &map_main;
444   vl_api_map_param_get_reply_t *rmp;
445   vl_api_registration_t *reg;
446
447   reg = vl_api_client_index_to_registration (mp->client_index);
448   if (!reg)
449     return;
450
451   rmp = vl_msg_api_alloc (sizeof (*rmp));
452   rmp->_vl_msg_id = htons (VL_API_MAP_PARAM_GET_REPLY + mm->msg_id_base);
453   rmp->context = mp->context;
454   rmp->retval = 0;
455
456   rmp->frag_inner = mm->frag_inner;
457   rmp->frag_ignore_df = mm->frag_ignore_df;
458
459   clib_memcpy (&rmp->icmp_ip4_err_relay_src,
460                &mm->icmp4_src_address, sizeof (rmp->icmp_ip4_err_relay_src));
461
462   rmp->icmp6_enable_unreachable = mm->icmp6_enabled;
463
464   /*
465    * FIXME: How are these addresses re-extracted from the FIB?
466    * Or should a local map_main copy be kept?
467    */
468   clib_memset (&rmp->ip4_nh_address, 0, sizeof (rmp->ip4_nh_address));
469   clib_memset (&rmp->ip6_nh_address, 0, sizeof (rmp->ip6_nh_address));
470
471   rmp->sec_check_enable = mm->sec_check;
472   rmp->sec_check_fragments = mm->sec_check_frag;
473
474   rmp->tc_copy = mm->tc_copy;
475   rmp->tc_class = mm->tc;
476
477   vl_api_send_msg (reg, (u8 *) rmp);
478 }
479
480
481 int
482 map_if_enable_disable (bool is_enable, u32 sw_if_index, bool is_translation)
483 {
484   map_main_t *mm = &map_main;
485
486   if (pool_is_free_index (mm->vnet_main->interface_main.sw_interfaces,
487                           sw_if_index))
488     return VNET_API_ERROR_INVALID_SW_IF_INDEX;
489
490   is_enable = ! !is_enable;
491
492   if (is_translation)
493     {
494       if (clib_bitmap_get (mm->bm_trans_enabled_by_sw_if, sw_if_index)
495           == is_enable)
496         return 0;
497     }
498   else
499     {
500       if (clib_bitmap_get (mm->bm_encap_enabled_by_sw_if, sw_if_index)
501           == is_enable)
502         return 0;
503     }
504
505   if (is_translation == false)
506     {
507       ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, is_enable);
508       ip6_full_reass_enable_disable_with_refcnt (sw_if_index, is_enable);
509       vnet_feature_enable_disable ("ip4-unicast", "ip4-map", sw_if_index,
510                                    is_enable ? 1 : 0, 0, 0);
511       vnet_feature_enable_disable ("ip6-unicast", "ip6-map", sw_if_index,
512                                    is_enable ? 1 : 0, 0, 0);
513       mm->bm_encap_enabled_by_sw_if =
514         clib_bitmap_set (mm->bm_encap_enabled_by_sw_if, sw_if_index,
515                          is_enable);
516     }
517   else
518     {
519       ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, is_enable);
520       ip6_sv_reass_enable_disable_with_refcnt (sw_if_index, is_enable);
521       vnet_feature_enable_disable ("ip4-unicast", "ip4-map-t", sw_if_index,
522                                    is_enable ? 1 : 0, 0, 0);
523       vnet_feature_enable_disable ("ip6-unicast", "ip6-map-t", sw_if_index,
524                                    is_enable ? 1 : 0, 0, 0);
525       mm->bm_trans_enabled_by_sw_if =
526         clib_bitmap_set (mm->bm_trans_enabled_by_sw_if, sw_if_index,
527                          is_enable);
528     }
529
530   return 0;
531 }
532
533
534 static void
535 vl_api_map_if_enable_disable_t_handler (vl_api_map_if_enable_disable_t * mp)
536 {
537   map_main_t *mm = &map_main;
538   vl_api_map_if_enable_disable_reply_t *rmp;
539   int rv = 0;
540
541   VALIDATE_SW_IF_INDEX (mp);
542
543   rv =
544     map_if_enable_disable (mp->is_enable, htonl (mp->sw_if_index),
545                            mp->is_translation);
546
547   BAD_SW_IF_INDEX_LABEL;
548   REPLY_MACRO (VL_API_MAP_IF_ENABLE_DISABLE_REPLY);
549 }
550
551 /* API definitions */
552 #include <vnet/format_fns.h>
553 #include <map/map.api.c>
554
555 /* Set up the API message handling tables */
556 clib_error_t *
557 map_plugin_api_hookup (vlib_main_t * vm)
558 {
559   map_main_t *mm = &map_main;
560
561   mm->msg_id_base = setup_message_id_table ();
562
563   api_main_t *am = vlibapi_get_main ();
564   am->is_autoendian[mm->msg_id_base + VL_API_MAP_ADD_DOMAIN] = 1;
565   return 0;
566 }
567
568 /*
569  * fd.io coding-style-patch-verification: ON
570  *
571  * Local Variables:
572  * eval: (c-set-style "gnu")
573  * End:
574  */