session: fix SDL to use remote instead local

The language is
local == VPP local interface
remote == sender prefix to VPP node
SDL acts on remote prefix.

Type: fix

Change-Id: I82917c6ef801fc67430dfdd15c5630cb7a6347e0
Signed-off-by: Steven Luong <sluong@cisco.com>
diff --git a/src/vnet/session/session.api b/src/vnet/session/session.api
index 26346ea..f678f8b 100644
--- a/src/vnet/session/session.api
+++ b/src/vnet/session/session.api
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-option version = "4.0.1";
+option version = "4.0.2";
 
 import "vnet/interface_types.api";
 import "vnet/ip/ip_types.api";
@@ -26,6 +26,13 @@
   string tag[64];
 };
 
+typedef sdl_rule_v2
+{
+  vl_api_prefix_t rmt;
+  u32 action_index;
+  string tag[64];
+};
+
 enum transport_proto : u8
 {
         TRANSPORT_PROTO_API_TCP,
@@ -440,6 +447,7 @@
 };
 
 autoreply define session_sdl_add_del {
+  option deprecated;
   u32 client_index;
   u32 context;
   u32 appns_index;
@@ -448,12 +456,22 @@
   vl_api_sdl_rule_t r[count];
 };
 
+autoreply define session_sdl_add_del_v2 {
+  u32 client_index;
+  u32 context;
+  u32 appns_index;
+  bool is_add;
+  u32 count;
+  vl_api_sdl_rule_v2_t r[count];
+};
+
 /** \brief Dump session sdl
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
  */
 define session_sdl_dump
 {
+  option deprecated;
   u32 client_index;
   u32 context;
 };
@@ -468,6 +486,7 @@
   */
 define session_sdl_details
 {
+  option deprecated;
   u32 context;
   vl_api_prefix_t lcl;
   u32 action_index;
@@ -475,6 +494,33 @@
   string tag[64];
 };
 
+/** \brief Dump session sdl v2
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+ */
+define session_sdl_v2_dump
+{
+  u32 client_index;
+  u32 context;
+};
+
+/** \brief Session sdl details v2
+    @param context - sender context, to match reply w/ request
+    @param rmt - remote prefix
+    @param action_index - the only action defined now is forward to
+                          application with index action_index
+    @param appns_index - application namespace where rule is to be applied to
+    @param tag - tag
+  */
+define session_sdl_v2_details
+{
+  u32 context;
+  vl_api_prefix_t rmt;
+  u32 action_index;
+  u32 appns_index;
+  string tag[64];
+};
+
 /*
  * Local Variables:
  * eval: (c-set-style "gnu")
diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c
index a729baa..f0043f9 100644
--- a/src/vnet/session/session_api.c
+++ b/src/vnet/session/session_api.c
@@ -59,6 +59,72 @@
 }
 
 static void
+vl_api_session_sdl_add_del_v2_t_handler (vl_api_session_sdl_add_del_v2_t *mp)
+{
+  vl_api_session_sdl_add_del_v2_reply_t *rmp;
+  session_rule_add_del_args_t args;
+  session_rule_table_add_del_args_t *table_args = &args.table_args;
+  int rv = 0;
+  u32 count = clib_net_to_host_u32 (mp->count);
+  u64 expected_len = sizeof (*mp) + count * sizeof (mp->r[0]);
+
+  if ((session_main.is_enabled == 0) || (session_sdl_is_enabled () == 0))
+    {
+      rv = VNET_API_ERROR_FEATURE_DISABLED;
+      goto done;
+    }
+
+  if (!verify_message_len (mp, expected_len, "session_sdl_add_del_v2"))
+    {
+      rv = VNET_API_ERROR_INVALID_VALUE;
+      goto done;
+    }
+
+  clib_memset (&args, 0, sizeof (args));
+  table_args->is_add = mp->is_add;
+  args.scope = SESSION_RULE_SCOPE_GLOBAL;
+  args.appns_index = clib_net_to_host_u32 (mp->appns_index);
+  for (int i = 0; i < count; i++)
+    {
+      mp->r[i].tag[sizeof (mp->r[i].tag) - 1] = 0;
+      table_args->tag = format (0, "%s", mp->r[i].tag);
+      ip_prefix_decode (&mp->r[i].rmt, &table_args->rmt);
+      table_args->action_index = clib_net_to_host_u32 (mp->r[i].action_index);
+
+      rv = vnet_session_rule_add_del (&args);
+      vec_free (table_args->tag);
+      if (rv)
+	{
+	  log_err ("session_sdl add del returned on %U @index %d: %U",
+		   format_ip46_address, &table_args->rmt.fp_addr,
+		   IP46_TYPE_ANY, i, format_session_error, rv);
+
+	  /* roll back */
+	  table_args->is_add = !mp->is_add;
+	  for (int j = i - 1; j >= 0; j--)
+	    {
+	      mp->r[j].tag[sizeof (mp->r[j].tag) - 1] = 0;
+	      table_args->tag = format (0, "%s", mp->r[j].tag);
+	      ip_prefix_decode (&mp->r[j].rmt, &table_args->rmt);
+	      table_args->action_index =
+		clib_net_to_host_u32 (mp->r[j].action_index);
+	      int rv2 = vnet_session_rule_add_del (&args);
+	      vec_free (table_args->tag);
+	      if (rv2)
+		log_err ("rollback session_sdl add del returned on %U "
+			 "@index %d: %U",
+			 format_ip46_address, &table_args->rmt.fp_addr,
+			 IP46_TYPE_ANY, j, format_session_error, rv2);
+	    }
+	  break;
+	}
+    }
+
+done:
+  REPLY_MACRO (VL_API_SESSION_SDL_ADD_DEL_V2_REPLY);
+}
+
+static void
 vl_api_session_sdl_add_del_t_handler (vl_api_session_sdl_add_del_t *mp)
 {
   vl_api_session_sdl_add_del_reply_t *rmp;
@@ -1293,6 +1359,73 @@
 } session_sdl_table_walk_ctx;
 
 static void
