16 #include <sys/socket.h> 22 #include <vpp/app/version.h> 23 #include <openssl/pem.h> 29 #include <quicly/streambuf.h> 30 #include <picotls/openssl.h> 31 #include <picotls/pembase64.h> 40 #define QUIC_INT_MAX 0x3FFFFFFFFFFFFFFF 66 memset (ctx, 0,
sizeof (*ctx));
109 ctx->c_thread_index = thread_index;
110 return ctx - qm->
ctx_pool[thread_index];
116 QUIC_DBG (2,
"Free ctx %u", ctx->c_c_index);
117 u32 thread_index = ctx->c_thread_index;
119 memset (ctx, 0xfb,
sizeof (*ctx));
139 QUIC_DBG (2,
"Called quic_disconnect_transport");
160 len = packet->data.len;
170 if (max_enqueue < len)
183 ASSERT (packet->sa.sa_family == AF_INET);
184 struct sockaddr_in *sa4 = (
struct sockaddr_in *) &packet->sa;
186 hdr.
rmt_ip.ip4.as_u32 = sa4->sin_addr.s_addr;
190 ASSERT (packet->sa.sa_family == AF_INET6);
191 struct sockaddr_in6 *sa6 = (
struct sockaddr_in6 *) &packet->sa;
197 ASSERT (rv ==
sizeof (hdr));
207 quicly_datagram_t *packets[16];
210 size_t num_packets,
i;
221 num_packets =
sizeof (packets) /
sizeof (packets[0]);
222 if ((ret = quicly_send (conn, packets, &num_packets)) == 0)
224 for (i = 0; i != num_packets; ++
i)
228 QUIC_DBG (2,
"quic_send_datagram failed");
232 quicly_default_free_packet_cb.cb
233 (&quicly_default_free_packet_cb, packets[i]);
238 QUIC_DBG (2,
"quicly_send returned %d, closing connection\n", ret);
242 while (ret == 0 && num_packets ==
sizeof (packets) /
sizeof (packets[0]));
260 QUIC_DBG (2,
"received STOP_SENDING: %d", error_code);
267 QUIC_DBG (2,
"received RESET_STREAM: %d", error_code);
275 QUIC_DBG (2,
"received data: %lu bytes", len);
276 u32 to_enqueue, ctx_id;
282 ctx_id = (
u64) * quicly_get_data (stream->conn);
285 rx_fifo = app_session->
rx_fifo;
287 if (to_enqueue > len)
301 .on_destroy = quicly_streambuf_destroy,
302 .on_send_shift = quicly_streambuf_egress_shift,
303 .on_send_emit = quicly_streambuf_egress_emit,
312 QUIC_DBG (2,
"on_stream_open called");
315 quicly_streambuf_create (stream,
sizeof (quicly_streambuf_t))) != 0)
327 int code, uint64_t frame_type,
328 const char *reason,
size_t reason_len)
330 QUIC_DBG (2,
"connection closed, reason: %s", reason);
331 u32 ctx_index = (
u64) * quicly_get_data (conn);
352 int is_encrypt, ptls_buffer_t *
dst, ptls_iovec_t
src)
361 free (self->data.base);
362 if ((self->data.base = malloc (src.len)) ==
NULL)
363 return PTLS_ERROR_NO_MEMORY;
365 ptls_get_context (tls)->random_bytes (self->id, sizeof (self->id));
366 memcpy (self->data.base, src.base, src.len);
367 self->data.len = src.len;
370 if ((ret = ptls_buffer_reserve (dst,
sizeof (self->id))) != 0)
372 memcpy (dst->base + dst->off, self->id, sizeof (self->id));
373 dst->off +=
sizeof (
self->id);
380 if (src.len != sizeof (self->id))
381 return PTLS_ERROR_SESSION_NOT_FOUND;
382 if (memcmp (self->id, src.base, sizeof (self->id)) != 0)
383 return PTLS_ERROR_SESSION_NOT_FOUND;
386 if ((ret = ptls_buffer_reserve (dst, self->data.len)) != 0)
388 memcpy (dst->base + dst->off, self->data.base, self->data.len);
389 dst->off +=
self->data.len;
403 .random_bytes = ptls_openssl_random_bytes,
404 .get_time = &ptls_get_time,
405 .key_exchanges = ptls_openssl_key_exchanges,
406 .cipher_suites = ptls_openssl_cipher_suites,
412 .on_client_hello =
NULL,
413 .emit_certificate =
NULL,
414 .sign_certificate =
NULL,
415 .verify_certificate =
NULL,
416 .ticket_lifetime = 86400,
417 .max_early_data_size = 8192,
418 .hkdf_label_prefix__obsolete =
NULL,
419 .require_dhe_on_psk = 1,
420 .encrypt_ticket = &sc.
super,
428 int ret = strncmp (line,
"-----", 5);
429 size_t text_index = 5;
433 size_t begin_or_end_length = strlen (begin_or_end);
434 ret = strncmp (line + text_index, begin_or_end, begin_or_end_length);
435 text_index += begin_or_end_length;
440 ret = line[text_index] -
' ';
446 size_t label_length = strlen (label);
447 ret = strncmp (line + text_index, label, label_length);
448 text_index += label_length;
453 ret = strncmp (line + text_index,
"-----", 5);
462 int ret = PTLS_ERROR_PEM_LABEL_NOT_FOUND;
464 ptls_base64_decode_state_t
state;
467 while (BIO_gets (bio, line, 256))
472 ptls_base64_decode_init (&state);
477 while (ret == 0 && BIO_gets (bio, line, 256))
481 if (state.status == PTLS_BASE64_DECODE_DONE
482 || (state.status == PTLS_BASE64_DECODE_IN_PROGRESS
489 ret = PTLS_ERROR_INCORRECT_BASE64;
495 ret = ptls_base64_decode (line, &state, buf);
504 size_t list_max,
size_t * nb_objects)
513 while (count < list_max)
517 ptls_buffer_init (&buf,
"", 0);
523 if (buf.off > 0 && buf.is_allocated)
525 list[
count].base = buf.base;
526 list[
count].len = buf.off;
531 ptls_buffer_dispose (&buf);
536 ptls_buffer_dispose (&buf);
542 if (ret == PTLS_ERROR_PEM_LABEL_NOT_FOUND && count > 0)
552 #define PTLS_MAX_CERTS_IN_CONTEXT 16 559 ctx->certificates.list =
561 sizeof (ptls_iovec_t));
563 if (ctx->certificates.list ==
NULL)
565 ret = PTLS_ERROR_NO_MEMORY;
572 &ctx->certificates.count);
582 cert_bio = BIO_new_mem_buf (cert_data, -1);
586 fprintf (stderr,
"failed to load certificate:%s\n", strerror (errno));
595 static ptls_openssl_sign_certificate_t
sc;
599 key_bio = BIO_new_mem_buf (pk_data, -1);
600 pkey = PEM_read_bio_PrivateKey (key_bio,
NULL,
NULL,
NULL);
605 fprintf (stderr,
"failed to read private key from app configuration\n");
609 ptls_openssl_init_sign_certificate (&sc, pkey);
610 EVP_PKEY_free (pkey);
612 ctx->sign_certificate = &sc.super;
618 QUIC_DBG (2,
"QUIC connection closed");
638 return (int64_t) (time * 1000.f);
645 QUIC_DBG (2,
"Called allocate_quicly_ctx");
651 quicly_context_t *quicly_ctx;
654 ctx_data = malloc (
sizeof (*ctx_data));
655 quicly_ctx = &ctx_data->_;
657 memcpy (quicly_ctx, &quicly_default_context,
sizeof (quicly_context_t));
664 quicly_amend_ptls_context (quicly_ctx->tls);
666 quicly_ctx->event_log.mask = INT64_MAX;
667 quicly_ctx->event_log.cb = quicly_new_default_event_log_cb (stderr);
670 quicly_ctx->transport_params.max_streams_uni =
QUIC_INT_MAX;
671 quicly_ctx->transport_params.max_streams_bidi =
QUIC_INT_MAX;
672 quicly_ctx->transport_params.max_stream_data.bidi_local =
QUIC_INT_MAX;
673 quicly_ctx->transport_params.max_stream_data.bidi_remote =
QUIC_INT_MAX;
674 quicly_ctx->transport_params.max_stream_data.uni =
QUIC_INT_MAX;
680 cid_key = ctx_data->cid_key;
681 quicly_ctx->tls->random_bytes (cid_key, 16);
683 quicly_ctx->encrypt_cid =
684 quicly_new_default_encrypt_cid_cb (&ptls_openssl_bfecb,
685 &ptls_openssl_sha256,
686 ptls_iovec_init (cid_key,
689 quicly_ctx->decrypt_cid =
690 quicly_new_default_decrypt_cid_cb (&ptls_openssl_bfecb,
691 &ptls_openssl_sha256,
692 ptls_iovec_init (cid_key,
714 QUIC_DBG (2,
"Timer expired for conn %u at %ld", conn_index,
727 tw_timer_wheel_1t_3w_1024sl_ov_t *tw;
728 int64_t next_timeout;
731 next_timeout = quicly_get_first_timeout (ctx->
c_quic_ctx_id.conn);
733 f64 next_timeout_f = ((
f64) next_timeout) / 1000.f;
735 clib_warning (
"Timer set to %ld (%lf)", next_timeout, next_timeout_f);
739 if (next_timeout == INT64_MAX)
742 tw_timer_start_1t_3w_1024sl_ov (tw, ctx->c_c_index, 0,
747 if (next_timeout == INT64_MAX)
749 tw_timer_stop_1t_3w_1024sl_ov (tw, ctx->
c_quic_ctx_id.timer_handle);
753 tw_timer_update_1t_3w_1024sl_ov (tw, ctx->
c_quic_ctx_id.timer_handle,
763 for (i = 0; i <
vec_len (expired_timers); i++)
779 QUIC_DBG (2,
"Called quic_connect");
793 ctx->c_s_index = 0xFAFAFAFA;
815 cargs->api_context = ctx_index;
820 cargs->sep_ext.ns_index = app->
ns_index;
827 QUIC_DBG (1,
"New connect request %u", ctx_index);
834 QUIC_DBG (2,
"Called quic_disconnect");
835 tw_timer_wheel_1t_3w_1024sl_ov_t *tw;
838 QUIC_DBG (1,
"Disconnecting %x", ctx_index);
844 tw_timer_stop_1t_3w_1024sl_ov (tw, ctx->
c_quic_ctx_id.timer_handle);
855 QUIC_DBG (2,
"Called quic_start_listen");
860 session_t *quic_listen_session, *app_listen_session;
874 memset (args, 0,
sizeof (*args));
876 args->sep_ext = *sep;
877 args->sep_ext.ns_index = app->
ns_index;
882 udp_handle = args->handle;
885 quic_listen_session->
opaque = lctx_index;
898 QUIC_DBG (1,
"Started listening %d", lctx_index);
905 QUIC_DBG (2,
"Called quic_stop_listen");
926 QUIC_DBG (2,
"Called quic_connection_get");
935 QUIC_DBG (2,
"Called quic_listener_get");
944 tw_timer_wheel_1t_3w_1024sl_ov_t *tw;
948 tw_timer_expire_timers_1t_3w_1024sl_ov (tw, now);
954 s =
format (s,
"[QUIC] connection");
961 u32 qc_index = va_arg (*args,
u32);
972 s =
format (s,
"[QUIC] listener");
985 ip46_address_t *
addr,
u16 port,
u8 is_ip4)
989 struct sockaddr_in *sa4 = (
struct sockaddr_in *) sa;
990 sa4->sin_family = AF_INET;
991 sa4->sin_port = port;
992 sa4->sin_addr.s_addr = addr->ip4.as_u32;
993 *salen =
sizeof (
struct sockaddr_in);
997 struct sockaddr_in6 *sa6 = (
struct sockaddr_in6 *) sa;
998 sa6->sin6_family = AF_INET6;
999 sa6->sin6_port = port;
1001 *salen =
sizeof (
struct sockaddr_in6);
1008 QUIC_DBG (1,
"quic_notify_app_connected");
1039 QUIC_DBG (1,
"failed to notify app");
1056 QUIC_DBG (2,
"Called quic_session_connected_callback");
1059 struct sockaddr_in6 sa6;
1060 struct sockaddr *sa = (
struct sockaddr *) &sa6;
1079 api_context = ho_ctx->c_s_index;
1103 ctx->c_c_index = ctx_index;
1105 QUIC_DBG (1,
"Quic connect for returned %u. New connection [%u]%x",
1156 QUIC_DBG (2,
"Called quic_add_segment_callback");
1165 QUIC_DBG (2,
"Called quic_del_segment_callback");
1186 QUIC_DBG (2,
"----------- > FOUND Stream id %d",
1188 QUIC_DBG (2,
"----------- > FOUND Stream is_open %d",
1189 ctx->
stream->sendstate.is_open);
1192 if (quicly_connection_is_ready (conn))
1195 QUIC_DBG (2,
"Stream is_open %d", ctx->
stream->sendstate.is_open);
1201 QUIC_DBG (2,
"Called quic_custom_tx_callback");
1225 if (quicly_streambuf_egress_write (ctx->
stream, data, deq_max))
1230 QUIC_DBG (2,
"Sent %u bytes", deq_max);
1241 struct sockaddr *sa, socklen_t salen,
1242 quicly_decoded_packet_t packet)
1245 quicly_conn_t *conn_;
1252 if (quicly_is_destination(conn_, sa, salen, &packet))
1256 QUIC_DBG (2,
"connection_found");
1267 quicly_decoded_packet_t packet)
1269 quicly_receive (conn, &packet);
1274 if (quicly_connection_is_ready (conn))
1277 if (quicly_is_client (conn))
1295 session_t *app_session, *app_listen_session;
1306 app_listen_session =
1317 QUIC_DBG (1,
"failed to allocate fifos");
1331 QUIC_DBG (1,
"failed to notify accept worker app");
1339 u64 quic_session_handle,
u32 lctx_index,
1340 quicly_conn_t * conn,
struct sockaddr *sa,
1341 socklen_t salen, quicly_decoded_packet_t packet)
1348 QUIC_DBG (2,
"New connection created");
1349 if (quicly_accept (&conn, quicly_ctx, sa, salen,
1350 &packet, ptls_iovec_init (
NULL, 0),
1365 *quicly_get_data (conn) = (
void *) (
u64) ctx_index;
1368 ctx->c_c_index = ctx_index;
1376 (
void *) (
u64) ctx_index);
1386 struct sockaddr *sa, socklen_t salen,
1387 quicly_decoded_packet_t packet)
1392 QUIC_DBG (2,
"Sending stateless reset");
1393 quicly_datagram_t *dgram;
1395 if (packet.cid.dest.plaintext.node_id == 0
1396 && packet.cid.dest.plaintext.thread_id == 0)
1398 dgram = quicly_send_stateless_reset (quicly_ctx, sa, salen,
1399 &packet.cid.dest.plaintext);
1411 QUIC_DBG (2,
"Called quic_app_rx_callback");
1413 quicly_decoded_packet_t packet;
1416 quicly_conn_t *conn =
NULL;
1420 struct sockaddr_in6 sa6;
1421 struct sockaddr *sa = (
struct sockaddr *) &sa6;
1443 ASSERT (ph.data_length >= ph.data_offset);
1444 len = ph.data_length - ph.data_offset;
1456 quicly_decode_packet ((quicly_context_t *) app->
quicly_ctx, &packet,
1458 if (plen != SIZE_MAX)
1463 else if (QUICLY_PACKET_IS_LONG_HEADER (packet.octets.base[0]))
1465 quic_session_handle, lctx_index, conn,
1467 else if (((quicly_context_t *) app->
quicly_ctx)->encrypt_cid)
1469 quic_session_handle, sa, salen, packet);
1472 ph.data_length + ph.data_offset +
1515 u32 add_segment_size = (4096ULL << 20) - 1, segment_size = 512 << 20;
1520 u32 fifo_size = 64 << 10;
1525 memset (a, 0,
sizeof (*a));
1526 memset (options, 0,
sizeof (options));
1530 a->options = options;
1531 a->name =
format (0,
"quic");
1549 tw_timer_wheel_1t_3w_1024sl_ov_t *tw;
1587 .version = VPP_BUILD_VER,
1588 .description =
"Quic Transport Protocol",
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
static void clib_rwlock_reader_lock(clib_rwlock_t *p)
static int quic_delayed_create_app_session(void *ctx_index)
int app_worker_lock_and_send_event(app_worker_t *app, session_t *s, u8 evt_type)
Send event to application.
u32 connection_index
Index of the transport connection associated to the session.
int app_worker_init_accepted(session_t *s)
int quic_find_packet_ctx(quic_ctx_t **ctx, quicly_conn_t **conn, struct sockaddr *sa, socklen_t salen, quicly_decoded_packet_t packet)
session_type_t session_type
Type built from transport and network protocol types.
quic_worker_ctx_t * wrk_ctx
static void clib_rwlock_writer_lock(clib_rwlock_t *p)
int ptls_load_bio_certificates(ptls_context_t *ctx, BIO *bio)
u32 ns_index
Namespace the application belongs to.
clib_rwlock_t half_open_rwlock
quicly_cid_plaintext_t next_cid
struct _vnet_connect_args vnet_connect_args_t
int quic_add_vpp_q_builtin_tx_evt(session_t *s)
static void load_bio_certificate_chain(ptls_context_t *ctx, const char *cert_data)
int quic_session_accepted_callback(session_t *s)
struct _vnet_unlisten_args_t vnet_unlisten_args_t
#define QUIC_TSTAMP_RESOLUTION
u32 session_index
Index in thread pool where session was allocated.
#define QUIC_CONN_STATE_READY
ptls_encrypt_ticket_t super
void session_transport_delete_notify(transport_connection_t *tc)
Notification from transport that connection is being deleted.
transport_connection_t * session_get_transport(session_t *s)
static f64 vlib_time_now(vlib_main_t *vm)
svm_fifo_t * rx_fifo
Pointers to rx/tx buffers.
u32 quic_ctx_half_open_index(quic_ctx_t *ctx)
static int quic_on_receive(quicly_stream_t *stream, size_t off, const void *src, size_t len)
static void load_bio_private_key(ptls_context_t *ctx, const char *pk_data)
static session_t * listen_session_get_from_handle(session_handle_t handle)
#define pool_get_aligned_will_expand(P, YESNO, A)
See if pool_get will expand the pool or not.
#define vec_terminate_c_string(V)
(If necessary) NULL terminate a vector containing a c-string.
static int quic_send_datagram(session_t *session, quicly_datagram_t *packet)
static void quic_build_sockaddr(struct sockaddr *sa, socklen_t *salen, ip46_address_t *addr, u16 port, u8 is_ip4)
static quic_ctx_t * quic_ctx_get_w_thread(u32 ctx_index, u8 thread_index)
static u32 svm_fifo_max_enqueue(svm_fifo_t *f)
int vnet_unlisten(vnet_unlisten_args_t *a)
static void quic_timer_expired(u32 conn_index)
f64 tstamp_ticks_per_clock
static int ptls_compare_separator_line(const char *line, const char *begin_or_end, const char *label)
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
transport_connection_t * quic_listener_get(u32 listener_index)
static void quic_expired_timers_dispatch(u32 *expired_timers)
int quic_connect(transport_endpoint_cfg_t *tep)
#define QUIC_DBG(_lvl, _fmt, _args...)
struct _vnet_bind_args_t vnet_listen_args_t
static session_handle_t session_handle(session_t *s)
struct _svm_fifo svm_fifo_t
#define clib_memcpy(d, s, n)
static int quic_on_stream_open(quicly_stream_open_cb *self, quicly_stream_t *stream)
int quic_session_connected_callback(u32 quic_app_index, u32 ho_ctx_idx, session_t *s, u8 is_fail)
int quic_app_rx_callback(session_t *quic_session)
void session_transport_closing_notify(transport_connection_t *tc)
Notification from transport that connection is being closed.
static int quic_reset_connection(quicly_context_t *quicly_ctx, u64 quic_session_handle, struct sockaddr *sa, socklen_t salen, quicly_decoded_packet_t packet)
static int quic_send_packets(quic_ctx_t *ctx)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
#define VLIB_INIT_FUNCTION(x)
struct _vnet_disconnect_args_t vnet_disconnect_args_t
static u32 svm_fifo_max_dequeue(svm_fifo_t *f)
#define clib_error_return(e, args...)
static const transport_proto_vft_t quic_proto
int svm_fifo_enqueue_nowait(svm_fifo_t *f, u32 max_bytes, const u8 *copy_from_here)
vhost_vring_state_t state
static int encrypt_ticket_cb(ptls_encrypt_ticket_t *_self, ptls_t *tls, int is_encrypt, ptls_buffer_t *dst, ptls_iovec_t src)
int session_send_io_evt_to_thread(svm_fifo_t *f, session_evt_type_t evt_type)
ptls_handshake_properties_t hs_properties
static u8 * svm_fifo_head(svm_fifo_t *f)
quicly_now_cb quicly_vpp_now_cb
#define FIFO_EVENT_APP_TX
struct _vnet_app_attach_args_t vnet_app_attach_args_t
struct _transport_proto_vft transport_proto_vft_t
struct _session_endpoint_cfg session_endpoint_cfg_t
#define QUIC_TIMER_HANDLE_INVALID
#define QUIC_DEFAULT_CA_CERT_PATH
static session_type_t session_type_from_proto_and_ip(transport_proto_t proto, u8 is_ip4)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
static void clib_rwlock_init(clib_rwlock_t *p)
void session_send_rpc_evt_to_thread_force(u32 thread_index, void *fp, void *rpc_args)
quic_ctx_id_t c_quic_ctx_id
static void clib_rwlock_reader_unlock(clib_rwlock_t *p)
int app_worker_accept_notify(app_worker_t *app_wrk, session_t *s)
static session_t * session_get_from_handle(session_handle_t handle)
session_t * app_listener_get_session(app_listener_t *al)
static u32 quic_set_time_now(u32 thread_index)
static void allocate_quicly_ctx(application_t *app, u8 is_client)
u32 app_index
Index of application that owns the listener.
#define pool_put(P, E)
Free an object E in pool P.
#define APP_INVALID_INDEX
static u8 * format_quic_connection(u8 *s, va_list *args)
int ptls_load_bio_pem_objects(BIO *bio, const char *label, ptls_iovec_t *list, size_t list_max, size_t *nb_objects)
static void svm_fifo_unset_event(svm_fifo_t *f)
Unsets fifo event flag.
static void quic_disconnect(u32 ctx_index, u32 thread_index)
app_worker_t * app_worker_get_if_valid(u32 wrk_index)
static quicly_stream_open_cb on_stream_open
#define foreach_vlib_main(body)
u32 quic_start_listen(u32 app_listen_session_index, transport_endpoint_t *tep)
static u64 listen_session_get_handle(session_t *s)
int vnet_application_attach(vnet_app_attach_args_t *a)
Attach application to vpp.
static u8 svm_fifo_set_event(svm_fifo_t *f)
Sets fifo event flag.
static void clib_rwlock_writer_unlock(clib_rwlock_t *p)
transport_connection_t connection
#define QUIC_CONN_STATE_HANDSHAKE
transport_connection_t * quic_connection_get(u32 ctx_index, u32 thread_index)
static_always_inline uword vlib_get_thread_index(void)
int quic_custom_tx_callback(void *session)
quic_main_t * vnet_quic_get_main(void)
#define PTLS_MAX_CERTS_IN_CONTEXT
static clib_error_t * quic_init(vlib_main_t *vm)
#define vec_free(V)
Free vector's memory (no header).
#define SESSION_CONN_HDR_LEN
void session_free(session_t *s)
#define clib_warning(format, args...)
struct _stream_session_cb_vft session_cb_vft_t
static quic_main_t quic_main
struct _transport_connection transport_connection_t
static quic_ctx_t * quic_ctx_get(u32 ctx_index)
static int quic_add_segment_callback(u32 client_index, u64 seg_handle)
int app_worker_init_connected(app_worker_t *app_wrk, session_t *s)
void quic_ctx_half_open_free(u32 ho_index)
static int quic_create_connection(quicly_context_t *quicly_ctx, u64 quic_session_handle, u32 lctx_index, quicly_conn_t *conn, struct sockaddr *sa, socklen_t salen, quicly_decoded_packet_t packet)
static void quic_update_time(f64 now, u8 thread_index)
tw_timer_wheel_1t_3w_1024sl_ov_t timer_wheel
worker timer wheel
application_t * application_get(u32 app_index)
static void quic_update_timer(quic_ctx_t *ctx)
void transport_register_protocol(transport_proto_t transport_proto, const transport_proto_vft_t *vft, fib_protocol_t fib_proto, u32 output_node)
Register transport virtual function table.
#define FIFO_EVENT_BUILTIN_TX
apps acting as transports
app_listener_t * app_listener_get_w_handle(session_handle_t handle)
static int quic_del_segment_callback(u32 client_index, u64 seg_handle)
#define pool_put_index(p, i)
Free pool element with given index.
static quicly_closed_by_peer_cb on_closed_by_peer
void quic_open_stream_if_ready(quic_ctx_t *ctx)
int vnet_listen(vnet_listen_args_t *a)
static u8 * format_quic_listener(u8 *s, va_list *args)
static void quic_connection_closed(u32 conn_index)
u8 * tls_key
PEM encoded key.
static int64_t quic_get_time(quicly_now_cb *self)
int vnet_connect(vnet_connect_args_t *a)
static vlib_main_t * vlib_get_main(void)
u8 thread_index
Index of the thread that allocated the session.
static int quic_on_stop_sending(quicly_stream_t *stream, int error_code)
session_t * session_alloc(u32 thread_index)
int vlib_main(vlib_main_t *volatile vm, unformat_input_t *input)
static void quic_disconnect_transport(quic_ctx_t *ctx)
static ptls_context_t quic_tlsctx
static session_cb_vft_t quic_app_cb_vft
void quic_ctx_half_open_reader_unlock()
int svm_fifo_dequeue_drop(svm_fifo_t *f, u32 max_bytes)
void quic_session_disconnect_callback(session_t *s)
static int quic_on_receive_reset(quicly_stream_t *stream, int error_code)
app_worker_t * app_worker_get(u32 wrk_index)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
volatile u8 session_state
State in session layer state machine.
u32 quic_stop_listen(u32 lctx_index)
u32 opaque
Opaque, for general use.
void quic_session_reset_callback(session_t *s)
int vnet_disconnect_session(vnet_disconnect_args_t *a)
static int quic_receive(quic_ctx_t *ctx, quicly_conn_t *conn, quicly_decoded_packet_t packet)
int session_send_io_evt_to_thread_custom(void *data, u32 thread_index, session_evt_type_t evt_type)
u32 quic_ctx_half_open_alloc(void)
u32 app_index
Index of owning app.
int session_lookup_add_connection(transport_connection_t *tc, u64 value)
Add transport connection to a session table.
static void quic_ctx_free(quic_ctx_t *ctx)
static struct st_util_session_cache_t sc
static vlib_thread_main_t * vlib_get_thread_main()
static u32 vlib_num_workers()
u8 * tls_cert
Certificate to be used for listen sessions.
u32 app_wrk_index
Index of the app worker that owns the session.
static int quic_delayed_notify_app_connected(void *ctx_index)
int svm_fifo_peek(svm_fifo_t *f, u32 relative_offset, u32 max_bytes, u8 *copy_here)
int app_worker_connect_notify(app_worker_t *app_wrk, session_t *s, u32 opaque)
struct session_dgram_header_ session_dgram_hdr_t
static int ptls_get_bio_pem_object(BIO *bio, const char *label, ptls_buffer_t *buf)
static const quicly_stream_callbacks_t quic_stream_callbacks
static u8 * format_quic_half_open(u8 *s, va_list *args)
static session_t * listen_session_get(u32 ls_index)
quic_ctx_t * quic_ctx_half_open_get(u32 ctx_index)
u32 listener_index
Parent listener session index if the result of an accept.
quic_ctx_t * half_open_ctx_pool
static void quic_on_conn_close(quicly_closed_by_peer_cb *self, quicly_conn_t *conn, int code, uint64_t frame_type, const char *reason, size_t reason_len)