/* * Copyright (c) 2020 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @brief The NAT44 inline functions */ #ifndef included_nat44_inlines_h__ #define included_nat44_inlines_h__ #include #include static_always_inline u8 nat44_maximum_sessions_exceeded (snat_main_t * sm, u32 thread_index) { if (pool_elts (sm->per_thread_data[thread_index].sessions) >= sm->max_translations) return 1; return 0; } static_always_inline void nat44_session_cleanup (snat_session_t * s, u32 thread_index) { snat_main_t *sm = &snat_main; nat_free_session_data (sm, s, thread_index, 0); nat44_delete_session (sm, s, thread_index); } static_always_inline void nat44_user_try_cleanup (snat_user_t * u, u32 thread_index, f64 now) { dlist_elt_t *elt; snat_session_t *s; u64 sess_timeout_time; snat_main_t *sm = &snat_main; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; // get head elt = pool_elt_at_index (tsm->list_pool, u->sessions_per_user_list_head_index); // get first element elt = pool_elt_at_index (tsm->list_pool, elt->next); while (elt->value != ~0) { s = pool_elt_at_index (tsm->sessions, elt->value); elt = pool_elt_at_index (tsm->list_pool, elt->next); sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s); if (now < sess_timeout_time) continue; nat44_session_cleanup (s, thread_index); } } static_always_inline void nat44_session_try_cleanup (ip4_address_t * addr, u32 fib_index, u32 thread_index, f64 now) { snat_user_t *u = 0; snat_user_key_t user_key; clib_bihash_kv_8_8_t kv, value; snat_main_t *sm = &snat_main; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; user_key.addr.as_u32 = addr->as_u32; user_key.fib_index = fib_index; kv.key = user_key.as_u64; // lookup user for this traffic if (PREDICT_FALSE (clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))) { // there is still place and a new user can be created if (PREDICT_TRUE (pool_elts (tsm->sessions) < sm->max_translations)) return; // there is no place so we try to cleanup all users in this thread /* *INDENT-OFF* */ pool_foreach (u, tsm->users, ({ nat44_user_try_cleanup (u, thread_index, now); })); /* *INDENT-ON* */ return; } // each time user creates a new session we try to cleanup expired sessions nat44_user_try_cleanup (pool_elt_at_index (tsm->users, value.value), thread_index, now); } static_always_inline void nat44_force_session_cleanup (void) { snat_user_t *u = 0; snat_main_t *sm = &snat_main; snat_main_per_thread_data_t *tsm; vlib_main_t *vm = vlib_get_main (); f64 now = vlib_time_now (vm); // TODO: consider own timeouts if (sm->num_workers > 1) { /* *INDENT-OFF* */ vec_foreach (tsm, sm->per_thread_data) { pool_foreach (u, tsm->users, ({ nat44_user_try_cleanup (u, tsm->thread_index, now); })); } /* *INDENT-ON* */ } else { tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); /* *INDENT-OFF* */ pool_foreach (u, tsm->users, ({ nat44_user_try_cleanup (u, tsm->thread_index, now); })); /* *INDENT-ON* */ } } #endif /* included_nat44_inlines_h__ */ /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */