IPSEC: no second lookup after tunnel encap
in the same maaner as with other tunnel tyeps we use
the FIB to cache and track the destination used to reach
the tunnel endpoint. Post encap we can then ship the packet
straight to this adjacency and thus elide the costly second
lookup.
- SA add and del function so they can be used both directly
from the API and for tunnels.
- API change for the SA dump to use the SA type
- ipsec_key_t type for convenience (copying, [un]formating)
- no matching tunnel counters in ipsec-if-input
Change-Id: I9d144a59667f7bf96442f4ca66bef5c1d3c7f1ea
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/ipsec/ipsec_if.c b/src/vnet/ipsec/ipsec_if.c
index 0dfb690..357d638 100644
--- a/src/vnet/ipsec/ipsec_if.c
+++ b/src/vnet/ipsec/ipsec_if.c
@@ -250,6 +250,18 @@
return 0;
}
+static u32
+ipsec_tun_mk_input_sa_id (u32 ti)
+{
+ return (0x80000000 | ti);
+}
+
+static u32
+ipsec_tun_mk_output_sa_id (u32 ti)
+{
+ return (0xc0000000 | ti);
+}
+
int
ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm,
ipsec_add_del_tunnel_args_t * args,
@@ -260,12 +272,13 @@
vnet_hw_interface_t *hi = NULL;
u32 hw_if_index = ~0;
uword *p;
- ipsec_sa_t *sa;
u32 dev_instance;
u32 slot;
- u32 tx_fib_index = ~0;
+ ipsec_key_t crypto_key, integ_key;
+ ipsec_sa_flags_t flags;
+ int rv;
- u64 key = (u64) args->remote_ip.as_u32 << 32 | (u64) args->remote_spi;
+ u64 key = (u64) args->remote_ip.ip4.as_u32 << 32 | (u64) args->remote_spi;
p = hash_get (im->ipsec_if_pool_index_by_key, key);
if (args->is_add)
@@ -274,10 +287,6 @@
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));
@@ -296,59 +305,53 @@
hash_set (im->ipsec_if_real_dev_by_show_dev, t->show_instance,
dev_instance);
- pool_get (im->sad, sa);
- clib_memset (sa, 0, sizeof (*sa));
- t->input_sa_index = sa - im->sad;
- sa->protocol = IPSEC_PROTOCOL_ESP;
- sa->spi = args->remote_spi;
- sa->tunnel_src_addr.ip4.as_u32 = args->remote_ip.as_u32;
- sa->tunnel_dst_addr.ip4.as_u32 = args->local_ip.as_u32;
- sa->is_tunnel = 1;
- sa->use_esn = args->esn;
- 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;
- clib_memcpy (sa->integ_key, args->remote_integ_key,
- args->remote_integ_key_len);
- }
- sa->crypto_alg = args->crypto_alg;
- if (args->remote_crypto_key_len <= sizeof (args->remote_crypto_key))
- {
- sa->crypto_key_len = args->remote_crypto_key_len;
- clib_memcpy (sa->crypto_key, args->remote_crypto_key,
- args->remote_crypto_key_len);
- }
+ flags = IPSEC_SA_FLAG_IS_TUNNEL;
+ if (args->udp_encap)
+ flags |= IPSEC_SA_FLAG_UDP_ENCAP;
+ if (args->esn)
+ flags |= IPSEC_SA_FLAG_USE_EXTENDED_SEQ_NUM;
+ if (args->anti_replay)
+ flags |= IPSEC_SA_FLAG_USE_ANTI_REPLAY;
- pool_get (im->sad, sa);
- clib_memset (sa, 0, sizeof (*sa));
- t->output_sa_index = sa - im->sad;
- sa->protocol = IPSEC_PROTOCOL_ESP;
- sa->spi = args->local_spi;
- sa->tunnel_src_addr.ip4.as_u32 = args->local_ip.as_u32;
- sa->tunnel_dst_addr.ip4.as_u32 = args->remote_ip.as_u32;
- sa->is_tunnel = 1;
- sa->use_esn = args->esn;
- 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;
- clib_memcpy (sa->integ_key, args->local_integ_key,
- args->local_integ_key_len);
- }
- sa->crypto_alg = args->crypto_alg;
- if (args->local_crypto_key_len <= sizeof (args->local_crypto_key))
- {
- sa->crypto_key_len = args->local_crypto_key_len;
- clib_memcpy (sa->crypto_key, args->local_crypto_key,
- args->local_crypto_key_len);
- }
+ ipsec_mk_key (&crypto_key,
+ args->remote_crypto_key, args->remote_crypto_key_len);
+ ipsec_mk_key (&integ_key,
+ args->remote_integ_key, args->remote_integ_key_len);
+
+ rv = ipsec_sa_add (ipsec_tun_mk_input_sa_id (dev_instance),
+ args->remote_spi,
+ IPSEC_PROTOCOL_ESP,
+ args->crypto_alg,
+ &crypto_key,
+ args->integ_alg,
+ &integ_key,
+ flags,
+ args->tx_table_id,
+ &args->remote_ip,
+ &args->local_ip, &t->input_sa_index);
+
+ if (rv)
+ return VNET_API_ERROR_UNIMPLEMENTED;
+
+ ipsec_mk_key (&crypto_key,
+ args->local_crypto_key, args->local_crypto_key_len);
+ ipsec_mk_key (&integ_key,
+ args->local_integ_key, args->local_integ_key_len);
+
+ rv = ipsec_sa_add (ipsec_tun_mk_output_sa_id (dev_instance),
+ args->local_spi,
+ IPSEC_PROTOCOL_ESP,
+ args->crypto_alg,
+ &crypto_key,
+ args->integ_alg,
+ &integ_key,
+ flags,
+ args->tx_table_id,
+ &args->local_ip,
+ &args->remote_ip, &t->output_sa_index);
+
+ if (rv)
+ return VNET_API_ERROR_UNIMPLEMENTED;
hash_set (im->ipsec_if_pool_index_by_key, key,
t - im->tunnel_interfaces);
@@ -392,18 +395,14 @@
vnet_delete_hw_interface (vnm, t->hw_if_index);
- /* delete input and output SA */
-
- sa = pool_elt_at_index (im->sad, t->input_sa_index);
- pool_put (im->sad, sa);
-
- sa = pool_elt_at_index (im->sad, t->output_sa_index);
- pool_put (im->sad, sa);
-
hash_unset (im->ipsec_if_pool_index_by_key, key);
hash_unset (im->ipsec_if_real_dev_by_show_dev, t->show_instance);
pool_put (im->tunnel_interfaces, t);
+
+ /* delete input and output SA */
+ ipsec_sa_del (ipsec_tun_mk_input_sa_id (p[0]));
+ ipsec_sa_del (ipsec_tun_mk_output_sa_id (p[0]));
}
if (sw_if_index)
@@ -493,29 +492,25 @@
{
sa = pool_elt_at_index (im->sad, t->output_sa_index);
sa->crypto_alg = alg;
- sa->crypto_key_len = vec_len (key);
- clib_memcpy (sa->crypto_key, key, vec_len (key));
+ ipsec_mk_key (&sa->crypto_key, key, vec_len (key));
}
else if (type == IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG)
{
sa = pool_elt_at_index (im->sad, t->output_sa_index);
sa->integ_alg = alg;
- sa->integ_key_len = vec_len (key);
- clib_memcpy (sa->integ_key, key, vec_len (key));
+ ipsec_mk_key (&sa->integ_key, key, vec_len (key));
}
else if (type == IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO)
{
sa = pool_elt_at_index (im->sad, t->input_sa_index);
sa->crypto_alg = alg;
- sa->crypto_key_len = vec_len (key);
- clib_memcpy (sa->crypto_key, key, vec_len (key));
+ ipsec_mk_key (&sa->crypto_key, key, vec_len (key));
}
else if (type == IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG)
{
sa = pool_elt_at_index (im->sad, t->input_sa_index);
sa->integ_alg = alg;
- sa->integ_key_len = vec_len (key);
- clib_memcpy (sa->integ_key, key, vec_len (key));
+ ipsec_mk_key (&sa->integ_key, key, vec_len (key));
}
else
return VNET_API_ERROR_INVALID_VALUE;