nat: nat44-ed add session timing out indicator in api 18/33618/4
authorAlexander Chernavin <achernavin@netgate.com>
Mon, 30 Aug 2021 08:55:27 +0000 (08:55 +0000)
committerOle Tr�an <otroan@employees.org>
Thu, 9 Sep 2021 16:29:49 +0000 (16:29 +0000)
Type: improvement

Currently, NAT44-ED users sessions details are returned for both active
and timed out NAT sessions. It may confuse users that expect to see only
active sessions in the response and make them think that timeouts for
NAT sessions do not work.

With this change, introduce an indicator of timing out for NAT sessions
returned in NAT44-ED user session details.

Signed-off-by: Alexander Chernavin <achernavin@netgate.com>
Change-Id: Ib81ed90369d4b495117538f521e5112e289cf7e6

src/plugins/nat/nat44-ed/nat44_ed.api
src/plugins/nat/nat44-ed/nat44_ed_api.c

index c65b7a8..bff00b8 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-option version = "5.3.0";
+option version = "5.4.0";
 import "vnet/ip/ip_types.api";
 import "vnet/interface_types.api";
 import "plugins/nat/lib/nat_types.api";
@@ -1040,6 +1040,62 @@ define nat44_user_session_details {
   u16 ext_host_nat_port;
 };
 
+/** \brief NAT44 user's sessions
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param ip_address - IPv4 address of the user to dump
+    @param vrf_id - VRF_ID
+*/
+define nat44_user_session_v2_dump {
+  option in_progress;
+  u32 client_index;
+  u32 context;
+  vl_api_ip4_address_t ip_address;
+  u32 vrf_id;
+};
+
+/** \brief NAT44 user's sessions response
+    @param context - sender context, to match reply w/ request
+    @param outside_ip_address - outside IPv4 address
+    @param outside_port - outside port
+    @param inside_ip_address - inside IPv4 address
+    @param inside_port - inside port
+    @param protocol - protocol
+    @param flags - flag NAT_IS_STATIC if session is static,
+                   flag NAT_IS_TWICE_NAT if session is twice-nat,
+                   flag NAT_IS_EXT_HOST_VALID if external host address
+                   and port are valid
+    @param last_heard - last heard timer
+    @param total_bytes - count of bytes sent through session
+    @param total_pkts - count of pakets sent through session
+    @param ext_host_address - external host IPv4 address
+    @param ext_host_port - external host port
+    @param ext_host_nat_address - post-NAT external host IPv4 address (valid
+                                  only if twice-nat session)
+    @param ext_host_nat_port - post-NAT external host port (valid only if
+                               twice-nat session)
+    @param is_timed_out - true, if session is timed out, and false, if session
+                          is active
+*/
+define nat44_user_session_v2_details {
+  option in_progress;
+  u32 context;
+  vl_api_ip4_address_t outside_ip_address;
+  u16 outside_port;
+  vl_api_ip4_address_t inside_ip_address;
+  u16 inside_port;
+  u16 protocol;
+  vl_api_nat_config_flags_t flags;
+  u64 last_heard;
+  u64 total_bytes;
+  u32 total_pkts;
+  vl_api_ip4_address_t ext_host_address;
+  u16 ext_host_port;
+  vl_api_ip4_address_t ext_host_nat_address;
+  u16 ext_host_nat_port;
+  bool is_timed_out;
+};
+
 /** \brief NAT44 load-balancing address and port pair
     @param addr - IPv4 address of the internal node
     @param port - L4 port number of the internal node
index 64946c7..e9c11c0 100644 (file)
@@ -1676,6 +1676,99 @@ vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
       }
 }
 
+static void
+send_nat44_user_session_v2_details (snat_session_t *s,
+                                   vl_api_registration_t *reg, u32 context)
+{
+  vl_api_nat44_user_session_v2_details_t *rmp;
+  snat_main_t *sm = &snat_main;
+  u64 now = vlib_time_now (sm->vnet_main->vlib_main);
+  u64 sess_timeout_time = 0;
+
+  rmp = vl_msg_api_alloc (sizeof (*rmp));
+  clib_memset (rmp, 0, sizeof (*rmp));
+  rmp->_vl_msg_id =
+    ntohs (VL_API_NAT44_USER_SESSION_V2_DETAILS + sm->msg_id_base);
+  clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
+  clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
+
+  if (snat_is_session_static (s))
+    rmp->flags |= NAT_API_IS_STATIC;
+
+  if (is_twice_nat_session (s))
+    rmp->flags |= NAT_API_IS_TWICE_NAT;
+
+  if (is_ed_session (s) || is_fwd_bypass_session (s))
+    rmp->flags |= NAT_API_IS_EXT_HOST_VALID;
+
+  rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
+  rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
+  rmp->total_pkts = ntohl (s->total_pkts);
+  rmp->context = context;
+  if (snat_is_unk_proto_session (s))
+    {
+      rmp->outside_port = 0;
+      rmp->inside_port = 0;
+      rmp->protocol = ntohs (s->in2out.port);
+    }
+  else
+    {
+      rmp->outside_port = s->out2in.port;
+      rmp->inside_port = s->in2out.port;
+      rmp->protocol = ntohs (nat_proto_to_ip_proto (s->nat_proto));
+    }
+  if (is_ed_session (s) || is_fwd_bypass_session (s))
+    {
+      clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
+      rmp->ext_host_port = s->ext_host_port;
+      if (is_twice_nat_session (s))
+       {
+         clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
+         rmp->ext_host_nat_port = s->ext_host_nat_port;
+       }
+    }
+
+  sess_timeout_time = s->last_heard + (f64) nat_session_get_timeout (
+                                       &sm->timeouts, s->nat_proto, s->state);
+  rmp->is_timed_out = (now >= sess_timeout_time);
+
+  vl_api_send_msg (reg, (u8 *) rmp);
+}
+
+static void
+vl_api_nat44_user_session_v2_dump_t_handler (
+  vl_api_nat44_user_session_v2_dump_t *mp)
+{
+  snat_main_per_thread_data_t *tsm;
+  snat_main_t *sm = &snat_main;
+  vl_api_registration_t *reg;
+  snat_user_key_t ukey;
+  snat_session_t *s;
+  ip4_header_t ip;
+
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
+
+  clib_memcpy (&ukey.addr, mp->ip_address, 4);
+  ip.src_address.as_u32 = ukey.addr.as_u32;
+  ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
+  if (sm->num_workers > 1)
+    tsm = vec_elt_at_index (
+      sm->per_thread_data,
+      nat44_ed_get_in2out_worker_index (0, &ip, ukey.fib_index, 0));
+  else
+    tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
+
+  pool_foreach (s, tsm->sessions)
+    {
+      if (s->in2out.addr.as_u32 == ukey.addr.as_u32)
+       {
+         send_nat44_user_session_v2_details (s, reg, mp->context);
+       }
+    }
+}
+
 /* API definitions */
 #include <vnet/format_fns.h>
 #include <nat/nat44-ed/nat44_ed.api.c>