+send_session_sdl_v2_details (u32 fei, ip46_address_t *rmt_ip, u16 fp_len,
+			     u32 action_index, u32 fp_proto, u8 *tag,
+			     void *args)
+{
+  session_sdl_table_walk_ctx *ctx = args;
+  vl_api_registration_t *reg = ctx->reg;
+  u32 appns_index = ctx->appns_index;
+  u32 context = ctx->mp_context;
+  vl_api_session_sdl_v2_details_t *rmp = 0;
+  fib_prefix_t rmt;
+
+  rmp = vl_msg_api_alloc (sizeof (*rmp));
+  clib_memset (rmp, 0, sizeof (*rmp));
+  rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_V2_DETAILS);
+  rmp->context = context;
+
+  clib_memset (&rmt, 0, sizeof (rmt));
+  if (fp_proto == FIB_PROTOCOL_IP4)
+    ip_set (&rmt.fp_addr, &rmt_ip->ip4, 1);
+  else
+    ip_set (&rmt.fp_addr, &rmt_ip->ip6, 0);
+  rmt.fp_len = fp_len;
+  rmt.fp_proto = fp_proto,
+
+  ip_prefix_encode (&rmt, &rmp->rmt);
+  rmp->action_index = clib_host_to_net_u32 (action_index);
+  rmp->appns_index = clib_host_to_net_u32 (appns_index);
+  if (tag)
+    {
+      clib_memcpy_fast (rmp->tag, tag, vec_len (tag));
+      rmp->tag[vec_len (tag)] = 0;
+    }
+
+  vl_api_send_msg (reg, (u8 *) rmp);
+}
+
+static void
+vl_api_session_sdl_v2_dump_t_handler (vl_api_session_sdl_v2_dump_t *mp)
+{
+  vl_api_registration_t *reg;
+  session_table_t *st;
+  session_sdl_table_walk_ctx ctx;
+
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
+
+  ctx.reg = reg;
+  ctx.mp_context = mp->context;
+
+  session_table_foreach (
+    st, ({
+      if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)
+	{
+	  ctx.appns_index = st->appns_index;
+
+	  if (st->active_fib_proto == FIB_PROTOCOL_IP4)
+	    session_sdl_table_walk4 (st->srtg_handle,
+				     send_session_sdl_v2_details, &ctx);
+	  else
+	    session_sdl_table_walk6 (st->srtg_handle,
+				     send_session_sdl_v2_details, &ctx);
+	}
+    }));
+}
+
+static void
 send_session_sdl_details (u32 fei, ip46_address_t *lcl_ip, u16 fp_len,
 			  u32 action_index, u32 fp_proto, u8 *tag, void *args)
 {
@@ -1329,7 +1462,7 @@
 }
 
 static void
-vl_api_session_sdl_dump_t_handler (vl_api_session_rules_dump_t *mp)
+vl_api_session_sdl_dump_t_handler (vl_api_session_sdl_dump_t *mp)
 {
   vl_api_registration_t *reg;
   session_table_t *st;
@@ -2063,11 +2196,19 @@
   vl_api_set_msg_thread_safe (
     am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_ADD_DEL, 1);
   vl_api_set_msg_thread_safe (
+    am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_ADD_DEL_V2, 1);
+  vl_api_set_msg_thread_safe (
     am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_ADD_DEL_REPLY, 1);
   vl_api_set_msg_thread_safe (am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_DUMP,
 			      1);
   vl_api_set_msg_thread_safe (
     am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_DETAILS, 1);
+  vl_api_set_msg_thread_safe (
+    am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_ADD_DEL_V2_REPLY, 1);
+  vl_api_set_msg_thread_safe (
+    am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_V2_DUMP, 1);
+  vl_api_set_msg_thread_safe (
+    am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_V2_DETAILS, 1);
   return 0;
 }
 
