FD.io VPP  v21.01.1
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 #include <cnat/cnat_inline.h>
19 
22 
23 
24 clib_bihash_40_48_t cnat_session_db;
26 
28 {
30  void *ctx;
32 
33 static int
34 cnat_session_walk_cb (BVT (clib_bihash_kv) * kv, void *arg)
35 {
36  cnat_session_t *session = (cnat_session_t *) kv;
38 
39  ctx->cb (session, ctx->ctx);
40 
41  return (BIHASH_WALK_CONTINUE);
42 }
43 
44 void
46 {
48  .cb = cb,
49  .ctx = ctx,
50  };
52  cnat_session_walk_cb, &wctx);
53 }
54 
56 {
59 
60 static int
61 cnat_session_purge_walk (BVT (clib_bihash_kv) * key, void *arg)
62 {
64 
65  vec_add1 (ctx->keys, *key);
66 
67  return (BIHASH_WALK_CONTINUE);
68 }
69 
70 u8 *
71 format_cnat_session (u8 * s, va_list * args)
72 {
73  cnat_session_t *sess = va_arg (*args, cnat_session_t *);
74  CLIB_UNUSED (int verbose) = va_arg (*args, int);
75  f64 ts = 0;
78 
79  s =
80  format (s,
81  "session:[%U;%d -> %U;%d, %U] => %U;%d -> %U;%d lb:%d age:%f",
83  clib_host_to_net_u16 (sess->key.cs_port[VLIB_RX]),
85  clib_host_to_net_u16 (sess->key.cs_port[VLIB_TX]),
88  clib_host_to_net_u16 (sess->value.cs_port[VLIB_RX]),
90  clib_host_to_net_u16 (sess->value.cs_port[VLIB_TX]),
91  sess->value.cs_lbi, ts);
92 
93  return (s);
94 }
95 
96 static clib_error_t *
98  unformat_input_t * input, vlib_cli_command_t * cmd)
99 {
100  u8 verbose = 0;
102  {
103  if (unformat (input, "verbose"))
104  verbose = 1;
105  else
106  return (clib_error_return (0, "unknown input '%U'",
107  format_unformat_error, input));
108  }
109 
110  vlib_cli_output (vm, "CNat Sessions: now:%f\n%U\n",
111  vlib_time_now (vm),
112  BV (format_bihash), &cnat_session_db, verbose);
113 
114  return (NULL);
115 }
116 
117 /* *INDENT-OFF* */
118 VLIB_CLI_COMMAND (cnat_session_show_cmd_node, static) = {
119  .path = "show cnat session",
120  .function = cnat_session_show,
121  .short_help = "show cnat session",
122  .is_mp_safe = 1,
123 };
124 /* *INDENT-ON* */
125 
126 void
128 {
130  /* age it */
133  session->key.cs_proto);
134  if (!(session->value.flags & CNAT_SESSION_FLAG_NO_CLIENT))
135  cnat_client_free_by_ip (&session->key.cs_ip[VLIB_TX], session->key.cs_af);
137 
138  clib_bihash_add_del_40_48 (&cnat_session_db, bkey, 0 /* is_add */ );
139 }
140 
141 int
143 {
144  /* flush all the session from the DB */
147 
150 
151  vec_foreach (key, ctx.keys) cnat_session_free ((cnat_session_t *) key);
152 
153  vec_free (ctx.keys);
154 
155  return (0);
156 }
157 
158 u64
159 cnat_session_scan (vlib_main_t * vm, f64 start_time, int i)
160 {
161  BVT (clib_bihash) * h = &cnat_session_db;
162  int j, k;
163 
164  /* Don't scan the l2 fib if it hasn't been instantiated yet */
165  if (alloc_arena (h) == 0)
166  return 0.0;
167 
168  for ( /* caller saves starting point */ ; i < h->nbuckets; i++)
169  {
170  /* allow no more than 100us without a pause */
171  if ((vlib_time_now (vm) - start_time) > 10e-5)
172  return (i);
173 
174  if (i < (h->nbuckets - 3))
175  {
176  BVT (clib_bihash_bucket) * b =
177  BV (clib_bihash_get_bucket) (h, i + 3);
179  b = BV (clib_bihash_get_bucket) (h, i + 1);
180  if (!BV (clib_bihash_bucket_is_empty) (b))
181  {
182  BVT (clib_bihash_value) * v =
183  BV (clib_bihash_get_value) (h, b->offset);
185  }
186  }
187 
188  BVT (clib_bihash_bucket) * b = BV (clib_bihash_get_bucket) (h, i);
189  if (BV (clib_bihash_bucket_is_empty) (b))
190  continue;
191  BVT (clib_bihash_value) * v = BV (clib_bihash_get_value) (h, b->offset);
192  for (j = 0; j < (1 << b->log2_pages); j++)
193  {
194  for (k = 0; k < BIHASH_KVP_PER_PAGE; k++)
195  {
196  if (v->kvp[k].key[0] == ~0ULL && v->kvp[k].value[0] == ~0ULL)
197  continue;
198 
199  cnat_session_t *session = (cnat_session_t *) & v->kvp[k];
200 
201  if (start_time >
203  {
204  /* age it */
205  cnat_session_free (session);
206 
207  /*
208  * Note: we may have just freed the bucket's backing
209  * storage, so check right here...
210  */
211  if (BV (clib_bihash_bucket_is_empty) (b))
212  goto doublebreak;
213  }
214  }
215  v++;
216  }
217  doublebreak:
218  ;
219  }
220 
221  /* start again */
222  return (0);
223 }
224 
225 static clib_error_t *
227 {
230  "CNat Session DB", cm->session_hash_buckets,
231  cm->session_hash_memory);
232  BV (clib_bihash_set_kvp_format_fn) (&cnat_session_db, format_cnat_session);
233 
234  return (NULL);
235 }
236 
238 
239 static clib_error_t *
241  unformat_input_t * input, vlib_cli_command_t * cmd)
242 {
243  cnat_timestamp_t *ts;
245  /* *INDENT-OFF* */
247  vlib_cli_output (vm, "[%d] last_seen:%f lifetime:%u ref:%u",
248  ts - cnat_timestamps,
249  ts->last_seen, ts->lifetime, ts->refcnt);
250  }
251  /* *INDENT-ON* */
253  return (NULL);
254 }
255 
256 /* *INDENT-OFF* */
257 VLIB_CLI_COMMAND (cnat_timestamp_show_cmd, static) = {
258  .path = "show cnat timestamp",
259  .function = cnat_timestamp_show,
260  .short_help = "show cnat timestamp",
261  .is_mp_safe = 1,
262 };
263 /* *INDENT-ON* */
264 
265 /*
266  * fd.io coding-style-patch-verification: ON
267  *
268  * Local Variables:
269  * eval: (c-set-style "gnu")
270  * End:
271  */
static void clib_rwlock_reader_lock(clib_rwlock_t *p)
Definition: lock.h:169
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:159
#define CLIB_UNUSED(x)
Definition: clib.h:87
This session source port was allocated, free it on cleanup.
Definition: cnat_session.h:120
#define BIHASH_KVP_PER_PAGE
Definition: bihash_16_8.h:25
void(* cnat_free_port_cb)(u16 port, ip_protocol_t iproto)
Port cleanup callback.
Definition: cnat_session.c:25
This session doesn&#39;t have a client, do not attempt to free it.
Definition: cnat_session.h:124
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:527
unsigned long u64
Definition: types.h:89
static void cnat_timestamp_free(u32 index)
Definition: cnat_inline.h:78
struct cnat_session_t_::@632 key
this key sits in the same memory location a &#39;key&#39; in the bihash kvp
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:334
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:71
vlib_main_t * vm
Definition: in2out_ed.c:1580
u32 session_hash_buckets
Definition: cnat_types.h:103
void cnat_session_free(cnat_session_t *session)
Free a session & update refcounts.
Definition: cnat_session.c:127
clib_bihash_40_48_t cnat_session_db
The DB of sessions.
Definition: cnat_session.c:24
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:142
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
clib_bihash_kv_40_48_t * keys
Definition: cnat_session.c:57
description fragment has unexpected format
Definition: map.api:433
#define clib_error_return(e, args...)
Definition: error.h:99
const cJSON *const b
Definition: cJSON.h:255
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
enum ip_protocol ip_protocol_t
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:184
static int cnat_session_purge_walk(BVT(clib_bihash_kv) *key, void *arg)
Definition: cnat_session.c:61
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
vec_header_t h
Definition: buffer.c:322
cnat_timestamp_t * cnat_timestamps
Definition: cnat_types.c:20
static f64 cnat_timestamp_exp(u32 index)
Definition: cnat_inline.h:65
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:1019
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
static clib_error_t * cnat_session_init(vlib_main_t *vm)
Definition: cnat_session.c:226
#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:298
static clib_error_t * cnat_timestamp_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cnat_session.c:240
static int cnat_session_walk_cb(BVT(clib_bihash_kv) *kv, void *arg)
Definition: cnat_session.c:34
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
u32 flags
session flags if cs_lbi == INDEX_INVALID
Definition: cnat_session.h:100
struct cnat_session_purge_walk_t_ cnat_session_purge_walk_ctx_t
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:58
uword session_hash_memory
Definition: cnat_types.h:100
clib_rwlock_t ts_lock
Definition: cnat_types.h:128
struct cnat_session_walk_ctx_t_ cnat_session_walk_ctx_t
typedef key
Definition: ipsec_types.api:86
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
cnat_main_t cnat_main
Definition: cnat_types.c:18
u16 port
Definition: lb_types.api:73
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:149
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:29
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:97
#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
struct cnat_session_t_::@633 value
this value sits in the same memory location a &#39;value&#39; in the bihash kvp
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
void cnat_session_walk(cnat_session_walk_cb_t cb, void *ctx)
Walk/visit each of the cnat session.
Definition: cnat_session.c:45