Skip to content

Commit 6e8e305

Browse files
committed
Addressed copilot's review comments
1 parent 88787f5 commit 6e8e305

3 files changed

Lines changed: 200 additions & 26 deletions

File tree

src/test/unit/unit.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,8 @@ Suite *wolf_suite(void)
774774
tcase_add_test(tc_proto, test_regression_full_txbuf_still_sends_pure_ack);
775775
tcase_add_test(tc_proto, test_regression_loopback_pure_ack_uses_deferred_buffer_until_poll);
776776
tcase_add_test(tc_proto, test_regression_loopback_pure_ack_drain_allows_next_send_cycle);
777+
tcase_add_test(tc_proto, test_regression_loopback_pure_ack_immediate_propagates_eagain_when_queue_full);
778+
tcase_add_test(tc_proto, test_regression_loopback_udp_tx_backpressure_retries_after_queue_drain);
777779
tcase_add_test(tc_proto, test_regression_tcp_tx_desc_payload_len_keeps_descriptor_layout_sanity);
778780
tcase_add_test(tc_proto, test_regression_fast_recovery_cwnd_ssthresh_rfc5681);
779781
tcase_add_test(tc_proto, test_regression_paws_rejects_stale_timestamp);

src/test/unit/unit_tests_proto.c

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4963,6 +4963,119 @@ START_TEST(test_regression_loopback_pure_ack_drain_allows_next_send_cycle)
49634963
}
49644964
END_TEST
49654965

