session: track number of tries to alloc lcl port 30/41830/4
authorFlorin Coras <[email protected]>
Thu, 14 Nov 2024 06:54:14 +0000 (22:54 -0800)
committerDave Barach <[email protected]>
Mon, 18 Nov 2024 17:13:30 +0000 (17:13 +0000)
Track number of tries to alloc local port and report it in stats
segment. Could be used to gauge how busy the port allocator is.

Also add cli to dump trasport sub-layer state.

Type: improvement

Signed-off-by: Florin Coras <[email protected]>
Change-Id: I3736a48488c491dee85aa2b074b87519a3857057

src/vnet/session/session.c
src/vnet/session/session.h
src/vnet/session/session_cli.c
src/vnet/session/transport.c
src/vnet/session/transport.h
src/vnet/session/transport_types.h

index ac02281..8a9fc4b 100644 (file)
@@ -1981,11 +1981,14 @@ session_stats_collector_fn (vlib_stats_collector_data_t *d)
     }
 
   vlib_stats_set_gauge (d->private_data, n_sessions);
+  vlib_stats_set_gauge (smm->stats_seg_idx.tp_port_alloc_max_tries,
+                       transport_port_alloc_max_tries ());
 }
 
 static void
 session_stats_collector_init (void)
 {
+  session_main_t *smm = &session_main;
   vlib_stats_collector_reg_t reg = {};
 
   reg.entry_index =
@@ -1994,6 +1997,10 @@ session_stats_collector_init (void)
   reg.collect_fn = session_stats_collector_fn;
   vlib_stats_register_collector_fn (&reg);
   vlib_stats_validate (reg.entry_index, 0, vlib_get_n_threads ());
+
+  smm->stats_seg_idx.tp_port_alloc_max_tries =
+    vlib_stats_add_gauge ("/sys/session/transport_port_alloc_max_tries");
+  vlib_stats_set_gauge (smm->stats_seg_idx.tp_port_alloc_max_tries, 0);
 }
 
 static clib_error_t *
index 24150fb..823bdcb 100644 (file)
@@ -197,6 +197,11 @@ typedef enum
 #undef _
 } session_rt_engine_type_t;
 
+typedef struct session_stats_seg_indices_
+{
+  u32 tp_port_alloc_max_tries;
+} session_stats_segs_indicies_t;
+
 typedef struct session_main_
 {
   /** Worker contexts */
@@ -294,6 +299,7 @@ typedef struct session_main_
 
   /** Query nat44-ed session to get original dst ip4 & dst port. */
   nat44_original_dst_lookup_fn original_dst_lookup;
+  session_stats_segs_indicies_t stats_seg_idx;
 } session_main_t;
 
 extern session_main_t session_main;
index c29a465..0ed2876 100644 (file)
@@ -613,6 +613,11 @@ show_session_command_fn (vlib_main_t * vm, unformat_input_t * input,
        vlib_cli_output (vm, "%U", format_transport_protos);
        goto done;
        }
