+#include <vppinfra/sparse_vec.h>
+
+udp_main_t udp_main;
+
+static void
+udp_connection_register_port (vlib_main_t * vm, u16 lcl_port, u8 is_ip4)
+{
+ udp_main_t *um = &udp_main;
+ udp_dst_port_info_t *pi;
+ u16 *n;
+
+ pi = udp_get_dst_port_info (um, lcl_port, is_ip4);
+ if (!pi)
+ {
+ udp_add_dst_port (um, lcl_port, 0, is_ip4);
+ pi = udp_get_dst_port_info (um, lcl_port, is_ip4);
+ pi->n_connections = 1;
+ }
+ else
+ {
+ pi->n_connections += 1;
+ /* Do not return. The fact that the pi is valid does not mean
+ * it's up to date */
+ }
+
+ pi->node_index = is_ip4 ? udp4_input_node.index : udp6_input_node.index;
+ pi->next_index = um->local_to_input_edge[is_ip4];
+
+ /* Setup udp protocol -> next index sparse vector mapping. */
+ if (is_ip4)
+ n = sparse_vec_validate (um->next_by_dst_port4,
+ clib_host_to_net_u16 (lcl_port));
+ else
+ n = sparse_vec_validate (um->next_by_dst_port6,
+ clib_host_to_net_u16 (lcl_port));
+
+ n[0] = pi->next_index;
+}
+
+static void
+udp_connection_unregister_port (u16 lcl_port, u8 is_ip4)
+{
+ udp_main_t *um = &udp_main;
+ udp_dst_port_info_t *pi;
+
+ pi = udp_get_dst_port_info (um, lcl_port, is_ip4);
+ if (!pi)
+ return;
+
+ if (!pi->n_connections)
+ {
+ clib_warning ("no connections using port %u", lcl_port);
+ return;
+ }
+
+ if (!clib_atomic_sub_fetch (&pi->n_connections, 1))
+ udp_unregister_dst_port (0, lcl_port, is_ip4);
+}
+
+void
+udp_connection_share_port (u16 lcl_port, u8 is_ip4)
+{
+ udp_main_t *um = &udp_main;
+ udp_dst_port_info_t *pi;
+
+ /* Done without a lock but the operation is atomic. Writers to pi hash
+ * table and vector should be guarded by a barrier sync */
+ pi = udp_get_dst_port_info (um, lcl_port, is_ip4);
+ clib_atomic_fetch_add_rel (&pi->n_connections, 1);
+}