+/* Crypto contexts */
+
+static inline void
+quic_crypto_context_make_key_from_ctx (clib_bihash_kv_24_8_t * kv,
+ quic_ctx_t * ctx)
+{
+ application_t *app = application_get (ctx->parent_app_id);
+ kv->key[0] = ((u64) ctx->ckpair_index) << 32 | (u64) ctx->crypto_engine;
+ kv->key[1] = app->sm_properties.rx_fifo_size - 1;
+ kv->key[2] = app->sm_properties.tx_fifo_size - 1;
+}
+
+static inline void
+quic_crypto_context_make_key_from_crctx (clib_bihash_kv_24_8_t * kv,
+ crypto_context_t * crctx)
+{
+ quic_crypto_context_data_t *data =
+ (quic_crypto_context_data_t *) crctx->data;
+ kv->key[0] = ((u64) crctx->ckpair_index) << 32 | (u64) crctx->crypto_engine;
+ kv->key[1] = data->quicly_ctx.transport_params.max_stream_data.bidi_local;
+ kv->key[2] = data->quicly_ctx.transport_params.max_stream_data.bidi_remote;
+}
+
+static void
+quic_crypto_context_free_if_needed (crypto_context_t * crctx, u8 thread_index)
+{
+ quic_main_t *qm = &quic_main;
+ clib_bihash_kv_24_8_t kv;
+ if (crctx->n_subscribers)
+ return;
+ quic_crypto_context_make_key_from_crctx (&kv, crctx);
+ clib_bihash_add_del_24_8 (&qm->wrk_ctx[thread_index].crypto_context_hash,
+ &kv, 0 /* is_add */ );
+ clib_mem_free (crctx->data);
+ pool_put (qm->wrk_ctx[thread_index].crypto_ctx_pool, crctx);
+}
+
+static quicly_datagram_t *
+quic_alloc_packet (quicly_packet_allocator_t * self, size_t payloadsize)
+{
+ quicly_datagram_t *packet;
+ if ((packet =
+ clib_mem_alloc (sizeof (*packet) + payloadsize +
+ sizeof (quic_encrypt_cb_ctx))) == NULL)
+ return NULL;
+ packet->data.base =
+ (uint8_t *) packet + sizeof (*packet) + sizeof (quic_encrypt_cb_ctx);
+ quic_encrypt_cb_ctx *encrypt_cb_ctx =
+ (quic_encrypt_cb_ctx *) ((uint8_t *) packet + sizeof (*packet));
+
+ clib_memset (encrypt_cb_ctx, 0, sizeof (*encrypt_cb_ctx));
+ return packet;
+}
+
+static void
+quic_free_packet (quicly_packet_allocator_t * self,
+ quicly_datagram_t * packet)
+{
+ clib_mem_free (packet);
+}
+
+quicly_packet_allocator_t quic_packet_allocator =
+ { quic_alloc_packet, quic_free_packet };
+