From b4d7238eb894e0f499a75eb5a88a2aec99a60150 Mon Sep 17 00:00:00 2001 From: sg Date: Wed, 16 Mar 2016 22:22:20 +0100 Subject: [PATCH] tcp_output_segment: don't count retransmitted segments in mib2.tcpoutsegs by detecting p->payload != tcphdr pointer; don't try to retransmit segments where p->ref != 1 (as it is invalid to mess up p->len/p->payload when we don't have exclusive access to the pbuf) --- src/core/tcp_out.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c index 74949968..aea7e199 100644 --- a/src/core/tcp_out.c +++ b/src/core/tcp_out.c @@ -1134,8 +1134,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) u32_t *opts; struct netif *netif; - /** @bug Exclude retransmitted segments from this count. */ - MIB2_STATS_INC(mib2.tcpoutsegs); + if (seg->p->ref != 1) { + /* This can happen if the pbuf of this segment is still referenced by the + netif driver due to deferred transmission. Since this function modifies + p->len, we must not continue in this case. */ + return ERR_OK; + } /* The TCP header has already been constructed, but the ackno and wnd fields remain. */ @@ -1214,6 +1218,10 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) seg->len)); len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); + if (len == 0) { + /** Exclude retransmitted segments from this count. */ + MIB2_STATS_INC(mib2.tcpoutsegs); + } seg->p->len -= len; seg->p->tot_len -= len;