sa->i_id.type = sai->i_id.type;
sa->profile_index = sai->profile_index;
sa->is_profile_index_set = sai->is_profile_index_set;
+ sa->tun_itf = sai->tun_itf;
+ sa->is_tun_itf_set = sai->is_tun_itf_set;
sa->i_id.data = _(sai->i_id.data);
sa->i_auth.method = sai->i_auth.method;
sa->i_auth.hex = sai->i_auth.hex;
vec_free (delete);
sa->initial_contact = 0;
-
- km->log_level = IKEV2_LOG_ERROR;
- km->log_class = vlib_log_register_class ("ikev2", 0);
}
static void
sa->childs[0].r_proposals =
ikev2_select_proposal (sa->childs[0].i_proposals,
IKEV2_PROTOCOL_ESP);
+
+ if (~0 != sel_p->tun_itf)
+ {
+ sa->is_tun_itf_set = 1;
+ sa->tun_itf = sel_p->tun_itf;
+ }
}
}
else
typedef struct
{
+ u32 sw_if_index;
u32 salt_local;
u32 salt_remote;
u32 local_sa_id;
{
ikev2_main_t *km = &ikev2_main;
u32 sw_if_index;
- int rv;
- uword *p = 0;
+ int rv = 0;
- rv = ipip_add_tunnel (IPIP_TRANSPORT_IP4, ~0,
- &a->local_ip, &a->remote_ip, 0,
- TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
- TUNNEL_MODE_P2P, &sw_if_index);
+ if (~0 == a->sw_if_index)
+ {
+ /* no tunnel associated with the SA/profile - create a new one */
+ rv = ipip_add_tunnel (IPIP_TRANSPORT_IP4, ~0,
+ &a->local_ip, &a->remote_ip, 0,
+ TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
+ TUNNEL_MODE_P2P, &sw_if_index);
- if (rv == VNET_API_ERROR_IF_ALREADY_EXISTS)
+ if (rv == VNET_API_ERROR_IF_ALREADY_EXISTS)
+ {
+ if (hash_get (km->sw_if_indices, sw_if_index))
+ /* interface is managed by IKE; proceed with updating SAs */
+ rv = 0;
+ }
+ hash_set1 (km->sw_if_indices, sw_if_index);
+ }
+ else
{
- p = hash_get (km->sw_if_indices, sw_if_index);
- if (p)
- /* interface is managed by IKE; proceed with updating SAs */
- rv = 0;
+ sw_if_index = a->sw_if_index;
+ vnet_sw_interface_admin_up (vnet_get_main (), sw_if_index);
}
if (rv)
u32 *sas_in = NULL;
vec_add1 (sas_in, a->remote_sa_id);
- rv |= ipsec_tun_protect_update (sw_if_index, a->local_sa_id, sas_in);
- hash_set1 (km->sw_if_indices, sw_if_index);
+ rv |= ipsec_tun_protect_update (sw_if_index, NULL, a->local_sa_id, sas_in);
}
static int
child->remote_sa_id =
a.remote_sa_id =
ikev2_mk_remote_sa_id (sa_index, child_index, thread_index);
+ a.sw_if_index = (sa->is_tun_itf_set ? sa->tun_itf : ~0);
vl_api_rpc_call_main_thread (ikev2_add_tunnel_from_main,
(u8 *) & a, sizeof (a));
ip46_address_t remote_ip;
u32 remote_sa_id;
u32 local_sa_id;
+ u32 sw_if_index;
} ikev2_del_ipsec_tunnel_args_t;
static void
ikev2_del_tunnel_from_main (ikev2_del_ipsec_tunnel_args_t * a)
{
ikev2_main_t *km = &ikev2_main;
- /* *INDENT-OFF* */
- ipip_tunnel_key_t key = {
- .src = a->local_ip,
- .dst = a->remote_ip,
- .transport = IPIP_TRANSPORT_IP4,
- .fib_index = 0,
- };
- ipip_tunnel_t *ipip;
- /* *INDENT-ON* */
+ ipip_tunnel_t *ipip = NULL;
+ u32 sw_if_index;
+
+ if (~0 == a->sw_if_index)
+ {
+ /* *INDENT-OFF* */
+ ipip_tunnel_key_t key = {
+ .src = a->local_ip,
+ .dst = a->remote_ip,
+ .transport = IPIP_TRANSPORT_IP4,
+ .fib_index = 0,
+ };
+ /* *INDENT-ON* */
- ipip = ipip_tunnel_db_find (&key);
+ ipip = ipip_tunnel_db_find (&key);
- if (ipip)
+ if (ipip)
+ {
+ sw_if_index = ipip->sw_if_index;
+ hash_unset (km->sw_if_indices, ipip->sw_if_index);
+ }
+ else
+ sw_if_index = ~0;
+ }
+ else
{
- hash_unset (km->sw_if_indices, ipip->sw_if_index);
- ipsec_tun_protect_del (ipip->sw_if_index);
- ipsec_sa_unlock_id (a->remote_sa_id);
- ipsec_sa_unlock_id (a->local_sa_id);
- ipip_del_tunnel (ipip->sw_if_index);
+ sw_if_index = a->sw_if_index;
+ vnet_sw_interface_admin_down (vnet_get_main (), sw_if_index);
}
+
+ if (~0 != sw_if_index)
+ ipsec_tun_protect_del (sw_if_index, NULL);
+
+ ipsec_sa_unlock_id (a->remote_sa_id);
+ ipsec_sa_unlock_id (a->local_sa_id);
+
+ if (ipip)
+ ipip_del_tunnel (ipip->sw_if_index);
}
static int
a.remote_sa_id = child->remote_sa_id;
a.local_sa_id = child->local_sa_id;
+ a.sw_if_index = (sa->is_tun_itf_set ? sa->tun_itf : ~0);
vl_api_rpc_call_main_thread (ikev2_del_tunnel_from_main, (u8 *) & a,
sizeof (a));
clib_memset (p, 0, sizeof (*p));
p->name = vec_dup (name);
p->responder.sw_if_index = ~0;
+ p->tun_itf = ~0;
uword index = p - km->profiles;
mhash_set_mem (&km->profile_index_by_name, name, &index, 0);
}
return 0;
}
+clib_error_t *
+ikev2_set_profile_tunnel_interface (vlib_main_t * vm,
+ u8 * name, u32 sw_if_index)
+{
+ ikev2_profile_t *p;
+ clib_error_t *r;
+
+ p = ikev2_profile_index_by_name (name);
+
+ if (!p)
+ {
+ r = clib_error_return (0, "unknown profile %v", name);
+ return r;
+ }
+
+ p->tun_itf = sw_if_index;
+
+ return 0;
+}
+
clib_error_t *
ikev2_set_profile_sa_lifetime (vlib_main_t * vm, u8 * name,
u64 lifetime, u32 jitter, u32 handover,
sa.profile_index = km->profiles - p;
sa.is_profile_index_set = 1;
sa.state = IKEV2_STATE_SA_INIT;
+ sa.tun_itf = p->tun_itf;
+ sa.is_tun_itf_set = 1;
ikev2_generate_sa_init_data (&sa);
ikev2_payload_add_ke (chain, sa.dh_group, sa.i_dh_data);
ikev2_payload_add_nonce (chain, sa.i_nonce);
ikev2_cli_reference ();
+ km->log_level = IKEV2_LOG_ERROR;
+ km->log_class = vlib_log_register_class ("ikev2", 0);
return 0;
}