VPP-158: VPP crashes in IKEv2 code when running multithreaded
Change tunnel interface creation to be done from the main thread instead
of a worker thread by calling vl_api_rpc_call_main_thread.
Make per-thread copies of volatile elements in ikev2_main.
Change-Id: I4cda8aaa392a04c2aea2d50a52a07933cf40c016
Signed-off-by: Matthew Smith <mgsmith@netgate.com>
diff --git a/vnet/vnet/ipsec/ikev2_cli.c b/vnet/vnet/ipsec/ikev2_cli.c
index e42f16d..c8c8ea1 100644
--- a/vnet/vnet/ipsec/ikev2_cli.c
+++ b/vnet/vnet/ipsec/ikev2_cli.c
@@ -50,106 +50,109 @@
vlib_cli_command_t * cmd)
{
ikev2_main_t * km = &ikev2_main;
+ ikev2_main_per_thread_data_t * tkm;
ikev2_sa_t * sa;
ikev2_ts_t * ts;
ikev2_child_sa_t * child;
ikev2_sa_transform_t * tr;
- pool_foreach (sa, km->sas, ({
- u8 * s = 0;
- vlib_cli_output(vm, " iip %U ispi %lx rip %U rspi %lx",
- format_ip4_address, &sa->iaddr, sa->ispi,
- format_ip4_address, &sa->raddr, sa->rspi);
-
- tr = ikev2_sa_get_td_for_type(sa->r_proposals, IKEV2_TRANSFORM_TYPE_ENCR);
- s = format(s, "%U ", format_ikev2_sa_transform, tr);
-
- tr = ikev2_sa_get_td_for_type(sa->r_proposals, IKEV2_TRANSFORM_TYPE_PRF);
- s = format(s, "%U ", format_ikev2_sa_transform, tr);
-
- tr = ikev2_sa_get_td_for_type(sa->r_proposals, IKEV2_TRANSFORM_TYPE_INTEG);
- s = format(s, "%U ", format_ikev2_sa_transform, tr);
-
- tr = ikev2_sa_get_td_for_type(sa->r_proposals, IKEV2_TRANSFORM_TYPE_DH);
- s = format(s, "%U ", format_ikev2_sa_transform, tr);
-
- vlib_cli_output(vm, " %v", s);
- vec_free(s);
-
- vlib_cli_output(vm, " nonce i:%U\n r:%U",
- format_hex_bytes, sa->i_nonce, vec_len(sa->i_nonce),
- format_hex_bytes, sa->r_nonce, vec_len(sa->r_nonce));
-
- vlib_cli_output(vm, " SK_d %U",
- format_hex_bytes, sa->sk_d, vec_len(sa->sk_d));
- vlib_cli_output(vm, " SK_a i:%U\n r:%U",
- format_hex_bytes, sa->sk_ai, vec_len(sa->sk_ai),
- format_hex_bytes, sa->sk_ar, vec_len(sa->sk_ar));
- vlib_cli_output(vm, " SK_e i:%U\n r:%U",
- format_hex_bytes, sa->sk_ei, vec_len(sa->sk_ei),
- format_hex_bytes, sa->sk_er, vec_len(sa->sk_er));
- vlib_cli_output(vm, " SK_p i:%U\n r:%U",
- format_hex_bytes, sa->sk_pi, vec_len(sa->sk_pi),
- format_hex_bytes, sa->sk_pr, vec_len(sa->sk_pr));
-
- vlib_cli_output(vm, " identifier (i) %U",
- format_ikev2_id_type_and_data, &sa->i_id);
- vlib_cli_output(vm, " identifier (r) %U",
- format_ikev2_id_type_and_data, &sa->r_id);
-
- vec_foreach(child, sa->childs)
- {
- vlib_cli_output(vm, " child sa %u:", child - sa->childs);
-
- tr = ikev2_sa_get_td_for_type(child->r_proposals, IKEV2_TRANSFORM_TYPE_ENCR);
- s = format(s, "%U ", format_ikev2_sa_transform, tr);
-
- tr = ikev2_sa_get_td_for_type(child->r_proposals, IKEV2_TRANSFORM_TYPE_INTEG);
- s = format(s, "%U ", format_ikev2_sa_transform, tr);
-
- tr = ikev2_sa_get_td_for_type(child->r_proposals, IKEV2_TRANSFORM_TYPE_ESN);
- s = format(s, "%U ", format_ikev2_sa_transform, tr);
-
- vlib_cli_output(vm, " %v", s);
- vec_free(s);
-
- vlib_cli_output(vm, " spi(i) %lx spi(r) %lx",
- child->i_proposals ? child->i_proposals[0].spi : 0,
- child->r_proposals ? child->r_proposals[0].spi : 0);
-
- vlib_cli_output(vm, " SK_e i:%U\n r:%U",
- format_hex_bytes, child->sk_ei, vec_len(child->sk_ei),
- format_hex_bytes, child->sk_er, vec_len(child->sk_er));
- vlib_cli_output(vm, " SK_a i:%U\n r:%U",
- format_hex_bytes, child->sk_ai, vec_len(child->sk_ai),
- format_hex_bytes, child->sk_ar, vec_len(child->sk_ar));
- vlib_cli_output(vm, " traffic selectors (i):");
- vec_foreach(ts, child->tsi)
- {
- vlib_cli_output(vm, " %u type %u protocol_id %u addr "
- "%U - %U port %u - %u",
- ts - child->tsi,
- ts->ts_type, ts->protocol_id,
- format_ip4_address, &ts->start_addr,
- format_ip4_address, &ts->end_addr,
- clib_net_to_host_u16( ts->start_port),
- clib_net_to_host_u16( ts->end_port));
- }
- vlib_cli_output(vm, " traffic selectors (r):");
- vec_foreach(ts, child->tsr)
- {
- vlib_cli_output(vm, " %u type %u protocol_id %u addr "
- "%U - %U port %u - %u",
- ts - child->tsr,
- ts->ts_type, ts->protocol_id,
- format_ip4_address, &ts->start_addr,
- format_ip4_address, &ts->end_addr,
- clib_net_to_host_u16( ts->start_port),
- clib_net_to_host_u16( ts->end_port));
- }
- }
- vlib_cli_output(vm, "");
- }));
+ vec_foreach(tkm, km->per_thread_data) {
+ pool_foreach (sa, tkm->sas, ({
+ u8 * s = 0;
+ vlib_cli_output(vm, " iip %U ispi %lx rip %U rspi %lx",
+ format_ip4_address, &sa->iaddr, sa->ispi,
+ format_ip4_address, &sa->raddr, sa->rspi);
+
+ tr = ikev2_sa_get_td_for_type(sa->r_proposals, IKEV2_TRANSFORM_TYPE_ENCR);
+ s = format(s, "%U ", format_ikev2_sa_transform, tr);
+
+ tr = ikev2_sa_get_td_for_type(sa->r_proposals, IKEV2_TRANSFORM_TYPE_PRF);
+ s = format(s, "%U ", format_ikev2_sa_transform, tr);
+
+ tr = ikev2_sa_get_td_for_type(sa->r_proposals, IKEV2_TRANSFORM_TYPE_INTEG);
+ s = format(s, "%U ", format_ikev2_sa_transform, tr);
+
+ tr = ikev2_sa_get_td_for_type(sa->r_proposals, IKEV2_TRANSFORM_TYPE_DH);
+ s = format(s, "%U ", format_ikev2_sa_transform, tr);
+
+ vlib_cli_output(vm, " %v", s);
+ vec_free(s);
+
+ vlib_cli_output(vm, " nonce i:%U\n r:%U",
+ format_hex_bytes, sa->i_nonce, vec_len(sa->i_nonce),
+ format_hex_bytes, sa->r_nonce, vec_len(sa->r_nonce));
+
+ vlib_cli_output(vm, " SK_d %U",
+ format_hex_bytes, sa->sk_d, vec_len(sa->sk_d));
+ vlib_cli_output(vm, " SK_a i:%U\n r:%U",
+ format_hex_bytes, sa->sk_ai, vec_len(sa->sk_ai),
+ format_hex_bytes, sa->sk_ar, vec_len(sa->sk_ar));
+ vlib_cli_output(vm, " SK_e i:%U\n r:%U",
+ format_hex_bytes, sa->sk_ei, vec_len(sa->sk_ei),
+ format_hex_bytes, sa->sk_er, vec_len(sa->sk_er));
+ vlib_cli_output(vm, " SK_p i:%U\n r:%U",
+ format_hex_bytes, sa->sk_pi, vec_len(sa->sk_pi),
+ format_hex_bytes, sa->sk_pr, vec_len(sa->sk_pr));
+
+ vlib_cli_output(vm, " identifier (i) %U",
+ format_ikev2_id_type_and_data, &sa->i_id);
+ vlib_cli_output(vm, " identifier (r) %U",
+ format_ikev2_id_type_and_data, &sa->r_id);
+
+ vec_foreach(child, sa->childs)
+ {
+ vlib_cli_output(vm, " child sa %u:", child - sa->childs);
+
+ tr = ikev2_sa_get_td_for_type(child->r_proposals, IKEV2_TRANSFORM_TYPE_ENCR);
+ s = format(s, "%U ", format_ikev2_sa_transform, tr);
+
+ tr = ikev2_sa_get_td_for_type(child->r_proposals, IKEV2_TRANSFORM_TYPE_INTEG);
+ s = format(s, "%U ", format_ikev2_sa_transform, tr);
+
+ tr = ikev2_sa_get_td_for_type(child->r_proposals, IKEV2_TRANSFORM_TYPE_ESN);
+ s = format(s, "%U ", format_ikev2_sa_transform, tr);
+
+ vlib_cli_output(vm, " %v", s);
+ vec_free(s);
+
+ vlib_cli_output(vm, " spi(i) %lx spi(r) %lx",
+ child->i_proposals ? child->i_proposals[0].spi : 0,
+ child->r_proposals ? child->r_proposals[0].spi : 0);
+
+ vlib_cli_output(vm, " SK_e i:%U\n r:%U",
+ format_hex_bytes, child->sk_ei, vec_len(child->sk_ei),
+ format_hex_bytes, child->sk_er, vec_len(child->sk_er));
+ vlib_cli_output(vm, " SK_a i:%U\n r:%U",
+ format_hex_bytes, child->sk_ai, vec_len(child->sk_ai),
+ format_hex_bytes, child->sk_ar, vec_len(child->sk_ar));
+ vlib_cli_output(vm, " traffic selectors (i):");
+ vec_foreach(ts, child->tsi)
+ {
+ vlib_cli_output(vm, " %u type %u protocol_id %u addr "
+ "%U - %U port %u - %u",
+ ts - child->tsi,
+ ts->ts_type, ts->protocol_id,
+ format_ip4_address, &ts->start_addr,
+ format_ip4_address, &ts->end_addr,
+ clib_net_to_host_u16( ts->start_port),
+ clib_net_to_host_u16( ts->end_port));
+ }
+ vlib_cli_output(vm, " traffic selectors (r):");
+ vec_foreach(ts, child->tsr)
+ {
+ vlib_cli_output(vm, " %u type %u protocol_id %u addr "
+ "%U - %U port %u - %u",
+ ts - child->tsr,
+ ts->ts_type, ts->protocol_id,
+ format_ip4_address, &ts->start_addr,
+ format_ip4_address, &ts->end_addr,
+ clib_net_to_host_u16( ts->start_port),
+ clib_net_to_host_u16( ts->end_port));
+ }
+ }
+ vlib_cli_output(vm, "");
+ }));
+ }
return 0;
}