FD.io VPP  v20.09-rc2-28-g3c5414029
Vector Packet Processing
cnat_session.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <vnet/ip/ip.h>
17 #include <cnat/cnat_session.h>
18 
21 
22 
23 clib_bihash_40_48_t cnat_session_db;
24 
25 
27 {
29  void *ctx;
31 
32 static int
33 cnat_session_walk_cb (BVT (clib_bihash_kv) * kv, void *arg)
34 {
35  cnat_session_t *session = (cnat_session_t *) kv;
37 
38  ctx->cb (session, ctx->ctx);
39 
40  return (BIHASH_WALK_CONTINUE);
41 }
42 
43 void
45 {
47  .cb = cb,
48  .ctx = ctx,
49  };
51  cnat_session_walk_cb, &wctx);
52 }
53 
55 {
58 
59 static int
60 cnat_session_purge_walk (BVT (clib_bihash_kv) * key, void *arg)
61 {
63 
64  vec_add1 (ctx->keys, *key);
65 
66  return (BIHASH_WALK_CONTINUE);
67 }
68 
69 u8 *
70 format_cnat_session (u8 * s, va_list * args)
71 {
72  cnat_session_t *sess = va_arg (*args, cnat_session_t *);
73  CLIB_UNUSED (int verbose) = va_arg (*args, int);
74  f64 ts = 0;
77 
78  s =
79  format (s,
80  "session:[%U;%d -> %U;%d, %U] => %U;%d -> %U;%d lb:%d age:%f",
82  clib_host_to_net_u16 (sess->key.cs_port[VLIB_RX]),
84  clib_host_to_net_u16 (sess->key.cs_port[VLIB_TX]),
87  clib_host_to_net_u16 (sess->value.cs_port[VLIB_RX]),
89  clib_host_to_net_u16 (sess->value.cs_port[VLIB_TX]),
90  sess->value.cs_lbi, ts);
91 
92  return (s);
93 }
94 
95 static clib_error_t *
97  unformat_input_t * input, vlib_cli_command_t * cmd)
98 {
99  u8 verbose = 0;
101  {
102  if (unformat (input, "verbose"))
103  verbose = 1;
104  else
105  return (clib_error_return (0, "unknown input '%U'",
106  format_unformat_error, input));
107  }
108 
109  vlib_cli_output (vm, "CNat Sessions: now:%f\n%U\n",
110  vlib_time_now (vm),
111  BV (format_bihash), &cnat_session_db, verbose);
112 
113  return (NULL);
114 }
115 
116 /* *INDENT-OFF* */
117 VLIB_CLI_COMMAND (cnat_session_show_cmd_node, static) = {
118  .path = "show cnat session",
119  .function = cnat_session_show,
120  .short_help = "show cnat session",
121  .is_mp_safe = 1,
122 };
123 /* *INDENT-ON* */
124 
125 void
127 {
129  /* age it */
131  cnat_free_port (session->value.cs_port[VLIB_RX]);
132  if (!(session->value.flags & CNAT_SESSION_FLAG_NO_CLIENT))
133  cnat_client_free_by_ip (&session->key.cs_ip[VLIB_TX], session->key.cs_af);
135 
136  clib_bihash_add_del_40_48 (&cnat_session_db, bkey, 0 /* is_add */ );
137 }
138 
139 int
141 {
142  /* flush all the session from the DB */
145 
148 
149  vec_foreach (key, ctx.keys) cnat_session_free ((cnat_session_t *) key);
150 
151  vec_free (ctx.keys);
152 
153  return (0);
154 }
155 
156 u64
157 cnat_session_scan (vlib_main_t * vm, f64 start_time, int i)
158 {
159  BVT (clib_bihash) * h = &cnat_session_db;
160  int j, k;
161 
162  /* Don't scan the l2 fib if it hasn't been instantiated yet */
163  if (alloc_arena (h) == 0)
164  return 0.0;
165 
166  for (i = 0; i < h->nbuckets; i++)
167  {
168  /* allow no more than 100us without a pause */
169  if ((vlib_time_now (vm) - start_time) > 10e-5)
170  return (i);
171 
172  if (i < (h->nbuckets - 3))
173  {
174  BVT (clib_bihash_bucket) * b =
175  BV (clib_bihash_get_bucket) (h, i + 3);
177  b = BV (clib_bihash_get_bucket) (h, i + 1);
178  if (!BV (clib_bihash_bucket_is_empty) (b))
179  {
180  BVT (clib_bihash_value) * v =
181  BV (clib_bihash_get_value) (h, b->offset);
183  }
184  }
185 
186  BVT (clib_bihash_bucket) * b = BV (clib_bihash_get_bucket) (h, i);
187  if (BV (clib_bihash_bucket_is_empty) (b))
188  continue;
189  BVT (clib_bihash_value) * v = BV (clib_bihash_get_value) (h, b->offset);
190  for (j = 0; j < (1 << b->log2_pages); j++)
191  {
192  for (k = 0; k < BIHASH_KVP_PER_PAGE; k++)
193  {
194  if (v->kvp[k].key[0] == ~0ULL && v->kvp[k].value[0] == ~0ULL)
195  continue;
196 
197  cnat_session_t *session = (cnat_session_t *) & v->kvp[k];
198 
199  if (start_time >
201  {
202  /* age it */
203  cnat_session_free (session);
204 
205  /*
206  * Note: we may have just freed the bucket's backing
207  * storage, so check right here...
208  */
209  if (BV (clib_bihash_bucket_is_empty) (b))
210  goto doublebreak;
211  }
212  }
213  v++;
214  }
215  doublebreak:
216  ;
217  }
218 
219  /* start again */
220  return (0);
221 }
222 
223 static clib_error_t *
225 {
228  "CNat Session DB", cm->session_hash_buckets,
229  cm->session_hash_memory);
230  BV (clib_bihash_set_kvp_format_fn) (&cnat_session_db, format_cnat_session);
231 
232  return (NULL);
233 }
234 
236 
237 static clib_error_t *
239  unformat_input_t * input, vlib_cli_command_t * cmd)
240 {
241  cnat_timestamp_t *ts;
243  /* *INDENT-OFF* */
245  vlib_cli_output (vm, "[%d] last_seen:%f lifetime:%u ref:%u",
246  ts - cnat_timestamps,
247  ts->last_seen, ts->lifetime, ts->refcnt);
248  }));
249  /* *INDENT-ON* */
251  return (NULL);
252 }
253 
254 /* *INDENT-OFF* */
255 VLIB_CLI_COMMAND (cnat_timestamp_show_cmd, static) = {
256  .path = "show cnat timestamp",
257  .function = cnat_timestamp_show,
258  .short_help = "show cnat timestamp",
259  .is_mp_safe = 1,
260 };
261 /* *INDENT-ON* */
262 
263 /*
264  * fd.io coding-style-patch-verification: ON
265  *
266  * Local Variables:
267  * eval: (c-set-style "gnu")
268  * End:
269  */
static void clib_rwlock_reader_lock(clib_rwlock_t *p)
Definition: lock.h:167
format_function_t format_ip_protocol
Definition: format.h:45
u64 cnat_session_scan(vlib_main_t *vm, f64 start_time, int i)
Scan the session DB for expired sessions.
Definition: cnat_session.c:157
#define CLIB_UNUSED(x)
Definition: clib.h:87
#define BIHASH_KVP_PER_PAGE
Definition: bihash_16_8.h:24
unsigned long u64
Definition: types.h:89
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:333
u16 cs_port[VLIB_N_DIR]
ports in rx/tx
Definition: cnat_session.h:53
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
u8 * format_cnat_session(u8 *s, va_list *args)
Definition: cnat_session.c:70
vlib_main_t * vm
Definition: in2out_ed.c:1582
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
u32 session_hash_buckets
Definition: cnat_types.h:89
void cnat_session_free(cnat_session_t *session)
Definition: cnat_session.c:126
clib_bihash_40_48_t cnat_session_db
The DB of sessions.
Definition: cnat_session.c:23
unsigned char u8
Definition: types.h:56
double f64
Definition: types.h:142
A session represents the memory of a translation.
Definition: cnat_session.h:38
u8 cs_af
The address family describing the IP addresses.
Definition: cnat_session.h:63
int cnat_session_purge(void)
Purge all the sessions.
Definition: cnat_session.c:140
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
clib_bihash_kv_40_48_t * keys
Definition: cnat_session.c:56
#define clib_error_return(e, args...)
Definition: error.h:99
static void cnat_free_port(u16 port)
Definition: cnat_types.h:243
ip46_address_t cs_ip[VLIB_N_DIR]
IP 4/6 address in the rx/tx direction.
Definition: cnat_session.h:48
u32 cs_ts_index
Timestamp index this session was last used.
Definition: cnat_session.h:93
static f64 cnat_timestamp_exp(u32 index)
Definition: cnat_types.h:217
vnet_crypto_main_t * cm
Definition: quic_crypto.c:53
void clib_bihash_foreach_key_value_pair(clib_bihash *h, clib_bihash_foreach_key_value_pair_cb *callback, void *arg)
Visit active (key,value) pairs in a bi-hash table.
static void clib_rwlock_reader_unlock(clib_rwlock_t *p)
Definition: lock.h:182
static int cnat_session_purge_walk(BVT(clib_bihash_kv) *key, void *arg)
Definition: cnat_session.c:60
struct _unformat_input_t unformat_input_t
vec_header_t h
Definition: buffer.c:322
cnat_timestamp_t * cnat_timestamps
Definition: cnat_types.c:20
static void cnat_timestamp_free(u32 index)
Definition: cnat_types.h:230
void clib_bihash_init(clib_bihash *h, char *name, u32 nbuckets, uword memory_size)
initialize a bounded index extensible hash table
index_t cs_lbi
The load balance object to use to forward.
Definition: cnat_session.h:88
format_function_t format_ip46_address
Definition: ip46_address.h:50
BVT(clib_bihash)
Definition: l2_fib.c:972
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
static clib_error_t * cnat_session_init(vlib_main_t *vm)
Definition: cnat_session.c:224
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
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_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:299
static clib_error_t * cnat_timestamp_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cnat_session.c:238
static int cnat_session_walk_cb(BVT(clib_bihash_kv) *kv, void *arg)
Definition: cnat_session.c:33
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
u32 flags
Indicates a return path session that was source NATed on the way in.
Definition: cnat_session.h:98
struct cnat_session_purge_walk_t_ cnat_session_purge_walk_ctx_t
struct cnat_session_t_::@637 value
this value sits in the same memory location a &#39;value&#39; in the bihash kvp
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
void cnat_client_free_by_ip(ip46_address_t *ip, u8 af)
Definition: cnat_client.c:59
uword session_hash_memory
Definition: cnat_types.h:86
clib_rwlock_t ts_lock
Definition: cnat_types.h:114
struct cnat_session_walk_ctx_t_ cnat_session_walk_ctx_t
typedef key
Definition: ipsec_types.api:85
template key/value backing page structure
Definition: bihash_doc.h:44
Definition: defs.h:47
ip_protocol_t cs_proto
The IP protocol TCP or UDP only supported.
Definition: cnat_session.h:58
struct cnat_session_t_::@636 key
this key sits in the same memory location a &#39;key&#39; in the bihash kvp
cnat_main_t cnat_main
Definition: cnat_types.c:18
walk_rc_t(* cnat_session_walk_cb_t)(const cnat_session_t *session, void *ctx)
Callback function invoked during a walk of all translations.
Definition: cnat_session.h:131
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define vec_foreach(var, vec)
Vector iterator.
cnat_session_walk_cb_t cb
Definition: cnat_session.c:28
static void * clib_bihash_get_value(clib_bihash *h, uword offset)
Get pointer to value page given its clib mheap offset.
static clib_error_t * cnat_session_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cnat_session.c:96
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
Definition: defs.h:46
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
void cnat_session_walk(cnat_session_walk_cb_t cb, void *ctx)
Walk/visit each of the cnat session.
Definition: cnat_session.c:44