Skip to content

Commit eeaa47a

Browse files
committed
Fix handling of non-ethernet packets, pass desc as argument
1 parent 1cce5e7 commit eeaa47a

3 files changed

Lines changed: 67 additions & 16 deletions

File tree

src/test/unit/unit.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,7 @@ Suite *wolf_suite(void)
750750
tcase_add_test(tc_proto, test_regression_syn_on_last_ack_not_silently_processed);
751751
tcase_add_test(tc_proto, test_regression_full_txbuf_still_sends_pure_ack);
752752
tcase_add_test(tc_proto, test_regression_loopback_immediate_pure_ack_uses_loopback_ll);
753+
tcase_add_test(tc_proto, test_regression_tcp_tx_desc_payload_len_uses_link_type_not_length_heuristic);
753754
tcase_add_test(tc_proto, test_regression_fast_recovery_cwnd_ssthresh_rfc5681);
754755
tcase_add_test(tc_proto, test_regression_paws_rejects_stale_timestamp);
755756
tcase_add_test(tc_proto, test_regression_paws_accepts_wrapped_newer_timestamp);

src/test/unit/unit_tests_proto.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4800,6 +4800,41 @@ START_TEST(test_regression_loopback_immediate_pure_ack_uses_loopback_ll)
48004800
}
48014801
END_TEST
48024802

4803+
START_TEST(test_regression_tcp_tx_desc_payload_len_uses_link_type_not_length_heuristic)
4804+
{
4805+
struct wolfIP s;
4806+
struct tsocket *ts;
4807+
struct pkt_desc desc;
4808+
struct wolfIP_tcp_seg seg;
4809+
4810+
wolfIP_init(&s);
4811+
mock_link_init(&s);
4812+
4813+
ts = &s.tcpsockets[0];
4814+
memset(ts, 0, sizeof(*ts));
4815+
ts->proto = WI_IPPROTO_TCP;
4816+
ts->S = &s;
4817+
ts->if_idx = TEST_PRIMARY_IF;
4818+
4819+
memset(&desc, 0, sizeof(desc));
4820+
memset(&seg, 0, sizeof(seg));
4821+
seg.hlen = TCP_HEADER_LEN << 2;
4822+
seg.ip.len = 0;
4823+
4824+
/* Short Ethernet-backed descriptors must not be treated as if desc->len
4825+
* were already an IP length. */
4826+
desc.len = IP_HEADER_LEN + TCP_HEADER_LEN + 4;
4827+
ck_assert_uint_eq(tcp_tx_desc_ip_len(ts, &desc, &seg), 0U);
4828+
ck_assert_uint_eq(tcp_tx_desc_payload_len(ts, &desc, &seg), 0U);
4829+
4830+
/* The same descriptor length is valid on non-Ethernet/L3 links. */
4831+
s.ll_dev[TEST_PRIMARY_IF].non_ethernet = 1;
4832+
ck_assert_uint_eq(tcp_tx_desc_ip_len(ts, &desc, &seg),
4833+
(uint32_t)desc.len);
4834+
ck_assert_uint_eq(tcp_tx_desc_payload_len(ts, &desc, &seg), 4U);
4835+
}
4836+
END_TEST
4837+
48034838

