udp: support close with data
Also adds connection flags.
Type: feature
Change-Id: I76f21eb88ab203076149b7c03dc31c22fc0f342e
Signed-off-by: Florin Coras <fcoras@cisco.com>
diff --git a/src/vnet/udp/udp.c b/src/vnet/udp/udp.c
index 7dd0d2a..949c635 100644
--- a/src/vnet/udp/udp.c
+++ b/src/vnet/udp/udp.c
@@ -63,6 +63,18 @@
clib_memset (uc, 0xFA, sizeof (*uc));
}
+void
+udp_connection_delete (udp_connection_t * uc)
+{
+ if ((uc->flags & UDP_CONN_F_OWNS_PORT)
+ || !(uc->flags & UDP_CONN_F_CONNECTED))
+ udp_unregister_dst_port (vlib_get_main (),
+ clib_net_to_host_u16 (uc->c_lcl_port),
+ uc->c_is_ip4);
+ session_transport_delete_notify (&uc->connection);
+ udp_connection_free (uc);
+}
+
u32
udp_session_bind (u32 session_index, transport_endpoint_t * lcl)
{
@@ -95,7 +107,7 @@
listener->c_proto = TRANSPORT_PROTO_UDP;
listener->c_s_index = session_index;
listener->c_fib_index = lcl->fib_index;
- listener->owns_port = 1;
+ listener->flags |= UDP_CONN_F_OWNS_PORT;
clib_spinlock_init (&listener->rx_lock);
node_index = lcl->is_ip4 ? udp4_input_node.index : udp6_input_node.index;
@@ -148,6 +160,12 @@
vnet_buffer (b)->sw_if_index[VLIB_TX] = uc->c_fib_index;
b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
+ if (PREDICT_FALSE (uc->flags & UDP_CONN_F_CLOSING))
+ {
+ if (!transport_max_tx_dequeue (&uc->connection))
+ udp_connection_delete (uc);
+ }
+
return 0;
}
@@ -164,17 +182,16 @@
void
udp_session_close (u32 connection_index, u32 thread_index)
{
- vlib_main_t *vm = vlib_get_main ();
udp_connection_t *uc;
+
uc = udp_connection_get (connection_index, thread_index);
- if (uc)
- {
- if (uc->owns_port || !uc->is_connected)
- udp_unregister_dst_port (vm, clib_net_to_host_u16 (uc->c_lcl_port),
- uc->c_is_ip4);
- session_transport_delete_notify (&uc->connection);
- udp_connection_free (uc);
- }
+ if (!uc)
+ return;
+
+ if (!transport_max_tx_dequeue (&uc->connection))
+ udp_connection_delete (uc);
+ else
+ uc->flags |= UDP_CONN_F_CLOSING;
}
void
@@ -308,7 +325,7 @@
uc->c_is_ip4 = rmt->is_ip4;
uc->c_proto = TRANSPORT_PROTO_UDP;
uc->c_fib_index = rmt->fib_index;
- uc->owns_port = 1;
+ uc->flags |= UDP_CONN_F_OWNS_PORT;
return uc->c_c_index;
}
@@ -362,7 +379,7 @@
if (uc_index == (u32) ~ 0)
return -1;
uc = udp_connection_get (uc_index, thread_index);
- uc->is_connected = 1;
+ uc->flags |= UDP_CONN_F_CONNECTED;
return uc_index;
}
@@ -375,7 +392,7 @@
if (li_index == (u32) ~ 0)
return -1;
listener = udp_listener_get (li_index);
- listener->is_connected = 1;
+ listener->flags |= UDP_CONN_F_CONNECTED;
return li_index;
}
diff --git a/src/vnet/udp/udp.h b/src/vnet/udp/udp.h
index f5efbbc..88a46db 100644
--- a/src/vnet/udp/udp.h
+++ b/src/vnet/udp/udp.h
@@ -34,14 +34,20 @@
UDP_N_ERROR,
} udp_error_t;
+typedef enum
+{
+ UDP_CONN_F_CONNECTED, /**< connected mode */
+ UDP_CONN_F_OWNS_PORT, /**< port belong to conn (UDPC) */
+ UDP_CONN_F_CLOSING, /**< conn closed with data */
+} udp_conn_flags_t;
+
typedef struct
{
/** Required for pool_get_aligned */
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
transport_connection_t connection; /**< must be first */
clib_spinlock_t rx_lock; /**< rx fifo lock */
- u8 is_connected; /**< connected mode */
- u8 owns_port; /**< does port belong to conn (UDPC) */
+ u8 flags; /**< connection flags */
} udp_connection_t;
#define foreach_udp4_dst_port \
@@ -235,7 +241,6 @@
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->is_connected = old_c->is_connected;
new_c->c_fib_index = old_c->c_fib_index;
return new_c;
}
diff --git a/src/vnet/udp/udp_input.c b/src/vnet/udp/udp_input.c
index cc5ae2b..f6d89dc 100644
--- a/src/vnet/udp/udp_input.c
+++ b/src/vnet/udp/udp_input.c
@@ -162,7 +162,7 @@
*/
tc0 = session_get_transport (s0);
uc0 = udp_get_connection_from_transport (tc0);
- if (uc0->is_connected)
+ if (uc0->flags & UDP_CONN_F_CONNECTED)
{
/*
* Clone the transport. It will be cleaned up with the
@@ -190,7 +190,7 @@
{
tc0 = listen_session_get_transport (s0);
uc0 = udp_get_connection_from_transport (tc0);
- if (uc0->is_connected)
+ if (uc0->flags & UDP_CONN_F_CONNECTED)
{
child0 = udp_connection_alloc (my_thread_index);
if (is_ip4)
@@ -207,7 +207,7 @@
child0->c_rmt_port = udp0->src_port;
child0->c_is_ip4 = is_ip4;
child0->c_fib_index = tc0->fib_index;
- child0->is_connected = 1;
+ child0->flags |= UDP_CONN_F_CONNECTED;
if (session_stream_accept (&child0->connection,
tc0->s_index, tc0->thread_index,