vcl session: enforce full dgram reads/writes
Type: improvement Signed-off-by: Florin Coras <fcoras@cisco.com> Change-Id: I4a3861e31ca42faf0b59f8f09393fb10413bf3af
This commit is contained in:
Florin Coras
committed by
Florin Coras
parent
57660d9df6
commit
7a2abce4c9
@ -75,17 +75,19 @@ send_data_chunk (echo_client_main_t * ecm, eclient_session_t * s)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
svm_fifo_t *f = s->data.tx_fifo;
|
||||||
|
u32 max_enqueue = svm_fifo_max_enqueue_prod (f);
|
||||||
|
|
||||||
|
if (max_enqueue < sizeof (session_dgram_hdr_t))
|
||||||
|
return;
|
||||||
|
|
||||||
|
max_enqueue -= sizeof (session_dgram_hdr_t);
|
||||||
|
|
||||||
if (ecm->no_copy)
|
if (ecm->no_copy)
|
||||||
{
|
{
|
||||||
session_dgram_hdr_t hdr;
|
session_dgram_hdr_t hdr;
|
||||||
svm_fifo_t *f = s->data.tx_fifo;
|
|
||||||
app_session_transport_t *at = &s->data.transport;
|
app_session_transport_t *at = &s->data.transport;
|
||||||
u32 max_enqueue = svm_fifo_max_enqueue_prod (f);
|
|
||||||
|
|
||||||
if (max_enqueue <= sizeof (session_dgram_hdr_t))
|
|
||||||
return;
|
|
||||||
|
|
||||||
max_enqueue -= sizeof (session_dgram_hdr_t);
|
|
||||||
rv = clib_min (max_enqueue, bytes_this_chunk);
|
rv = clib_min (max_enqueue, bytes_this_chunk);
|
||||||
|
|
||||||
hdr.data_length = rv;
|
hdr.data_length = rv;
|
||||||
@ -104,8 +106,11 @@ send_data_chunk (echo_client_main_t * ecm, eclient_session_t * s)
|
|||||||
SESSION_IO_EVT_TX);
|
SESSION_IO_EVT_TX);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rv = app_send_dgram (&s->data, test_data + test_buf_offset,
|
{
|
||||||
bytes_this_chunk, 0);
|
bytes_this_chunk = clib_min (bytes_this_chunk, max_enqueue);
|
||||||
|
rv = app_send_dgram (&s->data, test_data + test_buf_offset,
|
||||||
|
bytes_this_chunk, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we managed to enqueue data... */
|
/* If we managed to enqueue data... */
|
||||||
|
@ -390,6 +390,15 @@ vcl_session_write_ready (vcl_session_t * session)
|
|||||||
if (vcl_session_is_ct (session))
|
if (vcl_session_is_ct (session))
|
||||||
return svm_fifo_max_enqueue_prod (session->ct_tx_fifo);
|
return svm_fifo_max_enqueue_prod (session->ct_tx_fifo);
|
||||||
|
|
||||||
|
if (session->is_dgram)
|
||||||
|
{
|
||||||
|
u32 max_enq = svm_fifo_max_enqueue_prod (session->tx_fifo);
|
||||||
|
|
||||||
|
if (max_enq <= sizeof (session_dgram_hdr_t))
|
||||||
|
return 0;
|
||||||
|
return max_enq - sizeof (session_dgram_hdr_t);
|
||||||
|
}
|
||||||
|
|
||||||
return svm_fifo_max_enqueue_prod (session->tx_fifo);
|
return svm_fifo_max_enqueue_prod (session->tx_fifo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2004,13 +2004,22 @@ vcl_is_tx_evt_for_session (session_event_t * e, u32 sid, u8 is_ct)
|
|||||||
return (e->event_type == SESSION_IO_EVT_TX && e->session_index == sid);
|
return (e->event_type == SESSION_IO_EVT_TX && e->session_index == sid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
always_inline u8
|
||||||
vppcom_session_write_inline (uint32_t session_handle, void *buf, size_t n,
|
vcl_fifo_is_writeable (svm_fifo_t * f, u32 len, u8 is_dgram)
|
||||||
u8 is_flush)
|
{
|
||||||
|
u32 max_enq = svm_fifo_max_enqueue_prod (f);
|
||||||
|
if (is_dgram)
|
||||||
|
return max_enq >= (sizeof (session_dgram_hdr_t) + len);
|
||||||
|
else
|
||||||
|
return max_enq > 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
always_inline int
|
||||||
|
vppcom_session_write_inline (vcl_worker_t * wrk, vcl_session_t * s, void *buf,
|
||||||
|
size_t n, u8 is_flush, u8 is_dgram)
|
||||||
{
|
{
|
||||||
vcl_worker_t *wrk = vcl_worker_get_current ();
|
|
||||||
int n_write, is_nonblocking;
|
int n_write, is_nonblocking;
|
||||||
vcl_session_t *s = 0;
|
|
||||||
session_evt_type_t et;
|
session_evt_type_t et;
|
||||||
svm_msg_q_msg_t msg;
|
svm_msg_q_msg_t msg;
|
||||||
svm_fifo_t *tx_fifo;
|
svm_fifo_t *tx_fifo;
|
||||||
@ -2021,10 +2030,6 @@ vppcom_session_write_inline (uint32_t session_handle, void *buf, size_t n,
|
|||||||
if (PREDICT_FALSE (!buf || n == 0))
|
if (PREDICT_FALSE (!buf || n == 0))
|
||||||
return VPPCOM_EINVAL;
|
return VPPCOM_EINVAL;
|
||||||
|
|
||||||
s = vcl_session_get_w_handle (wrk, session_handle);
|
|
||||||
if (PREDICT_FALSE (!s))
|
|
||||||
return VPPCOM_EBADFD;
|
|
||||||
|
|
||||||
if (PREDICT_FALSE (s->is_vep))
|
if (PREDICT_FALSE (s->is_vep))
|
||||||
{
|
{
|
||||||
VDBG (0, "ERROR: session %u [0x%llx]: cannot write to an epoll"
|
VDBG (0, "ERROR: session %u [0x%llx]: cannot write to an epoll"
|
||||||
@ -2045,13 +2050,13 @@ vppcom_session_write_inline (uint32_t session_handle, void *buf, size_t n,
|
|||||||
is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
|
is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
|
||||||
|
|
||||||
mq = wrk->app_event_queue;
|
mq = wrk->app_event_queue;
|
||||||
if (svm_fifo_is_full_prod (tx_fifo))
|
if (!vcl_fifo_is_writeable (tx_fifo, n, is_dgram))
|
||||||
{
|
{
|
||||||
if (is_nonblocking)
|
if (is_nonblocking)
|
||||||
{
|
{
|
||||||
return VPPCOM_EWOULDBLOCK;
|
return VPPCOM_EWOULDBLOCK;
|
||||||
}
|
}
|
||||||
while (svm_fifo_is_full_prod (tx_fifo))
|
while (!vcl_fifo_is_writeable (tx_fifo, n, is_dgram))
|
||||||
{
|
{
|
||||||
svm_fifo_add_want_deq_ntf (tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
|
svm_fifo_add_want_deq_ntf (tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
|
||||||
if (vcl_session_is_closing (s))
|
if (vcl_session_is_closing (s))
|
||||||
@ -2074,7 +2079,7 @@ vppcom_session_write_inline (uint32_t session_handle, void *buf, size_t n,
|
|||||||
if (is_flush && !is_ct)
|
if (is_flush && !is_ct)
|
||||||
et = SESSION_IO_EVT_TX_FLUSH;
|
et = SESSION_IO_EVT_TX_FLUSH;
|
||||||
|
|
||||||
if (s->is_dgram)
|
if (is_dgram)
|
||||||
n_write = app_send_dgram_raw (tx_fifo, &s->transport,
|
n_write = app_send_dgram_raw (tx_fifo, &s->transport,
|
||||||
s->vpp_evt_q, buf, n, et,
|
s->vpp_evt_q, buf, n, et,
|
||||||
0 /* do_evt */ , SVM_Q_WAIT);
|
0 /* do_evt */ , SVM_Q_WAIT);
|
||||||
@ -2097,15 +2102,29 @@ vppcom_session_write_inline (uint32_t session_handle, void *buf, size_t n,
|
|||||||
int
|
int
|
||||||
vppcom_session_write (uint32_t session_handle, void *buf, size_t n)
|
vppcom_session_write (uint32_t session_handle, void *buf, size_t n)
|
||||||
{
|
{
|
||||||
return vppcom_session_write_inline (session_handle, buf, n,
|
vcl_worker_t *wrk = vcl_worker_get_current ();
|
||||||
0 /* is_flush */ );
|
vcl_session_t *s;
|
||||||
|
|
||||||
|
s = vcl_session_get_w_handle (wrk, session_handle);
|
||||||
|
if (PREDICT_FALSE (!s))
|
||||||
|
return VPPCOM_EBADFD;
|
||||||
|
|
||||||
|
return vppcom_session_write_inline (wrk, s, buf, n,
|
||||||
|
0 /* is_flush */ , s->is_dgram ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vppcom_session_write_msg (uint32_t session_handle, void *buf, size_t n)
|
vppcom_session_write_msg (uint32_t session_handle, void *buf, size_t n)
|
||||||
{
|
{
|
||||||
return vppcom_session_write_inline (session_handle, buf, n,
|
vcl_worker_t *wrk = vcl_worker_get_current ();
|
||||||
1 /* is_flush */ );
|
vcl_session_t *s;
|
||||||
|
|
||||||
|
s = vcl_session_get_w_handle (wrk, session_handle);
|
||||||
|
if (PREDICT_FALSE (!s))
|
||||||
|
return VPPCOM_EBADFD;
|
||||||
|
|
||||||
|
return vppcom_session_write_inline (wrk, s, buf, n,
|
||||||
|
1 /* is_flush */ , s->is_dgram ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define vcl_fifo_rx_evt_valid_or_break(_s) \
|
#define vcl_fifo_rx_evt_valid_or_break(_s) \
|
||||||
@ -3608,18 +3627,18 @@ int
|
|||||||
vppcom_session_sendto (uint32_t session_handle, void *buffer,
|
vppcom_session_sendto (uint32_t session_handle, void *buffer,
|
||||||
uint32_t buflen, int flags, vppcom_endpt_t * ep)
|
uint32_t buflen, int flags, vppcom_endpt_t * ep)
|
||||||
{
|
{
|
||||||
|
vcl_worker_t *wrk = vcl_worker_get_current ();
|
||||||
|
vcl_session_t *s;
|
||||||
|
|
||||||
|
s = vcl_session_get_w_handle (wrk, session_handle);
|
||||||
|
if (!s)
|
||||||
|
return VPPCOM_EBADFD;
|
||||||
|
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return VPPCOM_EINVAL;
|
return VPPCOM_EINVAL;
|
||||||
|
|
||||||
if (ep)
|
if (ep)
|
||||||
{
|
{
|
||||||
vcl_worker_t *wrk = vcl_worker_get_current ();
|
|
||||||
vcl_session_t *s;
|
|
||||||
|
|
||||||
s = vcl_session_get_w_handle (wrk, session_handle);
|
|
||||||
if (!s)
|
|
||||||
return VPPCOM_EBADFD;
|
|
||||||
|
|
||||||
if (s->session_type != VPPCOM_PROTO_UDP
|
if (s->session_type != VPPCOM_PROTO_UDP
|
||||||
|| (s->flags & VCL_SESSION_F_CONNECTED))
|
|| (s->flags & VCL_SESSION_F_CONNECTED))
|
||||||
return VPPCOM_EINVAL;
|
return VPPCOM_EINVAL;
|
||||||
@ -3643,7 +3662,8 @@ vppcom_session_sendto (uint32_t session_handle, void *buffer,
|
|||||||
VDBG (2, "handling flags 0x%u (%d) not implemented yet.", flags, flags);
|
VDBG (2, "handling flags 0x%u (%d) not implemented yet.", flags, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (vppcom_session_write_inline (session_handle, buffer, buflen, 1));
|
return (vppcom_session_write_inline (wrk, s, buffer, buflen, 1,
|
||||||
|
s->is_dgram ? 1 : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -608,7 +608,7 @@ app_send_dgram_raw (svm_fifo_t * f, app_session_transport_t * at,
|
|||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
max_enqueue = svm_fifo_max_enqueue_prod (f);
|
max_enqueue = svm_fifo_max_enqueue_prod (f);
|
||||||
if (max_enqueue <= sizeof (session_dgram_hdr_t))
|
if (max_enqueue < (sizeof (session_dgram_hdr_t) + len))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
max_enqueue -= sizeof (session_dgram_hdr_t);
|
max_enqueue -= sizeof (session_dgram_hdr_t);
|
||||||
@ -694,18 +694,16 @@ app_recv_dgram_raw (svm_fifo_t * f, u8 * buf, u32 len,
|
|||||||
|
|
||||||
svm_fifo_peek (f, 0, sizeof (ph), (u8 *) & ph);
|
svm_fifo_peek (f, 0, sizeof (ph), (u8 *) & ph);
|
||||||
ASSERT (ph.data_length >= ph.data_offset);
|
ASSERT (ph.data_length >= ph.data_offset);
|
||||||
if (!ph.data_offset)
|
svm_fifo_peek (f, sizeof (ph), sizeof (*at), (u8 *) at);
|
||||||
svm_fifo_peek (f, sizeof (ph), sizeof (*at), (u8 *) at);
|
|
||||||
len = clib_min (len, ph.data_length - ph.data_offset);
|
len = clib_min (len, ph.data_length - ph.data_offset);
|
||||||
rv = svm_fifo_peek (f, ph.data_offset + SESSION_CONN_HDR_LEN, len, buf);
|
rv = svm_fifo_peek (f, ph.data_offset + SESSION_CONN_HDR_LEN, len, buf);
|
||||||
if (peek)
|
if (peek)
|
||||||
return rv;
|
return rv;
|
||||||
ASSERT (rv > 0);
|
|
||||||
ph.data_offset += rv;
|
/* Discards data that did not fit in buffer */
|
||||||
if (ph.data_offset == ph.data_length)
|
svm_fifo_dequeue_drop (f, ph.data_length + SESSION_CONN_HDR_LEN);
|
||||||
svm_fifo_dequeue_drop (f, ph.data_length + SESSION_CONN_HDR_LEN);
|
|
||||||
else
|
|
||||||
svm_fifo_overwrite_head (f, (u8 *) & ph, sizeof (ph));
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,6 +320,8 @@ class TestUDP(VppTestCase):
|
|||||||
self.logger.critical(error)
|
self.logger.critical(error)
|
||||||
self.assertNotIn("failed", error)
|
self.assertNotIn("failed", error)
|
||||||
|
|
||||||
|
self.logger.debug(self.vapi.cli("show session verbose 2"))
|
||||||
|
|
||||||
# Delete inter-table routes
|
# Delete inter-table routes
|
||||||
ip_t01.remove_vpp_config()
|
ip_t01.remove_vpp_config()
|
||||||
ip_t10.remove_vpp_config()
|
ip_t10.remove_vpp_config()
|
||||||
|
Reference in New Issue
Block a user