]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
sandbox: fix wget test failure after fixing wget issue
authorYasuharu Shibata <yasuharu.shibata@gmail.com>
Wed, 14 Aug 2024 12:41:07 +0000 (21:41 +0900)
committerTom Rini <trini@konsulko.com>
Thu, 15 Aug 2024 17:32:12 +0000 (11:32 -0600)
After applying the following patch, wget test on sandbox failed[1].

  Commit: cab7867cff ("net: wget: Support retransmission a dropped packet")

Here are two reasons why the test is failed and how to fix it:

1. tcp_ack is calculated by the wrong value.
   tcp_ack needs to be calculated by the received TCP payload size.
2. wget command may have a problem that HTTP response from server
   must be divided into more than two packets.
   In this commit, HTTP response is divided into two packets.

In addition, I fixed the HTTP response returned at the correct timing.

[1] https://lore.kernel.org/u-boot/CAFLszThEbk2Jr8OZ6Hj21wPSnJjgJhaDe037RqwHvwt1KjB3_A@mail.gmail.com/

Signed-off-by: Yasuharu Shibata <yasuharu.shibata@gmail.com>
Reported-by: Simon Glass <sjg@chromium.org>
test/cmd/wget.c

index 356a4dcd8fadbf0e7b69f46b144f395d20a6952c..b0feb21dc41806a92a90cf5952b76a498cc13780 100644 (file)
@@ -26,6 +26,8 @@
 #define SHIFT_TO_TCPHDRLEN_FIELD(x) ((x) << 4)
 #define LEN_B_TO_DW(x) ((x) >> 2)
 
+int net_set_ack_options(union tcp_build_pkt *b);
+
 static int sb_arp_handler(struct udevice *dev, void *packet,
                          unsigned int len)
 {
@@ -105,6 +107,10 @@ static int sb_ack_handler(struct udevice *dev, void *packet,
        const char *payload1 = "HTTP/1.1 200 OK\r\n"
                "Content-Length: 30\r\n\r\n\r\n"
                "<html><body>Hi</body></html>\r\n";
+       union tcp_build_pkt *b = (union tcp_build_pkt *)tcp;
+       const int recv_payload_len = len - net_set_ack_options(b) - IP_HDR_SIZE - ETHER_HDR_SIZE;
+       static int next_seq;
+       const int bottom_payload_len = 10;
 
        /* Don't allow the buffer to overrun */
        if (priv->recv_packets >= PKTBUFSRX)
@@ -119,13 +125,31 @@ static int sb_ack_handler(struct udevice *dev, void *packet,
        tcp_send->tcp_dst = tcp->tcp_src;
        data = (void *)tcp_send + IP_TCP_HDR_SIZE;
 
-       if (ntohl(tcp->tcp_seq) == 1 && ntohl(tcp->tcp_ack) == 1) {
+       if (ntohl(tcp->tcp_seq) == 1 && ntohl(tcp->tcp_ack) == 1 && recv_payload_len == 0) {
+               // ignore ACK for three-way handshaking
+               return 0;
+       } else if (ntohl(tcp->tcp_seq) == 1 && ntohl(tcp->tcp_ack) == 1) {
+               // recv HTTP request message and reply top half data
                tcp_send->tcp_seq = htonl(ntohl(tcp->tcp_ack));
-               tcp_send->tcp_ack = htonl(ntohl(tcp->tcp_seq) + 1);
-               payload_len = strlen(payload1);
+               tcp_send->tcp_ack = htonl(ntohl(tcp->tcp_seq) + recv_payload_len);
+
+               payload_len = strlen(payload1) - bottom_payload_len;
                memcpy(data, payload1, payload_len);
                tcp_send->tcp_flags = TCP_ACK;
-       } else if (ntohl(tcp->tcp_seq) == 2) {
+
+               next_seq = ntohl(tcp_send->tcp_seq) + payload_len;
+       } else if (ntohl(tcp->tcp_ack) == next_seq) {
+               // reply bottom half data
+               const int top_payload_len = strlen(payload1) - bottom_payload_len;
+
+               tcp_send->tcp_seq = htonl(next_seq);
+               tcp_send->tcp_ack = htonl(ntohl(tcp->tcp_seq) + recv_payload_len);
+
+               payload_len = bottom_payload_len;
+               memcpy(data, payload1 + top_payload_len, payload_len);
+               tcp_send->tcp_flags = TCP_ACK;
+       } else {
+               // close connection
                tcp_send->tcp_seq = htonl(ntohl(tcp->tcp_ack));
                tcp_send->tcp_ack = htonl(ntohl(tcp->tcp_seq) + 1);
                payload_len = 0;
@@ -148,11 +172,9 @@ static int sb_ack_handler(struct udevice *dev, void *packet,
                          pkt_len,
                          IPPROTO_TCP);
 
-       if (ntohl(tcp->tcp_seq) == 1 || ntohl(tcp->tcp_seq) == 2) {
-               priv->recv_packet_length[priv->recv_packets] =
-                       ETHER_HDR_SIZE + IP_TCP_HDR_SIZE + payload_len;
-               ++priv->recv_packets;
-       }
+       priv->recv_packet_length[priv->recv_packets] =
+               ETHER_HDR_SIZE + IP_TCP_HDR_SIZE + payload_len;
+       ++priv->recv_packets;
 
        return 0;
 }