4966+
START_TEST(test_regression_loopback_pure_ack_immediate_propagates_eagain_when_queue_full)
4967+
{
4968+
struct wolfIP s;
4969+
struct tsocket *ts;
4970+
struct wolfIP_ll_dev *loop;
4971+
struct wolfIP_tcp_seg seg;
4972+
uint8_t frame[16] = {0};
4973+
unsigned int i;
4974+
4975+
wolfIP_init(&s);
4976+
loop = wolfIP_getdev_ex(&s, TEST_LOOPBACK_IF);
4977+
ck_assert_ptr_nonnull(loop);
4978+
4979+
for (i = 0; i < WOLFIP_LOOPBACK_QUEUE_DEPTH; i++) {
4980+
ck_assert_int_eq(wolfIP_loopback_send(loop, frame, sizeof(frame)),
4981+
(int)sizeof(frame));
4982+
}
4983+
4984+
ts = &s.tcpsockets[0];
4985+
memset(ts, 0, sizeof(*ts));
4986+
ts->proto = WI_IPPROTO_TCP;
4987+
ts->S = &s;
4988+
ts->if_idx = TEST_LOOPBACK_IF;
4989+
ts->sock.tcp.state = TCP_ESTABLISHED;
4990+
ts->sock.tcp.ack = 100;
4991+
ts->sock.tcp.seq = 1000;
4992+
ts->src_port = 1234;
4993+
ts->dst_port = 4321;
4994+
ts->local_ip = 0x7F000001U;
4995+
ts->remote_ip = 0x7F000001U;
4996+
4997+
memset(&seg, 0, sizeof(seg));
4998+
seg.src_port = ee16(ts->src_port);
4999+
seg.dst_port = ee16(ts->dst_port);
5000+
seg.seq = ee32(ts->sock.tcp.seq);
5001+
seg.ack = ee32(ts->sock.tcp.ack);
5002+
seg.hlen = TCP_HEADER_LEN << 2;
5003+
seg.flags = TCP_FLAG_ACK;
5004+
5005+
ck_assert_int_eq(tcp_send_empty_immediate(ts, &seg, (uint32_t)sizeof(seg)),
5006+
-WOLFIP_EAGAIN);
5007+
ck_assert_uint_eq(s.loopback_count, WOLFIP_LOOPBACK_QUEUE_DEPTH);
5008+
}
5009+
END_TEST
5010+
5011+
START_TEST(test_regression_loopback_udp_tx_backpressure_retries_after_queue_drain)
5012+
{
5013+
struct wolfIP s;
5014+
struct tsocket *tx;
5015+
int tx_sd, rx_sd;
5016+
struct wolfIP_sockaddr_in bind_addr, dst_addr;
5017+
uint8_t payload = 0x5A;
5018+
uint8_t rxbuf[4];
5019+
int ret;
5020+
int received = 0;
5021+
uint64_t now = 200;
5022+
unsigned int i;
5023+
5024+
wolfIP_init(&s);
5025+
5026+
rx_sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_UDP);
5027+
ck_assert_int_ge(rx_sd, 0);
5028+
memset(&bind_addr, 0, sizeof(bind_addr));
5029+
bind_addr.sin_family = AF_INET;
5030+
bind_addr.sin_port = ee16(7777);
5031+
bind_addr.sin_addr.s_addr = ee32(0x7F000001U);
5032+
ck_assert_int_eq(wolfIP_sock_bind(&s, rx_sd,
5033+
(struct wolfIP_sockaddr *)&bind_addr, sizeof(bind_addr)), 0);
5034+
5035+
tx_sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_UDP);
5036+
ck_assert_int_ge(tx_sd, 0);
5037+
memset(&bind_addr, 0, sizeof(bind_addr));
5038+
bind_addr.sin_family = AF_INET;
5039+
bind_addr.sin_port = ee16(9999);
5040+
bind_addr.sin_addr.s_addr = ee32(0x7F000001U);
5041+
ck_assert_int_eq(wolfIP_sock_bind(&s, tx_sd,
5042+
(struct wolfIP_sockaddr *)&bind_addr, sizeof(bind_addr)), 0);
5043+
5044+
memset(&dst_addr, 0, sizeof(dst_addr));
5045+
dst_addr.sin_family = AF_INET;
5046+
dst_addr.sin_port = ee16(7777);
5047+
dst_addr.sin_addr.s_addr = ee32(0x7F000001U);
5048+
5049+
for (i = 0; i < WOLFIP_LOOPBACK_QUEUE_DEPTH + 1U; i++) {
5050+
payload = (uint8_t)i;
5051+
ret = wolfIP_sock_sendto(&s, tx_sd, &payload, 1, 0,
5052+
(const struct wolfIP_sockaddr *)&dst_addr, sizeof(dst_addr));
5053+
ck_assert_int_eq(ret, 1);
5054+
}
5055+
5056+
tx = &s.udpsockets[SOCKET_UNMARK(tx_sd)];
5057+
5058+
(void)wolfIP_poll(&s, now++);
5059+
ck_assert_uint_eq(s.loopback_count, WOLFIP_LOOPBACK_QUEUE_DEPTH);
5060+
ck_assert_ptr_nonnull(fifo_peek(&tx->sock.udp.txbuf));
5061+
5062+
(void)wolfIP_poll(&s, now++);
5063+
ck_assert_uint_ne((uint32_t)(tx->events & CB_EVENT_WRITABLE), 0U);
5064+
(void)wolfIP_poll(&s, now++);
5065+
ck_assert_ptr_null(fifo_peek(&tx->sock.udp.txbuf));
5066+
5067+
for (;;) {
5068+
ret = wolfIP_sock_recvfrom(&s, rx_sd, rxbuf, sizeof(rxbuf), 0, NULL, NULL);
5069+
if (ret <= 0)
5070+
break;
5071+
received++;
5072+
}
5073+
5074+
ck_assert_int_eq(ret, -WOLFIP_EAGAIN);
5075+
ck_assert_int_eq(received, (int)(WOLFIP_LOOPBACK_QUEUE_DEPTH + 1U));
5076+
}
5077+
END_TEST
5078+
49665079
START_TEST(test_regression_tcp_tx_desc_payload_len_keeps_descriptor_layout_sanity)
49675080
{
49685081
struct wolfIP s;

src/wolfip.c

Lines changed: 85 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,9 +1265,9 @@ struct wolfIP {
12651265
#endif
12661266
uint8_t loopback_buf[WOLFIP_LOOPBACK_QUEUE_DEPTH][IP_MTU_MAX];
12671267
uint32_t loopback_pending_len[WOLFIP_LOOPBACK_QUEUE_DEPTH];
1268-
uint8_t loopback_head;
1269-
uint8_t loopback_tail;
1270-
uint8_t loopback_count;
1268+
uint32_t loopback_head;
1269+
uint32_t loopback_tail;
1270+
uint32_t loopback_count;
12711271
#endif
12721272
};
12731273

@@ -1372,10 +1372,46 @@ static inline uint32_t tcp_tx_payload_cap(const struct tsocket *t)
13721372

13731373
#if WOLFIP_ENABLE_LOOPBACK
13741374

1375+
static void wolfIP_notify_loopback_space_available(struct wolfIP *s)
1376+
{
1377+
int i;
1378+
1379+
if (!s)
1380+
return;
1381+
1382+
for (i = 0; i < MAX_TCPSOCKETS; i++) {
1383+
struct tsocket *t = &s->tcpsockets[i];
1384+
if (t->proto != WI_IPPROTO_TCP)
1385+
continue;
1386+
if (wolfIP_socket_if_idx(t) != WOLFIP_LOOPBACK_IF_IDX)
1387+
continue;
1388+
if (tx_has_writable_space(t))
1389+
t->events |= CB_EVENT_WRITABLE;
1390+
}
1391+
for (i = 0; i < MAX_UDPSOCKETS; i++) {
1392+
struct tsocket *t = &s->udpsockets[i];
1393+
if (t->proto != WI_IPPROTO_UDP)
1394+
continue;
1395+
if (wolfIP_socket_if_idx(t) != WOLFIP_LOOPBACK_IF_IDX)
1396+
continue;
1397+
if (tx_has_writable_space(t))
1398+
t->events |= CB_EVENT_WRITABLE;
1399+
}
1400+
for (i = 0; i < MAX_ICMPSOCKETS; i++) {
1401+
struct tsocket *t = &s->icmpsockets[i];
1402+
if (t->proto != WI_IPPROTO_ICMP)
1403+
continue;
1404+
if (wolfIP_socket_if_idx(t) != WOLFIP_LOOPBACK_IF_IDX)
1405+
continue;
1406+
if (tx_has_writable_space(t))
1407+
t->events |= CB_EVENT_WRITABLE;
1408+
}
1409+
}
1410+
13751411
static int wolfIP_loopback_send(struct wolfIP_ll_dev *ll, void *buf, uint32_t len)
13761412
{
13771413
struct wolfIP *s;
1378-
uint8_t slot;
1414+
uint32_t slot;
13791415
if (!ll || !buf)
13801416
return -1;
13811417
s = WOLFIP_CONTAINER_OF(ll, struct wolfIP, ll_dev);
@@ -1391,16 +1427,17 @@ static int wolfIP_loopback_send(struct wolfIP_ll_dev *ll, void *buf, uint32_t le
13911427
slot = s->loopback_tail;
13921428
memcpy(s->loopback_buf[slot], buf, len);
13931429
s->loopback_pending_len[slot] = len;
1394-
s->loopback_tail = (uint8_t)((slot + 1U) % WOLFIP_LOOPBACK_QUEUE_DEPTH);
1430+
s->loopback_tail = (slot + 1U) % WOLFIP_LOOPBACK_QUEUE_DEPTH;
13951431
s->loopback_count++;
13961432
return (int)len;
13971433
}
13981434

13991435
static int wolfIP_loopback_poll(struct wolfIP_ll_dev *ll, void *buf, uint32_t len)
14001436
{
14011437
struct wolfIP *s;
1402-
uint8_t slot;
1438+
uint32_t slot;
14031439
uint32_t pending;
1440+
int queue_was_full;
14041441
if (!ll || !buf)
14051442
return 0;
14061443
s = WOLFIP_CONTAINER_OF(ll, struct wolfIP, ll_dev);
@@ -1412,10 +1449,13 @@ static int wolfIP_loopback_poll(struct wolfIP_ll_dev *ll, void *buf, uint32_t le
14121449
pending = s->loopback_pending_len[slot];
14131450
if (pending > len)
14141451
return 0;
1452+
queue_was_full = (s->loopback_count >= WOLFIP_LOOPBACK_QUEUE_DEPTH) ? 1 : 0;
14151453
memcpy(buf, s->loopback_buf[slot], pending);
14161454
s->loopback_pending_len[slot] = 0;
1417-
s->loopback_head = (uint8_t)((slot + 1U) % WOLFIP_LOOPBACK_QUEUE_DEPTH);
1455+
s->loopback_head = (slot + 1U) % WOLFIP_LOOPBACK_QUEUE_DEPTH;
14181456
s->loopback_count--;
1457+
if (queue_was_full)
1458+
wolfIP_notify_loopback_space_available(s);
14191459
return (int)pending;
14201460
}
14211461
#endif
@@ -1436,24 +1476,23 @@ static inline int wolfIP_ll_is_non_ethernet(struct wolfIP *s, unsigned int if_id
14361476
return (ll && ll->non_ethernet) ? 1 : 0;
14371477
}
14381478

1439-
static inline void wolfIP_ll_send_frame(struct wolfIP *s, unsigned int if_idx,
1440-
void *buf, uint32_t len)
1479+
static inline int wolfIP_ll_send_frame(struct wolfIP *s, unsigned int if_idx,
1480+
void *buf, uint32_t len)
14411481
{
14421482
struct wolfIP_ll_dev *ll = wolfIP_ll_at(s, if_idx);
14431483
uint32_t frame_mtu;
14441484

14451485
if (!ll || !ll->send)
1446-
return;
1486+
return -1;
14471487
frame_mtu = wolfIP_ll_frame_mtu(ll);
14481488
if (len > frame_mtu)
1449-
return;
1489+
return -1;
14501490
if (ll->non_ethernet) {
14511491
if (len <= ETH_HEADER_LEN)
1452-
return;
1453-
ll->send(ll, (uint8_t *)buf + ETH_HEADER_LEN, len - ETH_HEADER_LEN);
1454-
return;
1492+
return -1;
1493+
return ll->send(ll, (uint8_t *)buf + ETH_HEADER_LEN, len - ETH_HEADER_LEN);
14551494
}
1456-
ll->send(ll, buf, len);
1495+
return ll->send(ll, buf, len);
14571496
}
14581497

14591498
static inline struct ipconf *wolfIP_ipconf_at(struct wolfIP *s, unsigned int if_idx)
@@ -2605,8 +2644,10 @@ static int tcp_send_empty_immediate(struct tsocket *t, struct wolfIP_tcp_seg *tc
26052644
}
26062645
#endif
26072646

2608-
wolfIP_ll_send_frame(t->S, tx_if, tcp, frame_len);
2609-
return 0;
2647+
{
2648+
int send_ret = wolfIP_ll_send_frame(t->S, tx_if, tcp, frame_len);
2649+
return (send_ret < 0) ? send_ret : 0;
2650+
}
26102651
}
26112652

26122653
static int tcp_send_empty(struct tsocket *t, uint8_t flags)
@@ -7567,6 +7608,7 @@ int wolfIP_poll(struct wolfIP *s, uint64_t now)
75677608
while (desc && send_guard++ < send_budget) {
75687609
unsigned int tx_if = wolfIP_socket_if_idx(ts);
75697610
struct pkt_desc *next_desc = NULL;
7611+
int send_ret = 0;
75707612
tcp = (struct wolfIP_tcp_seg *)(ts->txmem + desc->pos + sizeof(*desc));
75717613
if (desc->flags & PKT_FLAG_SENT) {
75727614
next_desc = fifo_next(&ts->sock.tcp.txbuf, desc);
@@ -7633,15 +7675,22 @@ int wolfIP_poll(struct wolfIP *s, uint64_t now)
76337675
if (esp_err == 1) {
76347676
/* ipsec not configured on this interface.
76357677
* send plaintext. */
7636-
wolfIP_ll_send_frame(s, tx_if, tcp, desc->len);
7678+
send_ret = wolfIP_ll_send_frame(s, tx_if, tcp, desc->len);
76377679
}
76387680
} else {
7639-
wolfIP_ll_send_frame(s, tx_if, tcp, desc->len);
7681+
send_ret = wolfIP_ll_send_frame(s, tx_if, tcp, desc->len);
76407682
}
76417683
#else
7642-
wolfIP_ll_send_frame(s, tx_if, tcp, desc->len);
7684+
send_ret = wolfIP_ll_send_frame(s, tx_if, tcp, desc->len);
76437685
#endif /* WOLFIP_ESP */
76447686
}
7687+
if (send_ret == -WOLFIP_EAGAIN) {
7688+
if (tx_has_writable_space(ts))
7689+
ts->events |= CB_EVENT_WRITABLE;
7690+
break;
7691+
}
7692+
if (send_ret < 0)
7693+
break;
76457694
desc->flags |= PKT_FLAG_SENT;
76467695
desc->flags &= ~PKT_FLAG_RETRANS;
76477696
if (is_retrans)
@@ -7697,6 +7746,7 @@ int wolfIP_poll(struct wolfIP *s, uint64_t now)
76977746
while (desc) {
76987747
struct wolfIP_udp_datagram *udp = (struct wolfIP_udp_datagram *)(t->txmem + desc->pos + sizeof(*desc));
76997748
unsigned int tx_if = wolfIP_socket_if_idx(t);
7749+
int send_ret = 0;
77007750
#ifdef ETHERNET
77017751
struct ipconf *conf = wolfIP_ipconf_at(s, tx_if);
77027752
ip4 nexthop = wolfIP_select_nexthop(conf, t->remote_ip);
@@ -7737,15 +7787,19 @@ int wolfIP_poll(struct wolfIP *s, uint64_t now)
77377787
if (esp_send(ll, (struct wolfIP_ip_packet *)udp, len) == 1) {
77387788
/* ipsec not configured on this interface.
77397789
* send plaintext. */
7740-
wolfIP_ll_send_frame(s, tx_if, udp, desc->len);
7790+
send_ret = wolfIP_ll_send_frame(s, tx_if, udp, desc->len);
77417791
}
77427792
} else {
7743-
wolfIP_ll_send_frame(s, tx_if, udp, desc->len);
7793+
send_ret = wolfIP_ll_send_frame(s, tx_if, udp, desc->len);
77447794
}
77457795
#else
7746-
wolfIP_ll_send_frame(s, tx_if, udp, desc->len);
7796+
send_ret = wolfIP_ll_send_frame(s, tx_if, udp, desc->len);
77477797
#endif /* WOLFIP_ESP */
77487798
}
7799+
if (send_ret == -WOLFIP_EAGAIN)
7800+
break;
7801+
if (send_ret < 0)
7802+
break;
77497803
fifo_pop(&t->sock.udp.txbuf);
77507804
desc = fifo_peek(&t->sock.udp.txbuf);
77517805
}
@@ -7756,6 +7810,7 @@ int wolfIP_poll(struct wolfIP *s, uint64_t now)
77567810
while (desc) {
77577811
struct wolfIP_icmp_packet *icmp = (struct wolfIP_icmp_packet *)(t->txmem + desc->pos + sizeof(*desc));
77587812
unsigned int tx_if = wolfIP_socket_if_idx(t);
7813+
int send_ret = 0;
77597814
#ifdef ETHERNET
77607815
struct ipconf *conf = wolfIP_ipconf_at(s, tx_if);
77617816
ip4 nexthop = wolfIP_select_nexthop(conf, t->remote_ip);
@@ -7792,15 +7847,19 @@ int wolfIP_poll(struct wolfIP *s, uint64_t now)
77927847
if (esp_send(ll, (struct wolfIP_ip_packet *)icmp, len) == 1) {
77937848
/* ipsec not configured on this interface.
77947849
* send plaintext. */
7795-
wolfIP_ll_send_frame(s, tx_if, icmp, desc->len);
7850+
send_ret = wolfIP_ll_send_frame(s, tx_if, icmp, desc->len);
77967851
}
77977852
} else {
7798-
wolfIP_ll_send_frame(s, tx_if, icmp, desc->len);
7853+
send_ret = wolfIP_ll_send_frame(s, tx_if, icmp, desc->len);
77997854
}
78007855
#else
7801-
wolfIP_ll_send_frame(s, tx_if, icmp, desc->len);
7856+
send_ret = wolfIP_ll_send_frame(s, tx_if, icmp, desc->len);
78027857
#endif /* WOLFIP_ESP */
78037858
}
7859+
if (send_ret == -WOLFIP_EAGAIN)
7860+
break;
7861+
if (send_ret < 0)
7862+
break;
78047863
fifo_pop(&t->sock.udp.txbuf);
78057864
desc = fifo_peek(&t->sock.udp.txbuf);
78067865
}

0 commit comments

Comments
 (0)