@@ -487,12 +487,12 @@ int qc_send_mux(struct quic_conn *qc, struct list *frms)
487487 qc -> state >= QUIC_HS_ST_COMPLETE ) {
488488 quic_build_post_handshake_frames (qc );
489489 qel_register_send (& send_list , qc -> ael , & qc -> ael -> pktns -> tx .frms );
490- qc_send (qc , 0 , & send_list );
490+ qc_send (qc , 0 , & send_list , NULL );
491491 }
492492
493493 TRACE_STATE ("preparing data (from MUX)" , QUIC_EV_CONN_TXPKT , qc );
494494 qel_register_send (& send_list , qc -> ael , frms );
495- ret = qc_send (qc , 0 , & send_list );
495+ ret = qc_send (qc , 0 , & send_list , NULL );
496496
497497 TRACE_LEAVE (QUIC_EV_CONN_TXPKT , qc );
498498 return ret ;
@@ -530,7 +530,7 @@ static inline void qc_select_tls_ver(struct quic_conn *qc,
530530 * (may be 0), or -1 if something wrong happened.
531531 */
532532static int qc_prep_pkts (struct quic_conn * qc , struct buffer * buf ,
533- struct list * qels )
533+ struct list * qels , int * max_pkts )
534534{
535535 int ret , cc , padding ;
536536 struct quic_tx_packet * first_pkt , * prv_pkt ;
@@ -547,6 +547,8 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
547547 */
548548 BUG_ON_HOT (buf -> head || buf -> data );
549549
550+ BUG_ON (max_pkts && * max_pkts <= 0 );
551+
550552 ret = -1 ;
551553 cc = qc -> flags & QUIC_FL_CONN_IMMEDIATE_CLOSE ;
552554 padding = 0 ;
@@ -589,6 +591,15 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
589591
590592 TRACE_PROTO ("TX prep pkts" , QUIC_EV_CONN_PHPKTS , qc , qel );
591593
594+ /* Start to decrement <max_pkts> after the first packet built. */
595+ if (!dglen && pos != (unsigned char * )b_head (buf )) {
596+ if (max_pkts && !-- (* max_pkts )) {
597+ BUG_ON (LIST_ISEMPTY (frms ));
598+ TRACE_PROTO ("reached max allowed built datagrams" , QUIC_EV_CONN_PHPKTS , qc , qel );
599+ goto out ;
600+ }
601+ }
602+
592603 if (!first_pkt )
593604 pos += QUIC_DGRAM_HEADLEN ;
594605
@@ -764,7 +775,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
764775* Returns 1 on success else 0. Note that <send_list> will always be reset
765776* after qc_send() exit.
766777 */
767- int qc_send (struct quic_conn * qc , int old_data , struct list * send_list )
778+ int qc_send (struct quic_conn * qc , int old_data , struct list * send_list , int * max_pkts )
768779{
769780 struct quic_enc_level * qel , * tmp_qel ;
770781 int ret = 0 , status = 0 ;
@@ -801,7 +812,7 @@ int qc_send(struct quic_conn *qc, int old_data, struct list *send_list)
801812 BUG_ON_HOT (b_data (buf ));
802813 b_reset (buf );
803814
804- ret = qc_prep_pkts (qc , buf , send_list );
815+ ret = qc_prep_pkts (qc , buf , send_list , max_pkts );
805816
806817 if (b_data (buf ) && !qc_send_ppkts (buf , qc -> xprt_ctx )) {
807818 if (qc -> flags & QUIC_FL_CONN_TO_KILL )
@@ -814,6 +825,11 @@ int qc_send(struct quic_conn *qc, int old_data, struct list *send_list)
814825 break ;
815826 }
816827
828+ if (max_pkts && !* max_pkts ) {
829+ TRACE_DEVEL ("stopping for artificial pacing" , QUIC_EV_CONN_TXPKT , qc );
830+ break ;
831+ }
832+
817833 if ((qc -> flags & QUIC_FL_CONN_DRAINING ) &&
818834 !(qc -> flags & QUIC_FL_CONN_IMMEDIATE_CLOSE )) {
819835 TRACE_DEVEL ("draining connection" , QUIC_EV_CONN_TXPKT , qc );
@@ -904,7 +920,7 @@ int qc_dgrams_retransmit(struct quic_conn *qc)
904920 if (qc -> hel )
905921 qel_register_send (& send_list , qc -> hel , & hfrms );
906922
907- sret = qc_send (qc , 1 , & send_list );
923+ sret = qc_send (qc , 1 , & send_list , NULL );
908924 qc_free_frm_list (qc , & ifrms );
909925 qc_free_frm_list (qc , & hfrms );
910926 if (!sret )
@@ -917,7 +933,7 @@ int qc_dgrams_retransmit(struct quic_conn *qc)
917933 */
918934 ipktns -> tx .pto_probe = 1 ;
919935 qel_register_send (& send_list , qc -> iel , & ifrms );
920- sret = qc_send (qc , 0 , & send_list );
936+ sret = qc_send (qc , 0 , & send_list , NULL );
921937 qc_free_frm_list (qc , & ifrms );
922938 qc_free_frm_list (qc , & hfrms );
923939 if (!sret )
@@ -946,7 +962,7 @@ int qc_dgrams_retransmit(struct quic_conn *qc)
946962 if (!LIST_ISEMPTY (& frms1 )) {
947963 hpktns -> tx .pto_probe = 1 ;
948964 qel_register_send (& send_list , qc -> hel , & frms1 );
949- sret = qc_send (qc , 1 , & send_list );
965+ sret = qc_send (qc , 1 , & send_list , NULL );
950966 qc_free_frm_list (qc , & frms1 );
951967 if (!sret )
952968 goto leave ;
@@ -969,7 +985,7 @@ int qc_dgrams_retransmit(struct quic_conn *qc)
969985 if (!LIST_ISEMPTY (& frms1 )) {
970986 apktns -> tx .pto_probe = 1 ;
971987 qel_register_send (& send_list , qc -> ael , & frms1 );
972- sret = qc_send (qc , 1 , & send_list );
988+ sret = qc_send (qc , 1 , & send_list , NULL );
973989 qc_free_frm_list (qc , & frms1 );
974990 if (!sret ) {
975991 qc_free_frm_list (qc , & frms2 );
@@ -980,7 +996,7 @@ int qc_dgrams_retransmit(struct quic_conn *qc)
980996 if (!LIST_ISEMPTY (& frms2 )) {
981997 apktns -> tx .pto_probe = 1 ;
982998 qel_register_send (& send_list , qc -> ael , & frms2 );
983- sret = qc_send (qc , 1 , & send_list );
999+ sret = qc_send (qc , 1 , & send_list , NULL );
9841000 qc_free_frm_list (qc , & frms2 );
9851001 if (!sret )
9861002 goto leave ;
0 commit comments