+ (void) nat64_add_del_pool_addr (address, ~0, 1);
+ return;
+ }
+ else
+ {
+ (void) nat64_add_del_pool_addr (address, ~0, 0);
+ return;
+ }
+ }
+ }
+}
+
+u32
+nat64_get_worker_in2out (ip6_address_t * addr)
+{
+ nat64_main_t *nm = &nat64_main;
+ snat_main_t *sm = nm->sm;
+ u32 next_worker_index = nm->sm->first_worker_index;
+ u32 hash;
+
+#ifdef clib_crc32c_uses_intrinsics
+ hash = clib_crc32c ((u8 *) addr->as_u32, 16);
+#else
+ u64 tmp = addr->as_u64[0] ^ addr->as_u64[1];
+ hash = clib_xxhash (tmp);
+#endif
+
+ if (PREDICT_TRUE (is_pow2 (_vec_len (sm->workers))))
+ next_worker_index += sm->workers[hash & (_vec_len (sm->workers) - 1)];
+ else
+ next_worker_index += sm->workers[hash % _vec_len (sm->workers)];
+
+ return next_worker_index;
+}
+
+u32
+nat64_get_worker_out2in (ip4_header_t * ip)
+{
+ nat64_main_t *nm = &nat64_main;
+ snat_main_t *sm = nm->sm;
+ udp_header_t *udp;
+ u16 port;
+ u32 proto;
+
+ proto = ip_proto_to_snat_proto (ip->protocol);
+ udp = ip4_next_header (ip);
+ port = udp->dst_port;
+
+ /* fragments */
+ if (PREDICT_FALSE (ip4_is_fragment (ip)))
+ {
+ if (PREDICT_FALSE (nat_reass_is_drop_frag (0)))
+ return vlib_get_thread_index ();
+
+ if (PREDICT_TRUE (!ip4_is_first_fragment (ip)))
+ {
+ nat_reass_ip4_t *reass;
+
+ reass = nat_ip4_reass_find (ip->src_address, ip->dst_address,
+ ip->fragment_id, ip->protocol);
+
+ if (reass && (reass->thread_index != (u32) ~ 0))
+ return reass->thread_index;
+ else
+ return vlib_get_thread_index ();
+ }
+ }
+
+ /* unknown protocol */
+ if (PREDICT_FALSE (proto == ~0))