4 * Copyright (c) 2020 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 #ifndef __included_ed_inlines_h__
19 #define __included_ed_inlines_h__
22 #include <vppinfra/clib.h>
24 #include <nat/nat_inlines.h>
26 static_always_inline int
27 nat_ed_lru_insert (snat_main_per_thread_data_t * tsm,
28 snat_session_t * s, f64 now, u8 proto)
30 dlist_elt_t *lru_list_elt;
31 pool_get (tsm->lru_pool, lru_list_elt);
32 s->lru_index = lru_list_elt - tsm->lru_pool;
36 s->lru_head_index = tsm->udp_lru_head_index;
39 s->lru_head_index = tsm->tcp_trans_lru_head_index;
41 case IP_PROTOCOL_ICMP:
42 s->lru_head_index = tsm->icmp_lru_head_index;
45 s->lru_head_index = tsm->unk_proto_lru_head_index;
48 clib_dlist_addtail (tsm->lru_pool, s->lru_head_index, s->lru_index);
49 lru_list_elt->value = s - tsm->sessions;
50 s->last_lru_update = now;
55 nat_ed_session_delete (snat_main_t * sm, snat_session_t * ses,
56 u32 thread_index, int lru_delete
57 /* delete from global LRU list */ )
59 snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data,
64 clib_dlist_remove (tsm->lru_pool, ses->lru_index);
66 pool_put_index (tsm->lru_pool, ses->lru_index);
67 pool_put (tsm->sessions, ses);
68 vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
69 pool_elts (tsm->sessions));
73 static_always_inline int
74 nat_lru_free_one_with_head (snat_main_t * sm, int thread_index,
75 f64 now, u32 head_index)
77 snat_session_t *s = NULL;
78 dlist_elt_t *oldest_elt;
79 f64 sess_timeout_time;
81 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
82 oldest_index = clib_dlist_remove_head (tsm->lru_pool, head_index);
83 if (~0 != oldest_index)
85 oldest_elt = pool_elt_at_index (tsm->lru_pool, oldest_index);
86 s = pool_elt_at_index (tsm->sessions, oldest_elt->value);
89 s->last_heard + (f64) nat44_session_get_timeout (sm, s);
90 if (now >= sess_timeout_time
91 || (s->tcp_closed_timestamp && now >= s->tcp_closed_timestamp))
93 nat_free_session_data (sm, s, thread_index, 0);
94 nat_ed_session_delete (sm, s, thread_index, 0);
99 clib_dlist_addhead (tsm->lru_pool, head_index, oldest_index);
105 static_always_inline int
106 nat_lru_free_one (snat_main_t * sm, int thread_index, f64 now)
108 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
111 if ((rc = nat_lru_free_one_with_head (sm, thread_index, now, \
112 tsm->p##_lru_head_index))) \
125 static_always_inline snat_session_t *
126 nat_ed_session_alloc (snat_main_t * sm, u32 thread_index, f64 now, u8 proto)
129 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
131 nat_lru_free_one (sm, thread_index, now);
133 pool_get (tsm->sessions, s);
134 clib_memset (s, 0, sizeof (*s));
136 nat_ed_lru_insert (tsm, s, now, proto);
138 s->ha_last_refreshed = now;
139 vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
140 pool_elts (tsm->sessions));
145 static_always_inline void
146 per_vrf_sessions_cleanup (u32 thread_index)
148 snat_main_t *sm = &snat_main;
149 snat_main_per_thread_data_t *tsm =
150 vec_elt_at_index (sm->per_thread_data, thread_index);
151 per_vrf_sessions_t *per_vrf_sessions;
152 u32 *to_free = 0, *i;
154 vec_foreach (per_vrf_sessions, tsm->per_vrf_sessions_vec)
156 if (per_vrf_sessions->expired)
158 if (per_vrf_sessions->ses_count == 0)
160 vec_add1 (to_free, per_vrf_sessions - tsm->per_vrf_sessions_vec);
165 if (vec_len (to_free))
167 vec_foreach (i, to_free)
169 vec_del1 (tsm->per_vrf_sessions_vec, *i);
177 static_always_inline void
178 per_vrf_sessions_register_session (snat_session_t * s, u32 thread_index)
180 snat_main_t *sm = &snat_main;
181 snat_main_per_thread_data_t *tsm =
182 vec_elt_at_index (sm->per_thread_data, thread_index);
183 per_vrf_sessions_t *per_vrf_sessions;
185 per_vrf_sessions_cleanup (thread_index);
187 // s->per_vrf_sessions_index == ~0 ... reuse of old session
189 vec_foreach (per_vrf_sessions, tsm->per_vrf_sessions_vec)
191 // ignore already expired registrations
192 if (per_vrf_sessions->expired)
195 if ((s->in2out.fib_index == per_vrf_sessions->rx_fib_index) &&
196 (s->out2in.fib_index == per_vrf_sessions->tx_fib_index))
200 if ((s->in2out.fib_index == per_vrf_sessions->tx_fib_index) &&
201 (s->out2in.fib_index == per_vrf_sessions->rx_fib_index))
207 // create a new registration
208 vec_add2 (tsm->per_vrf_sessions_vec, per_vrf_sessions, 1);
209 clib_memset (per_vrf_sessions, 0, sizeof (*per_vrf_sessions));
211 per_vrf_sessions->rx_fib_index = s->in2out.fib_index;
212 per_vrf_sessions->tx_fib_index = s->out2in.fib_index;
215 s->per_vrf_sessions_index = per_vrf_sessions - tsm->per_vrf_sessions_vec;
216 per_vrf_sessions->ses_count++;
220 static_always_inline void
221 per_vrf_sessions_unregister_session (snat_session_t * s, u32 thread_index)
223 snat_main_t *sm = &snat_main;
224 snat_main_per_thread_data_t *tsm;
225 per_vrf_sessions_t *per_vrf_sessions;
227 ASSERT (s->per_vrf_sessions_index != ~0);
229 tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
230 per_vrf_sessions = vec_elt_at_index (tsm->per_vrf_sessions_vec,
231 s->per_vrf_sessions_index);
233 ASSERT (per_vrf_sessions->ses_count != 0);
235 per_vrf_sessions->ses_count--;
236 s->per_vrf_sessions_index = ~0;
240 static_always_inline u8
241 per_vrf_sessions_is_expired (snat_session_t * s, u32 thread_index)
243 snat_main_t *sm = &snat_main;
244 snat_main_per_thread_data_t *tsm;
245 per_vrf_sessions_t *per_vrf_sessions;
247 ASSERT (s->per_vrf_sessions_index != ~0);
249 tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
250 per_vrf_sessions = vec_elt_at_index (tsm->per_vrf_sessions_vec,
251 s->per_vrf_sessions_index);
252 return per_vrf_sessions->expired;