@@ -3244,13 +3244,12 @@ static void qc_detach_th_ctx_list(struct quic_conn *qc, int closing)
32443244static int qc_parse_pkt_frms (struct quic_conn * qc , struct quic_rx_packet * pkt ,
32453245 struct quic_enc_level * qel )
32463246{
3247- struct list retry_frms = LIST_HEAD_INIT (retry_frms );
3248- struct quic_frame * frm = NULL , * frm_tmp ;
3247+ struct eb_root cf_frms_tree = EB_ROOT ;
3248+ struct eb64_node * node ;
3249+ struct quic_frame * frm = NULL ;
32493250 const unsigned char * pos , * end ;
32503251 enum quic_rx_ret_frm ret ;
32513252 int fast_retrans = 0 ;
3252- /* parsing may be rerun multiple times, but no more than <iter>. */
3253- int iter = 3 , parsing_stage = 0 ;
32543253
32553254 TRACE_ENTER (QUIC_EV_CONN_PRSHPKT , qc );
32563255 /* Skip the AAD */
@@ -3327,39 +3326,14 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
33273326 break ;
33283327 }
33293328 case QUIC_FT_CRYPTO :
3330- ret = qc_handle_crypto_frm (qc , & frm -> crypto , pkt , qel );
3331- switch (ret ) {
3332- case QUIC_RX_RET_FRM_FATAL :
3333- goto err ;
3334-
3335- case QUIC_RX_RET_FRM_AGAIN :
3336- if (parsing_stage == 0 ) {
3337- TRACE_STATE ("parsing stage set to 1 (AGAIN encountered)" , QUIC_EV_CONN_PRSHPKT , qc );
3338- ++ parsing_stage ;
3339- }
3340- /* Save frame in temp list to reparse it later. A new instance must be used for next packet frames. */
3341- LIST_APPEND (& retry_frms , & frm -> list );
3342- frm = NULL ;
3343- break ;
3344-
3345- case QUIC_RX_RET_FRM_DUP :
3346- if (qc_is_listener (qc ) && qel == & qc -> els [QUIC_TLS_ENC_LEVEL_INITIAL ] &&
3347- !(qc -> flags & QUIC_FL_CONN_HANDSHAKE_SPEED_UP )) {
3348- fast_retrans = 1 ;
3349- }
3350- break ;
3351- case QUIC_RX_RET_FRM_DONE :
3352- if (parsing_stage == 1 ) {
3353- TRACE_STATE ("parsing stage set to 2 (DONE after AGAIN)" , QUIC_EV_CONN_PRSHPKT , qc );
3354- ++ parsing_stage ;
3355- }
3356- break ;
3357- }
3329+ frm -> crypto .offset_node .key = frm -> crypto .offset ;
3330+ eb64_insert (& cf_frms_tree , & frm -> crypto .offset_node );
3331+ frm = NULL ;
33583332 break ;
33593333 case QUIC_FT_NEW_TOKEN :
33603334 if (qc_is_listener (qc )) {
33613335 TRACE_ERROR ("reject NEW_TOKEN frame emitted by client" ,
3362- QUIC_EV_CONN_PRSHPKT , qc );
3336+ QUIC_EV_CONN_PRSHPKT , qc );
33633337
33643338 /* RFC 9000 19.7. NEW_TOKEN Frames
33653339 * Clients MUST NOT send NEW_TOKEN frames. A server MUST treat receipt
@@ -3526,57 +3500,39 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
35263500 if (frm )
35273501 qc_frm_free (& frm );
35283502
3529- while (! LIST_ISEMPTY ( & retry_frms )) {
3530- if ( -- iter <= 0 ) {
3531- TRACE_ERROR ( "interrupt parsing due to max iteration reached" ,
3532- QUIC_EV_CONN_PRSHPKT , qc );
3533- goto err ;
3534- }
3535- else if ( parsing_stage <= 1 ) {
3536- TRACE_ERROR ( "interrupt parsing due to buffering blocked on gap size limit" ,
3537- QUIC_EV_CONN_PRSHPKT , qc );
3503+ node = eb64_first ( & cf_frms_tree );
3504+ while ( node ) {
3505+ frm = eb64_entry ( node , struct quic_frame , crypto . offset_node );
3506+ /* only CRYPTO frames may be reparsed for now */
3507+ BUG_ON ( frm -> type != QUIC_FT_CRYPTO ) ;
3508+ node = eb64_next ( node );
3509+ ret = qc_handle_crypto_frm ( qc , & frm -> crypto , pkt , qel );
3510+ switch ( ret ) {
3511+ case QUIC_RX_RET_FRM_FATAL :
35383512 goto err ;
3539- }
35403513
3541- parsing_stage = 0 ;
3542- list_for_each_entry_safe (frm , frm_tmp , & retry_frms , list ) {
3543- /* only CRYPTO frames may be reparsed for now */
3544- BUG_ON (frm -> type != QUIC_FT_CRYPTO );
3545- ret = qc_handle_crypto_frm (qc , & frm -> crypto , pkt , qel );
3546- switch (ret ) {
3547- case QUIC_RX_RET_FRM_FATAL :
3548- goto err ;
3514+ case QUIC_RX_RET_FRM_AGAIN :
3515+ TRACE_STATE ("AGAIN encountered" , QUIC_EV_CONN_PRSHPKT , qc );
3516+ goto err ;
35493517
3550- case QUIC_RX_RET_FRM_AGAIN :
3551- if (parsing_stage == 0 ) {
3552- TRACE_STATE ("parsing stage set to 1 (AGAIN encountered)" , QUIC_EV_CONN_PRSHPKT , qc );
3553- ++ parsing_stage ;
3554- }
3555- break ;
3518+ case QUIC_RX_RET_FRM_DONE :
3519+ TRACE_PROTO ("frame handled" , QUIC_EV_CONN_PRSAFRM , qc , frm );
3520+ break ;
35563521
3557- case QUIC_RX_RET_FRM_DONE :
3558- TRACE_PROTO ("frame handled after a new parsing iteration" ,
3559- QUIC_EV_CONN_PRSAFRM , qc , frm );
3560- if (parsing_stage == 1 ) {
3561- TRACE_STATE ("parsing stage set to 2 (DONE after AGAIN)" , QUIC_EV_CONN_PRSHPKT , qc );
3562- ++ parsing_stage ;
3563- }
3564- __fallthrough ;
3565- case QUIC_RX_RET_FRM_DUP :
3566- qc_frm_free (& frm );
3567- break ;
3522+ case QUIC_RX_RET_FRM_DUP :
3523+ if (qc_is_listener (qc ) && qel == & qc -> els [QUIC_TLS_ENC_LEVEL_INITIAL ] &&
3524+ !(qc -> flags & QUIC_FL_CONN_HANDSHAKE_SPEED_UP )) {
3525+ fast_retrans = 1 ;
35683526 }
3527+ break ;
35693528 }
35703529
3571- /* Always reset <frm> as it may be dangling after
3572- * list_for_each_entry_safe() usage. Especially necessary to
3573- * prevent a crash if loop is interrupted on max iteration.
3574- */
3575- frm = NULL ;
3530+ eb64_delete (& frm -> crypto .offset_node );
3531+ qc_frm_free (& frm );
35763532 }
35773533
35783534 /* Error should be returned if some frames cannot be parsed. */
3579- BUG_ON (!LIST_ISEMPTY ( & retry_frms ));
3535+ BUG_ON (!eb_is_empty ( & cf_frms_tree ));
35803536
35813537 if (fast_retrans ) {
35823538 struct quic_enc_level * iqel = & qc -> els [QUIC_TLS_ENC_LEVEL_INITIAL ];
@@ -3613,7 +3569,11 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
36133569 err :
36143570 if (frm )
36153571 qc_frm_free (& frm );
3616- list_for_each_entry_safe (frm , frm_tmp , & retry_frms , list ) {
3572+ node = eb64_first (& cf_frms_tree );
3573+ while (node ) {
3574+ frm = eb64_entry (node , struct quic_frame , crypto .offset_node );
3575+ node = eb64_next (node );
3576+ eb64_delete (& frm -> crypto .offset_node );
36173577 qc_frm_free (& frm );
36183578 }
36193579
0 commit comments