stream: detect spurious retransmissions early

pull/7496/head
Victor Julien 3 years ago
parent 8377b9dc7c
commit cc4e8f0936

@ -802,6 +802,10 @@ const struct DecodeEvents_ DEvents[] = {
"stream.pkt_retransmission",
STREAM_PKT_RETRANSMISSION,
},
{
"stream.pkt_spurious_retransmission",
STREAM_PKT_SPURIOUS_RETRANSMISSION,
},
{
"stream.pkt_bad_window_update",
STREAM_PKT_BAD_WINDOW_UPDATE,

@ -277,6 +277,7 @@ enum {
STREAM_PKT_BROKEN_ACK,
STREAM_RST_INVALID_ACK,
STREAM_PKT_RETRANSMISSION,
STREAM_PKT_SPURIOUS_RETRANSMISSION,
STREAM_PKT_BAD_WINDOW_UPDATE,
STREAM_SUSPECTED_RST_INJECT,

@ -2560,6 +2560,33 @@ static bool StreamTcpPacketIsOutdatedAck(TcpSession *ssn, Packet *p)
return false;
}
/** \internal
* \brief check if packet is before ack'd windows
* If packet is before last ack, we will not accept it
*/
static bool StreamTcpPacketIsSpuriousRetransmission(TcpSession *ssn, Packet *p)
{
TcpStream *stream;
if (PKT_IS_TOCLIENT(p)) {
stream = &ssn->server;
} else {
stream = &ssn->client;
}
/* take base_seq into account to avoid edge cases where last_ack might be
* too far ahead during heavy packet loss */
const uint32_t le = MIN(stream->last_ack, stream->base_seq);
if (p->payload_len > 0 && (SEQ_LEQ(TCP_GET_SEQ(p) + p->payload_len, le))) {
SCLogDebug("ssn %p: spurious retransmission; packet entirely before last_ack: SEQ %u(%u) "
"last_ack %u",
ssn, TCP_GET_SEQ(p), TCP_GET_SEQ(p) + p->payload_len, stream->last_ack);
return true;
}
SCLogDebug("ssn %p: NOT spurious retransmission; packet NOT entirely before last_ack: SEQ "
"%u(%u) last_ack %u, le %u",
ssn, TCP_GET_SEQ(p), TCP_GET_SEQ(p) + p->payload_len, stream->last_ack, le);
return false;
}
/**
* \brief Function to handle the TCP_ESTABLISHED state. The function handles
* ACK, FIN, RST packets and correspondingly changes the connection
@ -4960,6 +4987,11 @@ int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt,
}
}
if (StreamTcpPacketIsSpuriousRetransmission(ssn, p)) {
StreamTcpSetEvent(p, STREAM_PKT_SPURIOUS_RETRANSMISSION);
goto error;
}
/* handle the per 'state' logic */
if (StreamTcpStateDispatch(tv, p, stt, ssn, &stt->pseudo_queue, ssn->state) < 0)
goto error;

Loading…
Cancel
Save