+extern udp_main_t udp_main;
+extern vlib_node_registration_t udp4_input_node;
+extern vlib_node_registration_t udp6_input_node;
+extern vlib_node_registration_t udp4_local_node;
+extern vlib_node_registration_t udp6_local_node;
+
+always_inline udp_connection_t *
+udp_connection_get (u32 conn_index, u32 thread_index)
+{
+ if (pool_is_free_index (udp_main.connections[thread_index], conn_index))
+ return 0;
+ return pool_elt_at_index (udp_main.connections[thread_index], conn_index);
+}
+
+always_inline udp_connection_t *
+udp_listener_get (u32 conn_index)
+{
+ return pool_elt_at_index (udp_main.listener_pool, conn_index);
+}
+
+always_inline udp_main_t *
+vnet_get_udp_main ()
+{
+ return &udp_main;
+}
+
+always_inline udp_connection_t *
+udp_connection_from_transport (transport_connection_t * tc)
+{
+ return ((udp_connection_t *) tc);
+}
+
+always_inline u32
+udp_connection_index (udp_connection_t * uc)
+{
+ return (uc - udp_main.connections[uc->c_thread_index]);
+}
+
+void udp_connection_free (udp_connection_t * uc);
+udp_connection_t *udp_connection_alloc (u32 thread_index);
+
+/**
+ * Acquires a lock that blocks a connection pool from expanding.
+ */
+always_inline void
+udp_pool_add_peeker (u32 thread_index)
+{
+ if (thread_index != vlib_get_thread_index ())
+ return;
+ clib_spinlock_lock_if_init (&udp_main.peekers_readers_locks[thread_index]);
+ udp_main.connection_peekers[thread_index] += 1;
+ if (udp_main.connection_peekers[thread_index] == 1)
+ clib_spinlock_lock_if_init (&udp_main.peekers_write_locks[thread_index]);
+ clib_spinlock_unlock_if_init (&udp_main.peekers_readers_locks
+ [thread_index]);
+}
+
+always_inline void
+udp_pool_remove_peeker (u32 thread_index)
+{
+ if (thread_index != vlib_get_thread_index ())
+ return;
+ ASSERT (udp_main.connection_peekers[thread_index] > 0);
+ clib_spinlock_lock_if_init (&udp_main.peekers_readers_locks[thread_index]);
+ udp_main.connection_peekers[thread_index] -= 1;
+ if (udp_main.connection_peekers[thread_index] == 0)
+ clib_spinlock_unlock_if_init (&udp_main.peekers_write_locks
+ [thread_index]);
+ clib_spinlock_unlock_if_init (&udp_main.peekers_readers_locks
+ [thread_index]);
+}
+
+always_inline udp_connection_t *
+udp_connection_clone_safe (u32 connection_index, u32 thread_index)
+{
+ udp_connection_t *old_c, *new_c;
+ u32 current_thread_index = vlib_get_thread_index ();
+ new_c = udp_connection_alloc (current_thread_index);
+
+ /* If during the memcpy pool is reallocated AND the memory allocator
+ * decides to give the old chunk of memory to somebody in a hurry to
+ * scribble something on it, we have a problem. So add this thread as
+ * a session pool peeker.
+ */
+ udp_pool_add_peeker (thread_index);
+ old_c = udp_main.connections[thread_index] + connection_index;
+ clib_memcpy_fast (new_c, old_c, sizeof (*new_c));
+ old_c->flags |= UDP_CONN_F_MIGRATED;
+ udp_pool_remove_peeker (thread_index);
+ new_c->c_thread_index = current_thread_index;
+ new_c->c_c_index = udp_connection_index (new_c);
+ new_c->c_fib_index = old_c->c_fib_index;
+ return new_c;
+}
+