- pool_get (im->sad, sa);
- memset (sa, 0, sizeof (*sa));
- t->input_sa_index = sa - im->sad;
- 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;
- 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);
- }
-
- pool_get (im->sad, sa);
- memset (sa, 0, sizeof (*sa));
- t->output_sa_index = sa - im->sad;
- 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;
- 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);
- }
-
- hash_set (im->ipsec_if_pool_index_by_key, key,
- t - im->tunnel_interfaces);
+ flags = IPSEC_SA_FLAG_IS_TUNNEL;
+ if (args->is_ip6)
+ flags |= IPSEC_SA_FLAG_IS_TUNNEL_V6;
+ if (args->udp_encap)
+ flags |= IPSEC_SA_FLAG_UDP_ENCAP;
+ if (args->esn)
+ flags |= IPSEC_SA_FLAG_USE_ESN;
+ if (args->anti_replay)
+ flags |= IPSEC_SA_FLAG_USE_ANTI_REPLAY;
+
+ 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 | IPSEC_SA_FLAG_IS_INBOUND),
+ args->tx_table_id,
+ args->salt,
+ &args->remote_ip,
+ &args->local_ip, &t->input_sa_index);
+
+ if (rv)
+ return VNET_API_ERROR_INVALID_SRC_ADDRESS;
+
+ 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->salt,
+ &args->local_ip,
+ &args->remote_ip, &t->output_sa_index);
+
+ if (rv)
+ return VNET_API_ERROR_INVALID_DST_ADDRESS;
+
+ /* copy the key */
+ if (is_ip6)
+ hash_set_mem_alloc (&im->ipsec6_if_pool_index_by_key, &key6,
+ t - im->tunnel_interfaces);
+ else
+ hash_set (im->ipsec4_if_pool_index_by_key, key4.as_u64,
+ t - im->tunnel_interfaces);