2 * Copyright (c) 2020 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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <nat/det44/det44.h>
22 det44_map_command_fn (vlib_main_t * vm, unformat_input_t * input,
23 vlib_cli_command_t * cmd)
25 unformat_input_t _line_input, *line_input = &_line_input;
26 ip4_address_t in_addr, out_addr;
27 u32 in_plen, out_plen;
29 clib_error_t *error = 0;
31 if (!unformat_user (input, unformat_line_input, line_input))
34 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
37 (line_input, "in %U/%u", unformat_ip4_address, &in_addr, &in_plen))
41 (line_input, "out %U/%u", unformat_ip4_address, &out_addr,
44 else if (unformat (line_input, "del"))
48 error = clib_error_return (0, "unknown input '%U'",
49 format_unformat_error, line_input);
54 rv = snat_det_add_map (&in_addr, (u8) in_plen, &out_addr, (u8) out_plen,
59 error = clib_error_return (0, "snat_det_add_map return %d", rv);
64 unformat_free (line_input);
70 det44_show_mappings_command_fn (vlib_main_t * vm,
71 unformat_input_t * input,
72 vlib_cli_command_t * cmd)
74 det44_main_t *dm = &det44_main;
76 vlib_cli_output (vm, "NAT44 deterministic mappings:");
78 pool_foreach (mp, dm->det_maps)
80 vlib_cli_output (vm, " in %U/%d out %U/%d\n",
81 format_ip4_address, &mp->in_addr, mp->in_plen,
82 format_ip4_address, &mp->out_addr, mp->out_plen);
83 vlib_cli_output (vm, " outside address sharing ratio: %d\n",
85 vlib_cli_output (vm, " number of ports per inside host: %d\n",
87 vlib_cli_output (vm, " sessions number: %d\n", mp->ses_num);
94 det44_forward_command_fn (vlib_main_t * vm,
95 unformat_input_t * input, vlib_cli_command_t * cmd)
97 unformat_input_t _line_input, *line_input = &_line_input;
98 ip4_address_t in_addr, out_addr;
101 clib_error_t *error = 0;
103 if (!unformat_user (input, unformat_line_input, line_input))
106 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
108 if (unformat (line_input, "%U", unformat_ip4_address, &in_addr))
112 error = clib_error_return (0, "unknown input '%U'",
113 format_unformat_error, line_input);
118 mp = snat_det_map_by_user (&in_addr);
120 vlib_cli_output (vm, "no match");
123 snat_det_forward (mp, &in_addr, &out_addr, &lo_port);
124 vlib_cli_output (vm, "%U:<%d-%d>", format_ip4_address, &out_addr,
125 lo_port, lo_port + mp->ports_per_host - 1);
129 unformat_free (line_input);
134 static clib_error_t *
135 det44_reverse_command_fn (vlib_main_t * vm,
136 unformat_input_t * input, vlib_cli_command_t * cmd)
138 unformat_input_t _line_input, *line_input = &_line_input;
139 ip4_address_t in_addr, out_addr;
140 clib_error_t *error = 0;
144 if (!unformat_user (input, unformat_line_input, line_input))
147 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
150 (line_input, "%U:%d", unformat_ip4_address, &out_addr, &out_port))
154 error = clib_error_return (0, "unknown input '%U'",
155 format_unformat_error, line_input);
160 if (out_port < 1024 || out_port > 65535)
162 error = clib_error_return (0, "wrong port, must be <1024-65535>");
166 mp = snat_det_map_by_out (&out_addr);
168 vlib_cli_output (vm, "no match");
171 snat_det_reverse (mp, &out_addr, (u16) out_port, &in_addr);
172 vlib_cli_output (vm, "%U", format_ip4_address, &in_addr);
176 unformat_free (line_input);
181 static clib_error_t *
182 det44_show_sessions_command_fn (vlib_main_t * vm,
183 unformat_input_t * input,
184 vlib_cli_command_t * cmd)
186 det44_main_t *dm = &det44_main;
187 snat_det_session_t *ses;
189 vlib_cli_output (vm, "NAT44 deterministic sessions:");
191 pool_foreach (mp, dm->det_maps)
194 vec_foreach_index (i, mp->sessions)
196 ses = vec_elt_at_index (mp->sessions, i);
198 vlib_cli_output (vm, " %U", format_det_map_ses, mp, ses, &i);
205 static clib_error_t *
206 det44_close_session_out_fn (vlib_main_t * vm,
207 unformat_input_t * input,
208 vlib_cli_command_t * cmd)
210 unformat_input_t _line_input, *line_input = &_line_input;
211 ip4_address_t out_addr, ext_addr, in_addr;
212 u32 out_port, ext_port;
214 snat_det_session_t *ses;
215 snat_det_out_key_t key;
216 clib_error_t *error = 0;
218 if (!unformat_user (input, unformat_line_input, line_input))
221 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
223 if (unformat (line_input, "%U:%d %U:%d",
224 unformat_ip4_address, &out_addr, &out_port,
225 unformat_ip4_address, &ext_addr, &ext_port))
229 error = clib_error_return (0, "unknown input '%U'",
230 format_unformat_error, line_input);
235 unformat_free (line_input);
237 mp = snat_det_map_by_out (&out_addr);
239 vlib_cli_output (vm, "no match");
242 snat_det_reverse (mp, &ext_addr, (u16) out_port, &in_addr);
243 key.ext_host_addr = out_addr;
244 key.ext_host_port = ntohs ((u16) ext_port);
245 key.out_port = ntohs ((u16) out_port);
246 ses = snat_det_get_ses_by_out (mp, &out_addr, key.as_u64);
248 vlib_cli_output (vm, "no match");
250 snat_det_ses_close (mp, ses);
254 unformat_free (line_input);
259 static clib_error_t *
260 det44_close_session_in_fn (vlib_main_t * vm,
261 unformat_input_t * input, vlib_cli_command_t * cmd)
263 unformat_input_t _line_input, *line_input = &_line_input;
264 ip4_address_t in_addr, ext_addr;
265 u32 in_port, ext_port;
267 snat_det_session_t *ses;
268 snat_det_out_key_t key;
269 clib_error_t *error = 0;
271 if (!unformat_user (input, unformat_line_input, line_input))
274 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
276 if (unformat (line_input, "%U:%d %U:%d",
277 unformat_ip4_address, &in_addr, &in_port,
278 unformat_ip4_address, &ext_addr, &ext_port))
282 error = clib_error_return (0, "unknown input '%U'",
283 format_unformat_error, line_input);
288 unformat_free (line_input);
290 mp = snat_det_map_by_user (&in_addr);
292 vlib_cli_output (vm, "no match");
295 key.ext_host_addr = ext_addr;
296 key.ext_host_port = ntohs ((u16) ext_port);
298 snat_det_find_ses_by_in (mp, &in_addr, ntohs ((u16) in_port), key);
300 vlib_cli_output (vm, "no match");
302 snat_det_ses_close (mp, ses);
306 unformat_free (line_input);
311 static clib_error_t *
312 det44_set_timeouts_command_fn (vlib_main_t * vm,
313 unformat_input_t * input,
314 vlib_cli_command_t * cmd)
316 unformat_input_t _line_input, *line_input = &_line_input;
317 nat_timeouts_t timeouts = { 0 };
318 clib_error_t *error = 0;
321 if (!unformat_user (input, unformat_line_input, line_input))
324 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
326 if (unformat (line_input, "udp %u", &timeouts.udp));
327 else if (unformat (line_input, "tcp established %u",
328 &timeouts.tcp.established));
329 else if (unformat (line_input, "tcp transitory %u",
330 &timeouts.tcp.transitory));
331 else if (unformat (line_input, "icmp %u", &timeouts.icmp));
332 else if (unformat (line_input, "reset"))
336 error = clib_error_return (0, "unknown input '%U'",
337 format_unformat_error, line_input);
344 if (det44_set_timeouts (&timeouts))
346 error = clib_error_return (0, "error configuring timeouts");
350 det44_reset_timeouts ();
352 unformat_free (line_input);
356 static clib_error_t *
357 det44_show_timeouts_command_fn (vlib_main_t * vm,
358 unformat_input_t * input,
359 vlib_cli_command_t * cmd)
361 nat_timeouts_t timeouts;
362 timeouts = det44_get_timeouts ();
363 vlib_cli_output (vm, "udp timeout: %dsec", timeouts.udp);
364 vlib_cli_output (vm, "tcp established timeout: %dsec",
365 timeouts.tcp.established);
366 vlib_cli_output (vm, "tcp transitory timeout: %dsec",
367 timeouts.tcp.transitory);
368 vlib_cli_output (vm, "icmp timeout: %dsec", timeouts.icmp);
372 static clib_error_t *
373 det44_plugin_enable_disable_command_fn (vlib_main_t * vm,
374 unformat_input_t * input,
375 vlib_cli_command_t * cmd)
377 unformat_input_t _line_input, *line_input = &_line_input;
378 u8 enable = 0, is_set = 0;
379 clib_error_t *error = 0;
380 det44_config_t c = { 0 };
382 if (!unformat_user (input, unformat_line_input, line_input))
385 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
387 if (!is_set && unformat (line_input, "enable"))
389 unformat (line_input, "inside vrf %u", &c.inside_vrf_id);
390 unformat (line_input, "outside vrf %u", &c.outside_vrf_id);
393 else if (!is_set && unformat (line_input, "disable"));
396 error = clib_error_return (0, "unknown input '%U'",
397 format_unformat_error, line_input);
405 if (det44_plugin_enable (c))
406 error = clib_error_return (0, "plugin enable failed");
410 if (det44_plugin_disable ())
411 error = clib_error_return (0, "plugin disable failed");
414 unformat_free (line_input);
424 static clib_error_t *
425 det44_feature_command_fn (vlib_main_t * vm,
426 unformat_input_t * input, vlib_cli_command_t * cmd)
428 unformat_input_t _line_input, *line_input = &_line_input;
429 sw_if_indices_t *sw_if_indices = 0, *p, e;
430 vnet_main_t *vnm = vnet_get_main ();
431 clib_error_t *error = 0;
434 if (!unformat_user (input, unformat_line_input, line_input))
437 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
439 if (unformat (line_input, "inside %U", unformat_vnet_sw_interface,
440 vnm, &e.sw_if_index))
443 vec_add1 (sw_if_indices, e);
445 else if (unformat (line_input, "outside %U", unformat_vnet_sw_interface,
446 vnm, &e.sw_if_index))
449 vec_add1 (sw_if_indices, e);
451 else if (unformat (line_input, "del"))
455 error = clib_error_return (0, "unknown input '%U'",
456 format_unformat_error, line_input);
462 vec_foreach (p, sw_if_indices)
464 if (det44_interface_add_del (p->sw_if_index, p->is_inside, is_del))
466 error = clib_error_return (0, "%s %s %U failed",
467 is_del ? "del" : "add",
468 p->is_inside ? "inside" : "outside",
469 format_vnet_sw_if_index_name,
470 vnm, p->sw_if_index);
476 unformat_free (line_input);
477 vec_free (sw_if_indices);
481 static clib_error_t *
482 det44_show_interfaces_command_fn (vlib_main_t * vm, unformat_input_t * input,
483 vlib_cli_command_t * cmd)
485 vnet_main_t *vnm = vnet_get_main ();
486 det44_main_t *dm = &det44_main;
487 det44_interface_t *i;
488 vlib_cli_output (vm, "DET44 interfaces:");
490 pool_foreach (i, dm->interfaces)
492 vlib_cli_output (vm, " %U %s", format_vnet_sw_if_index_name, vnm,
494 (det44_interface_is_inside(i) &&
495 det44_interface_is_outside(i)) ? "in out" :
496 (det44_interface_is_inside(i) ? "in" : "out"));
505 * @cliexstart{det44 add}
506 * Create bijective mapping of inside address to outside address and port range
507 * pairs, with the purpose of enabling DET44 to reduce logging in CGN
509 * To create mapping between inside network 10.0.0.0/18 and
510 * outside network 1.1.1.0/30 use:
511 * # vpp# det44 add in 10.0.0.0/18 out 1.1.1.0/30
514 VLIB_CLI_COMMAND (det44_map_command, static) = {
516 .short_help = "det44 add in <addr>/<plen> out <addr>/<plen> [del]",
517 .function = det44_map_command_fn,
522 * @cliexpstart{show det44 mappings}
523 * Show DET44 mappings
524 * vpp# show det44 mappings
526 * in 10.0.0.0/24 out 1.1.1.1/32
527 * outside address sharing ratio: 256
528 * number of ports per inside host: 252
532 VLIB_CLI_COMMAND (det44_show_mappings_command, static) = {
533 .path = "show det44 mappings",
534 .short_help = "show det44 mappings",
535 .function = det44_show_mappings_command_fn,
540 * @cliexstart{det44 forward}
541 * Return outside address and port range from inside address for DET44.
542 * To obtain outside address and port of inside host use:
543 * vpp# det44 forward 10.0.0.2
544 * 1.1.1.0:<1054-1068>
547 VLIB_CLI_COMMAND (det44_forward_command, static) = {
548 .path = "det44 forward",
549 .short_help = "det44 forward <addr>",
550 .function = det44_forward_command_fn,
555 * @cliexstart{det44 reverse}
556 * Return inside address from outside address and port for DET44.
557 * To obtain inside host address from outside address and port use:
558 * #vpp det44 reverse 1.1.1.1:1276
562 VLIB_CLI_COMMAND (det44_reverse_command, static) = {
563 .path = "det44 reverse",
564 .short_help = "det44 reverse <addr>:<port>",
565 .function = det44_reverse_command_fn,
570 * @cliexstart{show det44 sessions}
571 * Show DET44 sessions.
572 * vpp# show det44 sessions
574 * in 10.0.0.3:3005 out 1.1.1.2:1146 external host 172.16.1.2:3006 state: udp-active expire: 306
575 * in 10.0.0.3:3000 out 1.1.1.2:1141 external host 172.16.1.2:3001 state: udp-active expire: 306
576 * in 10.0.0.4:3005 out 1.1.1.2:1177 external host 172.16.1.2:3006 state: udp-active expire: 306
579 VLIB_CLI_COMMAND (det44_show_sessions_command, static) = {
580 .path = "show det44 sessions",
581 .short_help = "show det44 sessions",
582 .function = det44_show_sessions_command_fn,
587 * @cliexstart{det44 close session out}
588 * Close session using outside ip address and port
589 * and external ip address and port, use:
590 * vpp# det44 close session out 1.1.1.1:1276 2.2.2.2:2387
593 VLIB_CLI_COMMAND (det44_close_sesion_out_command, static) = {
594 .path = "det44 close session out",
595 .short_help = "det44 close session out "
596 "<out_addr>:<out_port> <ext_addr>:<ext_port>",
597 .function = det44_close_session_out_fn,
602 * @cliexstart{det44 deterministic close session in}
603 * Close session using inside ip address and port
604 * and external ip address and port, use:
605 * vpp# det44 close session in 3.3.3.3:3487 2.2.2.2:2387
608 VLIB_CLI_COMMAND (det44_close_session_in_command, static) = {
609 .path = "det44 close session in",
610 .short_help = "det44 close session in "
611 "<in_addr>:<in_port> <ext_addr>:<ext_port>",
612 .function = det44_close_session_in_fn,
617 * @cliexstart{set det44 timeout}
618 * Set values of timeouts for DET44 sessions (in seconds), use:
619 * vpp# set det44 timeouts udp 120 tcp established 7500 tcp transitory 250 icmp 90
620 * To reset default values use:
621 * vpp# set det44 timeouts reset
624 VLIB_CLI_COMMAND (det44_set_timeouts_command, static) =
626 .path = "set det44 timeouts",
627 .short_help = "set det44 timeouts <[udp <sec>] [tcp established <sec>] "
628 "[tcp transitory <sec>] [icmp <sec>]|reset>",
629 .function = det44_set_timeouts_command_fn,
634 * @cliexstart{show det44 timeouts}
635 * Show values of timeouts for DET44 sessions.
636 * vpp# show det44 timeouts
637 * udp timeout: 300sec
638 * tcp-established timeout: 7440sec
639 * tcp-transitory timeout: 240sec
640 * icmp timeout: 60sec
643 VLIB_CLI_COMMAND (det44_show_timeouts_command, static) =
645 .path = "show det44 timeouts",
646 .short_help = "show det44 timeouts",
647 .function = det44_show_timeouts_command_fn,
652 * @cliexstart{det44 plugin}
653 * Enable/disable DET44 plugin.
656 VLIB_CLI_COMMAND (det44_plugin_enable_disable_command, static) =
658 .path = "det44 plugin",
659 .short_help = "det44 plugin <enable [inside vrf] [outside vrf]|disable>",
660 .function = det44_plugin_enable_disable_command_fn,
665 * @cliexstart{set interface det44}
666 * Enable/disable DET44 feature on the interface.
667 * To enable DET44 feature with local network interface use:
668 * vpp# set interface det44 inside GigabitEthernet0/8/0
669 * To enable DET44 feature with external network interface use:
670 * vpp# set interface det44 outside GigabitEthernet0/a/0
673 VLIB_CLI_COMMAND (det44_feature_command, static) =
675 .path = "set interface det44",
676 .short_help = "set interface det44 inside <intfc> outside <intfc> [del]",
677 .function = det44_feature_command_fn,
682 * @cliexstart{show det44 interfaces}
683 * Show interfaces with DET44 feature.
684 * vpp# show det44 interfaces
686 * GigabitEthernet0/8/0 in
687 * GigabitEthernet0/a/0 out
690 VLIB_CLI_COMMAND (det44_show_interfaces_command, static) =
692 .path = "show det44 interfaces",
693 .short_help = "show det44 interfaces",
694 .function = det44_show_interfaces_command_fn,
699 * fd.io coding-style-patch-verification: ON
702 * eval: (c-set-style "gnu")