48044839
/* RFC 5681 §3.2: fast recovery deviates in multiple ways.
48054840
* (a) ssthresh uses cwnd/2 instead of max(FlightSize/2, 2*SMSS)

src/wolfip.c

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2824,22 +2824,37 @@ static void tcp_fin_wait_2_timeout_stop(struct tsocket *t)
28242824
t->sock.tcp.fin_wait_2_timeout_active = 0;
28252825
}
28262826

2827-
static uint32_t tcp_tx_desc_payload_len(const struct pkt_desc *desc,
2828-
const struct wolfIP_tcp_seg *seg)
2827+
static uint32_t tcp_tx_desc_ip_len(const struct tsocket *t,
2828+
const struct pkt_desc *desc, const struct wolfIP_tcp_seg *seg)
28292829
{
28302830
uint32_t seg_ip_len;
28312831
uint32_t seg_hdr_len;
2832+
unsigned int tx_if;
28322833

2833-
if (!desc || !seg)
2834+
if (!t || !desc || !seg)
28342835
return 0;
28352836
seg_hdr_len = IP_HEADER_LEN + (uint32_t)(seg->hlen >> 2);
28362837
seg_ip_len = ee16(seg->ip.len);
2837-
if (seg_ip_len == 0) {
2838-
if (desc->len >= (ETH_HEADER_LEN + seg_hdr_len))
2839-
seg_ip_len = desc->len - ETH_HEADER_LEN;
2840-
else
2841-
seg_ip_len = desc->len;
2842-
}
2838+
if (seg_ip_len != 0)
2839+
return seg_ip_len;
2840+
tx_if = wolfIP_socket_if_idx(t);
2841+
if (wolfIP_ll_is_non_ethernet(t->S, tx_if))
2842+
return desc->len;
2843+
if (desc->len < (ETH_HEADER_LEN + seg_hdr_len))
2844+
return 0;
2845+
return desc->len - ETH_HEADER_LEN;
2846+
}
2847+
2848+
static uint32_t tcp_tx_desc_payload_len(const struct tsocket *t,
2849+
const struct pkt_desc *desc, const struct wolfIP_tcp_seg *seg)
2850+
{
2851+
uint32_t seg_ip_len;
2852+
uint32_t seg_hdr_len;
2853+
2854+
if (!t || !desc || !seg)
2855+
return 0;
2856+
seg_ip_len = tcp_tx_desc_ip_len(t, desc, seg);
2857+
seg_hdr_len = IP_HEADER_LEN + (uint32_t)(seg->hlen >> 2);
28432858
if (seg_ip_len <= seg_hdr_len)
28442859
return 0;
28452860
return seg_ip_len - seg_hdr_len;
@@ -2859,7 +2874,7 @@ static int tcp_has_pending_unsent_payload(struct tsocket *t)
28592874
struct wolfIP_tcp_seg *seg;
28602875
uint32_t seg_len;
28612876
seg = (struct wolfIP_tcp_seg *)(t->txmem + desc->pos + sizeof(*desc));
2862-
seg_len = tcp_tx_desc_payload_len(desc, seg);
2877+
seg_len = tcp_tx_desc_payload_len(t, desc, seg);
28632878
if (seg_len > 0 && !(desc->flags & PKT_FLAG_SENT))
28642879
return 1;
28652880
desc = fifo_next(&t->sock.tcp.txbuf, desc);
@@ -2936,7 +2951,7 @@ static int tcp_send_zero_wnd_probe(struct tsocket *t)
29362951
while (desc && guard++ < budget) {
29372952
struct wolfIP_tcp_seg *seg = (struct wolfIP_tcp_seg *)(t->txmem + desc->pos + sizeof(*desc));
29382953
uint32_t hdr_len = (uint32_t)(seg->hlen >> 2);
2939-
uint32_t seg_len = tcp_tx_desc_payload_len(desc, seg);
2954+
uint32_t seg_len = tcp_tx_desc_payload_len(t, desc, seg);
29402955
uint32_t seg_seq = ee32(seg->seq);
29412956
const uint8_t *payload;
29422957
if (seg_len == 0) {
@@ -3496,7 +3511,7 @@ static int tcp_mark_unsacked_for_retransmit(struct tsocket *t, uint32_t ack)
34963511
if (guard++ >= budget)
34973512
break;
34983513
seg = (struct wolfIP_tcp_seg *)(t->txmem + desc->pos + sizeof(*desc));
3499-
seg_len = tcp_tx_desc_payload_len(desc, seg);
3514+
seg_len = tcp_tx_desc_payload_len(t, desc, seg);
35003515
if (seg_len == 0) {
35013516
desc = fifo_next(&t->sock.tcp.txbuf, desc);
35023517
continue;
@@ -4238,7 +4253,7 @@ static void tcp_rto_cb(void *arg)
42384253
if (desc->flags & PKT_FLAG_SENT) {
42394254
struct wolfIP_tcp_seg *seg =
42404255
(struct wolfIP_tcp_seg *)(ts->txmem + desc->pos + sizeof(*desc));
4241-
uint32_t seg_len = tcp_tx_desc_payload_len(desc, seg);
4256+
uint32_t seg_len = tcp_tx_desc_payload_len(ts, desc, seg);
42424257
uint32_t seg_start = ee32(seg->seq);
42434258
uint32_t seg_end = tcp_seq_inc(seg_start, seg_len);
42444259

@@ -4260,7 +4275,7 @@ static void tcp_rto_cb(void *arg)
42604275
} else {
42614276
struct wolfIP_tcp_seg *seg =
42624277
(struct wolfIP_tcp_seg *)(ts->txmem + desc->pos + sizeof(*desc));
4263-
uint32_t seg_len = tcp_tx_desc_payload_len(desc, seg);
4278+
uint32_t seg_len = tcp_tx_desc_payload_len(ts, desc, seg);
42644279
uint32_t seg_start = ee32(seg->seq);
42654280
uint32_t seg_end = tcp_seq_inc(seg_start, seg_len);
42664281
if (seg_len > 0 &&
@@ -7409,13 +7424,13 @@ int wolfIP_poll(struct wolfIP *s, uint64_t now)
74097424
if (ts->sock.tcp.peer_rwnd < snd_wnd)
74107425
snd_wnd = ts->sock.tcp.peer_rwnd;
74117426
is_retrans = (desc->flags & PKT_FLAG_RETRANS) ? 1 : 0;
7412-
seg_ip_len = desc->len - ETH_HEADER_LEN;
7427+
seg_ip_len = tcp_tx_desc_ip_len(ts, desc, tcp);
74137428
seg_hdr_len = IP_HEADER_LEN + (uint32_t)(tcp->hlen >> 2);
74147429
seg_payload_len = (seg_ip_len > seg_hdr_len) ? (seg_ip_len - seg_hdr_len) : 0;
74157430
if (is_retrans || seg_payload_len == 0 ||
74167431
(in_flight < snd_wnd && seg_payload_len <= (snd_wnd - in_flight))) {
74177432
struct wolfIP_timer new_tmr = {};
7418-
size = desc->len - ETH_HEADER_LEN;
7433+
size = seg_ip_len;
74197434
tcp = (struct wolfIP_tcp_seg *)(ts->txmem + desc->pos + sizeof(*desc));
74207435
/* Refresh ack counter */
74217436
ts->sock.tcp.last_ack = ts->sock.tcp.ack;

0 commit comments

Comments
 (0)