FD.io VPP  v21.01.1
Vector Packet Processing
ed_inlines.h
Go to the documentation of this file.
1 /*
2  * simple nat plugin
3  *
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:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17 
18 #ifndef __included_ed_inlines_h__
19 #define __included_ed_inlines_h__
20 
21 #include <float.h>
22 #include <vppinfra/clib.h>
23 #include <nat/nat.h>
24 #include <nat/nat_inlines.h>
25 
28  snat_session_t * s, f64 now, u8 proto)
29 {
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;
33  switch (proto)
34  {
35  case IP_PROTOCOL_UDP:
36  s->lru_head_index = tsm->udp_lru_head_index;
37  break;
38  case IP_PROTOCOL_TCP:
39  s->lru_head_index = tsm->tcp_trans_lru_head_index;
40  break;
41  case IP_PROTOCOL_ICMP:
42  s->lru_head_index = tsm->icmp_lru_head_index;
43  break;
44  default:
45  s->lru_head_index = tsm->unk_proto_lru_head_index;
46  break;
47  }
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;
51  return 1;
52 }
53 
54 always_inline void
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 */ )
58 {
60  thread_index);
61 
62  if (lru_delete)
63  {
64  clib_dlist_remove (tsm->lru_pool, ses->lru_index);
65  }
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));
70 
71 }
72 
74 nat_lru_free_one_with_head (snat_main_t * sm, int thread_index,
75  f64 now, u32 head_index)
76 {
77  snat_session_t *s = NULL;
78  dlist_elt_t *oldest_elt;
79  f64 sess_timeout_time;
80  u32 oldest_index;
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)
84  {
85  oldest_elt = pool_elt_at_index (tsm->lru_pool, oldest_index);
86  s = pool_elt_at_index (tsm->sessions, oldest_elt->value);
87 
88  sess_timeout_time =
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))
92  {
93  nat_free_session_data (sm, s, thread_index, 0);
94  nat_ed_session_delete (sm, s, thread_index, 0);
95  return 1;
96  }
97  else
98  {
99  clib_dlist_addhead (tsm->lru_pool, head_index, oldest_index);
100  }
101  }
102  return 0;
103 }
104 
106 nat_lru_free_one (snat_main_t * sm, int thread_index, f64 now)
107 {
108  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
109  int rc = 0;
110 #define _(p) \
111  if ((rc = nat_lru_free_one_with_head (sm, thread_index, now, \
112  tsm->p##_lru_head_index))) \
113  { \
114  return rc; \
115  }
116  _(tcp_trans);
117  _(udp);
118  _(unk_proto);
119  _(icmp);
120  _(tcp_estab);
121 #undef _
122  return 0;
123 }
124 
125 static_always_inline snat_session_t *
126 nat_ed_session_alloc (snat_main_t * sm, u32 thread_index, f64 now, u8 proto)
127 {
128  snat_session_t *s;
129  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
130 
131  nat_lru_free_one (sm, thread_index, now);
132 
133  pool_get (tsm->sessions, s);
134  clib_memset (s, 0, sizeof (*s));
135 
136  nat_ed_lru_insert (tsm, s, now, proto);
137 
138  s->ha_last_refreshed = now;
139  vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
140  pool_elts (tsm->sessions));
141  return s;
142 }
143 
144 // slow path
147 {
148  snat_main_t *sm = &snat_main;
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;
153 
154  vec_foreach (per_vrf_sessions, tsm->per_vrf_sessions_vec)
155  {
156  if (per_vrf_sessions->expired)
157  {
158  if (per_vrf_sessions->ses_count == 0)
159  {
160  vec_add1 (to_free, per_vrf_sessions - tsm->per_vrf_sessions_vec);
161  }
162  }
163  }
164 
165  if (vec_len (to_free))
166  {
167  vec_foreach (i, to_free)
168  {
170  }
171  }
172 
173  vec_free (to_free);
174 }
175 
176 // slow path
178 per_vrf_sessions_register_session (snat_session_t * s, u32 thread_index)
179 {
180  snat_main_t *sm = &snat_main;
182  vec_elt_at_index (sm->per_thread_data, thread_index);
183  per_vrf_sessions_t *per_vrf_sessions;
184 
185  per_vrf_sessions_cleanup (thread_index);
186 
187  // s->per_vrf_sessions_index == ~0 ... reuse of old session
188 
189  vec_foreach (per_vrf_sessions, tsm->per_vrf_sessions_vec)
190  {
191  // ignore already expired registrations
192  if (per_vrf_sessions->expired)
193  continue;
194 
195  if ((s->in2out.fib_index == per_vrf_sessions->rx_fib_index) &&
196  (s->out2in.fib_index == per_vrf_sessions->tx_fib_index))
197  {
198  goto done;
199  }
200  if ((s->in2out.fib_index == per_vrf_sessions->tx_fib_index) &&
201  (s->out2in.fib_index == per_vrf_sessions->rx_fib_index))
202  {
203  goto done;
204  }
205  }
206 
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));
210 
211  per_vrf_sessions->rx_fib_index = s->in2out.fib_index;
212  per_vrf_sessions->tx_fib_index = s->out2in.fib_index;
213 
214 done:
215  s->per_vrf_sessions_index = per_vrf_sessions - tsm->per_vrf_sessions_vec;
216  per_vrf_sessions->ses_count++;
217 }
218 
219 // fast path
221 per_vrf_sessions_unregister_session (snat_session_t * s, u32 thread_index)
222 {
223  snat_main_t *sm = &snat_main;
225  per_vrf_sessions_t *per_vrf_sessions;
226 
227  ASSERT (s->per_vrf_sessions_index != ~0);
228 
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);
232 
233  ASSERT (per_vrf_sessions->ses_count != 0);
234 
235  per_vrf_sessions->ses_count--;
236  s->per_vrf_sessions_index = ~0;
237 }
238 
239 // fast path
241 per_vrf_sessions_is_expired (snat_session_t * s, u32 thread_index)
242 {
243  snat_main_t *sm = &snat_main;
245  per_vrf_sessions_t *per_vrf_sessions;
246 
247  ASSERT (s->per_vrf_sessions_index != ~0);
248 
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;
253 }
254 
255 #endif
dlist_elt_t * lru_pool
Definition: nat.h:459
static u32 nat44_session_get_timeout(snat_main_t *sm, snat_session_t *s)
Definition: nat_inlines.h:396
static_always_inline int nat_lru_free_one_with_head(snat_main_t *sm, int thread_index, f64 now, u32 head_index)
Definition: ed_inlines.h:74
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
per_vrf_sessions_t * per_vrf_sessions_vec
Definition: nat.h:472
void nat_free_session_data(snat_main_t *sm, snat_session_t *s, u32 thread_index, u8 is_ha)
Free NAT44 session data (lookup keys, external address port)
Definition: nat.c:376
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:630
static_always_inline void per_vrf_sessions_register_session(snat_session_t *s, u32 thread_index)
Definition: ed_inlines.h:178
static_always_inline void per_vrf_sessions_cleanup(u32 thread_index)
Definition: ed_inlines.h:146
static void nat_ed_session_delete(snat_main_t *sm, snat_session_t *ses, u32 thread_index, int lru_delete)
Definition: ed_inlines.h:55
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:251
unsigned char u8
Definition: types.h:56
double f64
Definition: types.h:142
#define static_always_inline
Definition: clib.h:109
static_always_inline u8 per_vrf_sessions_is_expired(snat_session_t *s, u32 thread_index)
Definition: ed_inlines.h:241
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
unsigned int u32
Definition: types.h:88
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
vl_api_ip_proto_t proto
Definition: acl_types.api:51
icmp
Definition: map.api:387
static void clib_dlist_addtail(dlist_elt_t *pool, u32 head_index, u32 new_index)
Definition: dlist.h:43
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:301
#define always_inline
Definition: ipsec.h:28
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:875
static void vlib_set_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 value)
Set a simple counter.
Definition: counter.h:113
static_always_inline int nat_ed_lru_insert(snat_main_per_thread_data_t *tsm, snat_session_t *s, f64 now, u8 proto)
Definition: ed_inlines.h:27
static_always_inline snat_session_t * nat_ed_session_alloc(snat_main_t *sm, u32 thread_index, f64 now, u8 proto)
Definition: ed_inlines.h:126
snat_main_t snat_main
Definition: nat.c:39
static void clib_dlist_addhead(dlist_elt_t *pool, u32 head_index, u32 new_index)
Definition: dlist.h:71
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:330
#define ASSERT(truth)
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
Definition: dlist.h:99
u32 value
Definition: dlist.h:32
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
snat_main_per_thread_data_t * per_thread_data
Definition: nat.h:529
#define vec_foreach(var, vec)
Vector iterator.
static_always_inline int nat_lru_free_one(snat_main_t *sm, int thread_index, f64 now)
Definition: ed_inlines.h:106
vlib_simple_counter_main_t total_sessions
Definition: nat.h:660
snat_session_t * sessions
Definition: nat.h:453
static_always_inline void per_vrf_sessions_unregister_session(snat_session_t *s, u32 thread_index)
Definition: ed_inlines.h:221
static u32 clib_dlist_remove_head(dlist_elt_t *pool, u32 head_index)
Definition: dlist.h:117
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127