/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Copyright (c) 2016-2019 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
int wrote0;
void *rmt_addr, *lcl_addr;
session_dgram_hdr_t hdr0;
+ u8 queue_event = 1;
/* speculatively enqueue b0 to the current next frame */
bi0 = from[0];
*/
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
- * session once we notify the session layer.
- */
- new_uc0 = udp_connection_clone_safe (s0->connection_index,
- s0->thread_index);
- ASSERT (s0->session_index == new_uc0->c_s_index);
-
- /*
- * Drop the 'lock' on pool resize
- */
- session_pool_remove_peeker (s0->thread_index);
- session_dgram_connect_notify (&new_uc0->connection,
- s0->thread_index, &s0);
- tc0 = &new_uc0->connection;
+ if (s0->thread_index != vlib_get_thread_index ())
+ {
+ /*
+ * Clone the transport. It will be cleaned up with the
+ * session once we notify the session layer.
+ */
+ new_uc0 =
+ udp_connection_clone_safe (s0->connection_index,
+ s0->thread_index);
+ ASSERT (s0->session_index == new_uc0->c_s_index);
+
+ /*
+ * Drop the 'lock' on pool resize
+ */
+ session_pool_remove_peeker (s0->thread_index);
+ session_dgram_connect_notify (&new_uc0->connection,
+ s0->thread_index, &s0);
+ tc0 = &new_uc0->connection;
+ uc0 = new_uc0;
+ queue_event = 0;
+ }
+ else
+ s0->session_state = SESSION_STATE_READY;
}
}
else if (s0->session_state == SESSION_STATE_READY)
{
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)
child0->c_lcl_port = udp0->dst_port;
child0->c_rmt_port = udp0->src_port;
child0->c_is_ip4 = is_ip4;
+ child0->c_fib_index = tc0->fib_index;
+ child0->flags |= UDP_CONN_F_CONNECTED;
if (session_stream_accept (&child0->connection,
- tc0->s_index, 1))
+ tc0->s_index, tc0->thread_index,
+ 1))
{
error0 = UDP_ERROR_CREATE_SESSION;
goto trace0;
}
- s0 =
- session_get (child0->c_s_index, child0->c_thread_index);
+ s0 = session_get (child0->c_s_index,
+ child0->c_thread_index);
s0->session_state = SESSION_STATE_READY;
tc0 = &child0->connection;
uc0 = udp_get_connection_from_transport (tc0);
goto trace0;
}
- if (!uc0->is_connected)
+
+ if (svm_fifo_max_enqueue_prod (s0->rx_fifo)
+ < b0->current_length + sizeof (session_dgram_hdr_t))
+ {
+ error0 = UDP_ERROR_FIFO_FULL;
+ goto trace0;
+ }
+ hdr0.data_length = b0->current_length;
+ hdr0.data_offset = 0;
+ ip_set (&hdr0.lcl_ip, lcl_addr, is_ip4);
+ ip_set (&hdr0.rmt_ip, rmt_addr, is_ip4);
+ hdr0.lcl_port = udp0->dst_port;
+ hdr0.rmt_port = udp0->src_port;
+ hdr0.is_ip4 = is_ip4;
+
+ clib_spinlock_lock (&uc0->rx_lock);
+ /* If session is owned by another thread and rx event needed,
+ * enqueue event now while we still have the peeker lock */
+ if (s0->thread_index != my_thread_index)
{
- if (svm_fifo_max_enqueue (s0->rx_fifo)
- < b0->current_length + sizeof (session_dgram_hdr_t))
- {
- error0 = UDP_ERROR_FIFO_FULL;
- goto trace0;
- }
- hdr0.data_length = b0->current_length;
- hdr0.data_offset = 0;
- ip_set (&hdr0.lcl_ip, lcl_addr, is_ip4);
- ip_set (&hdr0.rmt_ip, rmt_addr, is_ip4);
- hdr0.lcl_port = udp0->dst_port;
- hdr0.rmt_port = udp0->src_port;
- hdr0.is_ip4 = is_ip4;
-
- clib_spinlock_lock (&uc0->rx_lock);
wrote0 = session_enqueue_dgram_connection (s0, &hdr0, b0,
TRANSPORT_PROTO_UDP,
- 1 /* queue evt */ );
- clib_spinlock_unlock (&uc0->rx_lock);
- ASSERT (wrote0 > 0);
-
- if (s0->session_state != SESSION_STATE_LISTENING)
- session_pool_remove_peeker (s0->thread_index);
+ /* queue event */ 0);
+ if (queue_event && !svm_fifo_has_event (s0->rx_fifo))
+ session_enqueue_notify (s0);
}
else
{
- if (svm_fifo_max_enqueue (s0->rx_fifo) < b0->current_length)
- {
- error0 = UDP_ERROR_FIFO_FULL;
- goto trace0;
- }
- wrote0 = session_enqueue_stream_connection (tc0, b0, 0,
- 1 /* queue evt */ ,
- 1 /* in order */ );
- ASSERT (wrote0 > 0);
+ wrote0 = session_enqueue_dgram_connection (s0, &hdr0, b0,
+ TRANSPORT_PROTO_UDP,
+ queue_event);
}
+ clib_spinlock_unlock (&uc0->rx_lock);
+ ASSERT (wrote0 > 0);
+
+ if (s0->session_state != SESSION_STATE_LISTENING)
+ session_pool_remove_peeker (s0->thread_index);
trace0:
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
- errors = session_main_flush_all_enqueue_events (TRANSPORT_PROTO_UDP);
+ errors = session_main_flush_enqueue_events (TRANSPORT_PROTO_UDP,
+ my_thread_index);
udp_input_inc_counter (vm, is_ip4, UDP_ERROR_EVENT_FIFO_FULL, errors);
return frame->n_vectors;
}