]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-h2: create and initialize an rx offset per stream
authorWilly Tarreau <w@1wt.eu>
Tue, 27 Aug 2024 16:57:45 +0000 (18:57 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 12 Oct 2024 14:29:15 +0000 (16:29 +0200)
In H2, everything is accounted as budget. But if we want to moderate
the rcv window that's not very convenient, and we'd rather have offsets
instead so that we know where we are in the stream. Let's first add
the fields to the struct and initialize them. The curr_rx_ofs indicates
the position in the stream where next incoming bytes will be stored.
last_adv_ofs tells what's the offset that was last advertised as the
window limit, and next_max_ofs is the one that will need to be
advertised, which is curr_rx_ofs plus the current window. next_max_ofs
will have to cause a WINDOW_UPDATE to be emitted when it's higher than
last_adv_ofs, and once the WU is sent, its value will have to be copied
over last_adv_ofs.

The problem is, for now wherever we emit a stream WU, we have no notion
of stream (the stream might even not exist anymore, e.g. after aborting
an upload), because we currently keep a counter of stream window to be
acked for the current stream ID (h2c->dsi) in the connection (rcvd_s).
Similarly there are a few places early in the frame header processing
where rcvd_s is incremented without knowing the stream yet. Thus, lookups
will be needed for that, unless such a connection-level counter remains
used and poured into the stream's count once known (delicate).

Thus for now this commit only creates the fields and initializes them.

src/mux_h2.c

index 4699ab84be3af0a760d5211d4e4448e525ca0f83..ffcabc4cbdbd346878e5453a1ab6366d27d2faaf 100644 (file)
@@ -113,6 +113,9 @@ struct h2s {
        enum h2_ss st;
        uint16_t status;     /* HTTP response status */
        unsigned long long body_len; /* remaining body length according to content-length if H2_SF_DATA_CLEN */
+       uint64_t curr_rx_ofs;  /* stream offset at which next FC-data will arrive (includes padding) */
+       uint64_t last_adv_ofs; /* stream offset corresponding to last emitted WU */
+       uint64_t next_max_ofs; /* max stream offset that next WU must permit (curr_rx_ofs+rx_win) */
        struct buffer rxbuf; /* receive buffer, always valid (buf_empty or real buffer) */
        struct wait_event *subs;  /* recv wait_event the stream connector associated is waiting on (via h2_subscribe) */
        struct list list; /* To be used when adding in h2c->send_list or h2c->fctl_lsit */
@@ -1644,6 +1647,7 @@ static void h2s_destroy(struct h2s *h2s)
 static struct h2s *h2s_new(struct h2c *h2c, int id)
 {
        struct h2s *h2s;
+       uint iws;
 
        TRACE_ENTER(H2_EV_H2S_NEW, h2c->conn);
 
@@ -1678,6 +1682,16 @@ static struct h2s *h2s_new(struct h2c *h2c, int id)
        else
                h2c->nb_reserved++;
 
+       /* calculate the max offset permitted by the currently active
+        * initial window size.
+        */
+       iws = (h2c->flags & H2_CF_IS_BACK) ?
+             h2_be_settings_initial_window_size:
+             h2_fe_settings_initial_window_size;
+       iws = iws ? iws : h2_settings_initial_window_size;
+       h2s->last_adv_ofs = h2s->next_max_ofs = iws;
+       h2s->curr_rx_ofs = 0;
+
        eb32_insert(&h2c->streams_by_id, &h2s->by_id);
        h2c->nb_streams++;