diff --git a/src/vnet/session/session_sdl.c b/src/vnet/session/session_sdl.c
index 45ab705..9505ba1 100644
--- a/src/vnet/session/session_sdl.c
+++ b/src/vnet/session/session_sdl.c
@@ -87,7 +87,7 @@
 
   if (sdlb->ip6_fib_index == ~0)
     return SESSION_TABLE_INVALID_INDEX;
-  lbi = ip6_fib_table_fwding_lookup (sdlb->ip6_fib_index, lcl_ip);
+  lbi = ip6_fib_table_fwding_lookup (sdlb->ip6_fib_index, rmt_ip);
   dpo = load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
   if (dpo->dpoi_type != sdl_dpo_type)
     return SESSION_TABLE_INVALID_INDEX;
@@ -105,7 +105,7 @@
 
   if (sdlb->ip_fib_index == ~0)
     return SESSION_TABLE_INVALID_INDEX;
-  lbi = ip4_fib_forwarding_lookup (sdlb->ip_fib_index, lcl_ip);
+  lbi = ip4_fib_forwarding_lookup (sdlb->ip_fib_index, rmt_ip);
   dpo = load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
   if (dpo->dpoi_type != sdl_dpo_type)
     return SESSION_TABLE_INVALID_INDEX;
@@ -143,7 +143,7 @@
 }
 
 static void
-session_sdl_fib_table_show (u32 fei, ip46_address_t *lcl_ip, u16 fp_len,
+session_sdl_fib_table_show (u32 fei, ip46_address_t *rmt_ip, u16 fp_len,
 			    u32 action_index, u32 fp_proto, u8 *tag,
 			    void *args)
 {
@@ -151,7 +151,7 @@
   u32 type = (fp_proto == FIB_PROTOCOL_IP4) ? IP46_TYPE_IP4 : IP46_TYPE_IP6;
 
   vlib_cli_output (vm, "[%d] rule: %U/%d action: %d tag %U", fei,
-		   format_ip46_address, lcl_ip, type, fp_len, action_index,
+		   format_ip46_address, rmt_ip, type, fp_len, action_index,
 		   format_session_rule_tag, tag);
 }
 
@@ -230,11 +230,11 @@
 
   sdlb = &srt->sdl_block;
   if (is_ip4)
-    session_sdl4_fib_table_show_one (srt, sdlb->ip_fib_index, vm, &lcl_ip->ip4,
+    session_sdl4_fib_table_show_one (srt, sdlb->ip_fib_index, vm, &rmt_ip->ip4,
 				     32);
   else
     session_sdl6_fib_table_show_one (srt, sdlb->ip6_fib_index, vm,
-				     &lcl_ip->ip6, 128);
+				     &rmt_ip->ip6, 128);
 }
 
 static void
@@ -310,20 +310,16 @@
   u32 fib_index;
   dpo_proto_t dpo_proto;
   fib_route_path_t *paths = 0;
-  fib_prefix_t pfx = args->lcl;
+  fib_prefix_t pfx = args->rmt;
   session_error_t err = SESSION_E_NONE;
   fib_node_index_t fei;
   int is_ip4;
 
-  if (!(args->lcl_port == 0 && args->rmt_port == 0 &&
-	args->rmt.fp_addr.ip4.as_u32 == 0))
-    return SESSION_E_NOSUPPORT;
-
   fei = session_rules_table_rule_for_tag (srt, args->tag);
   if (args->is_add && fei != SESSION_RULES_TABLE_INVALID_INDEX)
     return SESSION_E_INVALID;
 
