nat: fixed return values of enable/disable call
[vpp.git] / src / plugins / nat / nat44-ei / nat44_ei_api.c
index 74e0774..8671a55 100644 (file)
@@ -173,7 +173,9 @@ vl_api_nat44_ei_plugin_enable_disable_t_handler (
       rv = nat44_ei_plugin_enable (c);
     }
   else
-    rv = nat44_ei_plugin_disable ();
+    {
+      rv = nat44_ei_plugin_disable ();
+    }
 
   REPLY_MACRO (VL_API_NAT44_EI_PLUGIN_ENABLE_DISABLE_REPLY);
 }
@@ -303,7 +305,8 @@ vl_api_nat44_ei_ha_set_listener_t_handler (
   int rv;
 
   memcpy (&addr, &mp->ip_address, sizeof (addr));
-  rv = nat_ha_set_listener (&addr, clib_net_to_host_u16 (mp->port),
+  rv = nat_ha_set_listener (vlib_get_main (), &addr,
+                           clib_net_to_host_u16 (mp->port),
                            clib_net_to_host_u32 (mp->path_mtu));
 
   REPLY_MACRO (VL_API_NAT44_EI_HA_SET_LISTENER_REPLY);
@@ -339,9 +342,9 @@ vl_api_nat44_ei_ha_set_failover_t_handler (
   int rv;
 
   memcpy (&addr, &mp->ip_address, sizeof (addr));
-  rv =
-    nat_ha_set_failover (&addr, clib_net_to_host_u16 (mp->port),
-                        clib_net_to_host_u32 (mp->session_refresh_interval));
+  rv = nat_ha_set_failover (
+    vlib_get_main (), &addr, clib_net_to_host_u16 (mp->port),
+    clib_net_to_host_u32 (mp->session_refresh_interval));
 
   REPLY_MACRO (VL_API_NAT44_EI_HA_SET_FAILOVER_REPLY);
 }
@@ -468,9 +471,9 @@ vl_api_nat44_ei_add_del_address_range_t_handler (
   for (i = 0; i < count; i++)
     {
       if (is_add)
-       rv = nat44_ei_add_address (nm, &this_addr, vrf_id);
+       rv = nat44_ei_add_address (&this_addr, vrf_id);
       else
-       rv = nat44_ei_del_address (nm, this_addr, 0);
+       rv = nat44_ei_del_address (this_addr, 0);
 
       if (rv)
        goto send_reply;
@@ -532,18 +535,22 @@ vl_api_nat44_ei_interface_add_del_feature_t_handler (
   nat44_ei_main_t *nm = &nat44_ei_main;
   vl_api_nat44_ei_interface_add_del_feature_reply_t *rmp;
   u32 sw_if_index = ntohl (mp->sw_if_index);
-  u8 is_del;
   int rv = 0;
 
-  is_del = !mp->is_add;
-
   VALIDATE_SW_IF_INDEX (mp);
 
-  rv = nat44_ei_interface_add_del (sw_if_index, mp->flags & NAT44_EI_IF_INSIDE,
-                                  is_del);
+  if (mp->is_add)
+    {
+      rv =
+       nat44_ei_add_interface (sw_if_index, mp->flags & NAT44_EI_IF_INSIDE);
+    }
+  else
+    {
+      rv =
+       nat44_ei_del_interface (sw_if_index, mp->flags & NAT44_EI_IF_INSIDE);
+    }
 
   BAD_SW_IF_INDEX_LABEL;
-
   REPLY_MACRO (VL_API_NAT44_EI_INTERFACE_ADD_DEL_FEATURE_REPLY);
 }
 
@@ -587,19 +594,75 @@ vl_api_nat44_ei_interface_dump_t_handler (vl_api_nat44_ei_interface_dump_t *mp)
     }
 }
 
+static_always_inline int
+add_del_dummy_output_interface (u32 sw_if_index, u8 is_inside, u8 is_add)
+{
+  nat44_ei_main_t *nm = &nat44_ei_main;
+  nat44_ei_interface_t *i;
+  int rv = 1;
+
+  pool_foreach (i, nm->output_feature_dummy_interfaces)
+    {
+      if (i->sw_if_index == sw_if_index)
+       {
+         if (!is_add)
+           {
+             pool_put (nm->output_feature_dummy_interfaces, i);
+             rv = 0;
+           }
+         goto done;
+       }
+    }
+
+  if (is_add)
+    {
+      pool_get (nm->output_feature_dummy_interfaces, i);
+      i->sw_if_index = sw_if_index;
+
+      if (is_inside)
+       {
+         i->flags |= NAT44_EI_INTERFACE_FLAG_IS_INSIDE;
+       }
+      else
+       {
+         i->flags |= NAT44_EI_INTERFACE_FLAG_IS_OUTSIDE;
+       }
+
+      rv = 0;
+    }
+
+done:
+  return rv;
+}
+
 static void
 vl_api_nat44_ei_interface_add_del_output_feature_t_handler (
   vl_api_nat44_ei_interface_add_del_output_feature_t *mp)
 {
-  nat44_ei_main_t *nm = &nat44_ei_main;
   vl_api_nat44_ei_interface_add_del_output_feature_reply_t *rmp;
-  u32 sw_if_index = ntohl (mp->sw_if_index);
+  nat44_ei_main_t *nm = &nat44_ei_main;
+  u32 sw_if_index;
   int rv = 0;
 
   VALIDATE_SW_IF_INDEX (mp);
 
-  rv = nat44_ei_interface_add_del_output_feature (
-    sw_if_index, mp->flags & NAT44_EI_IF_INSIDE, !mp->is_add);
+  sw_if_index = ntohl (mp->sw_if_index);
+
+  // register all interfaces in the dummy structure
+  rv = add_del_dummy_output_interface (
+    sw_if_index, mp->flags & NAT44_EI_IF_INSIDE, mp->is_add);
+
+  if (!(mp->flags & NAT44_EI_IF_INSIDE))
+    {
+      if (mp->is_add)
+       {
+         rv = nat44_ei_add_output_interface (sw_if_index);
+       }
+      else
+       {
+         rv = nat44_ei_del_output_interface (sw_if_index);
+       }
+    }
 
   BAD_SW_IF_INDEX_LABEL;
   REPLY_MACRO (VL_API_NAT44_EI_INTERFACE_ADD_DEL_OUTPUT_FEATURE_REPLY);
@@ -621,7 +684,9 @@ send_nat44_ei_interface_output_feature_details (nat44_ei_interface_t *i,
   rmp->context = context;
 
   if (nat44_ei_interface_is_inside (i))
-    rmp->flags |= NAT44_EI_IF_INSIDE;
+    {
+      rmp->flags |= NAT44_EI_IF_INSIDE;
+    }
 
   vl_api_send_msg (reg, (u8 *) rmp);
 }
@@ -638,49 +703,135 @@ vl_api_nat44_ei_interface_output_feature_dump_t_handler (
   if (!reg)
     return;
 
-  pool_foreach (i, nm->output_feature_interfaces)
+  pool_foreach (i, nm->output_feature_dummy_interfaces)
     {
       send_nat44_ei_interface_output_feature_details (i, reg, mp->context);
     }
 }
 
+static void
+vl_api_nat44_ei_add_del_output_interface_t_handler (
+  vl_api_nat44_ei_add_del_output_interface_t *mp)
+{
+  vl_api_nat44_ei_add_del_output_interface_reply_t *rmp;
+  nat44_ei_main_t *nm = &nat44_ei_main;
+  int rv = 0;
+
+  VALIDATE_SW_IF_INDEX_END (mp);
+
+  if (mp->is_add)
+    {
+      rv = nat44_ei_add_output_interface (mp->sw_if_index);
+    }
+  else
+    {
+      rv = nat44_ei_del_output_interface (mp->sw_if_index);
+    }
+
+bad_sw_if_index:
+  REPLY_MACRO_END (VL_API_NAT44_EI_ADD_DEL_OUTPUT_INTERFACE_REPLY);
+}
+
+#define vl_endianfun
+#include <nat/nat44-ei/nat44_ei.api.h>
+#undef vl_endianfun
+static void
+send_nat44_ei_output_interface_details (u32 index, vl_api_registration_t *rp,
+                                       u32 context)
+{
+  nat44_ei_main_t *nm = &nat44_ei_main;
+  vl_api_nat44_ei_output_interface_details_t *rmp;
+  nat44_ei_interface_t *i =
+    pool_elt_at_index (nm->output_feature_interfaces, index);
+
+  /* Make sure every field is initiated (or don't skip the clib_memset()) */
+  REPLY_MACRO_DETAILS4 (
+    VL_API_NAT44_EI_OUTPUT_INTERFACE_DETAILS, rp, context, ({
+      rmp->sw_if_index = i->sw_if_index;
+
+      /* Endian hack until apigen registers _details
+       * endian functions */
+      vl_api_nat44_ei_output_interface_details_t_endian (rmp);
+      rmp->_vl_msg_id = htons (rmp->_vl_msg_id);
+      rmp->context = htonl (rmp->context);
+    }));
+}
+
+static void
+vl_api_nat44_ei_output_interface_get_t_handler (
+  vl_api_nat44_ei_output_interface_get_t *mp)
+{
+  vl_api_nat44_ei_output_interface_get_reply_t *rmp;
+  nat44_ei_main_t *nm = &nat44_ei_main;
+  i32 rv = 0;
+
+  if (pool_elts (nm->output_feature_interfaces) == 0)
+    {
+      REPLY_MACRO (VL_API_NAT44_EI_OUTPUT_INTERFACE_GET_REPLY);
+      return;
+    }
+
+  REPLY_AND_DETAILS_MACRO (
+    VL_API_NAT44_EI_OUTPUT_INTERFACE_GET_REPLY, nm->output_feature_interfaces,
+    ({ send_nat44_ei_output_interface_details (cursor, rp, mp->context); }));
+}
+
 static void
 vl_api_nat44_ei_add_del_static_mapping_t_handler (
   vl_api_nat44_ei_add_del_static_mapping_t *mp)
 {
-  nat44_ei_main_t *nm = &nat44_ei_main;
   vl_api_nat44_ei_add_del_static_mapping_reply_t *rmp;
-  ip4_address_t local_addr, external_addr;
-  u16 local_port = 0, external_port = 0;
-  u32 vrf_id, external_sw_if_index;
+
+  nat44_ei_main_t *nm = &nat44_ei_main;
   int rv = 0;
-  nat_protocol_t proto;
+
+  ip4_address_t l_addr, e_addr, pool_addr = { 0 };
+  u32 sw_if_index, flags = 0, vrf_id;
+  u16 l_port = 0, e_port = 0;
+  nat_protocol_t proto = 0;
   u8 *tag = 0;
 
-  memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
-  memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
+  memcpy (&l_addr.as_u8, mp->local_ip_address, 4);
 
-  if (!(mp->flags & NAT44_EI_ADDR_ONLY_MAPPING))
+  if (mp->flags & NAT44_EI_ADDR_ONLY_MAPPING)
     {
-      local_port = mp->local_port;
-      external_port = mp->external_port;
+      flags |= NAT44_EI_SM_FLAG_ADDR_ONLY;
+    }
+  else
+    {
+      l_port = mp->local_port;
+      e_port = mp->external_port;
+      proto = ip_proto_to_nat_proto (mp->protocol);
     }
 
-  vrf_id = clib_net_to_host_u32 (mp->vrf_id);
-  external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
-  proto = ip_proto_to_nat_proto (mp->protocol);
-
-  mp->tag[sizeof (mp->tag) - 1] = 0;
-  tag = format (0, "%s", mp->tag);
-  vec_terminate_c_string (tag);
-
-  rv = nat44_ei_add_del_static_mapping (
-    local_addr, external_addr, local_port, external_port, proto,
-    external_sw_if_index, vrf_id, mp->flags & NAT44_EI_ADDR_ONLY_MAPPING, 0,
-    tag, mp->is_add);
+  sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
+  if (sw_if_index != ~0)
+    {
+      flags |= NAT44_EI_SM_FLAG_SWITCH_ADDRESS;
+    }
+  else
+    {
+      memcpy (&e_addr.as_u8, mp->external_ip_address, 4);
+    }
 
-  vec_free (tag);
+  vrf_id = clib_net_to_host_u32 (mp->vrf_id);
 
+  if (mp->is_add)
+    {
+      mp->tag[sizeof (mp->tag) - 1] = 0;
+      tag = format (0, "%s", mp->tag);
+      vec_terminate_c_string (tag);
+
+      rv = nat44_ei_add_static_mapping (l_addr, e_addr, l_port, e_port, proto,
+                                       vrf_id, sw_if_index, flags, pool_addr,
+                                       tag);
+      vec_free (tag);
+    }
+  else
+    {
+      rv = nat44_ei_del_static_mapping (l_addr, e_addr, l_port, e_port, proto,
+                                       vrf_id, sw_if_index, flags);
+    }
   REPLY_MACRO (VL_API_NAT44_EI_ADD_DEL_STATIC_MAPPING_REPLY);
 }
 
@@ -703,7 +854,7 @@ send_nat44_ei_static_mapping_details (nat44_ei_static_mapping_t *m,
   rmp->vrf_id = htonl (m->vrf_id);
   rmp->context = context;
 
-  if (nat44_ei_is_addr_only_static_mapping (m))
+  if (is_sm_addr_only (m->flags))
     {
       rmp->flags |= NAT44_EI_ADDR_ONLY_MAPPING;
     }
@@ -737,7 +888,7 @@ send_nat44_ei_static_map_resolve_details (nat44_ei_static_map_resolve_t *m,
   rmp->vrf_id = htonl (m->vrf_id);
   rmp->context = context;
 
-  if (m->addr_only)
+  if (is_sm_addr_only (m->flags))
     {
       rmp->flags |= NAT44_EI_ADDR_ONLY_MAPPING;
     }
@@ -769,14 +920,14 @@ vl_api_nat44_ei_static_mapping_dump_t_handler (
 
   pool_foreach (m, nm->static_mappings)
     {
-      if (!nat44_ei_is_identity_static_mapping (m))
+      if (!is_sm_identity_nat (m->flags))
        send_nat44_ei_static_mapping_details (m, reg, mp->context);
     }
 
   for (j = 0; j < vec_len (nm->to_resolve); j++)
     {
       rp = nm->to_resolve + j;
-      if (!rp->identity_nat)
+      if (!is_sm_identity_nat (rp->flags))
        send_nat44_ei_static_map_resolve_details (rp, reg, mp->context);
     }
 }
@@ -785,35 +936,56 @@ static void
 vl_api_nat44_ei_add_del_identity_mapping_t_handler (
   vl_api_nat44_ei_add_del_identity_mapping_t *mp)
 {
-  nat44_ei_main_t *nm = &nat44_ei_main;
   vl_api_nat44_ei_add_del_identity_mapping_reply_t *rmp;
-  ip4_address_t addr;
-  u16 port = 0;
-  u32 vrf_id, sw_if_index;
+
+  nat44_ei_main_t *nm = &nat44_ei_main;
   int rv = 0;
-  nat_protocol_t proto = NAT_PROTOCOL_OTHER;
+
+  ip4_address_t addr, pool_addr = { 0 };
+  u32 sw_if_index, flags, vrf_id;
+  nat_protocol_t proto = 0;
+  u16 port = 0;
   u8 *tag = 0;
 
-  if (!(mp->flags & NAT44_EI_ADDR_ONLY_MAPPING))
+  flags = NAT44_EI_SM_FLAG_IDENTITY_NAT;
+
+  if (mp->flags & NAT44_EI_ADDR_ONLY_MAPPING)
+    {
+      flags |= NAT44_EI_SM_FLAG_ADDR_ONLY;
+    }
+  else
     {
       port = mp->port;
       proto = ip_proto_to_nat_proto (mp->protocol);
     }
-  vrf_id = clib_net_to_host_u32 (mp->vrf_id);
+
   sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
   if (sw_if_index != ~0)
-    addr.as_u32 = 0;
+    {
+      flags |= NAT44_EI_SM_FLAG_SWITCH_ADDRESS;
+    }
   else
-    memcpy (&addr.as_u8, mp->ip_address, 4);
-  mp->tag[sizeof (mp->tag) - 1] = 0;
-  tag = format (0, "%s", mp->tag);
-  vec_terminate_c_string (tag);
+    {
+      memcpy (&addr.as_u8, mp->ip_address, 4);
+    }
 
-  rv = nat44_ei_add_del_static_mapping (
-    addr, addr, port, port, proto, sw_if_index, vrf_id,
-    mp->flags & NAT44_EI_ADDR_ONLY_MAPPING, 1, tag, mp->is_add);
+  vrf_id = clib_net_to_host_u32 (mp->vrf_id);
 
-  vec_free (tag);
+  if (mp->is_add)
+    {
+      mp->tag[sizeof (mp->tag) - 1] = 0;
+      tag = format (0, "%s", mp->tag);
+      vec_terminate_c_string (tag);
+
+      rv = nat44_ei_add_static_mapping (addr, addr, port, port, proto, vrf_id,
+                                       sw_if_index, flags, pool_addr, tag);
+      vec_free (tag);
+    }
+  else
+    {
+      rv = nat44_ei_del_static_mapping (addr, addr, port, port, proto, vrf_id,
+                                       sw_if_index, flags);
+    }
 
   REPLY_MACRO (VL_API_NAT44_EI_ADD_DEL_IDENTITY_MAPPING_REPLY);
 }
@@ -832,7 +1004,7 @@ send_nat44_ei_identity_mapping_details (nat44_ei_static_mapping_t *m,
   rmp->_vl_msg_id =
     ntohs (VL_API_NAT44_EI_IDENTITY_MAPPING_DETAILS + nm->msg_id_base);
 
-  if (nat44_ei_is_addr_only_static_mapping (m))
+  if (is_sm_addr_only (m->flags))
     rmp->flags |= NAT44_EI_ADDR_ONLY_MAPPING;
 
   clib_memcpy (rmp->ip_address, &(m->local_addr), 4);
@@ -859,7 +1031,7 @@ send_nat44_ei_identity_map_resolve_details (nat44_ei_static_map_resolve_t *m,
   rmp->_vl_msg_id =
     ntohs (VL_API_NAT44_EI_IDENTITY_MAPPING_DETAILS + nm->msg_id_base);
 
-  if (m->addr_only)
+  if (is_sm_addr_only (m->flags))
     rmp->flags = (vl_api_nat44_ei_config_flags_t) NAT44_EI_ADDR_ONLY_MAPPING;
 
   rmp->port = m->l_port;
@@ -889,7 +1061,7 @@ vl_api_nat44_ei_identity_mapping_dump_t_handler (
 
   pool_foreach (m, nm->static_mappings)
     {
-      if (nat44_ei_is_identity_static_mapping (m))
+      if (is_sm_identity_nat (m->flags))
        {
          pool_foreach_index (j, m->locals)
            {
@@ -901,7 +1073,7 @@ vl_api_nat44_ei_identity_mapping_dump_t_handler (
   for (j = 0; j < vec_len (nm->to_resolve); j++)
     {
       rp = nm->to_resolve + j;
-      if (rp->identity_nat)
+      if (is_sm_identity_nat (rp->flags))
        send_nat44_ei_identity_map_resolve_details (rp, reg, mp->context);
     }
 }
@@ -914,13 +1086,17 @@ vl_api_nat44_ei_add_del_interface_addr_t_handler (
   vl_api_nat44_ei_add_del_interface_addr_reply_t *rmp;
   u32 sw_if_index = ntohl (mp->sw_if_index);
   int rv = 0;
-  u8 is_del;
-
-  is_del = !mp->is_add;
 
   VALIDATE_SW_IF_INDEX (mp);
 
-  rv = nat44_ei_add_interface_address (nm, sw_if_index, is_del);
+  if (mp->is_add)
+    {
+      rv = nat44_ei_add_interface_address (sw_if_index);
+    }
+  else
+    {
+      rv = nat44_ei_del_interface_address (sw_if_index);
+    }
 
   BAD_SW_IF_INDEX_LABEL;
   REPLY_MACRO (VL_API_NAT44_EI_ADD_DEL_INTERFACE_ADDR_REPLY);
@@ -1042,6 +1218,44 @@ send_nat44_ei_user_session_details (nat44_ei_session_t *s,
   vl_api_send_msg (reg, (u8 *) rmp);
 }
 
+static void
+send_nat44_ei_user_session_v2_details (nat44_ei_session_t *s,
+                                      vl_api_registration_t *reg, u32 context)
+{
+  vl_api_nat44_ei_user_session_v2_details_t *rmp;
+  nat44_ei_main_t *nm = &nat44_ei_main;
+
+  rmp = vl_msg_api_alloc (sizeof (*rmp));
+  clib_memset (rmp, 0, sizeof (*rmp));
+  rmp->_vl_msg_id =
+    ntohs (VL_API_NAT44_EI_USER_SESSION_V2_DETAILS + nm->msg_id_base);
+  clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
+  clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
+
+  if (nat44_ei_is_session_static (s))
+    rmp->flags |= NAT44_EI_STATIC_MAPPING;
+
+  rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
+  rmp->time_since_last_heard = clib_host_to_net_u64 (
+    (u64) (vlib_time_now (vlib_get_main ()) - 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 (nat44_ei_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));
+    }
+  vl_api_send_msg (reg, (u8 *) rmp);
+}
+
 static void
 vl_api_nat44_ei_user_session_dump_t_handler (
   vl_api_nat44_ei_user_session_dump_t *mp)
@@ -1066,8 +1280,9 @@ vl_api_nat44_ei_user_session_dump_t_handler (
   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
   key.key = ukey.as_u64;
   if (nm->num_workers > 1)
-    tnm = vec_elt_at_index (nm->per_thread_data,
-                           nm->worker_in2out_cb (&ip, ukey.fib_index, 0));
+    tnm = vec_elt_at_index (
+      nm->per_thread_data,
+      nat44_ei_get_in2out_worker_index (&ip, ukey.fib_index, 0));
   else
     tnm = vec_elt_at_index (nm->per_thread_data, nm->num_workers);
 
@@ -1094,6 +1309,59 @@ vl_api_nat44_ei_user_session_dump_t_handler (
     }
 }
 
+static void
+vl_api_nat44_ei_user_session_v2_dump_t_handler (
+  vl_api_nat44_ei_user_session_dump_t *mp)
+{
+  vl_api_registration_t *reg;
+  nat44_ei_main_t *nm = &nat44_ei_main;
+  nat44_ei_main_per_thread_data_t *tnm;
+  nat44_ei_session_t *s;
+  clib_bihash_kv_8_8_t key, value;
+  nat44_ei_user_key_t ukey;
+  nat44_ei_user_t *u;
+  u32 session_index, head_index, elt_index;
+  dlist_elt_t *head, *elt;
+  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));
+  key.key = ukey.as_u64;
+  if (nm->num_workers > 1)
+    tnm = vec_elt_at_index (
+      nm->per_thread_data,
+      nat44_ei_get_in2out_worker_index (&ip, ukey.fib_index, 0));
+  else
+    tnm = vec_elt_at_index (nm->per_thread_data, nm->num_workers);
+
+  if (clib_bihash_search_8_8 (&tnm->user_hash, &key, &value))
+    return;
+  u = pool_elt_at_index (tnm->users, value.value);
+  if (!u->nsessions && !u->nstaticsessions)
+    return;
+
+  head_index = u->sessions_per_user_list_head_index;
+  head = pool_elt_at_index (tnm->list_pool, head_index);
+  elt_index = head->next;
+  elt = pool_elt_at_index (tnm->list_pool, elt_index);
+  session_index = elt->value;
+  while (session_index != ~0)
+    {
+      s = pool_elt_at_index (tnm->sessions, session_index);
+
+      send_nat44_ei_user_session_v2_details (s, reg, mp->context);
+
+      elt_index = elt->next;
+      elt = pool_elt_at_index (tnm->list_pool, elt_index);
+      session_index = elt->value;
+    }
+}
+
 static void
 vl_api_nat44_ei_del_session_t_handler (vl_api_nat44_ei_del_session_t *mp)
 {