+      else if (unformat (input, "transport"))
+       {
+       vlib_cli_output (vm, "%U", format_transport_state);
+       goto done;
+       }
       else if (unformat (input, "rt-backend"))
        {
        vlib_cli_output (vm, "%U", format_rt_backend, smm->rt_engine_type);
@@ -799,7 +804,7 @@ VLIB_CLI_COMMAND (vlib_cli_show_session_command) = {
   .path = "show session",
   .short_help =
     "show session [protos][states][rt-backend][verbose [n]] "
-    "[events][listeners <proto>] "
+    "[transport][events][listeners <proto>] "
     "[<session-id>][thread <n> [[proto <p>] index <n>]][elog] "
     "[thread <n>][proto <proto>][state <state>][range <min> [<max>]] "
     "[lcl|rmt|ep <ip>[:<port>]][force-print]",
@@ -1061,6 +1066,7 @@ clear_session_stats_fn (vlib_main_t *vm, unformat_input_t *input,
     {
       clib_memset (&wrk->stats, 0, sizeof (wrk->stats));
     }
+  transport_clear_stats ();
 
   return 0;
 }
index 1c2a926..e8c9490 100644 (file)
@@ -35,6 +35,7 @@ typedef struct transport_main_
   local_endpoint_t *local_endpoints;
   u32 *lcl_endpts_freelist;
   u32 port_allocator_seed;
+  u16 port_alloc_max_tries;
   u16 port_allocator_min_src_port;
   u16 port_allocator_max_src_port;
   u8 lcl_endpts_cleanup_pending;
@@ -212,14 +213,39 @@ unformat_transport_proto (unformat_input_t * input, va_list * args)
 u8 *
 format_transport_protos (u8 * s, va_list * args)
 {
+  u32 indent = format_get_indent (s) + 1;
   transport_proto_vft_t *tp_vft;
 
   vec_foreach (tp_vft, tp_vfts)
-    s = format (s, "%s\n", tp_vft->transport_options.name);
+    if (tp_vft->transport_options.name)
+      s = format (s, "%U%s\n", format_white_space, indent,
+                 tp_vft->transport_options.name);
 
   return s;
 }
 
+u8 *
+format_transport_state (u8 *s, va_list *args)
+{
+  transport_main_t *tm = &tp_main;
+
+  s = format (s, "registered protos:\n%U", format_transport_protos);
+
+  s = format (s, "configs:\n");
+  s =
+    format (s, " min_lcl_port: %u max_lcl_port: %u\n",
+           tm->port_allocator_min_src_port, tm->port_allocator_max_src_port);
+
+  s = format (s, "state:\n");
+  s = format (s, " lcl ports alloced: %u\n lcl ports freelist: %u \n",
+             pool_elts (tm->local_endpoints),
+             vec_len (tm->lcl_endpts_freelist));
+  s =
+    format (s, " port_alloc_max_tries: %u\n lcl_endpts_cleanup_pending: %u\n",
+           tm->port_alloc_max_tries, tm->lcl_endpts_cleanup_pending);
+  return s;
+}
+
 u32
 transport_endpoint_lookup (transport_endpoint_table_t * ht, u8 proto,
                           ip46_address_t * ip, u16 port)
@@ -606,7 +632,7 @@ transport_alloc_local_port (u8 proto, ip46_address_t *lcl_addr,
   transport_main_t *tm = &tp_main;
   u16 min = tm->port_allocator_min_src_port;
   u16 max = tm->port_allocator_max_src_port;
-  int tries, limit;
+  int tries, limit, port = -1;
 
   limit = max - min;
 
@@ -616,8 +642,6 @@ transport_alloc_local_port (u8 proto, ip46_address_t *lcl_addr,
   /* Search for first free slot */
   for (tries = 0; tries < limit; tries++)
     {
-      u16 port = 0;
-
       /* Find a port in the specified range */
       while (1)
        {
@@ -630,7 +654,7 @@ transport_alloc_local_port (u8 proto, ip46_address_t *lcl_addr,
        }
 
       if (!transport_endpoint_mark_used (proto, lcl_addr, port))
-       return port;
+       break;
 
       /* IP:port pair already in use, check if 6-tuple available */
       if (session_lookup_connection (rmt->fib_index, lcl_addr, &rmt->ip, port,
@@ -640,9 +664,26 @@ transport_alloc_local_port (u8 proto, ip46_address_t *lcl_addr,
       /* 6-tuple is available so increment lcl endpoint refcount */
       transport_share_local_endpoint (proto, lcl_addr, port);
 
-      return port;
+      break;
     }
-  return -1;
+
+  tm->port_alloc_max_tries = clib_max (tm->port_alloc_max_tries, tries);
+
+  return port;
+}
+
+u16
+transport_port_alloc_max_tries ()
+{
+  transport_main_t *tm = &tp_main;
+  return tm->port_alloc_max_tries;
+}
+
+void
+transport_clear_stats ()
+{
+  transport_main_t *tm = &tp_main;
+  tm->port_alloc_max_tries = 0;
 }
 
 static session_error_t
index e6ba1ec..289bf47 100644 (file)
@@ -252,6 +252,8 @@ void transport_share_local_endpoint (u8 proto, ip46_address_t * lcl_ip,
                                     u16 port);
 int transport_release_local_endpoint (u8 proto, ip46_address_t *lcl_ip,
                                      u16 port);
+u16 transport_port_alloc_max_tries ();
+void transport_clear_stats ();
 void transport_enable_disable (vlib_main_t * vm, u8 is_en);
 void transport_init (void);
 
index f3b8499..4a2f861 100644 (file)
@@ -196,6 +196,7 @@ u8 *format_transport_half_open_connection (u8 * s, va_list * args);
 
 uword unformat_transport_proto (unformat_input_t * input, va_list * args);
 u8 *format_transport_protos (u8 * s, va_list * args);
+u8 *format_transport_state (u8 *s, va_list *args);
 
 #define foreach_transport_endpoint_fields                              \
   _(ip46_address_t, ip) /**< ip address in net order */                        \