http: req_state_udp_tunnel_tx fix 41/43541/2
authorMatus Fabian <[email protected]>
Wed, 13 Aug 2025 14:10:08 +0000 (10:10 -0400)
committerMatus Fabian <[email protected]>
Thu, 14 Aug 2025 19:30:03 +0000 (15:30 -0400)
Type: fix

Change-Id: Ibf7afb69ba709dd28254807a34644ecc5bf892e8
Signed-off-by: Matus Fabian <[email protected]>
src/plugins/http/http1.c
src/plugins/http/http2/http2.c
src/plugins/http/http_private.h

index 146ee8d..9d458aa 100644 (file)
@@ -1706,7 +1706,7 @@ http1_req_state_udp_tunnel_tx (http_conn_t *hc, http_req_t *req,
   while (to_deq > 0)
     {
       /* read datagram header */
-      http_io_as_read (req, (u8 *) &hdr, sizeof (hdr), 1);
+      http_io_as_peek (req, (u8 *) &hdr, sizeof (hdr), 0);
       ASSERT (hdr.data_length <= HTTP_UDP_PAYLOAD_MAX_LEN);
       dgram_size = hdr.data_length + SESSION_CONN_HDR_LEN;
       ASSERT (to_deq >= dgram_size);
@@ -1722,7 +1722,7 @@ http1_req_state_udp_tunnel_tx (http_conn_t *hc, http_req_t *req,
       payload = http_encap_udp_payload_datagram (buf, hdr.data_length);
       capsule_size = (payload - buf) + hdr.data_length;
       /* read payload */
-      http_io_as_read (req, payload, hdr.data_length, 1);
+      http_io_as_peek (req, payload, hdr.data_length, sizeof (hdr));
       http_io_as_drain (req, dgram_size);
       /* send capsule */
       http_io_ts_write (hc, buf, capsule_size, sp);
index b56518a..fb70613 100644 (file)
@@ -719,6 +719,7 @@ http2_sched_dispatch_tunnel (http2_req_t *req, http_conn_t *hc,
   http_io_as_drain (&req->base, n_written);
   req->peer_window -= n_written;
   h2c->peer_window -= n_written;
+  HTTP_DBG (1, "written %lu", n_written);
 
   if (req->peer_window == 0)
     {
@@ -759,7 +760,8 @@ http2_sched_dispatch_udp_tunnel (http2_req_t *req, http_conn_t *hc,
       return;
     }
   /* read datagram header */
-  http_io_as_read (&req->base, (u8 *) &hdr, sizeof (hdr), 1);
+  http_io_as_peek (&req->base, (u8 *) &hdr, sizeof (hdr), 0);
+  HTTP_DBG (1, "datagram len %lu", hdr.data_length);
   ASSERT (hdr.data_length <= HTTP_UDP_PAYLOAD_MAX_LEN);
   dgram_size = hdr.data_length + SESSION_CONN_HDR_LEN;
   ASSERT (max_read >= dgram_size);
@@ -771,7 +773,7 @@ http2_sched_dispatch_udp_tunnel (http2_req_t *req, http_conn_t *hc,
        h2c->peer_settings.max_frame_size))
     {
       /* drop datagram if not fit into frame */
-      HTTP_DBG (1, "datagram too large, dropped");
+      HTTP_DBG (1, "datagram larger than maximum frame size, dropped");
       http_io_as_drain (&req->base, dgram_size);
       return;
     }
@@ -779,9 +781,11 @@ http2_sched_dispatch_udp_tunnel (http2_req_t *req, http_conn_t *hc,
   if (req->peer_window <
       (hdr.data_length + HTTP_UDP_PROXY_DATAGRAM_CAPSULE_OVERHEAD))
     {
+      HTTP_DBG (1, "not enough space in stream window (%lu) for capsule",
+               req->peer_window);
       /* mark that we need window update on stream */
-      HTTP_DBG (1, "not enough space in stream window for capsule");
       req->flags |= HTTP2_REQ_F_NEED_WINDOW_UPDATE;
+      return;
     }
 
   max_write = http_io_ts_max_write (hc, 0);
@@ -802,7 +806,7 @@ http2_sched_dispatch_udp_tunnel (http2_req_t *req, http_conn_t *hc,
   payload = http_encap_udp_payload_datagram (buf, hdr.data_length);
   capsule_size = (payload - buf) + hdr.data_length;
   /* read payload */
-  http_io_as_read (&req->base, payload, hdr.data_length, 1);
+  http_io_as_peek (&req->base, payload, hdr.data_length, sizeof (hdr));
   http_io_as_drain (&req->base, dgram_size);
 
   req->peer_window -= capsule_size;
@@ -814,6 +818,7 @@ http2_sched_dispatch_udp_tunnel (http2_req_t *req, http_conn_t *hc,
                             { buf, capsule_size } };
   n_written = http_io_ts_write_segs (hc, segs, 2, 0);
   ASSERT (n_written == (HTTP2_FRAME_HEADER_SIZE + capsule_size));
+  HTTP_DBG (1, "capsule payload len %lu", hdr.data_length);
 
   if (max_read - dgram_size)
     {
@@ -1670,7 +1675,7 @@ http2_req_state_tunnel_rx (http_conn_t *hc, http2_req_t *req,
 {
   u32 max_enq;
 
-  HTTP_DBG (1, "tunnel received data from client");
+  HTTP_DBG (1, "tunnel received data from peer");
 
   max_enq = http_io_as_max_write (&req->base);
   if (max_enq < req->payload_len)
@@ -1848,7 +1853,7 @@ http2_req_state_tunnel_tx (http_conn_t *hc, http2_req_t *req,
 
   ASSERT (!clib_llist_elt_is_linked (req, sched_list));
 
-  HTTP_DBG (1, "tunnel received data from target");
+  HTTP_DBG (1, "tunnel received data from app");
 
   /* add data back to stream scheduler */
   HTTP_DBG (1, "adding to data queue req_index %x",
@@ -2700,7 +2705,7 @@ http2_app_rx_evt_callback (http_conn_t *hc, u32 req_index,
   HTTP_DBG (1, "received app read notification stream id %u", req->stream_id);
   /* send stream window update if app read data in rx fifo and we expect more
    * data (stream is still open) */
-  expected_state = hc->flags & HTTP_CONN_F_IS_SERVER ?
+  expected_state = (hc->flags & HTTP_CONN_F_IS_SERVER || req->base.is_tunnel) ?
                     HTTP2_STREAM_STATE_OPEN :
                     HTTP2_STREAM_STATE_HALF_CLOSED;
   if (req->stream_state == expected_state)
@@ -2852,6 +2857,12 @@ http2_transport_rx_callback (http_conn_t *hc)
   if (PREDICT_FALSE (to_deq < HTTP2_FRAME_HEADER_SIZE))
     {
       HTTP_DBG (1, "to_deq %u is less than frame header size", to_deq);
+#if HTTP_DEBUG
+      u8 *tmp = 0;
+      vec_validate (tmp, to_deq - 1);
+      http_io_ts_read (hc, tmp, to_deq, 0);
+      clib_warning ("%U", format_hex_bytes, tmp, to_deq);
+#endif
       http2_connection_error (hc, HTTP2_ERROR_PROTOCOL_ERROR, 0);
       return;
     }
index b76f4f6..daa9d0a 100644 (file)
@@ -94,8 +94,6 @@ typedef struct http_req_
 #define hr_hc_index         c_http_req_id.hc_index
 #define hr_req_handle       connection.c_index
 
-  u32 as_fifo_offset; /* for peek */
-
   http_req_state_t state; /* state-machine state */
 
   http_buffer_t tx_buf; /* message body from app to be sent */
@@ -629,21 +627,13 @@ http_io_as_write_segs (http_req_t *req, const svm_fifo_seg_t segs[],
 }
 
 always_inline u32
-http_io_as_read (http_req_t *req, u8 *buf, u32 len, u8 peek)
+http_io_as_peek (http_req_t *req, u8 *buf, u32 len, u32 offset)
 {
   int n_read;
   session_t *as = session_get_from_handle (req->hr_pa_session_handle);
 
-  if (peek)
-    {
-      n_read = svm_fifo_peek (as->tx_fifo, req->as_fifo_offset, len, buf);
-      ASSERT (n_read > 0);
-      req->as_fifo_offset += len;
-      return (u32) n_read;
-    }
-
-  n_read = svm_fifo_dequeue (as->tx_fifo, len, buf);
-  ASSERT (n_read == len);
+  n_read = svm_fifo_peek (as->tx_fifo, offset, len, buf);
+  ASSERT (n_read > 0);
   return (u32) n_read;
 }
 
@@ -662,7 +652,6 @@ http_io_as_drain (http_req_t *req, u32 len)
 {
   session_t *as = session_get_from_handle (req->hr_pa_session_handle);
   svm_fifo_dequeue_drop (as->tx_fifo, len);
-  req->as_fifo_offset = 0;
 }
 
 always_inline void
@@ -670,7 +659,6 @@ http_io_as_drain_all (http_req_t *req)
 {
   session_t *as = session_get_from_handle (req->hr_pa_session_handle);
   svm_fifo_dequeue_drop_all (as->tx_fifo);
-  req->as_fifo_offset = 0;
 }
 
 always_inline void