static char *quic_error_strings[] = {
#define quic_error(n,s) s,
-#include "quic_error.def"
+#include <quic/quic_error.def>
#undef quic_error
};
static quic_main_t quic_main;
static void quic_update_timer (quic_ctx_t * ctx);
-static int quic_check_quic_session_connected (quic_ctx_t * ctx);
+static void quic_check_quic_session_connected (quic_ctx_t * ctx);
+static int quic_reset_connection (u64 udp_session_handle,
+ quic_rx_packet_ctx_t * pctx);
+static void quic_proto_on_close (u32 ctx_index, u32 thread_index);
+
+static quicly_stream_open_t on_stream_open;
+static quicly_closed_by_peer_t on_closed_by_peer;
+static quicly_now_t quicly_vpp_now_cb;
+
+static int
+quic_store_quicly_ctx (application_t * app, u32 ckpair_index,
+ u8 crypto_engine)
+{
+ quic_main_t *qm = &quic_main;
+ quicly_context_t *quicly_ctx;
+ ptls_iovec_t key_vec;
+ app_cert_key_pair_t *ckpair;
+ u64 max_enq;
+ if (app->quicly_ctx)
+ return 0;
+
+ if (crypto_engine == CRYPTO_ENGINE_NONE)
+ {
+ QUIC_DBG (2, "No crypto engine specified, using %d", crypto_engine);
+ crypto_engine = qm->default_crypto_engine;
+ }
+ if (!clib_bitmap_get (qm->available_crypto_engines, crypto_engine))
+ {
+ QUIC_DBG (1, "Quic does not support crypto engine %d", crypto_engine);
+ return VNET_API_ERROR_MISSING_CERT_KEY;
+ }
+
+ quicly_ctx_data_t *quicly_ctx_data =
+ clib_mem_alloc (sizeof (quicly_ctx_data_t));
+ clib_memset (quicly_ctx_data, 0, sizeof (*quicly_ctx_data)); /* picotls depends on this */
+ quicly_ctx = &quicly_ctx_data->quicly_ctx;
+ ptls_context_t *ptls_ctx = &quicly_ctx_data->ptls_ctx;
+ ptls_ctx->random_bytes = ptls_openssl_random_bytes;
+ ptls_ctx->get_time = &ptls_get_time;
+ ptls_ctx->key_exchanges = ptls_openssl_key_exchanges;
+ ptls_ctx->cipher_suites = qm->quic_ciphers[crypto_engine];
+ ptls_ctx->certificates.list = NULL;
+ ptls_ctx->certificates.count = 0;
+ ptls_ctx->esni = NULL;
+ ptls_ctx->on_client_hello = NULL;
+ ptls_ctx->emit_certificate = NULL;
+ ptls_ctx->sign_certificate = NULL;
+ ptls_ctx->verify_certificate = NULL;
+ ptls_ctx->ticket_lifetime = 86400;
+ ptls_ctx->max_early_data_size = 8192;
+ ptls_ctx->hkdf_label_prefix__obsolete = NULL;
+ ptls_ctx->require_dhe_on_psk = 1;
+ ptls_ctx->encrypt_ticket = &qm->session_cache.super;
+
+ app->quicly_ctx = (u64 *) quicly_ctx;
+ clib_memcpy (quicly_ctx, &quicly_spec_context, sizeof (quicly_context_t));
+
+ quicly_ctx->max_packet_size = QUIC_MAX_PACKET_SIZE;
+ quicly_ctx->tls = ptls_ctx;
+ quicly_ctx->stream_open = &on_stream_open;
+ quicly_ctx->closed_by_peer = &on_closed_by_peer;
+ quicly_ctx->now = &quicly_vpp_now_cb;
+ quicly_amend_ptls_context (quicly_ctx->tls);
+
+ quicly_ctx->transport_params.max_data = QUIC_INT_MAX;
+ quicly_ctx->transport_params.max_streams_uni = (uint64_t) 1 << 60;
+ quicly_ctx->transport_params.max_streams_bidi = (uint64_t) 1 << 60;
+ quicly_ctx->transport_params.idle_timeout = qm->connection_timeout;
+
+ /* max_enq is FIFO_SIZE - 1 */
+ max_enq = app->sm_properties.rx_fifo_size - 1;
+ quicly_ctx->transport_params.max_stream_data.bidi_local = max_enq;
+ max_enq = app->sm_properties.tx_fifo_size - 1;
+ quicly_ctx->transport_params.max_stream_data.bidi_remote = max_enq;
+ quicly_ctx->transport_params.max_stream_data.uni = QUIC_INT_MAX;
+
+ quicly_ctx->tls->random_bytes (quicly_ctx_data->cid_key, 16);
+ quicly_ctx_data->cid_key[16] = 0;
+ key_vec = ptls_iovec_init (quicly_ctx_data->cid_key,
+ strlen (quicly_ctx_data->cid_key));
+ quicly_ctx->cid_encryptor =
+ quicly_new_default_cid_encryptor (&ptls_openssl_bfecb,
+ &ptls_openssl_aes128ecb,
+ &ptls_openssl_sha256, key_vec);
+
+ ckpair = app_cert_key_pair_get_if_valid (ckpair_index);
+ if (!ckpair || !ckpair->key || !ckpair->cert)
+ {
+ QUIC_DBG (1, "Wrong ckpair id %d\n", ckpair_index);
+ goto error;
+ }
+ if (load_bio_private_key (quicly_ctx->tls, (char *) ckpair->key))
+ {
+ QUIC_DBG (1, "failed to read private key from app configuration\n");
+ goto error;
+ }
+ if (load_bio_certificate_chain (quicly_ctx->tls, (char *) ckpair->cert))
+ {
+ QUIC_DBG (1, "failed to load certificate\n");
+ goto error;
+ }
+ return 0;
+
+error:
+ clib_mem_free (quicly_ctx_data);
+ return VNET_API_ERROR_MISSING_CERT_KEY;
+}
/* Helper functions */
{
QUIC_DBG (2, "Free ctx %u %x", ctx->c_thread_index, ctx->c_c_index);
u32 thread_index = ctx->c_thread_index;
- ASSERT (ctx->timer_handle == QUIC_TIMER_HANDLE_INVALID);
+ QUIC_ASSERT (ctx->timer_handle == QUIC_TIMER_HANDLE_INVALID);
if (CLIB_DEBUG)
clib_memset (ctx, 0xfb, sizeof (*ctx));
pool_put (quic_main.ctx_pool[thread_index], ctx);
sctx = quic_ctx_get (stream_session->connection_index,
stream_session->thread_index);
- ASSERT (quic_ctx_is_stream (sctx));
+ QUIC_ASSERT (quic_ctx_is_stream (sctx));
stream = sctx->stream;
stream_data = (quic_stream_data_t *) stream->data;
f = stream_session->rx_fifo;
max_deq = svm_fifo_max_dequeue (f);
- ASSERT (stream_data->app_rx_data_len >= max_deq);
+ QUIC_ASSERT (stream_data->app_rx_data_len >= max_deq);
quicly_stream_sync_recvbuf (stream, stream_data->app_rx_data_len - max_deq);
QUIC_DBG (3, "Acking %u bytes", stream_data->app_rx_data_len - max_deq);
stream_data->app_rx_data_len = max_deq;
QUIC_DBG (2, "Deleting connection %u", ctx->c_c_index);
- ASSERT (!quic_ctx_is_stream (ctx));
+ QUIC_ASSERT (!quic_ctx_is_stream (ctx));
quic_stop_ctx_timer (ctx);
/* Delete the connection from the connection map */
/* App already confirmed close, we can delete the connection */
quic_connection_delete (ctx);
break;
- case QUIC_CONN_STATE_PASSIVE_CLOSING_QUIC_CLOSED:
- QUIC_DBG (0, "BUG");
- break;
+ case QUIC_CONN_STATE_OPENED:
+ case QUIC_CONN_STATE_HANDSHAKE:
case QUIC_CONN_STATE_ACTIVE_CLOSING:
quic_connection_delete (ctx);
break;
/* Read dest address from quicly-provided sockaddr */
if (hdr.is_ip4)
{
- ASSERT (packet->dest.sa.sa_family == AF_INET);
+ QUIC_ASSERT (packet->dest.sa.sa_family == AF_INET);
struct sockaddr_in *sa4 = (struct sockaddr_in *) &packet->dest.sa;
hdr.rmt_port = sa4->sin_port;
hdr.rmt_ip.ip4.as_u32 = sa4->sin_addr.s_addr;
}
else
{
- ASSERT (packet->dest.sa.sa_family == AF_INET6);
+ QUIC_ASSERT (packet->dest.sa.sa_family == AF_INET6);
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &packet->dest.sa;
hdr.rmt_port = sa6->sin6_port;
clib_memcpy (&hdr.rmt_ip.ip6, &sa6->sin6_addr, 16);
if (quic_ctx_is_stream (ctx))
ctx = quic_ctx_get (ctx->quic_connection_ctx_id, ctx->c_thread_index);
- ASSERT (!quic_ctx_is_stream (ctx));
+ QUIC_ASSERT (!quic_ctx_is_stream (ctx));
udp_session = session_get_from_handle_if_valid (ctx->udp_session_handle);
if (!udp_session)
size_t len)
{
QUIC_DBG (3, "received data: %lu bytes, offset %lu", len, off);
- u32 max_enq;
+ u32 max_enq, rlen, rv;
quic_ctx_t *sctx;
session_t *stream_session;
app_worker_t *app_wrk;
svm_fifo_t *f;
quic_stream_data_t *stream_data;
- int rlen, rv;
stream_data = (quic_stream_data_t *) stream->data;
sctx = quic_ctx_get (stream_data->ctx_id, stream_data->thread_index);
stream_session->app_wrk_index,
stream_session->thread_index, f, len, rlen, off, max_enq);
stream_data->app_rx_data_len += rlen;
- ASSERT (rlen >= len);
+ QUIC_ASSERT (rlen >= len);
app_wrk = app_worker_get_if_valid (stream_session->app_wrk_index);
if (PREDICT_TRUE (app_wrk != 0))
{
rlen = svm_fifo_enqueue_with_offset (f,
off - stream_data->app_rx_data_len,
len, (u8 *) src);
- ASSERT (rlen == 0);
+ QUIC_ASSERT (rlen == 0);
}
return 0;
}
void
quic_fifo_egress_shift (quicly_stream_t * stream, size_t delta)
{
+ quic_stream_data_t *stream_data;
session_t *stream_session;
svm_fifo_t *f;
- int rv;
+ u32 rv;
+ stream_data = (quic_stream_data_t *) stream->data;
stream_session = get_stream_session_from_stream (stream);
f = stream_session->tx_fifo;
+ QUIC_ASSERT (stream_data->app_tx_data_len >= delta);
+ stream_data->app_tx_data_len -= delta;
rv = svm_fifo_dequeue_drop (f, delta);
- ASSERT (rv == delta);
- quicly_stream_sync_sendbuf (stream, 0);
+ QUIC_ASSERT (rv == delta);
+
+ rv = quicly_stream_sync_sendbuf (stream, 0);
+ QUIC_ASSERT (!rv);
}
int
quic_fifo_egress_emit (quicly_stream_t * stream, size_t off, void *dst,
size_t * len, int *wrote_all)
{
+ u32 deq_max, first_deq, max_rd_chunk, rem_offset;
+ quic_stream_data_t *stream_data;
session_t *stream_session;
svm_fifo_t *f;
- u32 deq_max, first_deq, max_rd_chunk, rem_offset;
+ stream_data = (quic_stream_data_t *) stream->data;
stream_session = get_stream_session_from_stream (stream);
f = stream_session->tx_fifo;
QUIC_DBG (3, "Emitting %u, offset %u", *len, off);
deq_max = svm_fifo_max_dequeue_cons (f);
- ASSERT (off <= deq_max);
+ QUIC_ASSERT (off <= deq_max);
if (off + *len < deq_max)
{
*wrote_all = 0;
{
*wrote_all = 1;
*len = deq_max - off;
- QUIC_DBG (3, "Wrote ALL, %u", *len);
}
+ QUIC_ASSERT (*len > 0);
+
+ if (off + *len > stream_data->app_tx_data_len)
+ stream_data->app_tx_data_len = off + *len;
/* TODO, use something like : return svm_fifo_peek (f, off, *len, dst); */
max_rd_chunk = svm_fifo_max_read_chunk (f);
static int
quic_on_stream_open (quicly_stream_open_t * self, quicly_stream_t * stream)
{
+ /* Return code for this function ends either
+ * - in quicly_receive : if not QUICLY_ERROR_PACKET_IGNORED, will close connection
+ * - in quicly_open_stream, returned directly
+ */
+
session_t *stream_session, *quic_session;
quic_stream_data_t *stream_data;
app_worker_t *app_wrk;
stream_data->ctx_id = sctx_id;
stream_data->thread_index = sctx->c_thread_index;
stream_data->app_rx_data_len = 0;
+ stream_data->app_tx_data_len = 0;
sctx->c_s_index = stream_session->session_index;
stream_session->session_state = SESSION_STATE_CREATED;
if ((rv = app_worker_init_connected (app_wrk, stream_session)))
{
QUIC_ERR ("failed to allocate fifos");
- session_free (stream_session);
quicly_reset_stream (stream, QUIC_APP_ALLOCATION_ERROR);
return 0; /* Frame is still valid */
}
if ((rv = app_worker_accept_notify (app_wrk, stream_session)))
{
QUIC_ERR ("failed to notify accept worker app");
- session_free_w_fifos (stream_session);
quicly_reset_stream (stream, QUIC_APP_ACCEPT_NOTIFY_ERROR);
return 0; /* Frame is still valid */
}
session_transport_closing_notify (&ctx->connection);
}
-static quicly_stream_open_t on_stream_open = { quic_on_stream_open };
-static quicly_closed_by_peer_t on_closed_by_peer = { quic_on_closed_by_peer };
-
/* Timer handling */
static int64_t
return quic_get_thread_time (thread_index);
}
-static quicly_now_t quicly_vpp_now_cb = { quic_get_time };
-
static u32
quic_set_time_now (u32 thread_index)
{
}
}
-static int
-quic_encrypt_ticket_cb (ptls_encrypt_ticket_t * _self, ptls_t * tls,
- int is_encrypt, ptls_buffer_t * dst, ptls_iovec_t src)
-{
- quic_session_cache_t *self = (void *) _self;
- int ret;
-
- if (is_encrypt)
- {
-
- /* replace the cached entry along with a newly generated session id */
- clib_mem_free (self->data.base);
- if ((self->data.base = clib_mem_alloc (src.len)) == NULL)
- return PTLS_ERROR_NO_MEMORY;
-
- ptls_get_context (tls)->random_bytes (self->id, sizeof (self->id));
- clib_memcpy (self->data.base, src.base, src.len);
- self->data.len = src.len;
-
- /* store the session id in buffer */
- if ((ret = ptls_buffer_reserve (dst, sizeof (self->id))) != 0)
- return ret;
- clib_memcpy (dst->base + dst->off, self->id, sizeof (self->id));
- dst->off += sizeof (self->id);
-
- }
- else
- {
-
- /* check if session id is the one stored in cache */
- if (src.len != sizeof (self->id))
- return PTLS_ERROR_SESSION_NOT_FOUND;
- if (clib_memcmp (self->id, src.base, sizeof (self->id)) != 0)
- return PTLS_ERROR_SESSION_NOT_FOUND;
-
- /* return the cached value */
- if ((ret = ptls_buffer_reserve (dst, self->data.len)) != 0)
- return ret;
- clib_memcpy (dst->base + dst->off, self->data.base, self->data.len);
- dst->off += self->data.len;
- }
-
- return 0;
-}
-
-static int
-quic_store_quicly_ctx (application_t * app, u32 ckpair_index,
- u8 crypto_engine)
-{
- quic_main_t *qm = &quic_main;
- quicly_context_t *quicly_ctx;
- ptls_iovec_t key_vec;
- app_cert_key_pair_t *ckpair;
- u64 max_enq;
- if (app->quicly_ctx)
- return 0;
-
- if (crypto_engine == CRYPTO_ENGINE_NONE)
- {
- QUIC_DBG (2, "No crypto engine specified, using %d", crypto_engine);
- crypto_engine = qm->default_crypto_engine;
- }
- if (!clib_bitmap_get (qm->available_crypto_engines, crypto_engine))
- {
- QUIC_ERR ("Quic does not support crypto engine %d", crypto_engine);
- return VNET_API_ERROR_MISSING_CERT_KEY;
- }
-
- quicly_ctx_data_t *quicly_ctx_data =
- clib_mem_alloc (sizeof (quicly_ctx_data_t));
- clib_memset (quicly_ctx_data, 0, sizeof (*quicly_ctx_data)); /* picotls depends on this */
- quicly_ctx = &quicly_ctx_data->quicly_ctx;
- ptls_context_t *ptls_ctx = &quicly_ctx_data->ptls_ctx;
- ptls_ctx->random_bytes = ptls_openssl_random_bytes;
- ptls_ctx->get_time = &ptls_get_time;
- ptls_ctx->key_exchanges = ptls_openssl_key_exchanges;
- ptls_ctx->cipher_suites = qm->quic_ciphers[crypto_engine];
- ptls_ctx->certificates.list = NULL;
- ptls_ctx->certificates.count = 0;
- ptls_ctx->esni = NULL;
- ptls_ctx->on_client_hello = NULL;
- ptls_ctx->emit_certificate = NULL;
- ptls_ctx->sign_certificate = NULL;
- ptls_ctx->verify_certificate = NULL;
- ptls_ctx->ticket_lifetime = 86400;
- ptls_ctx->max_early_data_size = 8192;
- ptls_ctx->hkdf_label_prefix__obsolete = NULL;
- ptls_ctx->require_dhe_on_psk = 1;
- ptls_ctx->encrypt_ticket = &qm->session_cache.super;
-
- app->quicly_ctx = (u64 *) quicly_ctx;
- clib_memcpy (quicly_ctx, &quicly_spec_context, sizeof (quicly_context_t));
-
- quicly_ctx->max_packet_size = QUIC_MAX_PACKET_SIZE;
- quicly_ctx->tls = ptls_ctx;
- quicly_ctx->stream_open = &on_stream_open;
- quicly_ctx->closed_by_peer = &on_closed_by_peer;
- quicly_ctx->now = &quicly_vpp_now_cb;
- quicly_amend_ptls_context (quicly_ctx->tls);
-
- quicly_ctx->transport_params.max_data = QUIC_INT_MAX;
- quicly_ctx->transport_params.max_streams_uni = (uint64_t) 1 << 60;
- quicly_ctx->transport_params.max_streams_bidi = (uint64_t) 1 << 60;
-
- /* max_enq is FIFO_SIZE - 1 */
- max_enq = app->sm_properties.rx_fifo_size - 1;
- quicly_ctx->transport_params.max_stream_data.bidi_local = max_enq;
- max_enq = app->sm_properties.tx_fifo_size - 1;
- quicly_ctx->transport_params.max_stream_data.bidi_remote = max_enq;
- quicly_ctx->transport_params.max_stream_data.uni = QUIC_INT_MAX;
-
- quicly_ctx->tls->random_bytes (quicly_ctx_data->cid_key, 16);
- quicly_ctx_data->cid_key[16] = 0;
- key_vec = ptls_iovec_init (quicly_ctx_data->cid_key,
- strlen (quicly_ctx_data->cid_key));
- quicly_ctx->cid_encryptor =
- quicly_new_default_cid_encryptor (&ptls_openssl_bfecb,
- &ptls_openssl_aes128ecb,
- &ptls_openssl_sha256, key_vec);
-
- ckpair = app_cert_key_pair_get_if_valid (ckpair_index);
- if (!ckpair || !ckpair->key || !ckpair->cert)
- {
- QUIC_ERR ("Wrong ckpair id %d\n", ckpair_index);
- goto error;
- }
- if (load_bio_private_key (quicly_ctx->tls, (char *) ckpair->key))
- {
- QUIC_ERR ("failed to read private key from app configuration\n");
- goto error;
- }
- if (load_bio_certificate_chain (quicly_ctx->tls, (char *) ckpair->cert))
- {
- QUIC_ERR ("failed to load certificate\n");
- goto error;
- }
- return 0;
-
-error:
- clib_mem_free (quicly_ctx_data);
- return VNET_API_ERROR_MISSING_CERT_KEY;
-}
-
/* Transport proto functions */
static int
session_type_from_proto_and_ip (TRANSPORT_PROTO_QUIC, qctx->udp_is_ip4);
sctx->c_s_index = stream_session->session_index;
+ stream_data = (quic_stream_data_t *) stream->data;
+ stream_data->ctx_id = sctx->c_c_index;
+ stream_data->thread_index = sctx->c_thread_index;
+ stream_data->app_rx_data_len = 0;
+ stream_data->app_tx_data_len = 0;
+ stream_session->session_state = SESSION_STATE_READY;
+ /* For now we only reset streams. Cleanup will be triggered by timers */
if (app_worker_init_connected (app_wrk, stream_session))
{
QUIC_ERR ("failed to app_worker_init_connected");
- quicly_reset_stream (stream, QUIC_APP_ALLOCATION_ERROR);
- session_free_w_fifos (stream_session);
- quic_ctx_free (sctx);
+ quicly_reset_stream (stream, QUIC_APP_CONNECT_NOTIFY_ERROR);
return app_worker_connect_notify (app_wrk, NULL, opaque);
}
SVM_FIFO_WANT_DEQ_NOTIF_IF_FULL |
SVM_FIFO_WANT_DEQ_NOTIF_IF_EMPTY);
- stream_session->session_state = SESSION_STATE_READY;
if (app_worker_connect_notify (app_wrk, stream_session, opaque))
{
QUIC_ERR ("failed to notify app");
quicly_reset_stream (stream, QUIC_APP_CONNECT_NOTIFY_ERROR);
- session_free_w_fifos (stream_session);
- quic_ctx_free (sctx);
return -1;
}
- stream_data = (quic_stream_data_t *) stream->data;
- stream_data->ctx_id = sctx->c_c_index;
- stream_data->thread_index = sctx->c_thread_index;
- stream_data->app_rx_data_len = 0;
+
return 0;
}
app_worker_t *app_wrk;
application_t *app;
u32 ctx_index;
+ u32 thread_index = vlib_get_thread_index ();
int error;
clib_memset (cargs, 0, sizeof (*cargs));
- ctx_index = quic_ctx_alloc (vlib_get_thread_index ());
- ctx = quic_ctx_get (ctx_index, vlib_get_thread_index ());
+ ctx_index = quic_ctx_alloc (thread_index);
+ ctx = quic_ctx_get (ctx_index, thread_index);
ctx->parent_app_wrk_id = sep->app_wrk_index;
ctx->c_s_index = QUIC_SESSION_INVALID;
ctx->c_c_index = ctx_index;
switch (ctx->conn_state)
{
+ case QUIC_CONN_STATE_OPENED:
+ case QUIC_CONN_STATE_HANDSHAKE:
case QUIC_CONN_STATE_READY:
ctx->conn_state = QUIC_CONN_STATE_ACTIVE_CLOSING;
quicly_conn_t *conn = ctx->conn;
case QUIC_CONN_STATE_PASSIVE_CLOSING_QUIC_CLOSED:
quic_connection_delete (ctx);
break;
+ case QUIC_CONN_STATE_ACTIVE_CLOSING:
+ break;
default:
- QUIC_DBG (0, "BUG");
+ QUIC_ERR ("Trying to close conn in state %d", ctx->conn_state);
break;
}
}
quic_ctx_t *lctx;
u32 lctx_index;
app_listener_t *app_listener;
+ int rv;
sep = (session_endpoint_cfg_t *) tep;
app_wrk = app_worker_get (sep->app_wrk_index);
args->app_index = qm->app_index;
args->sep_ext = *sep;
args->sep_ext.ns_index = app->ns_index;
- if (vnet_listen (args))
- return -1;
+ if ((rv = vnet_listen (args)))
+ return rv;
lctx_index = quic_ctx_alloc (0);
udp_handle = args->handle;
QUIC_DBG (2, "Called quic_stop_listen");
quic_ctx_t *lctx;
lctx = quic_ctx_get (lctx_index, 0);
- ASSERT (quic_ctx_is_listener (lctx));
+ QUIC_ASSERT (quic_ctx_is_listener (lctx));
vnet_unlisten_args_t a = {
.handle = lctx->udp_session_handle,
.app_index = quic_main.app_index,
}
}
-static int
+static void
quic_on_quic_session_connected (quic_ctx_t * ctx)
{
session_t *quic_session;
u32 thread_index = ctx->c_thread_index;
int rv;
- app_wrk = app_worker_get_if_valid (ctx->parent_app_wrk_id);
- if (!app_wrk)
- {
- quic_disconnect_transport (ctx);
- return 0;
- }
-
quic_session = session_alloc (thread_index);
QUIC_DBG (2, "Allocated quic session 0x%lx", session_handle (quic_session));
quic_session->session_type =
session_type_from_proto_and_ip (TRANSPORT_PROTO_QUIC, ctx->udp_is_ip4);
+ /* If quic session connected fails, immediatly close connection */
+ app_wrk = app_worker_get (ctx->parent_app_wrk_id);
if (app_worker_init_connected (app_wrk, quic_session))
{
QUIC_ERR ("failed to app_worker_init_connected");
quic_proto_on_close (ctx_id, thread_index);
- return app_worker_connect_notify (app_wrk, NULL, ctx->client_opaque);
+ app_worker_connect_notify (app_wrk, NULL, ctx->client_opaque);
+ return;
}
quic_session->session_state = SESSION_STATE_CONNECTING;
{
QUIC_ERR ("failed to notify app %d", rv);
quic_proto_on_close (ctx_id, thread_index);
- return -1;
+ return;
}
/* If the app opens a stream in its callback it may invalidate ctx */
*/
quic_session = session_get (ctx->c_s_index, thread_index);
quic_session->session_state = SESSION_STATE_LISTENING;
-
- return 0;
}
-static int
+static void
quic_check_quic_session_connected (quic_ctx_t * ctx)
{
/* Called when we need to trigger quic session connected
/* Conn may be set to null if the connection is terminated */
if (!ctx->conn || ctx->conn_state != QUIC_CONN_STATE_HANDSHAKE)
- return 0;
+ return;
if (!quicly_connection_is_ready (ctx->conn))
- return 0;
+ return;
ctx->conn_state = QUIC_CONN_STATE_READY;
if (!quicly_is_client (ctx->conn))
- return 0;
- return quic_on_quic_session_connected (ctx);
+ return;
+ quic_on_quic_session_connected (ctx);
}
static void
QUIC_DBG (2, "Received conn %u (now %u)", temp_ctx->c_thread_index,
new_ctx_id);
-
clib_memcpy (new_ctx, temp_ctx, sizeof (quic_ctx_t));
clib_mem_free (temp_ctx);
QUIC_DBG (2, "Transferring conn %u to thread %u", ctx_index, dest_thread);
temp_ctx = clib_mem_alloc (sizeof (quic_ctx_t));
- ASSERT (temp_ctx);
+ QUIC_ASSERT (temp_ctx != NULL);
ctx = quic_ctx_get (ctx_index, thread_index);
clib_memcpy (temp_ctx, ctx, sizeof (quic_ctx_t));
quic_ctx_t *ctx;
QUIC_ERR ("Session %x migrated to %lx", s->session_index, new_sh);
- ASSERT (vlib_get_thread_index () == s->thread_index);
+ QUIC_ASSERT (vlib_get_thread_index () == s->thread_index);
ctx = quic_ctx_get (s->opaque, s->thread_index);
- ASSERT (ctx->udp_session_handle == session_handle (s));
+ QUIC_ASSERT (ctx->udp_session_handle == session_handle (s));
ctx->udp_session_handle = new_sh;
#if QUIC_DEBUG >= 1
{
/* New UDP connection, try to accept it */
u32 ctx_index;
- u32 *pool_index;
quic_ctx_t *ctx, *lctx;
session_t *udp_listen_session;
u32 thread_index = vlib_get_thread_index ();
udp_session->opaque = ctx_index;
- /* Put this ctx in the "opening" pool */
- pool_get (quic_main.wrk_ctx[ctx->c_thread_index].opening_ctx_pool,
- pool_index);
- *pool_index = ctx_index;
-
/* TODO timeout to delete these if they never connect */
return 0;
}
quic_custom_tx_callback (void *s, u32 max_burst_size)
{
session_t *stream_session = (session_t *) s;
+ quic_stream_data_t *stream_data;
quicly_stream_t *stream;
quic_ctx_t *ctx;
+ u32 max_deq;
int rv;
if (PREDICT_FALSE
QUIC_DBG (3, "Stream TX event");
quic_ack_rx_data (stream_session);
- if (!svm_fifo_max_dequeue (stream_session->tx_fifo))
- return 0;
-
stream = ctx->stream;
if (!quicly_sendstate_is_open (&stream->sendstate))
{
return -1;
}
- if ((rv = quicly_stream_sync_sendbuf (stream, 1)) != 0)
- return rv;
+ stream_data = (quic_stream_data_t *) stream->data;
+ max_deq = svm_fifo_max_dequeue (stream_session->tx_fifo);
+ QUIC_ASSERT (max_deq >= stream_data->app_tx_data_len);
+ if (max_deq == stream_data->app_tx_data_len)
+ {
+ QUIC_DBG (3, "TX but no data %d / %d", max_deq,
+ stream_data->app_tx_data_len);
+ return 0;
+ }
+ stream_data->app_tx_data_len = max_deq;
+ rv = quicly_stream_sync_sendbuf (stream, 1);
+ QUIC_ASSERT (!rv);
tx_end:
quic_send_packets (ctx);
return 0;
}
-
/*
* Returns 0 if a matching connection is found and is on the right thread.
* Otherwise returns -1.
* will be set.
*/
static inline int
-quic_find_packet_ctx (u32 * ctx_thread, u32 * ctx_index,
- struct sockaddr *sa, socklen_t salen,
- quicly_decoded_packet_t * packet,
- u32 caller_thread_index)
+quic_find_packet_ctx (quic_rx_packet_ctx_t * pctx, u32 caller_thread_index)
{
- quic_ctx_t *ctx_;
- quicly_conn_t *conn_;
clib_bihash_kv_16_8_t kv;
clib_bihash_16_8_t *h;
+ quic_ctx_t *ctx;
+ u32 index, thread_id;
h = &quic_main.connection_hash;
- quic_make_connection_key (&kv, &packet->cid.dest.plaintext);
+ quic_make_connection_key (&kv, &pctx->packet.cid.dest.plaintext);
QUIC_DBG (3, "Searching conn with id %lu %lu", kv.key[0], kv.key[1]);
- if (clib_bihash_search_16_8 (h, &kv, &kv) == 0)
+ if (clib_bihash_search_16_8 (h, &kv, &kv))
{
- u32 index = kv.value & UINT32_MAX;
- u32 thread_id = kv.value >> 32;
- /* Check if this connection belongs to this thread, otherwise
- * ask for it to be moved */
- if (thread_id != caller_thread_index)
- {
- QUIC_DBG (2, "Connection is on wrong thread");
- /* Cannot make full check with quicly_is_destination... */
- *ctx_index = index;
- *ctx_thread = thread_id;
- return -1;
- }
- ctx_ = quic_ctx_get (index, vlib_get_thread_index ());
- conn_ = ctx_->conn;
- if (conn_ && quicly_is_destination (conn_, NULL, sa, packet))
- {
- QUIC_DBG (3, "Connection found");
- *ctx_index = index;
- *ctx_thread = thread_id;
- return 0;
- }
+ QUIC_DBG (3, "connection not found");
+ return QUIC_PACKET_TYPE_NONE;
+ }
+
+ index = kv.value & UINT32_MAX;
+ thread_id = kv.value >> 32;
+ /* Check if this connection belongs to this thread, otherwise
+ * ask for it to be moved */
+ if (thread_id != caller_thread_index)
+ {
+ QUIC_DBG (2, "Connection is on wrong thread");
+ /* Cannot make full check with quicly_is_destination... */
+ pctx->ctx_index = index;
+ pctx->thread_index = thread_id;
+ return QUIC_PACKET_TYPE_MIGRATE;
+ }
+ ctx = quic_ctx_get (index, vlib_get_thread_index ());
+ if (!ctx->conn)
+ {
+ QUIC_ERR ("ctx has no conn");
+ return QUIC_PACKET_TYPE_NONE;
}
- QUIC_DBG (3, "connection not found");
- return -1;
+ if (!quicly_is_destination (ctx->conn, NULL, &pctx->sa, &pctx->packet))
+ return QUIC_PACKET_TYPE_NONE;
+
+ QUIC_DBG (3, "Connection found");
+ pctx->ctx_index = index;
+ pctx->thread_index = thread_id;
+ return QUIC_PACKET_TYPE_RECEIVE;
}
static int
-quic_accept_connection (u32 ctx_index, struct sockaddr *sa,
- socklen_t salen, quicly_decoded_packet_t packet)
+quic_accept_connection (u32 ctx_index, quic_rx_packet_ctx_t * pctx)
{
u32 thread_index = vlib_get_thread_index ();
quicly_context_t *quicly_ctx;
/* new connection, accept and create context if packet is valid
* TODO: check if socket is actually listening? */
ctx = quic_ctx_get (ctx_index, thread_index);
+ if (ctx->c_s_index != QUIC_SESSION_INVALID)
+ {
+ QUIC_DBG (2, "already accepted ctx 0x%x", ctx_index);
+ return 0;
+ }
+
quicly_ctx = quic_get_quicly_ctx_from_ctx (ctx);
- if ((rv = quicly_accept (&conn, quicly_ctx, NULL, sa,
- &packet, NULL, &quic_main.next_cid, NULL)))
+ if ((rv = quicly_accept (&conn, quicly_ctx, NULL, &pctx->sa,
+ &pctx->packet, NULL, &quic_main.next_cid, NULL)))
{
/* Invalid packet, pass */
assert (conn == NULL);
- QUIC_ERR ("Accept failed with %d", rv);
+ QUIC_ERR ("Accept failed with %U", quic_format_err, rv);
/* TODO: cleanup created quic ctx and UDP session */
return 0;
}
/* Save ctx handle in quicly connection */
quic_store_conn_ctx (conn, ctx);
ctx->conn = conn;
- ctx->conn_state = QUIC_CONN_STATE_HANDSHAKE;
quic_session = session_alloc (ctx->c_thread_index);
QUIC_DBG (2, "Allocated quic_session, 0x%lx ctx %u",
session_type_from_proto_and_ip (TRANSPORT_PROTO_QUIC, ctx->udp_is_ip4);
quic_session->listener_handle = lctx->c_s_index;
- /* TODO: don't alloc fifos when we don't transfer data on this session
- * but we still need fifos for the events? */
+ /* Register connection in connections map */
+ quic_make_connection_key (&kv, quicly_get_master_id (conn));
+ kv.value = ((u64) thread_index) << 32 | (u64) ctx_index;
+ clib_bihash_add_del_16_8 (&quic_main.connection_hash, &kv, 1 /* is_add */ );
+ QUIC_DBG (2, "Registering conn with id %lu %lu", kv.key[0], kv.key[1]);
+
+ /* If notify fails, reset connection immediatly */
if ((rv = app_worker_init_accepted (quic_session)))
{
QUIC_ERR ("failed to allocate fifos");
- session_free (quic_session);
+ quic_proto_on_close (ctx_index, thread_index);
return rv;
}
+
app_wrk = app_worker_get (quic_session->app_wrk_index);
if ((rv = app_worker_accept_notify (app_wrk, quic_session)))
{
QUIC_ERR ("failed to notify accept worker app");
+ quic_proto_on_close (ctx_index, thread_index);
return rv;
}
- /* Register connection in connections map */
- quic_make_connection_key (&kv, quicly_get_master_id (conn));
- kv.value = ((u64) thread_index) << 32 | (u64) ctx_index;
- clib_bihash_add_del_16_8 (&quic_main.connection_hash, &kv, 1 /* is_add */ );
- QUIC_DBG (2, "Registering conn with id %lu %lu", kv.key[0], kv.key[1]);
+ ctx->conn_state = QUIC_CONN_STATE_READY;
+ pctx->ctx_index = ctx_index;
+ pctx->thread_index = thread_index;
- return quic_send_packets (ctx);
+ return 0;
}
static int
-quic_reset_connection (u64 udp_session_handle,
- struct sockaddr *sa, socklen_t salen,
- quicly_decoded_packet_t packet)
+quic_reset_connection (u64 udp_session_handle, quic_rx_packet_ctx_t * pctx)
{
/* short header packet; potentially a dead connection. No need to check the
* length of the incoming packet, because loop is prevented by authenticating
quicly_datagram_t *dgram;
session_t *udp_session;
quicly_context_t *quicly_ctx;
- if (packet.cid.dest.plaintext.node_id != 0
- || packet.cid.dest.plaintext.thread_id != 0)
+ if (pctx->packet.cid.dest.plaintext.node_id != 0
+ || pctx->packet.cid.dest.plaintext.thread_id != 0)
return 0;
quicly_ctx = quic_get_quicly_ctx_from_udp (udp_session_handle);
- dgram = quicly_send_stateless_reset (quicly_ctx, sa, NULL,
- &packet.cid.dest.plaintext);
+ dgram = quicly_send_stateless_reset (quicly_ctx, &pctx->sa, NULL,
+ &pctx->packet.cid.dest.plaintext);
if (dgram == NULL)
return 1;
udp_session = session_get_from_handle (udp_session_handle);
static int
quic_process_one_rx_packet (u64 udp_session_handle, svm_fifo_t * f,
- u32 * fifo_offset, u32 * max_packet, u32 packet_n,
- quic_rx_packet_ctx_t * packet_ctx)
+ u32 fifo_offset, quic_rx_packet_ctx_t * pctx)
{
- session_dgram_hdr_t ph;
- quic_ctx_t *ctx = NULL;
size_t plen;
- struct sockaddr_in6 sa6;
- struct sockaddr *sa = (struct sockaddr *) &sa6;
- socklen_t salen;
u32 full_len, ret;
- int err, rv = 0;
- packet_ctx->thread_index = UINT32_MAX;
- packet_ctx->ctx_index = UINT32_MAX;
u32 thread_index = vlib_get_thread_index ();
- u32 *opening_ctx_pool, *ctx_index_ptr;
- u32 cur_deq = svm_fifo_max_dequeue (f) - *fifo_offset;
+ u32 cur_deq = svm_fifo_max_dequeue (f) - fifo_offset;
quicly_context_t *quicly_ctx;
+ int rv;
- if (cur_deq == 0)
- {
- *max_packet = packet_n + 1;
- return 0;
- }
-
- if (cur_deq < SESSION_CONN_HDR_LEN)
- {
- QUIC_ERR ("Not enough data for even a header in RX");
- return 1;
- }
- ret = svm_fifo_peek (f, *fifo_offset, SESSION_CONN_HDR_LEN, (u8 *) & ph);
- if (ret != SESSION_CONN_HDR_LEN)
- {
- QUIC_ERR ("Not enough data for header in RX");
- return 1;
- }
- ASSERT (ph.data_offset == 0);
- full_len = ph.data_length + SESSION_CONN_HDR_LEN;
+ ret = svm_fifo_peek (f, fifo_offset,
+ SESSION_CONN_HDR_LEN, (u8 *) & pctx->ph);
+ QUIC_ASSERT (ret == SESSION_CONN_HDR_LEN);
+ QUIC_ASSERT (pctx->ph.data_offset == 0);
+ full_len = pctx->ph.data_length + SESSION_CONN_HDR_LEN;
if (full_len > cur_deq)
{
QUIC_ERR ("Not enough data in fifo RX");
/* Quicly can read len bytes from the fifo at offset:
* ph.data_offset + SESSION_CONN_HDR_LEN */
- ret = svm_fifo_peek (f, SESSION_CONN_HDR_LEN + *fifo_offset,
- ph.data_length, packet_ctx->data);
- if (ret != ph.data_length)
+ ret = svm_fifo_peek (f, SESSION_CONN_HDR_LEN + fifo_offset,
+ pctx->ph.data_length, pctx->data);
+ if (ret != pctx->ph.data_length)
{
QUIC_ERR ("Not enough data peeked in RX");
return 1;
}
quic_increment_counter (QUIC_ERROR_RX_PACKETS, 1);
- rv = 0;
- quic_build_sockaddr (sa, &salen, &ph.rmt_ip, ph.rmt_port, ph.is_ip4);
+ quic_build_sockaddr (&pctx->sa, &pctx->salen, &pctx->ph.rmt_ip,
+ pctx->ph.rmt_port, pctx->ph.is_ip4);
quicly_ctx = quic_get_quicly_ctx_from_udp (udp_session_handle);
- plen = quicly_decode_packet (quicly_ctx, &packet_ctx->packet,
- packet_ctx->data, ph.data_length);
+ plen = quicly_decode_packet (quicly_ctx, &pctx->packet,
+ pctx->data, pctx->ph.data_length);
if (plen == SIZE_MAX)
{
- *fifo_offset += SESSION_CONN_HDR_LEN + ph.data_length;
return 1;
}
- err = quic_find_packet_ctx (&packet_ctx->thread_index,
- &packet_ctx->ctx_index, sa, salen,
- &packet_ctx->packet, thread_index);
- if (err == 0)
+ rv = quic_find_packet_ctx (pctx, thread_index);
+ if (rv == QUIC_PACKET_TYPE_RECEIVE)
{
- ctx = quic_ctx_get (packet_ctx->ctx_index, thread_index);
- rv = quicly_receive (ctx->conn, NULL, sa, &packet_ctx->packet);
- if (rv)
- QUIC_ERR ("quicly_receive errored %U", quic_format_err, rv);
+ pctx->ptype = QUIC_PACKET_TYPE_RECEIVE;
+ return 0;
}
- else if (packet_ctx->ctx_index != UINT32_MAX)
+ else if (rv == QUIC_PACKET_TYPE_MIGRATE)
{
+ pctx->ptype = QUIC_PACKET_TYPE_MIGRATE;
/* Connection found but on wrong thread, ask move */
- *max_packet = packet_n + 1;
- return 0;
}
- else if ((packet_ctx->packet.octets.base[0] & QUICLY_PACKET_TYPE_BITMASK) ==
- QUICLY_PACKET_TYPE_INITIAL)
+ else if (QUICLY_PACKET_IS_LONG_HEADER (pctx->packet.octets.base[0]))
{
- /* Try to find matching "opening" ctx */
- opening_ctx_pool = quic_main.wrk_ctx[thread_index].opening_ctx_pool;
-
- /* *INDENT-OFF* */
- pool_foreach (ctx_index_ptr, opening_ctx_pool,
- ({
- ctx = quic_ctx_get (*ctx_index_ptr, thread_index);
- if (ctx->udp_session_handle == udp_session_handle)
- {
- /* Right ctx found, create conn & remove from pool */
- quic_accept_connection (*ctx_index_ptr, sa, salen, packet_ctx->packet);
- *max_packet = packet_n + 1;
- packet_ctx->thread_index = thread_index;
- packet_ctx->ctx_index = *ctx_index_ptr;
- pool_put (opening_ctx_pool, ctx_index_ptr);
- goto updateOffset;
- }
- }));
- /* *INDENT-ON* */
- QUIC_ERR ("Missing opening ctx (in %d) Thread %d UDP 0x%lx",
- pool_elts (opening_ctx_pool), thread_index,
- udp_session_handle);
+ pctx->ptype = QUIC_PACKET_TYPE_ACCEPT;
}
else
{
- quic_reset_connection (udp_session_handle, sa, salen,
- packet_ctx->packet);
+ pctx->ptype = QUIC_PACKET_TYPE_RESET;
}
-
-updateOffset:
- *fifo_offset += SESSION_CONN_HDR_LEN + ph.data_length;
- return 0;
+ return 1;
}
static int
{
/* Read data from UDP rx_fifo and pass it to the quicly conn. */
quic_ctx_t *ctx = NULL;
- svm_fifo_t *f;
+ svm_fifo_t *f = udp_session->rx_fifo;
u32 max_deq;
u64 udp_session_handle = session_handle (udp_session);
int rv = 0;
u32 thread_index = vlib_get_thread_index ();
- quic_rx_packet_ctx_t packets_ctx[16];
- u32 i, fifo_offset, max_packets;
+ u32 cur_deq, fifo_offset, max_packets, i;
+
+ quic_rx_packet_ctx_t packets_ctx[QUIC_RCV_MAX_BATCH_PACKETS];
if (udp_session->flags & SESSION_F_IS_MIGRATING)
{
return 0;
}
- while (1)
+rx_start:
+ max_deq = svm_fifo_max_dequeue (f);
+ if (max_deq == 0)
+ return 0;
+
+ fifo_offset = 0;
+ max_packets = QUIC_RCV_MAX_BATCH_PACKETS;
+
+ for (i = 0; i < max_packets; i++)
{
- udp_session = session_get_from_handle (udp_session_handle); /* session alloc might have happened */
- f = udp_session->rx_fifo;
- max_deq = svm_fifo_max_dequeue (f);
- if (max_deq == 0)
- return 0;
+ packets_ctx[i].thread_index = UINT32_MAX;
+ packets_ctx[i].ctx_index = UINT32_MAX;
+ packets_ctx[i].ptype = QUIC_PACKET_TYPE_DROP;
- fifo_offset = 0;
- max_packets = 16;
- for (i = 0; i < max_packets; i++)
- quic_process_one_rx_packet (udp_session_handle, f, &fifo_offset,
- &max_packets, i, &packets_ctx[i]);
+ cur_deq = max_deq - fifo_offset;
+ if (cur_deq == 0)
+ {
+ max_packets = i + 1;
+ break;
+ }
+ if (cur_deq < SESSION_CONN_HDR_LEN)
+ {
+ fifo_offset = max_deq;
+ max_packets = i + 1;
+ QUIC_ERR ("Fifo %d < header size in RX", cur_deq);
+ break;
+ }
+ rv = quic_process_one_rx_packet (udp_session_handle, f,
+ fifo_offset, &packets_ctx[i]);
+ if (packets_ctx[i].ptype != QUIC_PACKET_TYPE_MIGRATE)
+ fifo_offset += SESSION_CONN_HDR_LEN + packets_ctx[i].ph.data_length;
+ if (rv)
+ {
+ max_packets = i + 1;
+ break;
+ }
+ }
- for (i = 0; i < max_packets; i++)
+ for (i = 0; i < max_packets; i++)
+ {
+ switch (packets_ctx[i].ptype)
{
- if (packets_ctx[i].thread_index != thread_index)
- continue;
+ case QUIC_PACKET_TYPE_RECEIVE:
+ ctx = quic_ctx_get (packets_ctx[i].ctx_index, thread_index);
+ rv = quicly_receive (ctx->conn, NULL, &packets_ctx[i].sa,
+ &packets_ctx[i].packet);
+ if (rv && rv != QUICLY_ERROR_PACKET_IGNORED)
+ {
+ QUIC_ERR ("quicly_receive return error %U",
+ quic_format_err, rv);
+ }
+ break;
+ case QUIC_PACKET_TYPE_ACCEPT:
+ udp_session = session_get_from_handle (udp_session_handle);
+ if ((rv = quic_accept_connection (udp_session->opaque,
+ &packets_ctx[i])))
+ {
+ QUIC_ERR ("quic accept errored with %d", rv);
+ }
+ break;
+ case QUIC_PACKET_TYPE_RESET:
+ quic_reset_connection (udp_session_handle, &packets_ctx[i]);
+ break;
+ }
+ }
+ for (i = 0; i < max_packets; i++)
+ {
+ switch (packets_ctx[i].ptype)
+ {
+ case QUIC_PACKET_TYPE_RECEIVE:
ctx = quic_ctx_get (packets_ctx[i].ctx_index,
packets_ctx[i].thread_index);
quic_check_quic_session_connected (ctx);
ctx = quic_ctx_get (packets_ctx[i].ctx_index,
packets_ctx[i].thread_index);
- quic_send_packets (ctx);
+ break;
+ case QUIC_PACKET_TYPE_ACCEPT:
+ ctx = quic_ctx_get (packets_ctx[i].ctx_index,
+ packets_ctx[i].thread_index);
+ break;
+ default:
+ continue;
}
- svm_fifo_dequeue_drop (f, fifo_offset);
+ quic_send_packets (ctx);
}
- return rv;
+
+ udp_session = session_get_from_handle (udp_session_handle); /* session alloc might have happened */
+ f = udp_session->rx_fifo;
+ svm_fifo_dequeue_drop (f, fifo_offset);
+
+ if (svm_fifo_max_dequeue (f))
+ goto rx_start;
+
+ return 0;
}
always_inline void
};
/* *INDENT-ON* */
+static quicly_stream_open_t on_stream_open = { quic_on_stream_open };
+static quicly_closed_by_peer_t on_closed_by_peer = { quic_on_closed_by_peer };
+static quicly_now_t quicly_vpp_now_cb = { quic_get_time };
+
static void
quic_register_cipher_suite (crypto_engine_type_t type,
ptls_cipher_suite_t ** ciphers)
{
quic_main_t *qm = &quic_main;
uword tmp;
+ u32 i;
qm->udp_fifo_size = QUIC_DEFAULT_FIFO_SIZE;
qm->udp_fifo_prealloc = 0;
+ qm->connection_timeout = QUIC_DEFAULT_CONN_TIMEOUT;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "fifo-size %U", unformat_memory_size, &tmp))
{
if (tmp >= 0x100000000ULL)
{
- return clib_error_return
- (0, "fifo-size %llu (0x%llx) too large", tmp, tmp);
+ return clib_error_return (0,
+ "fifo-size %llu (0x%llx) too large",
+ tmp, tmp);
}
qm->udp_fifo_size = tmp;
}
- else
- if (unformat
- (input, "fifo-prealloc %u", &quic_main.udp_fifo_prealloc))
- ;
+ else if (unformat (input, "conn-timeout %u", &i))
+ qm->connection_timeout = i;
+ else if (unformat (input, "fifo-prealloc %u", &i))
+ qm->udp_fifo_prealloc = i;
else
return clib_error_return (0, "unknown input '%U'",
format_unformat_error, input);