2 * snat.c - simple nat plugin
4 * Copyright (c) 2016 Cisco and/or its affiliates.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include <vnet/vnet.h>
19 #include <vnet/ip/ip.h>
20 #include <vnet/ip/ip4.h>
21 #include <vnet/plugin/plugin.h>
23 #include <nat/nat_dpo.h>
24 #include <nat/nat_ipfix_logging.h>
25 #include <nat/nat_det.h>
26 #include <nat/nat64.h>
27 #include <nat/nat66.h>
28 #include <nat/dslite.h>
29 #include <nat/nat_reass.h>
30 #include <nat/nat_inlines.h>
31 #include <nat/nat_affinity.h>
32 #include <nat/nat_syslog.h>
33 #include <nat/nat_ha.h>
34 #include <vnet/fib/fib_table.h>
35 #include <vnet/fib/ip4_fib.h>
37 #include <vpp/app/version.h>
39 snat_main_t snat_main;
43 /* Hook up input features */
44 VNET_FEATURE_INIT (ip4_snat_in2out, static) = {
45 .arc_name = "ip4-unicast",
46 .node_name = "nat44-in2out",
47 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
49 VNET_FEATURE_INIT (ip4_snat_out2in, static) = {
50 .arc_name = "ip4-unicast",
51 .node_name = "nat44-out2in",
52 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
53 "ip4-dhcp-client-detect"),
55 VNET_FEATURE_INIT (ip4_nat_classify, static) = {
56 .arc_name = "ip4-unicast",
57 .node_name = "nat44-classify",
58 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
60 VNET_FEATURE_INIT (ip4_snat_det_in2out, static) = {
61 .arc_name = "ip4-unicast",
62 .node_name = "nat44-det-in2out",
63 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
65 VNET_FEATURE_INIT (ip4_snat_det_out2in, static) = {
66 .arc_name = "ip4-unicast",
67 .node_name = "nat44-det-out2in",
68 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
69 "ip4-dhcp-client-detect"),
71 VNET_FEATURE_INIT (ip4_nat_det_classify, static) = {
72 .arc_name = "ip4-unicast",
73 .node_name = "nat44-det-classify",
74 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
76 VNET_FEATURE_INIT (ip4_nat44_ed_in2out, static) = {
77 .arc_name = "ip4-unicast",
78 .node_name = "nat44-ed-in2out",
79 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
81 VNET_FEATURE_INIT (ip4_nat44_ed_out2in, static) = {
82 .arc_name = "ip4-unicast",
83 .node_name = "nat44-ed-out2in",
84 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
85 "ip4-dhcp-client-detect"),
87 VNET_FEATURE_INIT (ip4_nat44_ed_classify, static) = {
88 .arc_name = "ip4-unicast",
89 .node_name = "nat44-ed-classify",
90 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
92 VNET_FEATURE_INIT (ip4_snat_in2out_worker_handoff, static) = {
93 .arc_name = "ip4-unicast",
94 .node_name = "nat44-in2out-worker-handoff",
95 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
97 VNET_FEATURE_INIT (ip4_snat_out2in_worker_handoff, static) = {
98 .arc_name = "ip4-unicast",
99 .node_name = "nat44-out2in-worker-handoff",
100 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
101 "ip4-dhcp-client-detect"),
103 VNET_FEATURE_INIT (ip4_nat_handoff_classify, static) = {
104 .arc_name = "ip4-unicast",
105 .node_name = "nat44-handoff-classify",
106 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
108 VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = {
109 .arc_name = "ip4-unicast",
110 .node_name = "nat44-in2out-fast",
111 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
113 VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = {
114 .arc_name = "ip4-unicast",
115 .node_name = "nat44-out2in-fast",
116 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
117 "ip4-dhcp-client-detect"),
119 VNET_FEATURE_INIT (ip4_snat_hairpin_dst, static) = {
120 .arc_name = "ip4-unicast",
121 .node_name = "nat44-hairpin-dst",
122 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
124 VNET_FEATURE_INIT (ip4_nat44_ed_hairpin_dst, static) = {
125 .arc_name = "ip4-unicast",
126 .node_name = "nat44-ed-hairpin-dst",
127 .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
130 /* Hook up output features */
131 VNET_FEATURE_INIT (ip4_snat_in2out_output, static) = {
132 .arc_name = "ip4-output",
133 .node_name = "nat44-in2out-output",
134 .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
136 VNET_FEATURE_INIT (ip4_snat_in2out_output_worker_handoff, static) = {
137 .arc_name = "ip4-output",
138 .node_name = "nat44-in2out-output-worker-handoff",
139 .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
141 VNET_FEATURE_INIT (ip4_snat_hairpin_src, static) = {
142 .arc_name = "ip4-output",
143 .node_name = "nat44-hairpin-src",
144 .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
146 VNET_FEATURE_INIT (ip4_nat44_ed_in2out_output, static) = {
147 .arc_name = "ip4-output",
148 .node_name = "nat44-ed-in2out-output",
149 .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
151 VNET_FEATURE_INIT (ip4_nat44_ed_hairpin_src, static) = {
152 .arc_name = "ip4-output",
153 .node_name = "nat44-ed-hairpin-src",
154 .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
157 /* Hook up ip4-local features */
158 VNET_FEATURE_INIT (ip4_nat_hairpinning, static) =
160 .arc_name = "ip4-local",
161 .node_name = "nat44-hairpinning",
162 .runs_before = VNET_FEATURES("ip4-local-end-of-arc"),
164 VNET_FEATURE_INIT (ip4_nat44_ed_hairpinning, static) =
166 .arc_name = "ip4-local",
167 .node_name = "nat44-ed-hairpinning",
168 .runs_before = VNET_FEATURES("ip4-local-end-of-arc"),
172 VLIB_PLUGIN_REGISTER () = {
173 .version = VPP_BUILD_VER,
174 .description = "Network Address Translation (NAT)",
179 nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
182 snat_session_key_t key;
183 clib_bihash_kv_8_8_t kv;
184 nat_ed_ses_key_t ed_key;
185 clib_bihash_kv_16_8_t ed_kv;
186 snat_main_per_thread_data_t *tsm =
187 vec_elt_at_index (sm->per_thread_data, thread_index);
189 if (is_fwd_bypass_session (s))
191 if (snat_is_unk_proto_session (s))
193 ed_key.proto = s->in2out.port;
199 ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
200 ed_key.l_port = s->in2out.port;
201 ed_key.r_port = s->ext_host_port;
203 ed_key.l_addr = s->in2out.addr;
204 ed_key.r_addr = s->ext_host_addr;
205 ed_key.fib_index = 0;
206 ed_kv.key[0] = ed_key.as_u64[0];
207 ed_kv.key[1] = ed_key.as_u64[1];
208 if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
209 nat_log_warn ("in2out_ed key del failed");
213 /* session lookup tables */
214 if (is_ed_session (s))
216 if (is_affinity_sessions (s))
217 nat_affinity_unlock (s->ext_host_addr, s->out2in.addr,
218 s->in2out.protocol, s->out2in.port);
219 ed_key.l_addr = s->out2in.addr;
220 ed_key.r_addr = s->ext_host_addr;
221 ed_key.fib_index = s->out2in.fib_index;
222 if (snat_is_unk_proto_session (s))
224 ed_key.proto = s->in2out.port;
230 ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
231 ed_key.l_port = s->out2in.port;
232 ed_key.r_port = s->ext_host_port;
234 ed_kv.key[0] = ed_key.as_u64[0];
235 ed_kv.key[1] = ed_key.as_u64[1];
236 if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0))
237 nat_log_warn ("out2in_ed key del failed");
238 ed_key.l_addr = s->in2out.addr;
239 ed_key.fib_index = s->in2out.fib_index;
240 if (!snat_is_unk_proto_session (s))
241 ed_key.l_port = s->in2out.port;
242 if (is_twice_nat_session (s))
244 ed_key.r_addr = s->ext_host_nat_addr;
245 ed_key.r_port = s->ext_host_nat_port;
247 ed_kv.key[0] = ed_key.as_u64[0];
248 ed_kv.key[1] = ed_key.as_u64[1];
249 if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
250 nat_log_warn ("in2out_ed key del failed");
253 nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
254 &s->in2out.addr, s->in2out.port,
255 &s->ext_host_nat_addr, s->ext_host_nat_port,
256 &s->out2in.addr, s->out2in.port,
257 &s->ext_host_addr, s->ext_host_port,
258 s->in2out.protocol, is_twice_nat_session (s));
262 kv.key = s->in2out.as_u64;
263 if (clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 0))
264 nat_log_warn ("in2out key del failed");
265 kv.key = s->out2in.as_u64;
266 if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0))
267 nat_log_warn ("out2in key del failed");
270 nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index,
271 &s->in2out.addr, s->in2out.port,
272 &s->out2in.addr, s->out2in.port,
276 if (snat_is_unk_proto_session (s))
282 snat_ipfix_logging_nat44_ses_delete (thread_index,
283 s->in2out.addr.as_u32,
284 s->out2in.addr.as_u32,
288 s->in2out.fib_index);
290 nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
291 s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
295 /* Twice NAT address and port for external host */
296 if (is_twice_nat_session (s))
298 key.protocol = s->in2out.protocol;
299 key.port = s->ext_host_nat_port;
300 key.addr.as_u32 = s->ext_host_nat_addr.as_u32;
301 snat_free_outside_address_and_port (sm->twice_nat_addresses,
305 if (snat_is_session_static (s))
308 snat_free_outside_address_and_port (sm->addresses, thread_index,
313 nat_user_get_or_create (snat_main_t * sm, ip4_address_t * addr, u32 fib_index,
317 snat_user_key_t user_key;
318 clib_bihash_kv_8_8_t kv, value;
319 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
320 dlist_elt_t *per_user_list_head_elt;
322 user_key.addr.as_u32 = addr->as_u32;
323 user_key.fib_index = fib_index;
324 kv.key = user_key.as_u64;
326 /* Ever heard of the "user" = src ip4 address before? */
327 if (clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
329 /* no, make a new one */
330 pool_get (tsm->users, u);
331 clib_memset (u, 0, sizeof (*u));
332 u->addr.as_u32 = addr->as_u32;
333 u->fib_index = fib_index;
335 pool_get (tsm->list_pool, per_user_list_head_elt);
337 u->sessions_per_user_list_head_index = per_user_list_head_elt -
340 clib_dlist_init (tsm->list_pool, u->sessions_per_user_list_head_index);
342 kv.value = u - tsm->users;
345 if (clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 1))
346 nat_log_warn ("user_hash keay add failed");
348 vlib_set_simple_counter (&sm->total_users, thread_index, 0,
349 pool_elts (tsm->users));
353 u = pool_elt_at_index (tsm->users, value.value);
360 nat_session_alloc_or_recycle (snat_main_t * sm, snat_user_t * u,
361 u32 thread_index, f64 now)
364 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
365 u32 oldest_per_user_translation_list_index, session_index;
366 dlist_elt_t *oldest_per_user_translation_list_elt;
367 dlist_elt_t *per_user_translation_list_elt;
369 /* Over quota? Recycle the least recently used translation */
370 if ((u->nsessions + u->nstaticsessions) >= sm->max_translations_per_user)
372 oldest_per_user_translation_list_index =
373 clib_dlist_remove_head (tsm->list_pool,
374 u->sessions_per_user_list_head_index);
376 ASSERT (oldest_per_user_translation_list_index != ~0);
378 /* Add it back to the end of the LRU list */
379 clib_dlist_addtail (tsm->list_pool,
380 u->sessions_per_user_list_head_index,
381 oldest_per_user_translation_list_index);
382 /* Get the list element */
383 oldest_per_user_translation_list_elt =
384 pool_elt_at_index (tsm->list_pool,
385 oldest_per_user_translation_list_index);
387 /* Get the session index from the list element */
388 session_index = oldest_per_user_translation_list_elt->value;
390 /* Get the session */
391 s = pool_elt_at_index (tsm->sessions, session_index);
392 nat_free_session_data (sm, s, thread_index, 0);
393 if (snat_is_session_static (s))
394 u->nstaticsessions--;
401 s->ext_host_addr.as_u32 = 0;
402 s->ext_host_port = 0;
403 s->ext_host_nat_addr.as_u32 = 0;
404 s->ext_host_nat_port = 0;
408 pool_get (tsm->sessions, s);
409 clib_memset (s, 0, sizeof (*s));
411 /* Create list elts */
412 pool_get (tsm->list_pool, per_user_translation_list_elt);
413 clib_dlist_init (tsm->list_pool,
414 per_user_translation_list_elt - tsm->list_pool);
416 per_user_translation_list_elt->value = s - tsm->sessions;
417 s->per_user_index = per_user_translation_list_elt - tsm->list_pool;
418 s->per_user_list_head_index = u->sessions_per_user_list_head_index;
420 clib_dlist_addtail (tsm->list_pool,
421 s->per_user_list_head_index,
422 per_user_translation_list_elt - tsm->list_pool);
424 s->user_index = u - tsm->users;
425 vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
426 pool_elts (tsm->sessions));
429 s->ha_last_refreshed = now;
435 nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index,
439 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
440 dlist_elt_t *per_user_translation_list_elt, *oldest_elt;
442 u64 sess_timeout_time;
444 if (PREDICT_FALSE (!(u->nsessions) && !(u->nstaticsessions)))
448 clib_dlist_remove_head (tsm->list_pool,
449 u->sessions_per_user_list_head_index);
450 oldest_elt = pool_elt_at_index (tsm->list_pool, oldest_index);
451 s = pool_elt_at_index (tsm->sessions, oldest_elt->value);
452 sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
453 if (now >= sess_timeout_time)
455 clib_dlist_addtail (tsm->list_pool,
456 u->sessions_per_user_list_head_index, oldest_index);
457 nat_free_session_data (sm, s, thread_index, 0);
458 if (snat_is_session_static (s))
459 u->nstaticsessions--;
466 s->ext_host_addr.as_u32 = 0;
467 s->ext_host_port = 0;
468 s->ext_host_nat_addr.as_u32 = 0;
469 s->ext_host_nat_port = 0;
473 clib_dlist_addhead (tsm->list_pool,
474 u->sessions_per_user_list_head_index, oldest_index);
475 if ((u->nsessions + u->nstaticsessions) >=
476 sm->max_translations_per_user)
478 nat_log_warn ("max translations per user %U", format_ip4_address,
480 snat_ipfix_logging_max_entries_per_user
481 (thread_index, sm->max_translations_per_user, u->addr.as_u32);
487 pool_get (tsm->sessions, s);
488 clib_memset (s, 0, sizeof (*s));
490 /* Create list elts */
491 pool_get (tsm->list_pool, per_user_translation_list_elt);
492 clib_dlist_init (tsm->list_pool,
493 per_user_translation_list_elt - tsm->list_pool);
495 per_user_translation_list_elt->value = s - tsm->sessions;
496 s->per_user_index = per_user_translation_list_elt - tsm->list_pool;
497 s->per_user_list_head_index = u->sessions_per_user_list_head_index;
499 clib_dlist_addtail (tsm->list_pool,
500 s->per_user_list_head_index,
501 per_user_translation_list_elt - tsm->list_pool);
504 vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
505 pool_elts (tsm->sessions));
508 s->ha_last_refreshed = now;
514 snat_add_del_addr_to_fib (ip4_address_t * addr, u8 p_len, u32 sw_if_index,
517 fib_prefix_t prefix = {
519 .fp_proto = FIB_PROTOCOL_IP4,
521 .ip4.as_u32 = addr->as_u32,
524 u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
527 fib_table_entry_update_one_path (fib_index,
529 FIB_SOURCE_PLUGIN_LOW,
530 (FIB_ENTRY_FLAG_CONNECTED |
531 FIB_ENTRY_FLAG_LOCAL |
532 FIB_ENTRY_FLAG_EXCLUSIVE),
536 ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
538 fib_table_entry_delete (fib_index, &prefix, FIB_SOURCE_PLUGIN_LOW);
542 snat_add_address (snat_main_t * sm, ip4_address_t * addr, u32 vrf_id,
547 vlib_thread_main_t *tm = vlib_get_thread_main ();
549 if (twice_nat && !sm->endpoint_dependent)
550 return VNET_API_ERROR_FEATURE_DISABLED;
552 /* Check if address already exists */
554 vec_foreach (ap, twice_nat ? sm->twice_nat_addresses : sm->addresses)
556 if (ap->addr.as_u32 == addr->as_u32)
557 return VNET_API_ERROR_VALUE_EXIST;
562 vec_add2 (sm->twice_nat_addresses, ap, 1);
564 vec_add2 (sm->addresses, ap, 1);
569 fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
570 FIB_SOURCE_PLUGIN_LOW);
573 #define _(N, i, n, s) \
574 clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535); \
575 ap->busy_##n##_ports = 0; \
576 ap->busy_##n##_ports_per_thread = 0;\
577 vec_validate_init_empty (ap->busy_##n##_ports_per_thread, tm->n_vlib_mains - 1, 0);
578 foreach_snat_protocol
583 /* Add external address to FIB */
585 pool_foreach (i, sm->interfaces,
587 if (nat_interface_is_inside(i) || sm->out2in_dpo)
590 snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
593 pool_foreach (i, sm->output_feature_interfaces,
595 if (nat_interface_is_inside(i) || sm->out2in_dpo)
598 snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
607 is_snat_address_used_in_static_mapping (snat_main_t * sm, ip4_address_t addr)
609 snat_static_mapping_t *m;
611 pool_foreach (m, sm->static_mappings,
613 if (is_addr_only_static_mapping (m) ||
614 is_out2in_only_static_mapping (m) ||
615 is_identity_static_mapping (m))
617 if (m->external_addr.as_u32 == addr.as_u32)
626 increment_v4_address (ip4_address_t * a)
630 v = clib_net_to_host_u32 (a->as_u32) + 1;
631 a->as_u32 = clib_host_to_net_u32 (v);
635 snat_add_static_mapping_when_resolved (snat_main_t * sm,
636 ip4_address_t l_addr,
641 snat_protocol_t proto,
642 int addr_only, int is_add, u8 * tag,
643 int twice_nat, int out2in_only,
646 snat_static_map_resolve_t *rp;
648 vec_add2 (sm->to_resolve, rp, 1);
649 rp->l_addr.as_u32 = l_addr.as_u32;
651 rp->sw_if_index = sw_if_index;
655 rp->addr_only = addr_only;
657 rp->twice_nat = twice_nat;
658 rp->out2in_only = out2in_only;
659 rp->identity_nat = identity_nat;
660 rp->tag = vec_dup (tag);
664 get_thread_idx_by_port (u16 e_port)
666 snat_main_t *sm = &snat_main;
667 u32 thread_idx = sm->num_workers;
668 if (sm->num_workers > 1)
671 sm->first_worker_index +
672 sm->workers[(e_port - 1024) / sm->port_per_thread];
678 snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
679 u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
680 u32 sw_if_index, snat_protocol_t proto, int is_add,
681 twice_nat_type_t twice_nat, u8 out2in_only, u8 * tag,
684 snat_main_t *sm = &snat_main;
685 snat_static_mapping_t *m;
686 snat_session_key_t m_key;
687 clib_bihash_kv_8_8_t kv, value;
688 snat_address_t *a = 0;
690 snat_interface_t *interface;
692 snat_main_per_thread_data_t *tsm;
693 snat_user_key_t u_key;
695 dlist_elt_t *head, *elt;
696 u32 elt_index, head_index;
700 snat_static_map_resolve_t *rp, *rp_match = 0;
701 nat44_lb_addr_port_t *local;
704 if (!sm->endpoint_dependent)
706 if (twice_nat || out2in_only)
707 return VNET_API_ERROR_FEATURE_DISABLED;
710 /* If the external address is a specific interface address */
711 if (sw_if_index != ~0)
713 ip4_address_t *first_int_addr;
715 for (i = 0; i < vec_len (sm->to_resolve); i++)
717 rp = sm->to_resolve + i;
718 if (rp->sw_if_index != sw_if_index ||
719 rp->l_addr.as_u32 != l_addr.as_u32 ||
720 rp->vrf_id != vrf_id || rp->addr_only != addr_only)
725 if ((rp->l_port != l_port && rp->e_port != e_port)
726 || rp->proto != proto)
734 /* Might be already set... */
735 first_int_addr = ip4_interface_first_address
736 (sm->ip4_main, sw_if_index, 0 /* just want the address */ );
741 return VNET_API_ERROR_VALUE_EXIST;
743 snat_add_static_mapping_when_resolved
744 (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
745 addr_only, is_add, tag, twice_nat, out2in_only, identity_nat);
747 /* DHCP resolution required? */
748 if (first_int_addr == 0)
754 e_addr.as_u32 = first_int_addr->as_u32;
755 /* Identity mapping? */
756 if (l_addr.as_u32 == 0)
757 l_addr.as_u32 = e_addr.as_u32;
763 return VNET_API_ERROR_NO_SUCH_ENTRY;
765 vec_del1 (sm->to_resolve, i);
769 e_addr.as_u32 = first_int_addr->as_u32;
770 /* Identity mapping? */
771 if (l_addr.as_u32 == 0)
772 l_addr.as_u32 = e_addr.as_u32;
780 m_key.port = addr_only ? 0 : e_port;
781 m_key.protocol = addr_only ? 0 : proto;
783 kv.key = m_key.as_u64;
784 if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
787 m = pool_elt_at_index (sm->static_mappings, value.value);
793 if (is_identity_static_mapping (m))
796 pool_foreach (local, m->locals,
798 if (local->vrf_id == vrf_id)
799 return VNET_API_ERROR_VALUE_EXIST;
802 pool_get (m->locals, local);
803 local->vrf_id = vrf_id;
805 fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
806 FIB_SOURCE_PLUGIN_LOW);
807 m_key.addr = m->local_addr;
808 m_key.port = m->local_port;
809 m_key.protocol = m->proto;
810 m_key.fib_index = local->fib_index;
811 kv.key = m_key.as_u64;
812 kv.value = m - sm->static_mappings;
813 clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
817 return VNET_API_ERROR_VALUE_EXIST;
820 if (twice_nat && addr_only)
821 return VNET_API_ERROR_UNSUPPORTED;
823 /* Convert VRF id to FIB index */
826 fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
827 FIB_SOURCE_PLUGIN_LOW);
828 /* If not specified use inside VRF id from SNAT plugin startup config */
831 fib_index = sm->inside_fib_index;
832 vrf_id = sm->inside_vrf_id;
835 if (!(out2in_only || identity_nat))
838 m_key.port = addr_only ? 0 : l_port;
839 m_key.protocol = addr_only ? 0 : proto;
840 m_key.fib_index = fib_index;
841 kv.key = m_key.as_u64;
842 if (!clib_bihash_search_8_8
843 (&sm->static_mapping_by_local, &kv, &value))
844 return VNET_API_ERROR_VALUE_EXIST;
847 /* Find external address in allocated addresses and reserve port for
848 address and port pair mapping when dynamic translations enabled */
849 if (!(addr_only || sm->static_mapping_only || out2in_only))
851 for (i = 0; i < vec_len (sm->addresses); i++)
853 if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
855 a = sm->addresses + i;
856 /* External port must be unused */
859 #define _(N, j, n, s) \
860 case SNAT_PROTOCOL_##N: \
861 if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \
862 return VNET_API_ERROR_INVALID_VALUE; \
863 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \
866 a->busy_##n##_ports++; \
867 a->busy_##n##_ports_per_thread[get_thread_idx_by_port(e_port)]++; \
870 foreach_snat_protocol
873 nat_log_info ("unknown protocol");
874 return VNET_API_ERROR_INVALID_VALUE_2;
879 /* External address must be allocated */
880 if (!a && (l_addr.as_u32 != e_addr.as_u32))
882 if (sw_if_index != ~0)
884 for (i = 0; i < vec_len (sm->to_resolve); i++)
886 rp = sm->to_resolve + i;
889 if (rp->sw_if_index != sw_if_index &&
890 rp->l_addr.as_u32 != l_addr.as_u32 &&
891 rp->vrf_id != vrf_id && rp->l_port != l_port &&
892 rp->e_port != e_port && rp->proto != proto)
895 vec_del1 (sm->to_resolve, i);
899 return VNET_API_ERROR_NO_SUCH_ENTRY;
903 pool_get (sm->static_mappings, m);
904 clib_memset (m, 0, sizeof (*m));
905 m->tag = vec_dup (tag);
906 m->local_addr = l_addr;
907 m->external_addr = e_addr;
908 m->twice_nat = twice_nat;
910 m->flags |= NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY;
912 m->flags |= NAT_STATIC_MAPPING_FLAG_ADDR_ONLY;
915 m->flags |= NAT_STATIC_MAPPING_FLAG_IDENTITY_NAT;
916 pool_get (m->locals, local);
917 local->vrf_id = vrf_id;
918 local->fib_index = fib_index;
923 m->fib_index = fib_index;
927 m->local_port = l_port;
928 m->external_port = e_port;
932 if (sm->num_workers > 1)
935 .src_address = m->local_addr,
937 vec_add1 (m->workers, sm->worker_in2out_cb (&ip, m->fib_index));
938 tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
941 tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
943 m_key.addr = m->local_addr;
944 m_key.port = m->local_port;
945 m_key.protocol = m->proto;
946 m_key.fib_index = fib_index;
947 kv.key = m_key.as_u64;
948 kv.value = m - sm->static_mappings;
950 clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
952 m_key.addr = m->external_addr;
953 m_key.port = m->external_port;
955 kv.key = m_key.as_u64;
956 kv.value = m - sm->static_mappings;
957 clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 1);
959 /* Delete dynamic sessions matching local address (+ local port) */
960 if (!(sm->static_mapping_only))
962 u_key.addr = m->local_addr;
963 u_key.fib_index = m->fib_index;
964 kv.key = u_key.as_u64;
965 if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
967 user_index = value.value;
968 u = pool_elt_at_index (tsm->users, user_index);
971 head_index = u->sessions_per_user_list_head_index;
972 head = pool_elt_at_index (tsm->list_pool, head_index);
973 elt_index = head->next;
974 elt = pool_elt_at_index (tsm->list_pool, elt_index);
975 ses_index = elt->value;
976 while (ses_index != ~0)
978 s = pool_elt_at_index (tsm->sessions, ses_index);
979 elt = pool_elt_at_index (tsm->list_pool, elt->next);
980 ses_index = elt->value;
982 if (snat_is_session_static (s))
986 && (clib_net_to_host_u16 (s->in2out.port) !=
990 nat_free_session_data (sm, s,
991 tsm - sm->per_thread_data, 0);
992 nat44_delete_session (sm, s, tsm - sm->per_thread_data);
994 if (!addr_only && !sm->endpoint_dependent)
1005 if (sw_if_index != ~0)
1008 return VNET_API_ERROR_NO_SUCH_ENTRY;
1014 vrf_id = sm->inside_vrf_id;
1017 pool_foreach (local, m->locals,
1019 if (local->vrf_id == vrf_id)
1020 find = local - m->locals;
1024 return VNET_API_ERROR_NO_SUCH_ENTRY;
1026 local = pool_elt_at_index (m->locals, find);
1027 fib_index = local->fib_index;
1028 pool_put (m->locals, local);
1031 fib_index = m->fib_index;
1033 /* Free external address port */
1034 if (!(addr_only || sm->static_mapping_only || out2in_only))
1036 for (i = 0; i < vec_len (sm->addresses); i++)
1038 if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1040 a = sm->addresses + i;
1043 #define _(N, j, n, s) \
1044 case SNAT_PROTOCOL_##N: \
1045 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \
1046 if (e_port > 1024) \
1048 a->busy_##n##_ports--; \
1049 a->busy_##n##_ports_per_thread[get_thread_idx_by_port(e_port)]--; \
1052 foreach_snat_protocol
1055 nat_log_info ("unknown protocol");
1056 return VNET_API_ERROR_INVALID_VALUE_2;
1063 if (sm->num_workers > 1)
1064 tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
1066 tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1068 m_key.addr = m->local_addr;
1069 m_key.port = m->local_port;
1070 m_key.protocol = m->proto;
1071 m_key.fib_index = fib_index;
1072 kv.key = m_key.as_u64;
1074 clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0);
1076 /* Delete session(s) for static mapping if exist */
1077 if (!(sm->static_mapping_only) ||
1078 (sm->static_mapping_only && sm->static_mapping_connection_tracking))
1080 u_key.addr = m->local_addr;
1081 u_key.fib_index = fib_index;
1082 kv.key = u_key.as_u64;
1083 if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
1085 user_index = value.value;
1086 u = pool_elt_at_index (tsm->users, user_index);
1087 if (u->nstaticsessions)
1089 head_index = u->sessions_per_user_list_head_index;
1090 head = pool_elt_at_index (tsm->list_pool, head_index);
1091 elt_index = head->next;
1092 elt = pool_elt_at_index (tsm->list_pool, elt_index);
1093 ses_index = elt->value;
1094 while (ses_index != ~0)
1096 s = pool_elt_at_index (tsm->sessions, ses_index);
1097 elt = pool_elt_at_index (tsm->list_pool, elt->next);
1098 ses_index = elt->value;
1102 if ((s->out2in.addr.as_u32 != e_addr.as_u32) ||
1103 (clib_net_to_host_u16 (s->out2in.port) !=
1108 if (is_lb_session (s))
1111 if (!snat_is_session_static (s))
1114 nat_free_session_data (sm, s,
1115 tsm - sm->per_thread_data, 0);
1116 nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1118 if (!addr_only && !sm->endpoint_dependent)
1125 fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_LOW);
1126 if (pool_elts (m->locals))
1129 m_key.addr = m->external_addr;
1130 m_key.port = m->external_port;
1131 m_key.fib_index = 0;
1132 kv.key = m_key.as_u64;
1133 clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 0);
1136 vec_free (m->workers);
1137 /* Delete static mapping from pool */
1138 pool_put (sm->static_mappings, m);
1141 if (!addr_only || (l_addr.as_u32 == e_addr.as_u32))
1144 /* Add/delete external address to FIB */
1146 pool_foreach (interface, sm->interfaces,
1148 if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1151 snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
1154 pool_foreach (interface, sm->output_feature_interfaces,
1156 if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1159 snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
1168 nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
1169 snat_protocol_t proto,
1170 nat44_lb_addr_port_t * locals, u8 is_add,
1171 twice_nat_type_t twice_nat, u8 out2in_only,
1172 u8 * tag, u32 affinity)
1174 snat_main_t *sm = &snat_main;
1175 snat_static_mapping_t *m;
1176 snat_session_key_t m_key;
1177 clib_bihash_kv_8_8_t kv, value;
1178 snat_address_t *a = 0;
1180 nat44_lb_addr_port_t *local;
1181 u32 elt_index, head_index, ses_index;
1182 snat_main_per_thread_data_t *tsm;
1183 snat_user_key_t u_key;
1186 dlist_elt_t *head, *elt;
1189 if (!sm->endpoint_dependent)
1190 return VNET_API_ERROR_FEATURE_DISABLED;
1192 m_key.addr = e_addr;
1193 m_key.port = e_port;
1194 m_key.protocol = proto;
1195 m_key.fib_index = 0;
1196 kv.key = m_key.as_u64;
1197 if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
1200 m = pool_elt_at_index (sm->static_mappings, value.value);
1205 return VNET_API_ERROR_VALUE_EXIST;
1207 if (vec_len (locals) < 2)
1208 return VNET_API_ERROR_INVALID_VALUE;
1210 /* Find external address in allocated addresses and reserve port for
1211 address and port pair mapping when dynamic translations enabled */
1212 if (!(sm->static_mapping_only || out2in_only))
1214 for (i = 0; i < vec_len (sm->addresses); i++)
1216 if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1218 a = sm->addresses + i;
1219 /* External port must be unused */
1222 #define _(N, j, n, s) \
1223 case SNAT_PROTOCOL_##N: \
1224 if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \
1225 return VNET_API_ERROR_INVALID_VALUE; \
1226 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \
1227 if (e_port > 1024) \
1229 a->busy_##n##_ports++; \
1230 a->busy_##n##_ports_per_thread[get_thread_idx_by_port(e_port)]++; \
1233 foreach_snat_protocol
1236 nat_log_info ("unknown protocol");
1237 return VNET_API_ERROR_INVALID_VALUE_2;
1242 /* External address must be allocated */
1244 return VNET_API_ERROR_NO_SUCH_ENTRY;
1247 pool_get (sm->static_mappings, m);
1248 clib_memset (m, 0, sizeof (*m));
1249 m->tag = vec_dup (tag);
1250 m->external_addr = e_addr;
1251 m->external_port = e_port;
1253 m->twice_nat = twice_nat;
1254 m->flags |= NAT_STATIC_MAPPING_FLAG_LB;
1256 m->flags |= NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY;
1257 m->affinity = affinity;
1260 m->affinity_per_service_list_head_index =
1261 nat_affinity_get_per_service_list_head_index ();
1263 m->affinity_per_service_list_head_index = ~0;
1265 m_key.addr = m->external_addr;
1266 m_key.port = m->external_port;
1267 m_key.protocol = m->proto;
1268 m_key.fib_index = 0;
1269 kv.key = m_key.as_u64;
1270 kv.value = m - sm->static_mappings;
1271 if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 1))
1273 nat_log_err ("static_mapping_by_external key add failed");
1274 return VNET_API_ERROR_UNSPECIFIED;
1277 m_key.fib_index = m->fib_index;
1278 for (i = 0; i < vec_len (locals); i++)
1280 locals[i].fib_index =
1281 fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
1283 FIB_SOURCE_PLUGIN_LOW);
1284 m_key.addr = locals[i].addr;
1285 m_key.fib_index = locals[i].fib_index;
1288 m_key.port = locals[i].port;
1289 kv.key = m_key.as_u64;
1290 kv.value = m - sm->static_mappings;
1291 clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1);
1293 locals[i].prefix = (i == 0) ? locals[i].probability :
1294 (locals[i - 1].prefix + locals[i].probability);
1295 pool_get (m->locals, local);
1297 if (sm->num_workers > 1)
1300 .src_address = locals[i].addr,
1303 clib_bitmap_set (bitmap,
1304 sm->worker_in2out_cb (&ip, m->fib_index), 1);
1308 /* Assign workers */
1309 if (sm->num_workers > 1)
1312 clib_bitmap_foreach (i, bitmap,
1314 vec_add1(m->workers, i);
1322 return VNET_API_ERROR_NO_SUCH_ENTRY;
1324 if (!is_lb_static_mapping (m))
1325 return VNET_API_ERROR_INVALID_VALUE;
1327 /* Free external address port */
1328 if (!(sm->static_mapping_only || out2in_only))
1330 for (i = 0; i < vec_len (sm->addresses); i++)
1332 if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
1334 a = sm->addresses + i;
1337 #define _(N, j, n, s) \
1338 case SNAT_PROTOCOL_##N: \
1339 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \
1340 if (e_port > 1024) \
1342 a->busy_##n##_ports--; \
1343 a->busy_##n##_ports_per_thread[get_thread_idx_by_port(e_port)]--; \
1346 foreach_snat_protocol
1349 nat_log_info ("unknown protocol");
1350 return VNET_API_ERROR_INVALID_VALUE_2;
1357 m_key.addr = m->external_addr;
1358 m_key.port = m->external_port;
1359 m_key.protocol = m->proto;
1360 m_key.fib_index = 0;
1361 kv.key = m_key.as_u64;
1362 if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 0))
1364 nat_log_err ("static_mapping_by_external key del failed");
1365 return VNET_API_ERROR_UNSPECIFIED;
1369 pool_foreach (local, m->locals,
1371 fib_table_unlock (local->fib_index, FIB_PROTOCOL_IP4,
1372 FIB_SOURCE_PLUGIN_LOW);
1373 m_key.addr = local->addr;
1376 m_key.port = local->port;
1377 m_key.fib_index = local->fib_index;
1378 kv.key = m_key.as_u64;
1379 if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0))
1381 nat_log_err ("static_mapping_by_local key del failed");
1382 return VNET_API_ERROR_UNSPECIFIED;
1386 if (sm->num_workers > 1)
1389 .src_address = local->addr,
1391 tsm = vec_elt_at_index (sm->per_thread_data,
1392 sm->worker_in2out_cb (&ip, m->fib_index));
1395 tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1397 /* Delete sessions */
1398 u_key.addr = local->addr;
1399 u_key.fib_index = local->fib_index;
1400 kv.key = u_key.as_u64;
1401 if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
1403 u = pool_elt_at_index (tsm->users, value.value);
1404 if (u->nstaticsessions)
1406 head_index = u->sessions_per_user_list_head_index;
1407 head = pool_elt_at_index (tsm->list_pool, head_index);
1408 elt_index = head->next;
1409 elt = pool_elt_at_index (tsm->list_pool, elt_index);
1410 ses_index = elt->value;
1411 while (ses_index != ~0)
1413 s = pool_elt_at_index (tsm->sessions, ses_index);
1414 elt = pool_elt_at_index (tsm->list_pool, elt->next);
1415 ses_index = elt->value;
1417 if (!(is_lb_session (s)))
1420 if ((s->in2out.addr.as_u32 != local->addr.as_u32) ||
1421 (clib_net_to_host_u16 (s->in2out.port) != local->port))
1424 nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
1425 nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1432 nat_affinity_flush_service (m->affinity_per_service_list_head_index);
1433 pool_free (m->locals);
1435 vec_free (m->workers);
1437 pool_put (sm->static_mappings, m);
1444 nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
1445 ip4_address_t l_addr, u16 l_port,
1446 snat_protocol_t proto, u32 vrf_id,
1447 u8 probability, u8 is_add)
1449 snat_main_t *sm = &snat_main;
1450 snat_static_mapping_t *m = 0;
1451 snat_session_key_t m_key;
1452 clib_bihash_kv_8_8_t kv, value;
1453 nat44_lb_addr_port_t *local, *prev_local, *match_local = 0;
1454 snat_main_per_thread_data_t *tsm;
1455 snat_user_key_t u_key;
1458 dlist_elt_t *head, *elt;
1459 u32 elt_index, head_index, ses_index, *locals = 0;
1463 if (!sm->endpoint_dependent)
1464 return VNET_API_ERROR_FEATURE_DISABLED;
1466 m_key.addr = e_addr;
1467 m_key.port = e_port;
1468 m_key.protocol = proto;
1469 m_key.fib_index = 0;
1470 kv.key = m_key.as_u64;
1471 if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
1472 m = pool_elt_at_index (sm->static_mappings, value.value);
1475 return VNET_API_ERROR_NO_SUCH_ENTRY;
1477 if (!is_lb_static_mapping (m))
1478 return VNET_API_ERROR_INVALID_VALUE;
1481 pool_foreach (local, m->locals,
1483 if ((local->addr.as_u32 == l_addr.as_u32) && (local->port == l_port) &&
1484 (local->vrf_id == vrf_id))
1486 match_local = local;
1495 return VNET_API_ERROR_VALUE_EXIST;
1497 pool_get (m->locals, local);
1498 clib_memset (local, 0, sizeof (*local));
1499 local->addr.as_u32 = l_addr.as_u32;
1500 local->port = l_port;
1501 local->probability = probability;
1502 local->vrf_id = vrf_id;
1504 fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
1505 FIB_SOURCE_PLUGIN_LOW);
1507 if (!is_out2in_only_static_mapping (m))
1509 m_key.addr = l_addr;
1510 m_key.port = l_port;
1511 m_key.fib_index = local->fib_index;
1512 kv.key = m_key.as_u64;
1513 kv.value = m - sm->static_mappings;
1514 if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1))
1515 nat_log_err ("static_mapping_by_local key add failed");
1521 return VNET_API_ERROR_NO_SUCH_ENTRY;
1523 if (pool_elts (m->locals) < 3)
1524 return VNET_API_ERROR_UNSPECIFIED;
1526 fib_table_unlock (match_local->fib_index, FIB_PROTOCOL_IP4,
1527 FIB_SOURCE_PLUGIN_LOW);
1529 if (!is_out2in_only_static_mapping (m))
1531 m_key.addr = l_addr;
1532 m_key.port = l_port;
1533 m_key.fib_index = match_local->fib_index;
1534 kv.key = m_key.as_u64;
1535 if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0))
1536 nat_log_err ("static_mapping_by_local key del failed");
1539 if (sm->num_workers > 1)
1542 .src_address = local->addr,
1544 tsm = vec_elt_at_index (sm->per_thread_data,
1545 sm->worker_in2out_cb (&ip, m->fib_index));
1548 tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1550 /* Delete sessions */
1551 u_key.addr = match_local->addr;
1552 u_key.fib_index = match_local->fib_index;
1553 kv.key = u_key.as_u64;
1554 if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
1556 u = pool_elt_at_index (tsm->users, value.value);
1557 if (u->nstaticsessions)
1559 head_index = u->sessions_per_user_list_head_index;
1560 head = pool_elt_at_index (tsm->list_pool, head_index);
1561 elt_index = head->next;
1562 elt = pool_elt_at_index (tsm->list_pool, elt_index);
1563 ses_index = elt->value;
1564 while (ses_index != ~0)
1566 s = pool_elt_at_index (tsm->sessions, ses_index);
1567 elt = pool_elt_at_index (tsm->list_pool, elt->next);
1568 ses_index = elt->value;
1570 if (!(is_lb_session (s)))
1573 if ((s->in2out.addr.as_u32 != match_local->addr.as_u32) ||
1574 (clib_net_to_host_u16 (s->in2out.port) !=
1578 nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
1579 nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1584 pool_put (m->locals, match_local);
1587 vec_free (m->workers);
1590 pool_foreach (local, m->locals,
1592 vec_add1 (locals, local - m->locals);
1593 if (sm->num_workers > 1)
1596 ip.src_address.as_u32 = local->addr.as_u32,
1597 bitmap = clib_bitmap_set (bitmap,
1598 sm->worker_in2out_cb (&ip, local->fib_index),
1604 ASSERT (vec_len (locals) > 1);
1606 local = pool_elt_at_index (m->locals, locals[0]);
1607 local->prefix = local->probability;
1608 for (i = 1; i < vec_len (locals); i++)
1610 local = pool_elt_at_index (m->locals, locals[i]);
1611 prev_local = pool_elt_at_index (m->locals, locals[i - 1]);
1612 local->prefix = local->probability + prev_local->prefix;
1615 /* Assign workers */
1616 if (sm->num_workers > 1)
1619 clib_bitmap_foreach (i, bitmap, ({ vec_add1(m->workers, i); }));
1627 snat_del_address (snat_main_t * sm, ip4_address_t addr, u8 delete_sm,
1630 snat_address_t *a = 0;
1631 snat_session_t *ses;
1632 u32 *ses_to_be_removed = 0, *ses_index;
1633 snat_main_per_thread_data_t *tsm;
1634 snat_static_mapping_t *m;
1635 snat_interface_t *interface;
1637 snat_address_t *addresses =
1638 twice_nat ? sm->twice_nat_addresses : sm->addresses;
1640 /* Find SNAT address */
1641 for (i = 0; i < vec_len (addresses); i++)
1643 if (addresses[i].addr.as_u32 == addr.as_u32)
1650 return VNET_API_ERROR_NO_SUCH_ENTRY;
1655 pool_foreach (m, sm->static_mappings,
1657 if (m->external_addr.as_u32 == addr.as_u32)
1658 (void) snat_add_static_mapping (m->local_addr, m->external_addr,
1659 m->local_port, m->external_port,
1660 m->vrf_id, is_addr_only_static_mapping(m), ~0,
1661 m->proto, 0, m->twice_nat,
1662 is_out2in_only_static_mapping(m), m->tag, is_identity_static_mapping(m));
1668 /* Check if address is used in some static mapping */
1669 if (is_snat_address_used_in_static_mapping (sm, addr))
1671 nat_log_notice ("address used in static mapping");
1672 return VNET_API_ERROR_UNSPECIFIED;
1676 if (a->fib_index != ~0)
1677 fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_LOW);
1679 /* Delete sessions using address */
1680 if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
1683 vec_foreach (tsm, sm->per_thread_data)
1685 pool_foreach (ses, tsm->sessions, ({
1686 if (ses->out2in.addr.as_u32 == addr.as_u32)
1688 nat_free_session_data (sm, ses, tsm - sm->per_thread_data, 0);
1689 vec_add1 (ses_to_be_removed, ses - tsm->sessions);
1693 vec_foreach (ses_index, ses_to_be_removed)
1695 ses = pool_elt_at_index (tsm->sessions, ses_index[0]);
1696 nat44_delete_session (sm, ses, tsm - sm->per_thread_data);
1699 vec_free (ses_to_be_removed);
1704 #define _(N, i, n, s) \
1705 clib_bitmap_free (a->busy_##n##_port_bitmap); \
1706 vec_free (a->busy_##n##_ports_per_thread);
1707 foreach_snat_protocol
1711 vec_del1 (sm->twice_nat_addresses, i);
1715 vec_del1 (sm->addresses, i);
1717 /* Delete external address from FIB */
1719 pool_foreach (interface, sm->interfaces,
1721 if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1724 snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
1727 pool_foreach (interface, sm->output_feature_interfaces,
1729 if (nat_interface_is_inside(interface) || sm->out2in_dpo)
1732 snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
1741 snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
1743 snat_main_t *sm = &snat_main;
1744 snat_interface_t *i;
1745 const char *feature_name, *del_feature_name;
1747 snat_static_mapping_t *m;
1749 nat_outside_fib_t *outside_fib;
1750 u32 fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
1753 if (sm->out2in_dpo && !is_inside)
1754 return VNET_API_ERROR_UNSUPPORTED;
1757 pool_foreach (i, sm->output_feature_interfaces,
1759 if (i->sw_if_index == sw_if_index)
1760 return VNET_API_ERROR_VALUE_EXIST;
1764 if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))
1765 feature_name = is_inside ? "nat44-in2out-fast" : "nat44-out2in-fast";
1768 if (sm->num_workers > 1 && !sm->deterministic)
1770 is_inside ? "nat44-in2out-worker-handoff" :
1771 "nat44-out2in-worker-handoff";
1772 else if (sm->deterministic)
1773 feature_name = is_inside ? "nat44-det-in2out" : "nat44-det-out2in";
1774 else if (sm->endpoint_dependent)
1775 feature_name = is_inside ? "nat44-ed-in2out" : "nat44-ed-out2in";
1777 feature_name = is_inside ? "nat44-in2out" : "nat44-out2in";
1780 if (sm->fq_in2out_index == ~0 && !sm->deterministic && sm->num_workers > 1)
1781 sm->fq_in2out_index = vlib_frame_queue_main_init (sm->in2out_node_index,
1784 if (sm->fq_out2in_index == ~0 && !sm->deterministic && sm->num_workers > 1)
1785 sm->fq_out2in_index = vlib_frame_queue_main_init (sm->out2in_node_index,
1791 vec_foreach (outside_fib, sm->outside_fibs)
1793 if (outside_fib->fib_index == fib_index)
1797 outside_fib->refcount--;
1798 if (!outside_fib->refcount)
1799 vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
1802 outside_fib->refcount++;
1809 vec_add2 (sm->outside_fibs, outside_fib, 1);
1810 outside_fib->refcount = 1;
1811 outside_fib->fib_index = fib_index;
1816 pool_foreach (i, sm->interfaces,
1818 if (i->sw_if_index == sw_if_index)
1822 if (nat_interface_is_inside(i) && nat_interface_is_outside(i))
1825 i->flags &= ~NAT_INTERFACE_FLAG_IS_INSIDE;
1827 i->flags &= ~NAT_INTERFACE_FLAG_IS_OUTSIDE;
1829 if (sm->num_workers > 1 && !sm->deterministic)
1831 del_feature_name = "nat44-handoff-classify";
1832 feature_name = !is_inside ? "nat44-in2out-worker-handoff" :
1833 "nat44-out2in-worker-handoff";
1835 else if (sm->deterministic)
1837 del_feature_name = "nat44-det-classify";
1838 feature_name = !is_inside ? "nat44-det-in2out" :
1841 else if (sm->endpoint_dependent)
1843 del_feature_name = "nat44-ed-classify";
1844 feature_name = !is_inside ? "nat44-ed-in2out" :
1849 del_feature_name = "nat44-classify";
1850 feature_name = !is_inside ? "nat44-in2out" : "nat44-out2in";
1853 vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
1854 sw_if_index, 0, 0, 0);
1855 vnet_feature_enable_disable ("ip4-unicast", feature_name,
1856 sw_if_index, 1, 0, 0);
1859 if (sm->endpoint_dependent)
1860 vnet_feature_enable_disable ("ip4-local",
1861 "nat44-ed-hairpinning",
1862 sw_if_index, 1, 0, 0);
1863 else if (!sm->deterministic)
1864 vnet_feature_enable_disable ("ip4-local",
1865 "nat44-hairpinning",
1866 sw_if_index, 1, 0, 0);
1871 vnet_feature_enable_disable ("ip4-unicast", feature_name,
1872 sw_if_index, 0, 0, 0);
1873 pool_put (sm->interfaces, i);
1876 if (sm->endpoint_dependent)
1877 vnet_feature_enable_disable ("ip4-local",
1878 "nat44-ed-hairpinning",
1879 sw_if_index, 0, 0, 0);
1880 else if (!sm->deterministic)
1881 vnet_feature_enable_disable ("ip4-local",
1882 "nat44-hairpinning",
1883 sw_if_index, 0, 0, 0);
1889 if ((nat_interface_is_inside(i) && is_inside) ||
1890 (nat_interface_is_outside(i) && !is_inside))
1893 if (sm->num_workers > 1 && !sm->deterministic)
1895 del_feature_name = !is_inside ? "nat44-in2out-worker-handoff" :
1896 "nat44-out2in-worker-handoff";
1897 feature_name = "nat44-handoff-classify";
1899 else if (sm->deterministic)
1901 del_feature_name = !is_inside ? "nat44-det-in2out" :
1903 feature_name = "nat44-det-classify";
1905 else if (sm->endpoint_dependent)
1907 del_feature_name = !is_inside ? "nat44-ed-in2out" :
1909 feature_name = "nat44-ed-classify";
1913 del_feature_name = !is_inside ? "nat44-in2out" : "nat44-out2in";
1914 feature_name = "nat44-classify";
1917 vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
1918 sw_if_index, 0, 0, 0);
1919 vnet_feature_enable_disable ("ip4-unicast", feature_name,
1920 sw_if_index, 1, 0, 0);
1923 if (sm->endpoint_dependent)
1924 vnet_feature_enable_disable ("ip4-local", "nat44-ed-hairpinning",
1925 sw_if_index, 0, 0, 0);
1926 else if (!sm->deterministic)
1927 vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
1928 sw_if_index, 0, 0, 0);
1939 return VNET_API_ERROR_NO_SUCH_ENTRY;
1941 pool_get (sm->interfaces, i);
1942 i->sw_if_index = sw_if_index;
1944 vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, 0,
1947 if (is_inside && !sm->out2in_dpo)
1949 if (sm->endpoint_dependent)
1950 vnet_feature_enable_disable ("ip4-local", "nat44-ed-hairpinning",
1951 sw_if_index, 1, 0, 0);
1952 else if (!sm->deterministic)
1953 vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning",
1954 sw_if_index, 1, 0, 0);
1960 i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
1964 i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
1966 /* Add/delete external addresses to FIB */
1969 vec_foreach (ap, sm->addresses)
1970 snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
1972 pool_foreach (m, sm->static_mappings,
1974 if (!(is_addr_only_static_mapping(m)) || (m->local_addr.as_u32 == m->external_addr.as_u32))
1977 snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
1980 pool_foreach (dm, sm->det_maps,
1982 snat_add_del_addr_to_fib(&dm->out_addr, dm->out_plen, sw_if_index, !is_del);
1990 snat_interface_add_del_output_feature (u32 sw_if_index,
1991 u8 is_inside, int is_del)
1993 snat_main_t *sm = &snat_main;
1994 snat_interface_t *i;
1996 snat_static_mapping_t *m;
1997 nat_outside_fib_t *outside_fib;
1998 u32 fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
2002 if (sm->deterministic ||
2003 (sm->static_mapping_only && !(sm->static_mapping_connection_tracking)))
2004 return VNET_API_ERROR_UNSUPPORTED;
2007 pool_foreach (i, sm->interfaces,
2009 if (i->sw_if_index == sw_if_index)
2010 return VNET_API_ERROR_VALUE_EXIST;
2017 vec_foreach (outside_fib, sm->outside_fibs)
2019 if (outside_fib->fib_index == fib_index)
2023 outside_fib->refcount--;
2024 if (!outside_fib->refcount)
2025 vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
2028 outside_fib->refcount++;
2035 vec_add2 (sm->outside_fibs, outside_fib, 1);
2036 outside_fib->refcount = 1;
2037 outside_fib->fib_index = fib_index;
2044 if (sm->endpoint_dependent)
2046 vnet_feature_enable_disable ("ip4-unicast", "nat44-ed-hairpin-dst",
2047 sw_if_index, !is_del, 0, 0);
2048 vnet_feature_enable_disable ("ip4-output", "nat44-ed-hairpin-src",
2049 sw_if_index, !is_del, 0, 0);
2053 vnet_feature_enable_disable ("ip4-unicast", "nat44-hairpin-dst",
2054 sw_if_index, !is_del, 0, 0);
2055 vnet_feature_enable_disable ("ip4-output", "nat44-hairpin-src",
2056 sw_if_index, !is_del, 0, 0);
2061 if (sm->num_workers > 1)
2063 vnet_feature_enable_disable ("ip4-unicast",
2064 "nat44-out2in-worker-handoff",
2065 sw_if_index, !is_del, 0, 0);
2066 vnet_feature_enable_disable ("ip4-output",
2067 "nat44-in2out-output-worker-handoff",
2068 sw_if_index, !is_del, 0, 0);
2072 if (sm->endpoint_dependent)
2074 vnet_feature_enable_disable ("ip4-unicast", "nat44-ed-out2in",
2075 sw_if_index, !is_del, 0, 0);
2076 vnet_feature_enable_disable ("ip4-output", "nat44-ed-in2out-output",
2077 sw_if_index, !is_del, 0, 0);
2081 vnet_feature_enable_disable ("ip4-unicast", "nat44-out2in",
2082 sw_if_index, !is_del, 0, 0);
2083 vnet_feature_enable_disable ("ip4-output", "nat44-in2out-output",
2084 sw_if_index, !is_del, 0, 0);
2089 if (sm->fq_in2out_output_index == ~0 && sm->num_workers > 1)
2090 sm->fq_in2out_output_index =
2091 vlib_frame_queue_main_init (sm->in2out_output_node_index, 0);
2093 if (sm->fq_out2in_index == ~0 && sm->num_workers > 1)
2094 sm->fq_out2in_index =
2095 vlib_frame_queue_main_init (sm->out2in_node_index, 0);
2098 pool_foreach (i, sm->output_feature_interfaces,
2100 if (i->sw_if_index == sw_if_index)
2103 pool_put (sm->output_feature_interfaces, i);
2105 return VNET_API_ERROR_VALUE_EXIST;
2113 return VNET_API_ERROR_NO_SUCH_ENTRY;
2115 pool_get (sm->output_feature_interfaces, i);
2116 i->sw_if_index = sw_if_index;
2119 i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
2121 i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
2123 /* Add/delete external addresses to FIB */
2129 vec_foreach (ap, sm->addresses)
2130 snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
2132 pool_foreach (m, sm->static_mappings,
2134 if (!((is_addr_only_static_mapping(m))) || (m->local_addr.as_u32 == m->external_addr.as_u32))
2137 snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
2145 snat_set_workers (uword * bitmap)
2147 snat_main_t *sm = &snat_main;
2150 if (sm->num_workers < 2)
2151 return VNET_API_ERROR_FEATURE_DISABLED;
2153 if (clib_bitmap_last_set (bitmap) >= sm->num_workers)
2154 return VNET_API_ERROR_INVALID_WORKER;
2156 vec_free (sm->workers);
2158 clib_bitmap_foreach (i, bitmap,
2160 vec_add1(sm->workers, i);
2161 sm->per_thread_data[sm->first_worker_index + i].snat_thread_index = j;
2166 sm->port_per_thread = (0xffff - 1024) / _vec_len (sm->workers);
2167 sm->num_snat_thread = _vec_len (sm->workers);
2173 snat_update_outside_fib (u32 sw_if_index, u32 new_fib_index,
2176 snat_main_t *sm = &snat_main;
2177 nat_outside_fib_t *outside_fib;
2178 snat_interface_t *i;
2181 if (new_fib_index == old_fib_index)
2184 if (!vec_len (sm->outside_fibs))
2187 pool_foreach (i, sm->interfaces, (
2189 if (i->sw_if_index == sw_if_index)
2191 if (!(nat_interface_is_outside (i)))
2195 vec_foreach (outside_fib, sm->outside_fibs)
2197 if (outside_fib->fib_index == old_fib_index)
2199 outside_fib->refcount--;
2200 if (!outside_fib->refcount)
2201 vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
2206 vec_foreach (outside_fib, sm->outside_fibs)
2208 if (outside_fib->fib_index == new_fib_index)
2210 outside_fib->refcount++;
2218 vec_add2 (sm->outside_fibs, outside_fib, 1);
2219 outside_fib->refcount = 1;
2220 outside_fib->fib_index = new_fib_index;
2225 snat_ip4_table_bind (ip4_main_t * im,
2227 u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
2229 snat_update_outside_fib (sw_if_index, new_fib_index, old_fib_index);
2233 snat_ip4_add_del_interface_address_cb (ip4_main_t * im,
2236 ip4_address_t * address,
2238 u32 if_address_index, u32 is_delete);
2241 nat_ip4_add_del_addr_only_sm_cb (ip4_main_t * im,
2244 ip4_address_t * address,
2246 u32 if_address_index, u32 is_delete);
2249 nat_alloc_addr_and_port_default (snat_address_t * addresses,
2252 snat_session_key_t * k,
2253 u16 port_per_thread, u32 snat_thread_index);
2255 static clib_error_t *
2256 snat_init (vlib_main_t * vm)
2258 snat_main_t *sm = &snat_main;
2259 clib_error_t *error = 0;
2260 ip4_main_t *im = &ip4_main;
2261 ip_lookup_main_t *lm = &im->lookup_main;
2263 vlib_thread_registration_t *tr;
2264 vlib_thread_main_t *tm = vlib_get_thread_main ();
2267 ip4_add_del_interface_address_callback_t cb4;
2271 sm->vnet_main = vnet_get_main ();
2273 sm->ip4_lookup_main = lm;
2274 sm->api_main = &api_main;
2275 sm->first_worker_index = 0;
2276 sm->num_workers = 0;
2277 sm->num_snat_thread = 1;
2279 sm->port_per_thread = 0xffff - 1024;
2280 sm->fq_in2out_index = ~0;
2281 sm->fq_in2out_output_index = ~0;
2282 sm->fq_out2in_index = ~0;
2283 sm->udp_timeout = SNAT_UDP_TIMEOUT;
2284 sm->tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
2285 sm->tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
2286 sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
2287 sm->alloc_addr_and_port = nat_alloc_addr_and_port_default;
2288 sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_DEFAULT;
2289 sm->forwarding_enabled = 0;
2290 sm->log_class = vlib_log_register_class ("nat", 0);
2291 sm->mss_clamping = 0;
2293 node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
2294 sm->error_node_index = node->index;
2296 node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out");
2297 sm->in2out_node_index = node->index;
2298 node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output");
2299 sm->in2out_output_node_index = node->index;
2300 node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-fast");
2301 sm->in2out_fast_node_index = node->index;
2302 node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-slowpath");
2303 sm->in2out_slowpath_node_index = node->index;
2304 node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output-slowpath");
2305 sm->in2out_slowpath_output_node_index = node->index;
2306 node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-reass");
2307 sm->in2out_reass_node_index = node->index;
2309 node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out");
2310 sm->ed_in2out_node_index = node->index;
2311 node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-slowpath");
2312 sm->ed_in2out_slowpath_node_index = node->index;
2313 node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-reass");
2314 sm->ed_in2out_reass_node_index = node->index;
2316 node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in");
2317 sm->out2in_node_index = node->index;
2318 node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in-fast");
2319 sm->out2in_fast_node_index = node->index;
2320 node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in-reass");
2321 sm->out2in_reass_node_index = node->index;
2323 node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in");
2324 sm->ed_out2in_node_index = node->index;
2325 node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in-slowpath");
2326 sm->ed_out2in_slowpath_node_index = node->index;
2327 node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in-reass");
2328 sm->ed_out2in_reass_node_index = node->index;
2330 node = vlib_get_node_by_name (vm, (u8 *) "nat44-det-in2out");
2331 sm->det_in2out_node_index = node->index;
2332 node = vlib_get_node_by_name (vm, (u8 *) "nat44-det-out2in");
2333 sm->det_out2in_node_index = node->index;
2335 node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpinning");
2336 sm->hairpinning_node_index = node->index;
2337 node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpin-dst");
2338 sm->hairpin_dst_node_index = node->index;
2339 node = vlib_get_node_by_name (vm, (u8 *) "nat44-hairpin-src");
2340 sm->hairpin_src_node_index = node->index;
2341 node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-hairpinning");
2342 sm->ed_hairpinning_node_index = node->index;
2343 node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-hairpin-dst");
2344 sm->ed_hairpin_dst_node_index = node->index;
2345 node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-hairpin-src");
2346 sm->ed_hairpin_src_node_index = node->index;
2348 p = hash_get_mem (tm->thread_registrations_by_name, "workers");
2351 tr = (vlib_thread_registration_t *) p[0];
2354 sm->num_workers = tr->count;
2355 sm->first_worker_index = tr->first_index;
2359 vec_validate (sm->per_thread_data, tm->n_vlib_mains - 1);
2361 /* Use all available workers by default */
2362 if (sm->num_workers > 1)
2364 for (i = 0; i < sm->num_workers; i++)
2365 bitmap = clib_bitmap_set (bitmap, i, 1);
2366 snat_set_workers (bitmap);
2367 clib_bitmap_free (bitmap);
2371 sm->per_thread_data[0].snat_thread_index = 0;
2374 error = snat_api_init (vm, sm);
2378 /* Set up the interface address add/del callback */
2379 cb4.function = snat_ip4_add_del_interface_address_cb;
2380 cb4.function_opaque = 0;
2382 vec_add1 (im->add_del_interface_address_callbacks, cb4);
2384 cb4.function = nat_ip4_add_del_addr_only_sm_cb;
2385 cb4.function_opaque = 0;
2387 vec_add1 (im->add_del_interface_address_callbacks, cb4);
2389 nat_dpo_module_init ();
2392 sm->total_users.name = "total-users";
2393 sm->total_users.stat_segment_name = "/nat44/total-users";
2394 vlib_validate_simple_counter (&sm->total_users, 0);
2395 vlib_zero_simple_counter (&sm->total_users, 0);
2396 sm->total_sessions.name = "total-sessions";
2397 sm->total_sessions.stat_segment_name = "/nat44/total-sessions";
2398 vlib_validate_simple_counter (&sm->total_sessions, 0);
2399 vlib_zero_simple_counter (&sm->total_sessions, 0);
2401 /* Init IPFIX logging */
2402 snat_ipfix_logging_init (vm);
2405 error = nat64_init (vm);
2413 ip4_table_bind_callback_t cbt4 = {
2414 .function = snat_ip4_table_bind,
2416 vec_add1 (ip4_main.table_bind_callbacks, cbt4);
2418 /* Init virtual fragmenentation reassembly */
2419 return nat_reass_init (vm);
2422 VLIB_INIT_FUNCTION (snat_init);
2425 snat_free_outside_address_and_port (snat_address_t * addresses,
2426 u32 thread_index, snat_session_key_t * k)
2430 u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
2432 for (address_index = 0; address_index < vec_len (addresses);
2435 if (addresses[address_index].addr.as_u32 == k->addr.as_u32)
2439 ASSERT (address_index < vec_len (addresses));
2441 a = addresses + address_index;
2443 switch (k->protocol)
2445 #define _(N, i, n, s) \
2446 case SNAT_PROTOCOL_##N: \
2447 ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
2448 port_host_byte_order) == 1); \
2449 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
2450 port_host_byte_order, 0); \
2451 a->busy_##n##_ports--; \
2452 a->busy_##n##_ports_per_thread[thread_index]--; \
2454 foreach_snat_protocol
2457 nat_log_info ("unknown protocol");
2463 nat_set_outside_address_and_port (snat_address_t * addresses,
2464 u32 thread_index, snat_session_key_t * k)
2466 snat_address_t *a = 0;
2468 u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
2470 for (address_index = 0; address_index < vec_len (addresses);
2473 if (addresses[address_index].addr.as_u32 != k->addr.as_u32)
2476 a = addresses + address_index;
2477 switch (k->protocol)
2479 #define _(N, j, n, s) \
2480 case SNAT_PROTOCOL_##N: \
2481 if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, port_host_byte_order)) \
2482 return VNET_API_ERROR_INSTANCE_IN_USE; \
2483 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, port_host_byte_order, 1); \
2484 a->busy_##n##_ports_per_thread[thread_index]++; \
2485 a->busy_##n##_ports++; \
2487 foreach_snat_protocol
2490 nat_log_info ("unknown protocol");
2495 return VNET_API_ERROR_NO_SUCH_ENTRY;
2499 snat_static_mapping_match (snat_main_t * sm,
2500 snat_session_key_t match,
2501 snat_session_key_t * mapping,
2504 twice_nat_type_t * twice_nat,
2505 lb_nat_type_t * lb, ip4_address_t * ext_host_addr,
2506 u8 * is_identity_nat)
2508 clib_bihash_kv_8_8_t kv, value;
2509 snat_static_mapping_t *m;
2510 snat_session_key_t m_key;
2511 clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
2512 u32 rand, lo = 0, hi, mid, *tmp = 0, i;
2514 nat44_lb_addr_port_t *local;
2516 m_key.fib_index = match.fib_index;
2519 mapping_hash = &sm->static_mapping_by_external;
2520 m_key.fib_index = 0;
2523 m_key.addr = match.addr;
2524 m_key.port = clib_net_to_host_u16 (match.port);
2525 m_key.protocol = match.protocol;
2527 kv.key = m_key.as_u64;
2529 if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2531 /* Try address only mapping */
2534 kv.key = m_key.as_u64;
2535 if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
2539 m = pool_elt_at_index (sm->static_mappings, value.value);
2543 if (is_lb_static_mapping (m))
2545 if (PREDICT_FALSE (lb != 0))
2546 *lb = m->affinity ? AFFINITY_LB_NAT : LB_NAT;
2549 if (nat_affinity_find_and_lock (ext_host_addr[0], match.addr,
2550 match.protocol, match.port,
2554 local = pool_elt_at_index (m->locals, backend_index);
2555 mapping->addr = local->addr;
2556 mapping->port = clib_host_to_net_u16 (local->port);
2557 mapping->fib_index = local->fib_index;
2562 pool_foreach_index (i, m->locals,
2567 hi = vec_len (tmp) - 1;
2568 local = pool_elt_at_index (m->locals, tmp[hi]);
2569 rand = 1 + (random_u32 (&sm->random_seed) % local->prefix);
2572 mid = ((hi - lo) >> 1) + lo;
2573 local = pool_elt_at_index (m->locals, tmp[mid]);
2574 (rand > local->prefix) ? (lo = mid + 1) : (hi = mid);
2576 local = pool_elt_at_index (m->locals, tmp[lo]);
2577 if (!(local->prefix >= rand))
2579 if (PREDICT_FALSE (sm->num_workers > 1))
2582 .src_address = local->addr,
2584 if (sm->worker_in2out_cb (&ip, m->fib_index) !=
2585 vlib_get_thread_index ())
2588 mapping->addr = local->addr;
2589 mapping->port = clib_host_to_net_u16 (local->port);
2590 mapping->fib_index = local->fib_index;
2593 if (nat_affinity_create_and_lock (ext_host_addr[0], match.addr,
2594 match.protocol, match.port,
2595 tmp[lo], m->affinity,
2596 m->affinity_per_service_list_head_index))
2597 nat_log_info ("create affinity record failed");
2603 if (PREDICT_FALSE (lb != 0))
2605 mapping->fib_index = m->fib_index;
2606 mapping->addr = m->local_addr;
2607 /* Address only mapping doesn't change port */
2608 mapping->port = is_addr_only_static_mapping (m) ? match.port
2609 : clib_host_to_net_u16 (m->local_port);
2611 mapping->protocol = m->proto;
2615 mapping->addr = m->external_addr;
2616 /* Address only mapping doesn't change port */
2617 mapping->port = is_addr_only_static_mapping (m) ? match.port
2618 : clib_host_to_net_u16 (m->external_port);
2619 mapping->fib_index = sm->outside_fib_index;
2623 if (PREDICT_FALSE (is_addr_only != 0))
2624 *is_addr_only = is_addr_only_static_mapping (m);
2626 if (PREDICT_FALSE (twice_nat != 0))
2627 *twice_nat = m->twice_nat;
2629 if (PREDICT_FALSE (is_identity_nat != 0))
2630 *is_identity_nat = is_identity_static_mapping (m);
2635 static_always_inline u16
2636 snat_random_port (u16 min, u16 max)
2638 snat_main_t *sm = &snat_main;
2639 return min + random_u32 (&sm->random_seed) /
2640 (random_u32_max () / (max - min + 1) + 1);
2644 snat_alloc_outside_address_and_port (snat_address_t * addresses,
2647 snat_session_key_t * k,
2648 u16 port_per_thread,
2649 u32 snat_thread_index)
2651 snat_main_t *sm = &snat_main;
2653 return sm->alloc_addr_and_port (addresses, fib_index, thread_index, k,
2654 port_per_thread, snat_thread_index);
2658 nat_alloc_addr_and_port_default (snat_address_t * addresses,
2661 snat_session_key_t * k,
2662 u16 port_per_thread, u32 snat_thread_index)
2665 snat_address_t *a, *ga = 0;
2668 for (i = 0; i < vec_len (addresses); i++)
2671 switch (k->protocol)
2673 #define _(N, j, n, s) \
2674 case SNAT_PROTOCOL_##N: \
2675 if (a->busy_##n##_ports_per_thread[thread_index] < port_per_thread) \
2677 if (a->fib_index == fib_index) \
2681 portnum = (port_per_thread * \
2682 snat_thread_index) + \
2683 snat_random_port(1, port_per_thread) + 1024; \
2684 if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2686 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2687 a->busy_##n##_ports_per_thread[thread_index]++; \
2688 a->busy_##n##_ports++; \
2689 k->addr = a->addr; \
2690 k->port = clib_host_to_net_u16(portnum); \
2694 else if (a->fib_index == ~0) \
2700 foreach_snat_protocol
2703 nat_log_info ("unknown protocol");
2712 switch (k->protocol)
2714 #define _(N, j, n, s) \
2715 case SNAT_PROTOCOL_##N: \
2718 portnum = (port_per_thread * \
2719 snat_thread_index) + \
2720 snat_random_port(1, port_per_thread) + 1024; \
2721 if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2723 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2724 a->busy_##n##_ports_per_thread[thread_index]++; \
2725 a->busy_##n##_ports++; \
2726 k->addr = a->addr; \
2727 k->port = clib_host_to_net_u16(portnum); \
2731 foreach_snat_protocol
2734 nat_log_info ("unknown protocol");
2739 /* Totally out of translations to use... */
2740 snat_ipfix_logging_addresses_exhausted (thread_index, 0);
2745 nat_alloc_addr_and_port_mape (snat_address_t * addresses,
2748 snat_session_key_t * k,
2749 u16 port_per_thread, u32 snat_thread_index)
2751 snat_main_t *sm = &snat_main;
2752 snat_address_t *a = addresses;
2753 u16 m, ports, portnum, A, j;
2754 m = 16 - (sm->psid_offset + sm->psid_length);
2755 ports = (1 << (16 - sm->psid_length)) - (1 << m);
2757 if (!vec_len (addresses))
2760 switch (k->protocol)
2762 #define _(N, i, n, s) \
2763 case SNAT_PROTOCOL_##N: \
2764 if (a->busy_##n##_ports < ports) \
2768 A = snat_random_port(1, pow2_mask(sm->psid_offset)); \
2769 j = snat_random_port(0, pow2_mask(m)); \
2770 portnum = A | (sm->psid << sm->psid_offset) | (j << (16 - m)); \
2771 if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2773 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2774 a->busy_##n##_ports++; \
2775 k->addr = a->addr; \
2776 k->port = clib_host_to_net_u16 (portnum); \
2781 foreach_snat_protocol
2784 nat_log_info ("unknown protocol");
2789 /* Totally out of translations to use... */
2790 snat_ipfix_logging_addresses_exhausted (thread_index, 0);
2795 nat_alloc_addr_and_port_range (snat_address_t * addresses,
2798 snat_session_key_t * k,
2799 u16 port_per_thread, u32 snat_thread_index)
2801 snat_main_t *sm = &snat_main;
2802 snat_address_t *a = addresses;
2805 ports = sm->end_port - sm->start_port + 1;
2807 if (!vec_len (addresses))
2810 switch (k->protocol)
2812 #define _(N, i, n, s) \
2813 case SNAT_PROTOCOL_##N: \
2814 if (a->busy_##n##_ports < ports) \
2818 portnum = snat_random_port(sm->start_port, sm->end_port); \
2819 if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
2821 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
2822 a->busy_##n##_ports++; \
2823 k->addr = a->addr; \
2824 k->port = clib_host_to_net_u16 (portnum); \
2829 foreach_snat_protocol
2832 nat_log_info ("unknown protocol");
2837 /* Totally out of translations to use... */
2838 snat_ipfix_logging_addresses_exhausted (thread_index, 0);
2843 nat44_add_del_address_dpo (ip4_address_t addr, u8 is_add)
2845 dpo_id_t dpo_v4 = DPO_INVALID;
2846 fib_prefix_t pfx = {
2847 .fp_proto = FIB_PROTOCOL_IP4,
2849 .fp_addr.ip4.as_u32 = addr.as_u32,
2854 nat_dpo_create (DPO_PROTO_IP4, 0, &dpo_v4);
2855 fib_table_entry_special_dpo_add (0, &pfx, FIB_SOURCE_PLUGIN_HI,
2856 FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4);
2857 dpo_reset (&dpo_v4);
2861 fib_table_entry_special_remove (0, &pfx, FIB_SOURCE_PLUGIN_HI);
2866 format_session_kvp (u8 * s, va_list * args)
2868 clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2869 snat_session_key_t k;
2873 s = format (s, "%U session-index %llu", format_snat_key, &k, v->value);
2879 format_static_mapping_kvp (u8 * s, va_list * args)
2881 clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2882 snat_session_key_t k;
2886 s = format (s, "%U static-mapping-index %llu",
2887 format_static_mapping_key, &k, v->value);
2893 format_user_kvp (u8 * s, va_list * args)
2895 clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
2900 s = format (s, "%U fib %d user-index %llu", format_ip4_address, &k.addr,
2901 k.fib_index, v->value);
2907 format_ed_session_kvp (u8 * s, va_list * args)
2909 clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *);
2912 k.as_u64[0] = v->key[0];
2913 k.as_u64[1] = v->key[1];
2916 format (s, "local %U:%d remote %U:%d proto %U fib %d session-index %llu",
2917 format_ip4_address, &k.l_addr, clib_net_to_host_u16 (k.l_port),
2918 format_ip4_address, &k.r_addr, clib_net_to_host_u16 (k.r_port),
2919 format_ip_protocol, k.proto, k.fib_index, v->value);
2925 snat_get_worker_in2out_cb (ip4_header_t * ip0, u32 rx_fib_index0)
2927 snat_main_t *sm = &snat_main;
2928 u32 next_worker_index = 0;
2931 next_worker_index = sm->first_worker_index;
2932 hash = ip0->src_address.as_u32 + (ip0->src_address.as_u32 >> 8) +
2933 (ip0->src_address.as_u32 >> 16) + (ip0->src_address.as_u32 >> 24);
2935 if (PREDICT_TRUE (is_pow2 (_vec_len (sm->workers))))
2936 next_worker_index += sm->workers[hash & (_vec_len (sm->workers) - 1)];
2938 next_worker_index += sm->workers[hash % _vec_len (sm->workers)];
2940 return next_worker_index;
2944 snat_get_worker_out2in_cb (ip4_header_t * ip0, u32 rx_fib_index0)
2946 snat_main_t *sm = &snat_main;
2949 snat_session_key_t m_key;
2950 clib_bihash_kv_8_8_t kv, value;
2951 snat_static_mapping_t *m;
2953 u32 next_worker_index = 0;
2955 /* first try static mappings without port */
2956 if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
2958 m_key.addr = ip0->dst_address;
2961 m_key.fib_index = rx_fib_index0;
2962 kv.key = m_key.as_u64;
2963 if (!clib_bihash_search_8_8
2964 (&sm->static_mapping_by_external, &kv, &value))
2966 m = pool_elt_at_index (sm->static_mappings, value.value);
2967 return m->workers[0];
2971 proto = ip_proto_to_snat_proto (ip0->protocol);
2972 udp = ip4_next_header (ip0);
2973 port = udp->dst_port;
2975 if (PREDICT_FALSE (ip4_is_fragment (ip0)))
2977 if (PREDICT_FALSE (nat_reass_is_drop_frag (0)))
2978 return vlib_get_thread_index ();
2980 nat_reass_ip4_t *reass;
2981 reass = nat_ip4_reass_find (ip0->src_address, ip0->dst_address,
2982 ip0->fragment_id, ip0->protocol);
2984 if (reass && (reass->thread_index != (u32) ~ 0))
2985 return reass->thread_index;
2987 if (ip4_is_first_fragment (ip0))
2990 nat_ip4_reass_create (ip0->src_address, ip0->dst_address,
2991 ip0->fragment_id, ip0->protocol);
2995 if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
2997 m_key.addr = ip0->dst_address;
2998 m_key.port = clib_net_to_host_u16 (port);
2999 m_key.protocol = proto;
3000 m_key.fib_index = rx_fib_index0;
3001 kv.key = m_key.as_u64;
3002 if (!clib_bihash_search_8_8
3003 (&sm->static_mapping_by_external, &kv, &value))
3005 m = pool_elt_at_index (sm->static_mappings, value.value);
3006 reass->thread_index = m->workers[0];
3007 return reass->thread_index;
3010 reass->thread_index = sm->first_worker_index;
3011 reass->thread_index +=
3012 sm->workers[(clib_net_to_host_u16 (port) - 1024) /
3013 sm->port_per_thread];
3014 return reass->thread_index;
3017 return vlib_get_thread_index ();
3021 /* unknown protocol */
3022 if (PREDICT_FALSE (proto == ~0))
3024 /* use current thread */
3025 return vlib_get_thread_index ();
3028 if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_ICMP))
3030 icmp46_header_t *icmp = (icmp46_header_t *) udp;
3031 icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1);
3032 if (!icmp_is_error_message (icmp))
3033 port = echo->identifier;
3036 ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1);
3037 proto = ip_proto_to_snat_proto (inner_ip->protocol);
3038 void *l4_header = ip4_next_header (inner_ip);
3041 case SNAT_PROTOCOL_ICMP:
3042 icmp = (icmp46_header_t *) l4_header;
3043 echo = (icmp_echo_header_t *) (icmp + 1);
3044 port = echo->identifier;
3046 case SNAT_PROTOCOL_UDP:
3047 case SNAT_PROTOCOL_TCP:
3048 port = ((tcp_udp_header_t *) l4_header)->src_port;
3051 return vlib_get_thread_index ();
3056 /* try static mappings with port */
3057 if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
3059 m_key.addr = ip0->dst_address;
3060 m_key.port = clib_net_to_host_u16 (port);
3061 m_key.protocol = proto;
3062 m_key.fib_index = rx_fib_index0;
3063 kv.key = m_key.as_u64;
3064 if (!clib_bihash_search_8_8
3065 (&sm->static_mapping_by_external, &kv, &value))
3067 m = pool_elt_at_index (sm->static_mappings, value.value);
3068 return m->workers[0];
3072 /* worker by outside port */
3073 next_worker_index = sm->first_worker_index;
3074 next_worker_index +=
3075 sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
3076 return next_worker_index;
3080 nat44_ed_get_worker_out2in_cb (ip4_header_t * ip, u32 rx_fib_index)
3082 snat_main_t *sm = &snat_main;
3083 clib_bihash_kv_8_8_t kv, value;
3084 u32 proto, next_worker_index = 0;
3087 snat_static_mapping_t *m;
3090 /* first try static mappings without port */
3091 if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
3093 make_sm_kv (&kv, &ip->dst_address, 0, rx_fib_index, 0);
3094 if (!clib_bihash_search_8_8
3095 (&sm->static_mapping_by_external, &kv, &value))
3097 m = pool_elt_at_index (sm->static_mappings, value.value);
3098 return m->workers[0];
3102 proto = ip_proto_to_snat_proto (ip->protocol);
3104 /* unknown protocol */
3105 if (PREDICT_FALSE (proto == ~0))
3107 /* use current thread */
3108 return vlib_get_thread_index ();
3111 udp = ip4_next_header (ip);
3112 port = udp->dst_port;
3114 if (PREDICT_FALSE (ip->protocol == IP_PROTOCOL_ICMP))
3116 icmp46_header_t *icmp = (icmp46_header_t *) udp;
3117 icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1);
3118 if (!icmp_is_error_message (icmp))
3119 port = echo->identifier;
3122 ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1);
3123 proto = ip_proto_to_snat_proto (inner_ip->protocol);
3124 void *l4_header = ip4_next_header (inner_ip);
3127 case SNAT_PROTOCOL_ICMP:
3128 icmp = (icmp46_header_t *) l4_header;
3129 echo = (icmp_echo_header_t *) (icmp + 1);
3130 port = echo->identifier;
3132 case SNAT_PROTOCOL_UDP:
3133 case SNAT_PROTOCOL_TCP:
3134 port = ((tcp_udp_header_t *) l4_header)->src_port;
3137 return vlib_get_thread_index ();
3142 /* try static mappings with port */
3143 if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
3145 make_sm_kv (&kv, &ip->dst_address, proto, rx_fib_index,
3146 clib_net_to_host_u16 (port));
3147 if (!clib_bihash_search_8_8
3148 (&sm->static_mapping_by_external, &kv, &value))
3150 m = pool_elt_at_index (sm->static_mappings, value.value);
3151 if (!is_lb_static_mapping (m))
3152 return m->workers[0];
3154 hash = ip->src_address.as_u32 + (ip->src_address.as_u32 >> 8) +
3155 (ip->src_address.as_u32 >> 16) + (ip->src_address.as_u32 >> 24);
3157 if (PREDICT_TRUE (is_pow2 (_vec_len (m->workers))))
3158 return m->workers[hash & (_vec_len (m->workers) - 1)];
3160 return m->workers[hash % _vec_len (m->workers)];
3164 /* worker by outside port */
3165 next_worker_index = sm->first_worker_index;
3166 next_worker_index +=
3167 sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
3169 return next_worker_index;
3173 nat_ha_sadd_cb (ip4_address_t * in_addr, u16 in_port,
3174 ip4_address_t * out_addr, u16 out_port,
3175 ip4_address_t * eh_addr, u16 eh_port,
3176 ip4_address_t * ehn_addr, u16 ehn_port, u8 proto,
3177 u32 fib_index, u16 flags, u32 thread_index)
3179 snat_main_t *sm = &snat_main;
3180 snat_session_key_t key;
3183 clib_bihash_kv_8_8_t kv;
3184 f64 now = vlib_time_now (sm->vlib_main);
3185 nat_outside_fib_t *outside_fib;
3186 fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
3187 snat_main_per_thread_data_t *tsm;
3188 fib_prefix_t pfx = {
3189 .fp_proto = FIB_PROTOCOL_IP4,
3192 .ip4.as_u32 = eh_addr->as_u32,
3196 tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3198 key.addr.as_u32 = out_addr->as_u32;
3199 key.port = out_port;
3200 key.protocol = proto;
3202 if (!(flags & SNAT_SESSION_FLAG_STATIC_MAPPING))
3204 if (nat_set_outside_address_and_port
3205 (sm->addresses, thread_index, &key))
3209 u = nat_user_get_or_create (sm, in_addr, fib_index, thread_index);
3213 s = nat_session_alloc_or_recycle (sm, u, thread_index, now);
3217 s->last_heard = now;
3219 s->ext_host_addr.as_u32 = eh_addr->as_u32;
3220 s->ext_host_port = eh_port;
3221 user_session_increment (sm, u, snat_is_session_static (s));
3222 switch (vec_len (sm->outside_fibs))
3225 key.fib_index = sm->outside_fib_index;
3228 key.fib_index = sm->outside_fibs[0].fib_index;
3232 vec_foreach (outside_fib, sm->outside_fibs)
3234 fei = fib_table_lookup (outside_fib->fib_index, &pfx);
3235 if (FIB_NODE_INDEX_INVALID != fei)
3237 if (fib_entry_get_resolving_interface (fei) != ~0)
3239 key.fib_index = outside_fib->fib_index;
3248 kv.key = key.as_u64;
3249 kv.value = s - tsm->sessions;
3250 if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 1))
3251 nat_log_warn ("out2in key add failed");
3253 key.addr.as_u32 = in_addr->as_u32;
3255 key.fib_index = fib_index;
3257 kv.key = key.as_u64;
3258 if (clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 1))
3259 nat_log_warn ("in2out key add failed");
3263 nat_ha_sdel_cb (ip4_address_t * out_addr, u16 out_port,
3264 ip4_address_t * eh_addr, u16 eh_port, u8 proto, u32 fib_index,
3267 snat_main_t *sm = &snat_main;
3268 snat_session_key_t key;
3269 clib_bihash_kv_8_8_t kv, value;
3272 snat_main_per_thread_data_t *tsm;
3274 if (sm->num_workers > 1)
3276 sm->first_worker_index +
3277 (sm->workers[(clib_net_to_host_u16 (out_port) -
3278 1024) / sm->port_per_thread]);
3280 thread_index = sm->num_workers;
3281 tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3283 key.addr.as_u32 = out_addr->as_u32;
3284 key.port = out_port;
3285 key.protocol = proto;
3286 key.fib_index = fib_index;
3287 kv.key = key.as_u64;
3288 if (clib_bihash_search_8_8 (&tsm->out2in, &kv, &value))
3291 s = pool_elt_at_index (tsm->sessions, value.value);
3292 nat_free_session_data (sm, s, thread_index, 1);
3293 nat44_delete_session (sm, s, thread_index);
3297 nat_ha_sref_cb (ip4_address_t * out_addr, u16 out_port,
3298 ip4_address_t * eh_addr, u16 eh_port, u8 proto, u32 fib_index,
3299 u32 total_pkts, u64 total_bytes, u32 thread_index)
3301 snat_main_t *sm = &snat_main;
3302 snat_session_key_t key;
3303 clib_bihash_kv_8_8_t kv, value;
3305 snat_main_per_thread_data_t *tsm;
3307 tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3309 key.addr.as_u32 = out_addr->as_u32;
3310 key.port = out_port;
3311 key.protocol = proto;
3312 key.fib_index = fib_index;
3313 kv.key = key.as_u64;
3314 if (clib_bihash_search_8_8 (&tsm->out2in, &kv, &value))
3317 s = pool_elt_at_index (tsm->sessions, value.value);
3318 s->total_pkts = total_pkts;
3319 s->total_bytes = total_bytes;
3323 nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port,
3324 ip4_address_t * out_addr, u16 out_port,
3325 ip4_address_t * eh_addr, u16 eh_port,
3326 ip4_address_t * ehn_addr, u16 ehn_port, u8 proto,
3327 u32 fib_index, u16 flags, u32 thread_index)
3329 snat_main_t *sm = &snat_main;
3330 snat_session_key_t key;
3333 clib_bihash_kv_16_8_t kv;
3334 f64 now = vlib_time_now (sm->vlib_main);
3335 nat_outside_fib_t *outside_fib;
3336 fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
3337 snat_main_per_thread_data_t *tsm;
3338 fib_prefix_t pfx = {
3339 .fp_proto = FIB_PROTOCOL_IP4,
3342 .ip4.as_u32 = eh_addr->as_u32,
3346 tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3348 key.addr.as_u32 = out_addr->as_u32;
3349 key.port = out_port;
3350 key.protocol = proto;
3352 if (!(flags & SNAT_SESSION_FLAG_STATIC_MAPPING))
3354 if (nat_set_outside_address_and_port
3355 (sm->addresses, thread_index, &key))
3359 key.addr.as_u32 = ehn_addr->as_u32;
3360 key.port = ehn_port;
3361 if (flags & SNAT_SESSION_FLAG_TWICE_NAT)
3363 if (nat_set_outside_address_and_port
3364 (sm->twice_nat_addresses, thread_index, &key))
3368 u = nat_user_get_or_create (sm, in_addr, fib_index, thread_index);
3372 s = nat_ed_session_alloc (sm, u, thread_index, now);
3376 s->last_heard = now;
3378 s->ext_host_nat_addr.as_u32 = s->ext_host_addr.as_u32 = eh_addr->as_u32;
3379 s->ext_host_nat_port = s->ext_host_port = eh_port;
3380 if (is_twice_nat_session (s))
3382 s->ext_host_nat_addr.as_u32 = ehn_addr->as_u32;
3383 s->ext_host_nat_port = ehn_port;
3385 user_session_increment (sm, u, snat_is_session_static (s));
3386 switch (vec_len (sm->outside_fibs))
3389 key.fib_index = sm->outside_fib_index;
3392 key.fib_index = sm->outside_fibs[0].fib_index;
3396 vec_foreach (outside_fib, sm->outside_fibs)
3398 fei = fib_table_lookup (outside_fib->fib_index, &pfx);
3399 if (FIB_NODE_INDEX_INVALID != fei)
3401 if (fib_entry_get_resolving_interface (fei) != ~0)
3403 key.fib_index = outside_fib->fib_index;
3411 key.addr.as_u32 = out_addr->as_u32;
3412 key.port = out_port;
3414 kv.value = s - tsm->sessions;
3416 key.addr.as_u32 = in_addr->as_u32;
3418 key.fib_index = fib_index;
3421 make_ed_kv (&kv, in_addr, &s->ext_host_nat_addr,
3422 snat_proto_to_ip_proto (proto), fib_index, in_port,
3423 s->ext_host_nat_port);
3424 if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &kv, 1))
3425 nat_log_warn ("in2out key add failed");
3427 make_ed_kv (&kv, out_addr, eh_addr, snat_proto_to_ip_proto (proto),
3428 s->out2in.fib_index, out_port, eh_port);
3429 if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &kv, 1))
3430 nat_log_warn ("out2in key add failed");
3434 nat_ha_sdel_ed_cb (ip4_address_t * out_addr, u16 out_port,
3435 ip4_address_t * eh_addr, u16 eh_port, u8 proto,
3436 u32 fib_index, u32 ti)
3438 snat_main_t *sm = &snat_main;
3439 nat_ed_ses_key_t key;
3440 clib_bihash_kv_16_8_t kv, value;
3443 snat_main_per_thread_data_t *tsm;
3445 if (sm->num_workers > 1)
3447 sm->first_worker_index +
3448 (sm->workers[(clib_net_to_host_u16 (out_port) -
3449 1024) / sm->port_per_thread]);
3451 thread_index = sm->num_workers;
3452 tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3454 key.l_addr.as_u32 = out_addr->as_u32;
3455 key.l_port = out_port;
3456 key.r_addr.as_u32 = eh_addr->as_u32;
3457 key.r_port = eh_port;
3459 key.fib_index = fib_index;
3460 kv.key[0] = key.as_u64[0];
3461 kv.key[1] = key.as_u64[1];
3462 if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
3465 s = pool_elt_at_index (tsm->sessions, value.value);
3466 nat_free_session_data (sm, s, thread_index, 1);
3467 nat44_delete_session (sm, s, thread_index);
3471 nat_ha_sref_ed_cb (ip4_address_t * out_addr, u16 out_port,
3472 ip4_address_t * eh_addr, u16 eh_port, u8 proto,
3473 u32 fib_index, u32 total_pkts, u64 total_bytes,
3476 snat_main_t *sm = &snat_main;
3477 nat_ed_ses_key_t key;
3478 clib_bihash_kv_16_8_t kv, value;
3480 snat_main_per_thread_data_t *tsm;
3482 tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
3484 key.l_addr.as_u32 = out_addr->as_u32;
3485 key.l_port = out_port;
3486 key.r_addr.as_u32 = eh_addr->as_u32;
3487 key.r_port = eh_port;
3489 key.fib_index = fib_index;
3490 kv.key[0] = key.as_u64[0];
3491 kv.key[1] = key.as_u64[1];
3492 if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
3495 s = pool_elt_at_index (tsm->sessions, value.value);
3496 s->total_pkts = total_pkts;
3497 s->total_bytes = total_bytes;
3500 static clib_error_t *
3501 snat_config (vlib_main_t * vm, unformat_input_t * input)
3503 snat_main_t *sm = &snat_main;
3504 nat66_main_t *nm = &nat66_main;
3505 u32 translation_buckets = 1024;
3506 u32 translation_memory_size = 128 << 20;
3507 u32 user_buckets = 128;
3508 u32 user_memory_size = 64 << 20;
3509 u32 max_translations_per_user = 100;
3510 u32 outside_vrf_id = 0;
3511 u32 outside_ip6_vrf_id = 0;
3512 u32 inside_vrf_id = 0;
3513 u32 static_mapping_buckets = 1024;
3514 u32 static_mapping_memory_size = 64 << 20;
3515 u32 nat64_bib_buckets = 1024;
3516 u32 nat64_bib_memory_size = 128 << 20;
3517 u32 nat64_st_buckets = 2048;
3518 u32 nat64_st_memory_size = 256 << 20;
3519 u8 static_mapping_only = 0;
3520 u8 static_mapping_connection_tracking = 0;
3521 snat_main_per_thread_data_t *tsm;
3522 dslite_main_t *dm = &dslite_main;
3524 sm->deterministic = 0;
3526 sm->endpoint_dependent = 0;
3528 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3531 (input, "translation hash buckets %d", &translation_buckets))
3533 else if (unformat (input, "translation hash memory %d",
3534 &translation_memory_size));
3535 else if (unformat (input, "user hash buckets %d", &user_buckets))
3537 else if (unformat (input, "user hash memory %d", &user_memory_size))
3539 else if (unformat (input, "max translations per user %d",
3540 &max_translations_per_user))
3542 else if (unformat (input, "outside VRF id %d", &outside_vrf_id))
3544 else if (unformat (input, "outside ip6 VRF id %d", &outside_ip6_vrf_id))
3546 else if (unformat (input, "inside VRF id %d", &inside_vrf_id))
3548 else if (unformat (input, "static mapping only"))
3550 static_mapping_only = 1;
3551 if (unformat (input, "connection tracking"))
3552 static_mapping_connection_tracking = 1;
3554 else if (unformat (input, "deterministic"))
3555 sm->deterministic = 1;
3556 else if (unformat (input, "nat64 bib hash buckets %d",
3557 &nat64_bib_buckets))
3559 else if (unformat (input, "nat64 bib hash memory %d",
3560 &nat64_bib_memory_size))
3563 if (unformat (input, "nat64 st hash buckets %d", &nat64_st_buckets))
3565 else if (unformat (input, "nat64 st hash memory %d",
3566 &nat64_st_memory_size))
3568 else if (unformat (input, "out2in dpo"))
3570 else if (unformat (input, "dslite ce"))
3571 dslite_set_ce (dm, 1);
3572 else if (unformat (input, "endpoint-dependent"))
3573 sm->endpoint_dependent = 1;
3575 return clib_error_return (0, "unknown input '%U'",
3576 format_unformat_error, input);
3579 if (sm->deterministic && sm->endpoint_dependent)
3580 return clib_error_return (0,
3581 "deterministic and endpoint-dependent modes are mutually exclusive");
3583 if (static_mapping_only && (sm->deterministic || sm->endpoint_dependent))
3584 return clib_error_return (0,
3585 "static mapping only mode available only for simple nat");
3587 if (sm->out2in_dpo && (sm->deterministic || sm->endpoint_dependent))
3588 return clib_error_return (0,
3589 "out2in dpo mode available only for simple nat");
3591 /* for show commands, etc. */
3592 sm->translation_buckets = translation_buckets;
3593 sm->translation_memory_size = translation_memory_size;
3594 /* do not exceed load factor 10 */
3595 sm->max_translations = 10 * translation_buckets;
3596 sm->user_buckets = user_buckets;
3597 sm->user_memory_size = user_memory_size;
3598 sm->max_translations_per_user = max_translations_per_user;
3599 sm->outside_vrf_id = outside_vrf_id;
3600 sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
3602 FIB_SOURCE_PLUGIN_HI);
3603 nm->outside_vrf_id = outside_ip6_vrf_id;
3604 nm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
3606 FIB_SOURCE_PLUGIN_HI);
3607 sm->inside_vrf_id = inside_vrf_id;
3608 sm->inside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
3610 FIB_SOURCE_PLUGIN_HI);
3611 sm->static_mapping_only = static_mapping_only;
3612 sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
3614 nat64_set_hash (nat64_bib_buckets, nat64_bib_memory_size, nat64_st_buckets,
3615 nat64_st_memory_size);
3617 if (sm->deterministic)
3619 sm->in2out_node_index = snat_det_in2out_node.index;
3620 sm->in2out_output_node_index = ~0;
3621 sm->out2in_node_index = snat_det_out2in_node.index;
3622 sm->icmp_match_in2out_cb = icmp_match_in2out_det;
3623 sm->icmp_match_out2in_cb = icmp_match_out2in_det;
3627 if (sm->endpoint_dependent)
3629 sm->worker_in2out_cb = snat_get_worker_in2out_cb;
3630 sm->worker_out2in_cb = nat44_ed_get_worker_out2in_cb;
3631 sm->in2out_node_index = nat44_ed_in2out_node.index;
3632 sm->in2out_output_node_index = nat44_ed_in2out_output_node.index;
3633 sm->out2in_node_index = nat44_ed_out2in_node.index;
3634 sm->icmp_match_in2out_cb = icmp_match_in2out_ed;
3635 sm->icmp_match_out2in_cb = icmp_match_out2in_ed;
3636 nat_affinity_init (vm);
3637 nat_ha_init (vm, nat_ha_sadd_ed_cb, nat_ha_sdel_ed_cb,
3642 sm->worker_in2out_cb = snat_get_worker_in2out_cb;
3643 sm->worker_out2in_cb = snat_get_worker_out2in_cb;
3644 sm->in2out_node_index = snat_in2out_node.index;
3645 sm->in2out_output_node_index = snat_in2out_output_node.index;
3646 sm->out2in_node_index = snat_out2in_node.index;
3647 sm->icmp_match_in2out_cb = icmp_match_in2out_slow;
3648 sm->icmp_match_out2in_cb = icmp_match_out2in_slow;
3649 nat_ha_init (vm, nat_ha_sadd_cb, nat_ha_sdel_cb, nat_ha_sref_cb);
3651 if (!static_mapping_only ||
3652 (static_mapping_only && static_mapping_connection_tracking))
3655 vec_foreach (tsm, sm->per_thread_data)
3657 if (sm->endpoint_dependent)
3659 clib_bihash_init_16_8 (&tsm->in2out_ed, "in2out-ed",
3660 translation_buckets,
3661 translation_memory_size);
3662 clib_bihash_set_kvp_format_fn_16_8 (&tsm->in2out_ed,
3663 format_ed_session_kvp);
3665 clib_bihash_init_16_8 (&tsm->out2in_ed, "out2in-ed",
3666 translation_buckets,
3667 translation_memory_size);
3668 clib_bihash_set_kvp_format_fn_16_8 (&tsm->out2in_ed,
3669 format_ed_session_kvp);
3673 clib_bihash_init_8_8 (&tsm->in2out, "in2out",
3674 translation_buckets,
3675 translation_memory_size);
3676 clib_bihash_set_kvp_format_fn_8_8 (&tsm->in2out,
3677 format_session_kvp);
3679 clib_bihash_init_8_8 (&tsm->out2in, "out2in",
3680 translation_buckets,
3681 translation_memory_size);
3682 clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in,
3683 format_session_kvp);
3686 clib_bihash_init_8_8 (&tsm->user_hash, "users", user_buckets,
3688 clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash,
3696 sm->icmp_match_in2out_cb = icmp_match_in2out_fast;
3697 sm->icmp_match_out2in_cb = icmp_match_out2in_fast;
3699 clib_bihash_init_8_8 (&sm->static_mapping_by_local,
3700 "static_mapping_by_local", static_mapping_buckets,
3701 static_mapping_memory_size);
3702 clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local,
3703 format_static_mapping_kvp);
3705 clib_bihash_init_8_8 (&sm->static_mapping_by_external,
3706 "static_mapping_by_external",
3707 static_mapping_buckets,
3708 static_mapping_memory_size);
3709 clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external,
3710 format_static_mapping_kvp);
3716 VLIB_CONFIG_FUNCTION (snat_config, "nat");
3719 nat_ip4_add_del_addr_only_sm_cb (ip4_main_t * im,
3722 ip4_address_t * address,
3724 u32 if_address_index, u32 is_delete)
3726 snat_main_t *sm = &snat_main;
3727 snat_static_map_resolve_t *rp;
3728 snat_static_mapping_t *m;
3729 snat_session_key_t m_key;
3730 clib_bihash_kv_8_8_t kv, value;
3732 ip4_address_t l_addr;
3734 for (i = 0; i < vec_len (sm->to_resolve); i++)
3736 rp = sm->to_resolve + i;
3737 if (rp->addr_only == 0)
3739 if (rp->sw_if_index == sw_if_index)
3746 m_key.addr.as_u32 = address->as_u32;
3747 m_key.port = rp->addr_only ? 0 : rp->e_port;
3748 m_key.protocol = rp->addr_only ? 0 : rp->proto;
3749 m_key.fib_index = sm->outside_fib_index;
3750 kv.key = m_key.as_u64;
3751 if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
3754 m = pool_elt_at_index (sm->static_mappings, value.value);
3758 /* Don't trip over lease renewal, static config */
3768 /* Indetity mapping? */
3769 if (rp->l_addr.as_u32 == 0)
3770 l_addr.as_u32 = address[0].as_u32;
3772 l_addr.as_u32 = rp->l_addr.as_u32;
3773 /* Add the static mapping */
3774 rv = snat_add_static_mapping (l_addr,
3779 rp->addr_only, ~0 /* sw_if_index */ ,
3780 rp->proto, !is_delete, rp->twice_nat,
3781 rp->out2in_only, rp->tag, rp->identity_nat);
3783 nat_log_notice ("snat_add_static_mapping returned %d", rv);
3787 snat_ip4_add_del_interface_address_cb (ip4_main_t * im,
3790 ip4_address_t * address,
3792 u32 if_address_index, u32 is_delete)
3794 snat_main_t *sm = &snat_main;
3795 snat_static_map_resolve_t *rp;
3796 ip4_address_t l_addr;
3800 snat_address_t *addresses = sm->addresses;
3802 for (i = 0; i < vec_len (sm->auto_add_sw_if_indices); i++)
3804 if (sw_if_index == sm->auto_add_sw_if_indices[i])
3808 for (i = 0; i < vec_len (sm->auto_add_sw_if_indices_twice_nat); i++)
3811 addresses = sm->twice_nat_addresses;
3812 if (sw_if_index == sm->auto_add_sw_if_indices_twice_nat[i])
3821 /* Don't trip over lease renewal, static config */
3822 for (j = 0; j < vec_len (addresses); j++)
3823 if (addresses[j].addr.as_u32 == address->as_u32)
3826 (void) snat_add_address (sm, address, ~0, twice_nat);
3827 /* Scan static map resolution vector */
3828 for (j = 0; j < vec_len (sm->to_resolve); j++)
3830 rp = sm->to_resolve + j;
3833 /* On this interface? */
3834 if (rp->sw_if_index == sw_if_index)
3836 /* Indetity mapping? */
3837 if (rp->l_addr.as_u32 == 0)
3838 l_addr.as_u32 = address[0].as_u32;
3840 l_addr.as_u32 = rp->l_addr.as_u32;
3841 /* Add the static mapping */
3842 rv = snat_add_static_mapping (l_addr,
3848 ~0 /* sw_if_index */ ,
3850 rp->is_add, rp->twice_nat,
3851 rp->out2in_only, rp->tag,
3854 nat_log_notice ("snat_add_static_mapping returned %d", rv);
3861 (void) snat_del_address (sm, address[0], 1, twice_nat);
3868 snat_add_interface_address (snat_main_t * sm, u32 sw_if_index, int is_del,
3871 ip4_main_t *ip4_main = sm->ip4_main;
3872 ip4_address_t *first_int_addr;
3873 snat_static_map_resolve_t *rp;
3874 u32 *indices_to_delete = 0;
3876 u32 *auto_add_sw_if_indices =
3878 auto_add_sw_if_indices_twice_nat : sm->auto_add_sw_if_indices;
3880 first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0 /* just want the address */
3883 for (i = 0; i < vec_len (auto_add_sw_if_indices); i++)
3885 if (auto_add_sw_if_indices[i] == sw_if_index)
3889 /* if have address remove it */
3891 (void) snat_del_address (sm, first_int_addr[0], 1, twice_nat);
3894 for (j = 0; j < vec_len (sm->to_resolve); j++)
3896 rp = sm->to_resolve + j;
3897 if (rp->sw_if_index == sw_if_index)
3898 vec_add1 (indices_to_delete, j);
3900 if (vec_len (indices_to_delete))
3902 for (j = vec_len (indices_to_delete) - 1; j >= 0; j--)
3903 vec_del1 (sm->to_resolve, j);
3904 vec_free (indices_to_delete);
3908 vec_del1 (sm->auto_add_sw_if_indices_twice_nat, i);
3910 vec_del1 (sm->auto_add_sw_if_indices, i);
3913 return VNET_API_ERROR_VALUE_EXIST;
3920 return VNET_API_ERROR_NO_SUCH_ENTRY;
3922 /* add to the auto-address list */
3924 vec_add1 (sm->auto_add_sw_if_indices_twice_nat, sw_if_index);
3926 vec_add1 (sm->auto_add_sw_if_indices, sw_if_index);
3928 /* If the address is already bound - or static - add it now */
3930 (void) snat_add_address (sm, first_int_addr, ~0, twice_nat);
3936 nat44_del_session (snat_main_t * sm, ip4_address_t * addr, u16 port,
3937 snat_protocol_t proto, u32 vrf_id, int is_in)
3939 snat_main_per_thread_data_t *tsm;
3940 clib_bihash_kv_8_8_t kv, value;
3942 u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
3943 snat_session_key_t key;
3945 clib_bihash_8_8_t *t;
3947 if (sm->endpoint_dependent)
3948 return VNET_API_ERROR_UNSUPPORTED;
3950 ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
3951 if (sm->num_workers > 1)
3953 vec_elt_at_index (sm->per_thread_data,
3954 sm->worker_in2out_cb (&ip, fib_index));
3956 tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
3958 key.addr.as_u32 = addr->as_u32;
3959 key.port = clib_host_to_net_u16 (port);
3960 key.protocol = proto;
3961 key.fib_index = fib_index;
3962 kv.key = key.as_u64;
3963 t = is_in ? &tsm->in2out : &tsm->out2in;
3964 if (!clib_bihash_search_8_8 (t, &kv, &value))
3966 if (pool_is_free_index (tsm->sessions, value.value))
3967 return VNET_API_ERROR_UNSPECIFIED;
3969 s = pool_elt_at_index (tsm->sessions, value.value);
3970 nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
3971 nat44_delete_session (sm, s, tsm - sm->per_thread_data);
3975 return VNET_API_ERROR_NO_SUCH_ENTRY;
3979 nat44_del_ed_session (snat_main_t * sm, ip4_address_t * addr, u16 port,
3980 ip4_address_t * eh_addr, u16 eh_port, u8 proto,
3981 u32 vrf_id, int is_in)
3984 clib_bihash_16_8_t *t;
3985 nat_ed_ses_key_t key;
3986 clib_bihash_kv_16_8_t kv, value;
3987 u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
3989 snat_main_per_thread_data_t *tsm;
3991 if (!sm->endpoint_dependent)
3992 return VNET_API_ERROR_FEATURE_DISABLED;
3994 ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
3995 if (sm->num_workers > 1)
3997 vec_elt_at_index (sm->per_thread_data,
3998 sm->worker_in2out_cb (&ip, fib_index));
4000 tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
4002 t = is_in ? &tsm->in2out_ed : &tsm->out2in_ed;
4003 key.l_addr.as_u32 = addr->as_u32;
4004 key.r_addr.as_u32 = eh_addr->as_u32;
4005 key.l_port = clib_host_to_net_u16 (port);
4006 key.r_port = clib_host_to_net_u16 (eh_port);
4008 key.fib_index = fib_index;
4009 kv.key[0] = key.as_u64[0];
4010 kv.key[1] = key.as_u64[1];
4011 if (clib_bihash_search_16_8 (t, &kv, &value))
4012 return VNET_API_ERROR_NO_SUCH_ENTRY;
4014 if (pool_is_free_index (tsm->sessions, value.value))
4015 return VNET_API_ERROR_UNSPECIFIED;
4016 s = pool_elt_at_index (tsm->sessions, value.value);
4017 nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
4018 nat44_delete_session (sm, s, tsm - sm->per_thread_data);
4023 nat_set_alloc_addr_and_port_mape (u16 psid, u16 psid_offset, u16 psid_length)
4025 snat_main_t *sm = &snat_main;
4027 sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_MAPE;
4028 sm->alloc_addr_and_port = nat_alloc_addr_and_port_mape;
4030 sm->psid_offset = psid_offset;
4031 sm->psid_length = psid_length;
4035 nat_set_alloc_addr_and_port_range (u16 start_port, u16 end_port)
4037 snat_main_t *sm = &snat_main;
4039 sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_RANGE;
4040 sm->alloc_addr_and_port = nat_alloc_addr_and_port_range;
4041 sm->start_port = start_port;
4042 sm->end_port = end_port;
4046 nat_set_alloc_addr_and_port_default (void)
4048 snat_main_t *sm = &snat_main;
4050 sm->addr_and_port_alloc_alg = NAT_ADDR_AND_PORT_ALLOC_ALG_DEFAULT;
4051 sm->alloc_addr_and_port = nat_alloc_addr_and_port_default;
4055 * fd.io coding-style-patch-verification: ON
4058 * eval: (c-set-style "gnu")