- pool_get (um->udp_listeners, listener);
- listener->c_lcl_port = clib_host_to_net_u16 (port_number_host_byte_order);
- clib_memcpy (&listener->c_lcl_ip6, &ip->ip6, sizeof (ip6_address_t));
- listener->c_proto = SESSION_TYPE_IP6_UDP;
- udp_register_dst_port (um->vlib_main, port_number_host_byte_order,
- udp4_uri_input_node.index, 0 /* is_ipv4 */ );
- return 0;
+ 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);
+}
+
+udp_connection_t *
+udp_connection_alloc (u32 thread_index)
+{
+ udp_main_t *um = &udp_main;
+ udp_connection_t *uc;
+ u32 will_expand = 0;
+ pool_get_aligned_will_expand (um->connections[thread_index], will_expand,
+ CLIB_CACHE_LINE_BYTES);
+
+ if (PREDICT_FALSE (will_expand))
+ {
+ clib_spinlock_lock_if_init (&udp_main.peekers_write_locks
+ [thread_index]);
+ pool_get_aligned (udp_main.connections[thread_index], uc,
+ CLIB_CACHE_LINE_BYTES);
+ clib_spinlock_unlock_if_init (&udp_main.peekers_write_locks
+ [thread_index]);
+ }
+ else
+ {
+ pool_get_aligned (um->connections[thread_index], uc,
+ CLIB_CACHE_LINE_BYTES);
+ }
+ clib_memset (uc, 0, sizeof (*uc));
+ uc->c_c_index = uc - um->connections[thread_index];
+ uc->c_thread_index = thread_index;
+ uc->c_proto = TRANSPORT_PROTO_UDP;
+ clib_spinlock_init (&uc->rx_lock);
+ return uc;
+}
+
+void
+udp_connection_free (udp_connection_t * uc)
+{
+ u32 thread_index = uc->c_thread_index;
+ if (CLIB_DEBUG)
+ clib_memset (uc, 0xFA, sizeof (*uc));
+ pool_put (udp_main.connections[thread_index], uc);
+}
+
+void
+udp_connection_delete (udp_connection_t * uc)
+{
+ udp_connection_unregister_port (clib_net_to_host_u16 (uc->c_lcl_port),
+ uc->c_is_ip4);
+ session_transport_delete_notify (&uc->connection);
+ udp_connection_free (uc);