-  if (args->lcl.fp_proto == FIB_PROTOCOL_IP4)
+  if (args->rmt.fp_proto == FIB_PROTOCOL_IP4)
     {
       fib_index = sdlb->ip_fib_index;
       dpo_proto = DPO_PROTO_IP4;
@@ -463,9 +459,9 @@
 {
   u32 appns_index;
   app_namespace_t *app_ns;
-  u32 lcl_plen = 0, action = 0;
+  u32 rmt_plen = 0, action = 0;
   clib_error_t *error = 0;
-  ip46_address_t lcl_ip;
+  ip46_address_t rmt_ip;
   u8 conn_set = 0;
   u8 fib_proto = -1, is_add = 1, *ns_id = 0;
   u8 *tag = 0, tag_only = 0;
@@ -485,14 +481,14 @@
 	;
       else if (unformat (input, "appns %_%v%_", &ns_id))
 	;
-      else if (unformat (input, "%U/%d", unformat_ip4_address, &lcl_ip.ip4,
-			 &lcl_plen))
+      else if (unformat (input, "%U/%d", unformat_ip4_address, &rmt_ip.ip4,
+			 &rmt_plen))
 	{
 	  fib_proto = FIB_PROTOCOL_IP4;
 	  conn_set = 1;
 	}
-      else if (unformat (input, "%U/%d", unformat_ip6_address, &lcl_ip.ip6,
-			 &lcl_plen))
+      else if (unformat (input, "%U/%d", unformat_ip6_address, &rmt_ip.ip6,
+			 &rmt_plen))
 	{
 	  fib_proto = FIB_PROTOCOL_IP6;
 	  conn_set = 1;
@@ -549,9 +545,8 @@
 
   memset (&args, 0, sizeof (args));
   args.transport_proto = TRANSPORT_PROTO_TCP;
-  args.table_args.lcl.fp_addr = lcl_ip;
-  args.table_args.lcl.fp_len = lcl_plen;
-  args.table_args.lcl.fp_proto = fib_proto;
+  args.table_args.rmt.fp_addr = rmt_ip;
+  args.table_args.rmt.fp_len = rmt_plen;
   args.table_args.rmt.fp_proto = fib_proto;
   args.table_args.action_index = action;
   args.table_args.is_add = is_add;
@@ -585,7 +580,7 @@
 
 VLIB_CLI_COMMAND (session_sdl_command, static) = {
   .path = "session sdl",
-  .short_help = "session sdl [add|del] [appns <ns_id>] <lcl-ip/plen> action "
+  .short_help = "session sdl [add|del] [appns <ns_id>] <rmt-ip/plen> action "
 		"<action> [tag <tag>]",
   .function = session_sdl_command_fn,
   .is_mp_safe = 1,
@@ -596,7 +591,7 @@
 			     vlib_cli_command_t *cmd)
 {
   u32 fib_index;
-  ip46_address_t lcl_ip;
+  ip46_address_t rmt_ip;
   u8 show_one = 0;
   app_namespace_t *app_ns;
   session_table_t *st;
@@ -604,17 +599,17 @@
 
   session_cli_return_if_not_enabled ();
 
-  clib_memset (&lcl_ip, 0, sizeof (lcl_ip));
+  clib_memset (&rmt_ip, 0, sizeof (rmt_ip));
   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     {
       if (unformat (input, "appns %_%s%_", &ns_id))
 	;
-      else if (unformat (input, "%U", unformat_ip4_address, &lcl_ip.ip4))
+      else if (unformat (input, "%U", unformat_ip4_address, &rmt_ip.ip4))
 	{
 	  fib_proto = FIB_PROTOCOL_IP4;
 	  show_one = 1;
 	}
-      else if (unformat (input, "%U", unformat_ip6_address, &lcl_ip.ip6))
+      else if (unformat (input, "%U", unformat_ip6_address, &rmt_ip.ip6))
 	{
 	  fib_proto = FIB_PROTOCOL_IP6;
 	  show_one = 1;
@@ -652,7 +647,7 @@
       fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
       st = session_table_get_for_fib_index (fib_proto, fib_index);
       if (st && (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID))
-	session_rules_table_show_rule (vm, st->srtg_handle, 0, &lcl_ip, 0, 0,
+	session_rules_table_show_rule (vm, st->srtg_handle, 0, &rmt_ip, 0, 0,
 				       0, (fib_proto == FIB_PROTOCOL_IP4));
       goto done;
     }
@@ -754,7 +749,7 @@
 
 VLIB_CLI_COMMAND (show_session_sdl_command, static) = {
   .path = "show session sdl",
-  .short_help = "show session sdl [appns <id> <lcl-ip>]",
+  .short_help = "show session sdl [appns <id> <rmt-ip>]",
   .function = show_session_sdl_command_fn,
   .is_mp_safe = 1,
 };
diff --git a/src/vnet/session/session_test.c b/src/vnet/session/session_test.c
index 1c865b8..e248dd7 100644
--- a/src/vnet/session/session_test.c
+++ b/src/vnet/session/session_test.c
@@ -366,8 +366,19 @@
   return -1;
 }
 
+static int
+api_session_sdl_add_del_v2 (vat_main_t *vam)
+{
+  return -1;
+}
+
 static void
-vl_api_session_sdl_details_t_handler (vl_api_session_rules_details_t *mp)
+vl_api_session_sdl_details_t_handler (vl_api_session_sdl_details_t *mp)
+{
+}
+
+static void
+vl_api_session_sdl_v2_details_t_handler (vl_api_session_sdl_v2_details_t *mp)
 {
 }
 
@@ -377,6 +388,12 @@
   return -1;
 }
 
+static int
+api_session_sdl_v2_dump (vat_main_t *vam)
+{
+  return -1;
+}
+
 #include <vnet/session/session.api_test.c>
 
 /*