+ /* ICMP */
+ if (PREDICT_FALSE (ip->protocol == IP_PROTOCOL_ICMP))
+ {
+ icmp46_header_t *icmp = (icmp46_header_t *) udp;
+ icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1);
+ if (!icmp_is_error_message (icmp))
+ port = echo->identifier;
+ else
+ {
+ ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1);
+ proto = ip_proto_to_snat_proto (inner_ip->protocol);
+ void *l4_header = ip4_next_header (inner_ip);
+ switch (proto)
+ {
+ case SNAT_PROTOCOL_ICMP:
+ icmp = (icmp46_header_t *) l4_header;
+ echo = (icmp_echo_header_t *) (icmp + 1);
+ port = echo->identifier;
+ break;
+ case SNAT_PROTOCOL_UDP:
+ case SNAT_PROTOCOL_TCP:
+ port = ((tcp_udp_header_t *) l4_header)->src_port;
+ break;
+ default:
+ return vlib_get_thread_index ();
+ }
+ }
+ }
+
+ /* worker by outside port (TCP/UDP) */
+ port = clib_net_to_host_u16 (port);
+ if (port > 1024)
+ return nm->sm->first_worker_index + ((port - 1024) / sm->port_per_thread);
+
+ return vlib_get_thread_index ();
+}
+
+clib_error_t *
+nat64_init (vlib_main_t * vm)
+{
+ nat64_main_t *nm = &nat64_main;
+ vlib_thread_main_t *tm = vlib_get_thread_main ();
+ ip4_add_del_interface_address_callback_t cb4;
+ ip4_main_t *im = &ip4_main;
+ vlib_node_t *error_drop_node =
+ vlib_get_node_by_name (vm, (u8 *) "error-drop");
+
+ vec_validate (nm->db, tm->n_vlib_mains - 1);
+
+ nm->sm = &snat_main;
+
+ nm->fq_in2out_index = ~0;
+ nm->fq_out2in_index = ~0;
+ nm->error_node_index = error_drop_node->index;
+