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;
 }