Skip to content

Commit c74109e

Browse files
committed
Ensure tcp_mss is calculated at runtime for cwnd grow calculation
1 parent b84b33c commit c74109e

2 files changed

Lines changed: 105 additions & 27 deletions

File tree

src/test/unit/unit.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14569,6 +14569,62 @@ START_TEST(test_tcp_ack_updates_rtt_and_cwnd)
1456914569
}
1457014570
END_TEST
1457114571

14572+
START_TEST(test_tcp_ack_uses_interface_mss_for_cwnd_growth)
14573+
{
14574+
struct wolfIP s;
14575+
struct tsocket *ts;
14576+
uint8_t buf[sizeof(struct wolfIP_tcp_seg) + TCP_OPTION_TS_LEN + 1];
14577+
struct wolfIP_tcp_seg *seg = (struct wolfIP_tcp_seg *)buf;
14578+
struct tcp_opt_ts *tsopt;
14579+
struct wolfIP_tcp_seg ackseg;
14580+
struct pkt_desc *desc;
14581+
uint32_t smss;
14582+
14583+
wolfIP_init(&s);
14584+
mock_link_init(&s);
14585+
ck_assert_int_eq(wolfIP_mtu_set(&s, TEST_PRIMARY_IF, 320U), 0);
14586+
14587+
ts = &s.tcpsockets[0];
14588+
memset(ts, 0, sizeof(*ts));
14589+
ts->proto = WI_IPPROTO_TCP;
14590+
ts->S = &s;
14591+
ts->if_idx = TEST_PRIMARY_IF;
14592+
ts->sock.tcp.state = TCP_ESTABLISHED;
14593+
smss = tcp_cc_mss(ts);
14594+
ts->sock.tcp.cwnd = smss;
14595+
ts->sock.tcp.ssthresh = smss * 4;
14596+
ts->sock.tcp.peer_rwnd = smss * 8;
14597+
fifo_init(&ts->sock.tcp.txbuf, ts->txmem, TXBUF_SIZE);
14598+
s.last_tick = 1000;
14599+
14600+
memset(buf, 0, sizeof(buf));
14601+
seg->ip.len = ee16(IP_HEADER_LEN + (TCP_HEADER_LEN + TCP_OPTION_TS_LEN) + 1);
14602+
seg->hlen = (TCP_HEADER_LEN + TCP_OPTION_TS_LEN) << 2;
14603+
seg->seq = ee32(100);
14604+
tsopt = (struct tcp_opt_ts *)seg->data;
14605+
tsopt->opt = TCP_OPTION_TS;
14606+
tsopt->len = TCP_OPTION_TS_LEN;
14607+
tsopt->val = ee32(123);
14608+
tsopt->ecr = ee32(990);
14609+
14610+
fifo_push(&ts->sock.tcp.txbuf, seg, sizeof(buf));
14611+
desc = fifo_peek(&ts->sock.tcp.txbuf);
14612+
ck_assert_ptr_nonnull(desc);
14613+
desc->flags |= PKT_FLAG_SENT;
14614+
ts->sock.tcp.bytes_in_flight = ts->sock.tcp.cwnd;
14615+
ts->sock.tcp.snd_una = 100;
14616+
ts->sock.tcp.seq = 100 + smss;
14617+
14618+
memset(&ackseg, 0, sizeof(ackseg));
14619+
ackseg.ack = ee32(101);
14620+
ackseg.hlen = TCP_HEADER_LEN << 2;
14621+
ackseg.flags = TCP_FLAG_ACK;
14622+
14623+
tcp_ack(ts, &ackseg);
14624+
ck_assert_uint_eq(ts->sock.tcp.cwnd, smss * 2);
14625+
}
14626+
END_TEST
14627+
1457214628
START_TEST(test_tcp_ack_last_seq_not_last_ack_state)
1457314629
{
1457414630
struct wolfIP s;
@@ -19361,6 +19417,7 @@ Suite *wolf_suite(void)
1936119417
tcase_add_test(tc_utils, test_tcp_ack_duplicate_discards_zero_len_segment);
1936219418
tcase_add_test(tc_utils, test_tcp_ack_cwnd_count_wrap);
1936319419
tcase_add_test(tc_utils, test_tcp_ack_updates_rtt_and_cwnd);
19420+
tcase_add_test(tc_utils, test_tcp_ack_uses_interface_mss_for_cwnd_growth);
1936419421
tcase_add_test(tc_utils, test_tcp_ack_last_seq_not_last_ack_state);
1936519422
tcase_add_test(tc_utils, test_tcp_ack_no_progress_when_ack_far_ahead);
1936619423
tcase_add_test(tc_utils, test_tcp_ack_coarse_rtt_sets_writable);

src/wolfip.c

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,10 @@ struct wolfIP_icmp_packet;
117117
#define IP_MTU_MAX 1500U
118118
#define WI_IP_STD_MTU IP_MTU_MAX
119119
#define WI_IP_MTU WI_IP_STD_MTU
120-
#define TCP_MSS (WI_IP_STD_MTU - (IP_HEADER_LEN + TCP_HEADER_LEN))
120+
/* Maximum MSS based on standard MTU; prefer per-socket MSS where possible. */
121+
#define TCP_MSS_MAX (WI_IP_STD_MTU - (IP_HEADER_LEN + TCP_HEADER_LEN))
122+
/* Compatibility alias for legacy fixed-size uses. */
123+
#define TCP_MSS TCP_MSS_MAX
121124
#define TCP_DEFAULT_MSS 536U
122125
#define TCP_CTRL_RTO_MAXRTX 6U
123126
#define TCP_RTO_MAX_BACKOFF 15U /* Max retries before closing; also clamps shift */
@@ -683,7 +686,7 @@ struct tcp_sack_block {
683686
struct tcp_ooo_seg {
684687
uint32_t seq, len;
685688
uint8_t used;
686-
uint8_t data[TCP_MSS];
689+
uint8_t data[TCP_MSS_MAX];
687690
};
688691

689692
/* UDP datagram */
@@ -1272,6 +1275,15 @@ static inline uint32_t wolfIP_socket_tcp_mss(const struct tsocket *t)
12721275
return ip_mtu - (IP_HEADER_LEN + TCP_HEADER_LEN);
12731276
}
12741277

1278+
static inline uint32_t tcp_cc_mss(const struct tsocket *t)
1279+
{
1280+
uint32_t mss = t ? wolfIP_socket_tcp_mss(t) : TCP_MSS_MAX;
1281+
1282+
if (mss == 0)
1283+
mss = TCP_MSS_MAX;
1284+
return mss;
1285+
}
1286+
12751287
static inline uint32_t tcp_tx_payload_cap(const struct tsocket *t)
12761288
{
12771289
uint32_t cap = wolfIP_socket_tcp_mss(t);
@@ -1816,11 +1828,11 @@ static void icmp_try_recv(struct wolfIP *s, unsigned int if_idx,
18161828
}
18171829

18181830
/* TCP */
1819-
static uint32_t tcp_initial_cwnd(uint32_t peer_rwnd)
1831+
static uint32_t tcp_initial_cwnd(uint32_t peer_rwnd, uint32_t smss)
18201832
{
18211833
uint32_t cwnd = peer_rwnd / 2U;
18221834
uint32_t tx_half = TXBUF_SIZE / 2U;
1823-
uint32_t min_cwnd = 2U * TCP_MSS;
1835+
uint32_t min_cwnd = 2U * smss;
18241836

18251837
if (cwnd > tx_half)
18261838
cwnd = tx_half;
@@ -1862,7 +1874,7 @@ static struct tsocket *tcp_new_socket(struct wolfIP *s)
18621874
t->sock.tcp.ctrl_rto_active = 0;
18631875
t->sock.tcp.last_early_rexmit_ack = 0;
18641876
t->sock.tcp.peer_rwnd = 0xFFFF;
1865-
t->sock.tcp.cwnd = tcp_initial_cwnd(t->sock.tcp.peer_rwnd);
1877+
t->sock.tcp.cwnd = tcp_initial_cwnd(t->sock.tcp.peer_rwnd, tcp_cc_mss(t));
18661878
t->sock.tcp.ssthresh = tcp_initial_ssthresh(t->sock.tcp.peer_rwnd);
18671879
t->sock.tcp.peer_mss = TCP_DEFAULT_MSS;
18681880
t->sock.tcp.snd_wscale = 0;
@@ -2074,7 +2086,7 @@ static int tcp_store_ooo_segment(struct tsocket *t, const uint8_t *data,
20742086
* - cache full: reject (caller still ACKs; peer will retransmit)
20752087
*
20762088
* SACK block generation is rebuilt from cache state after each update. */
2077-
if (len == 0 || len > TCP_MSS)
2089+
if (len == 0 || len > TCP_MSS_MAX)
20782090
return -1;
20792091
for (i = 0; i < TCP_OOO_MAX_SEGS; i++) {
20802092
if (!t->sock.tcp.ooo[i].used) {
@@ -3199,16 +3211,19 @@ static void tcp_ack(struct tsocket *t, const struct wolfIP_tcp_seg *tcp)
31993211
}
32003212
/* Grow cwnd only on forward ACK progress (never on duplicate ACKs),
32013213
* and only if we were cwnd-limited. */
3202-
if (ack_advanced &&
3203-
((t->sock.tcp.cwnd <= inflight_pre + TCP_MSS) ||
3204-
(t->sock.tcp.cwnd <= 2 * TCP_MSS))) {
3205-
if (t->sock.tcp.cwnd < t->sock.tcp.ssthresh) {
3206-
t->sock.tcp.cwnd += TCP_MSS;
3207-
} else {
3208-
t->sock.tcp.cwnd_count += TCP_MSS;
3209-
if (t->sock.tcp.cwnd_count >= t->sock.tcp.cwnd) {
3210-
t->sock.tcp.cwnd_count -= t->sock.tcp.cwnd;
3211-
t->sock.tcp.cwnd += TCP_MSS;
3214+
{
3215+
uint32_t smss = tcp_cc_mss(t);
3216+
if (ack_advanced &&
3217+
((t->sock.tcp.cwnd <= inflight_pre + smss) ||
3218+
(t->sock.tcp.cwnd <= 2 * smss))) {
3219+
if (t->sock.tcp.cwnd < t->sock.tcp.ssthresh) {
3220+
t->sock.tcp.cwnd += smss;
3221+
} else {
3222+
t->sock.tcp.cwnd_count += smss;
3223+
if (t->sock.tcp.cwnd_count >= t->sock.tcp.cwnd) {
3224+
t->sock.tcp.cwnd_count -= t->sock.tcp.cwnd;
3225+
t->sock.tcp.cwnd += smss;
3226+
}
32123227
}
32133228
}
32143229
}
@@ -3236,11 +3251,14 @@ static void tcp_ack(struct tsocket *t, const struct wolfIP_tcp_seg *tcp)
32363251
}
32373252
if (t->sock.tcp.dup_acks < 3)
32383253
return;
3239-
t->sock.tcp.ssthresh = t->sock.tcp.cwnd / 2;
3240-
if (t->sock.tcp.ssthresh < 2 * TCP_MSS) {
3241-
t->sock.tcp.ssthresh = 2 * TCP_MSS;
3254+
{
3255+
uint32_t smss = tcp_cc_mss(t);
3256+
t->sock.tcp.ssthresh = t->sock.tcp.cwnd / 2;
3257+
if (t->sock.tcp.ssthresh < 2 * smss) {
3258+
t->sock.tcp.ssthresh = 2 * smss;
3259+
}
3260+
t->sock.tcp.cwnd = t->sock.tcp.ssthresh + smss;
32423261
}
3243-
t->sock.tcp.cwnd = t->sock.tcp.ssthresh + TCP_MSS;
32443262
t->sock.tcp.cwnd_count = 0;
32453263
(void)tcp_mark_unsacked_for_retransmit(t, ack);
32463264
}
@@ -3450,7 +3468,7 @@ static void tcp_input(struct wolfIP *S, unsigned int if_idx,
34503468
t->sock.tcp.ack = tcp_seq_inc(ee32(tcp->seq), 1);
34513469
t->sock.tcp.seq = ee32(tcp->ack);
34523470
t->sock.tcp.snd_una = t->sock.tcp.seq;
3453-
t->sock.tcp.cwnd = tcp_initial_cwnd(t->sock.tcp.peer_rwnd);
3471+
t->sock.tcp.cwnd = tcp_initial_cwnd(t->sock.tcp.peer_rwnd, tcp_cc_mss(t));
34543472
t->sock.tcp.ssthresh = tcp_initial_ssthresh(t->sock.tcp.peer_rwnd);
34553473
if (tx_has_writable_space(t))
34563474
t->events |= CB_EVENT_WRITABLE;
@@ -3474,7 +3492,7 @@ static void tcp_input(struct wolfIP *S, unsigned int if_idx,
34743492
t->sock.tcp.ack = ee32(tcp->seq);
34753493
t->sock.tcp.seq = ee32(tcp->ack);
34763494
t->sock.tcp.snd_una = t->sock.tcp.seq;
3477-
t->sock.tcp.cwnd = tcp_initial_cwnd(t->sock.tcp.peer_rwnd);
3495+
t->sock.tcp.cwnd = tcp_initial_cwnd(t->sock.tcp.peer_rwnd, tcp_cc_mss(t));
34783496
t->sock.tcp.ssthresh = tcp_initial_ssthresh(t->sock.tcp.peer_rwnd);
34793497
if (tx_has_writable_space(t))
34803498
t->events |= CB_EVENT_WRITABLE;
@@ -3675,10 +3693,13 @@ static void tcp_rto_cb(void *arg)
36753693
return;
36763694
}
36773695
ts->sock.tcp.rto_backoff++;
3678-
ts->sock.tcp.cwnd = TCP_MSS;
3679-
ts->sock.tcp.ssthresh = prev_in_flight / 2;
3680-
if (ts->sock.tcp.ssthresh < (2 * TCP_MSS))
3681-
ts->sock.tcp.ssthresh = 2 * TCP_MSS;
3696+
{
3697+
uint32_t smss = tcp_cc_mss(ts);
3698+
ts->sock.tcp.cwnd = smss;
3699+
ts->sock.tcp.ssthresh = prev_in_flight / 2;
3700+
if (ts->sock.tcp.ssthresh < (2 * smss))
3701+
ts->sock.tcp.ssthresh = 2 * smss;
3702+
}
36823703

36833704
ptmr = &tmr;
36843705
ptmr->expires = ts->S->last_tick + (ts->sock.tcp.rto << ts->sock.tcp.rto_backoff);
@@ -3994,7 +4015,7 @@ int wolfIP_sock_accept(struct wolfIP *s, int sockfd, struct wolfIP_sockaddr *add
39944015
newts->sock.tcp.snd_una = newts->sock.tcp.seq;
39954016
newts->sock.tcp.last_ts = ts->sock.tcp.last_ts;
39964017
newts->sock.tcp.peer_rwnd = ts->sock.tcp.peer_rwnd;
3997-
newts->sock.tcp.cwnd = tcp_initial_cwnd(newts->sock.tcp.peer_rwnd);
4018+
newts->sock.tcp.cwnd = tcp_initial_cwnd(newts->sock.tcp.peer_rwnd, tcp_cc_mss(newts));
39984019
newts->sock.tcp.ssthresh = tcp_initial_ssthresh(newts->sock.tcp.peer_rwnd);
39994020
newts->sock.tcp.peer_mss = ts->sock.tcp.peer_mss;
40004021
newts->sock.tcp.snd_wscale = ts->sock.tcp.snd_wscale;

0 commit comments

Comments
 (0)