Commit 5f9cdf29 authored by jan.koester's avatar jan.koester
Browse files

debug



Co-authored-by: default avatarCopilot <copilot@github.com>
parent be291efd
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
libnetplus (20260504+5) unstable; urgency=medium

  * QUIC: fix critical data-loss bug in loss-detection retransmit — if
    sendPacket() failed (EAGAIN / send-buffer full after a burst), the
    stream data was erased from _sent_packets but never re-inserted,
    causing permanent loss of ~47 in-flight packets.  Fix: on send
    failure, re-queue under the original PN so the next loss-detection
    cycle retries the retransmit.
  * QUIC: fix same data-loss bug in PTO retransmit path — only erase
    the original entry and increment _pto_count after sendPacket()
    succeeds; re-queue on failure.
  * QUIC: improve [QUIC-DIAG] retransmit logging — report retransmit_ok
    / retransmit_fail counts and PTO re-queue events

libnetplus (20260504+4) unstable; urgency=medium

  * QUIC: add client-side [QUIC-DIAG] logging for ACK processing (first
+28 −17
Original line number Diff line number Diff line
@@ -3661,8 +3661,8 @@ void quic::checkLossAndRetransmit() {
        if (age >= pto_thresh) {
            // Retransmit the oldest unacked packet as a probe
            auto sp = oldest; // copy — will be erased below
            uint64_t old_pn = _sent_packets.begin()->first;
            _sent_packets.erase(_sent_packets.begin());
            ++_pto_count;

            if (sp.data_length > 0 || sp.fin) {
                uint8_t frame_type = 0x08 | 0x02;
@@ -3689,14 +3689,16 @@ void quic::checkLossAndRetransmit() {
                    recordSentPacket(new_pn, sp.stream_id, sp.stream_offset,
                                    sp.stream_data.data(), sp.stream_data.size(),
                                    sp.fin, packet.size());
                    ++_pto_count;
                } else {
                    // Send failed (EAGAIN) — re-queue under original PN
                    // so the data is not permanently lost
                    _sent_packets[old_pn] = std::move(sp);
                    std::cerr << "[QUIC-DIAG] PTO send failed, re-queued pn="
                              << old_pn << "\n";
                }
                QUIC_DBG("PTO probe: new_pn=%lu age=%.3fs pto=%.3fs",
                         (unsigned long)new_pn, age, pto_thresh);
                std::cerr << "[QUIC-DIAG] PTO probe: age=" << age
                          << "s pto=" << pto_thresh
                          << "s sent_packets=" << _sent_packets.size()
                          << " largest_acked=" << _largest_acked_pn
                          << "\n";
            }
        }
    }
@@ -3744,12 +3746,7 @@ void quic::checkLossAndRetransmit() {
    }

    // Retransmit lost stream data with new packet numbers
    if (!lost.empty()) {
        std::cerr << "[QUIC-DIAG] loss detected: " << lost.size()
                  << " packets, largest_acked=" << _largest_acked_pn
                  << " sent_packets_remaining=" << _sent_packets.size()
                  << "\n";
    }
    size_t retransmit_ok = 0, retransmit_fail = 0;
    for (auto& sp : lost) {
        if (sp.data_length == 0 && !sp.fin) continue;

@@ -3784,9 +3781,6 @@ void quic::checkLossAndRetransmit() {

        ssize_t sent = sendPacket(packet.data(), packet.size());
        if (sent < 0) {
            // Single non-blocking retry — do not sleep with quic_mtx held.
            // If the socket is still busy the packet will be retransmitted
            // on the next loss-detection cycle.
            sent = sendPacket(packet.data(), packet.size());
        }

@@ -3794,12 +3788,29 @@ void quic::checkLossAndRetransmit() {
            // Track retransmitted packet under new PN
            recordSentPacket(new_pn, sp.stream_id, sp.stream_offset,
                            sp.stream_data.data(), sp.stream_data.size(), sp.fin, packet.size());
            ++retransmit_ok;
        } else {
            // Send failed (EAGAIN / send-buffer full) — re-insert under
            // the original PN so the packet is retried on the next
            // loss-detection cycle instead of being permanently lost.
            size_t saved_size = sp.sent_size;
            _sent_packets[sp.pn] = std::move(sp);
            _bytes_in_flight += saved_size;
            ++retransmit_fail;
        }

        QUIC_DBG("RETRANSMIT: old_pn=%lu new_pn=%lu sid=%lu off=%lu len=%zu fin=%d",
        QUIC_DBG("RETRANSMIT: old_pn=%lu new_pn=%lu sid=%lu off=%lu len=%zu fin=%d sent=%zd",
                 (unsigned long)sp.pn, (unsigned long)new_pn,
                 (unsigned long)sp.stream_id, (unsigned long)sp.stream_offset,
                 sp.data_length, (int)sp.fin);
                 sp.data_length, (int)sp.fin, sent);
    }
    if (!lost.empty()) {
        std::cerr << "[QUIC-DIAG] loss detected: " << lost.size()
                  << " packets, largest_acked=" << _largest_acked_pn
                  << " retransmit_ok=" << retransmit_ok
                  << " retransmit_fail=" << retransmit_fail
                  << " sent_packets=" << _sent_packets.size()
                  << "\n";
    }
}