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