Add IPSec interface FIB index for TX packet 12/16412/6
authorPierre Pfister <ppfister@cisco.com>
Mon, 10 Dec 2018 10:19:08 +0000 (11:19 +0100)
committerNeale Ranns <nranns@cisco.com>
Tue, 11 Dec 2018 12:42:09 +0000 (12:42 +0000)
This patch adds a configuration parameter to IPSec tunnels, enabling
custom FIB selection for encapsulated packets.
Although this option could also be used for policy-based IPSec,
this change only enables it for virtual-tunnel-interface mode.

Note that this patch does change the API default behavior regarding
TX fib selection for encapsulated packets.
Previous behavior was to use the same FIB after and before encap.
The new default behavior consists in using the FIB 0 as default.

Change-Id: I5c212af909940a8cf6c7e3971bdc7623a2296452
Signed-off-by: Pierre Pfister <ppfister@cisco.com>
src/vnet/ipsec/esp_encrypt.c
src/vnet/ipsec/ipsec.api
src/vnet/ipsec/ipsec.h
src/vnet/ipsec/ipsec_api.c
src/vnet/ipsec/ipsec_cli.c
src/vnet/ipsec/ipsec_if.c

index ff9c1e6..16f985c 100644 (file)
@@ -279,7 +279,7 @@ esp_encrypt_inline (vlib_main_t * vm,
              oh0->ip4.src_address.as_u32 = sa0->tunnel_src_addr.ip4.as_u32;
              oh0->ip4.dst_address.as_u32 = sa0->tunnel_dst_addr.ip4.as_u32;
 
-             vnet_buffer (o_b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
+             vnet_buffer (o_b0)->sw_if_index[VLIB_TX] = sa0->tx_fib_index;
            }
          else if (is_ip6 && sa0->is_tunnel && sa0->is_tunnel_ip6)
            {
@@ -292,7 +292,7 @@ esp_encrypt_inline (vlib_main_t * vm,
              oh6_0->ip6.dst_address.as_u64[1] =
                sa0->tunnel_dst_addr.ip6.as_u64[1];
 
-             vnet_buffer (o_b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
+             vnet_buffer (o_b0)->sw_if_index[VLIB_TX] = sa0->tx_fib_index;
            }
          else
            {
index 610f232..2b015f9 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-option version = "2.0.0";
+option version = "2.1.0";
 
 /** \brief IPsec: Add/delete Security Policy Database
     @param client_index - opaque cookie to identify the sender
@@ -563,6 +563,7 @@ define ipsec_spd_interface_details {
     @param renumber - intf display name uses a specified instance if != 0
     @param show_instance - instance to display for intf if renumber is set
     @param udp_encap - enable UDP encapsulation for NAT traversal
+    @param tx_table_id - the FIB id used after packet encap
 */
 define ipsec_tunnel_if_add_del {
   u32 client_index;
@@ -587,6 +588,7 @@ define ipsec_tunnel_if_add_del {
   u8 renumber;
   u32 show_instance;
   u8 udp_encap;
+  u32 tx_table_id;
 };
 
 /** \brief Add/delete IPsec tunnel interface response
@@ -637,6 +639,7 @@ define ipsec_sa_dump {
     @param replay_window - bit map of seq nums received relative to last_seq if using anti-replay
     @param total_data_size - total bytes sent or received
     @param udp_encap - 1 if UDP encap enabled, 0 otherwise
+    @param tx_table_id - the FIB id used for encapsulated packets
 */
 define ipsec_sa_details {
   u32 context;
@@ -669,6 +672,8 @@ define ipsec_sa_details {
 
   u64 total_data_size;
   u8 udp_encap;
+
+  u32 tx_table_id;
 };
 
 /** \brief Set key on IPsec interface
index d407670..691bc07 100644 (file)
@@ -139,6 +139,7 @@ typedef struct
   ip46_address_t tunnel_src_addr;
   ip46_address_t tunnel_dst_addr;
 
+  u32 tx_fib_index;
   u32 salt;
 
   /* runtime */
@@ -183,6 +184,7 @@ typedef struct
   u8 renumber;
   u32 show_instance;
   u8 udp_encap;
+  u32 tx_table_id;
 } ipsec_add_del_tunnel_args_t;
 
 typedef struct
index 3f30a7d..59fb868 100644 (file)
@@ -23,6 +23,7 @@
 #include <vnet/interface.h>
 #include <vnet/api_errno.h>
 #include <vnet/ip/ip.h>
+#include <vnet/fib/fib.h>
 
 #include <vnet/vnet_msg_enum.h>
 
@@ -471,6 +472,7 @@ vl_api_ipsec_tunnel_if_add_del_t_handler (vl_api_ipsec_tunnel_if_add_del_t *
   tun.local_integ_key_len = mp->local_integ_key_len;
   tun.remote_integ_key_len = mp->remote_integ_key_len;
   tun.udp_encap = mp->udp_encap;
+  tun.tx_table_id = ntohl (mp->tx_table_id);
   memcpy (&tun.local_ip, mp->local_ip, 4);
   memcpy (&tun.remote_ip, mp->remote_ip, 4);
   memcpy (&tun.local_crypto_key, &mp->local_crypto_key,
@@ -555,6 +557,9 @@ send_ipsec_sa_details (ipsec_sa_t * sa, vl_api_registration_t * reg,
   mp->total_data_size = clib_host_to_net_u64 (sa->total_data_size);
   mp->udp_encap = sa->udp_encap;
 
+  mp->tx_table_id =
+    htonl (fib_table_get_table_id (sa->tx_fib_index, FIB_PROTOCOL_IP4));
+
   vl_api_send_msg (reg, (u8 *) mp);
 }
 
index f965514..f0717e9 100644 (file)
@@ -19,6 +19,7 @@
 #include <vnet/api_errno.h>
 #include <vnet/ip/ip.h>
 #include <vnet/interface.h>
+#include <vnet/fib/fib.h>
 
 #include <vnet/ipsec/ipsec.h>
 
@@ -80,6 +81,7 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm,
   clib_error_t *error = NULL;
 
   clib_memset (&sa, 0, sizeof (sa));
+  sa.tx_fib_index = ~((u32) 0);        /* Only supported for ipsec interfaces */
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -458,6 +460,7 @@ show_ipsec_command_fn (vlib_main_t * vm,
   vnet_hw_interface_t *hi;
   u8 *protocol = NULL;
   u8 *policy = NULL;
+  u32 tx_table_id;
 
   /* *INDENT-OFF* */
   pool_foreach (sa, im->sad, ({
@@ -670,8 +673,11 @@ show_ipsec_command_fn (vlib_main_t * vm,
     hi = vnet_get_hw_interface (im->vnet_main, t->hw_if_index);
     vlib_cli_output(vm, "  %s seq", hi->name);
     sa = pool_elt_at_index(im->sad, t->output_sa_index);
-    vlib_cli_output(vm, "   seq %u seq-hi %u esn %u anti-replay %u udp-encap %u",
-                    sa->seq, sa->seq_hi, sa->use_esn, sa->use_anti_replay, sa->udp_encap);
+
+    tx_table_id = fib_table_get_table_id(sa->tx_fib_index, FIB_PROTOCOL_IP4);
+
+    vlib_cli_output(vm, "   seq %u seq-hi %u esn %u anti-replay %u udp-encap %u tx-table %u",
+                    sa->seq, sa->seq_hi, sa->use_esn, sa->use_anti_replay, sa->udp_encap, tx_table_id);
     vlib_cli_output(vm, "   local-spi %u local-ip %U", sa->spi,
                     format_ip4_address, &sa->tunnel_src_addr.ip4);
     vlib_cli_output(vm, "   local-crypto %U %U",
@@ -910,6 +916,8 @@ create_ipsec_tunnel_command_fn (vlib_main_t * vm,
        a.is_add = 0;
       else if (unformat (line_input, "udp-encap"))
        a.udp_encap = 1;
+      else if (unformat (line_input, "tx-table %u", &a.tx_table_id))
+       ;
       else
        {
          error = clib_error_return (0, "unknown input `%U'",
@@ -952,7 +960,9 @@ done:
 /* *INDENT-OFF* */
 VLIB_CLI_COMMAND (create_ipsec_tunnel_command, static) = {
   .path = "create ipsec tunnel",
-  .short_help = "create ipsec tunnel local-ip <addr> local-spi <spi> remote-ip <addr> remote-spi <spi> [instance <inst_num>] [udp-encap]",
+  .short_help = "create ipsec tunnel local-ip <addr> local-spi <spi> "
+      "remote-ip <addr> remote-spi <spi> [instance <inst_num>] [udp-encap] "
+      "[tx-table <table-id>]",
   .function = create_ipsec_tunnel_command_fn,
 };
 /* *INDENT-ON* */
index 2e0dae0..3054af1 100644 (file)
@@ -18,6 +18,7 @@
 #include <vnet/vnet.h>
 #include <vnet/api_errno.h>
 #include <vnet/ip/ip.h>
+#include <vnet/fib/fib.h>
 
 #include <vnet/ipsec/ipsec.h>
 #include <vnet/ipsec/esp.h>
@@ -262,6 +263,7 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm,
   ipsec_sa_t *sa;
   u32 dev_instance;
   u32 slot;
+  u32 tx_fib_index = ~0;
 
   u64 key = (u64) args->remote_ip.as_u32 << 32 | (u64) args->remote_spi;
   p = hash_get (im->ipsec_if_pool_index_by_key, key);
@@ -272,6 +274,10 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm,
       if (p)
        return VNET_API_ERROR_INVALID_VALUE;
 
+      tx_fib_index = fib_table_find (FIB_PROTOCOL_IP4, args->tx_table_id);
+      if (tx_fib_index == ~((u32) 0))
+       return VNET_API_ERROR_NO_SUCH_FIB;
+
       pool_get_aligned (im->tunnel_interfaces, t, CLIB_CACHE_LINE_BYTES);
       clib_memset (t, 0, sizeof (*t));
 
@@ -301,6 +307,7 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm,
       sa->use_anti_replay = args->anti_replay;
       sa->integ_alg = args->integ_alg;
       sa->udp_encap = args->udp_encap;
+      sa->tx_fib_index = ~((u32) 0);   /* Not used, but set for troubleshooting */
       if (args->remote_integ_key_len <= sizeof (args->remote_integ_key))
        {
          sa->integ_key_len = args->remote_integ_key_len;
@@ -326,6 +333,7 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm,
       sa->use_anti_replay = args->anti_replay;
       sa->integ_alg = args->integ_alg;
       sa->udp_encap = args->udp_encap;
+      sa->tx_fib_index = tx_fib_index;
       if (args->local_integ_key_len <= sizeof (args->local_integ_key))
        {
          sa->integ_key_len = args->local_integ_key_len;