From: Chia-Yu Chang <[email protected]>

Currently, GRO does not flush packets when the CWR bit is set.
A corresponding self-test is being added, in which the CWR flag
is set for two consecutive packets, but the first packet with the
CWR flag set will not be flushed immediately.

+===================+==========+===============+===========+
|     Packet id     | CWR flag |    Payload    | Flushing? |
+===================+==========+===============+===========+
|         0         |     0    |  PAYLOAD_LEN  |     0     |
|        ...        |     0    |  PAYLOAD_LEN  |     1     |
+-------------------+----------+---------------+-----------+
| NUM_PACKETS/2 - 1 |     1    |  payload_len  |     0     |
|   NUM_PACKETS/2   |     1    |  payload_len  |     1     |
+-------------------+----------+---------------+-----------+
|        ...        |     0    |  PAYLOAD_LEN  |     0     |
|   NUM_PACKETS     |     0    |  PAYLOAD_LEN  |     1     |
+===================+==========+===============+===========+

Signed-off-by: Chia-Yu Chang <[email protected]>
Acked-by: Paolo Abeni <[email protected]>

---
v7:
- Update comments
---
 tools/testing/selftests/drivers/net/gro.c | 81 ++++++++++++++++-------
 1 file changed, 58 insertions(+), 23 deletions(-)

diff --git a/tools/testing/selftests/drivers/net/gro.c 
b/tools/testing/selftests/drivers/net/gro.c
index e894037d2e3e..736da13f85a0 100644
--- a/tools/testing/selftests/drivers/net/gro.c
+++ b/tools/testing/selftests/drivers/net/gro.c
@@ -11,8 +11,8 @@
  * 2.ack
  *  Pure ACK does not coalesce.
  * 3.flags
- *  Specific test cases: no packets with PSH, SYN, URG, RST set will
- *  be coalesced.
+ *  Specific test cases: no packets with PSH, SYN, URG, RST, CWR set
+ *  will be coalesced.
  * 4.tcp
  *  Packets with incorrect checksum, non-consecutive seqno and
  *  different TCP header options shouldn't coalesce. Nit: given that
@@ -333,32 +333,58 @@ static void create_packet(void *buf, int seq_offset, int 
ack_offset,
        fill_datalinklayer(buf);
 }
 
-/* send one extra flag, not first and not last pkt */
-static void send_flags(int fd, struct sockaddr_ll *daddr, int psh, int syn,
-                      int rst, int urg)
+#ifndef TH_CWR
+#define TH_CWR 0x80
+#endif
+static void set_flags(struct tcphdr *tcph, int payload_len, int psh, int syn,
+                     int rst, int urg, int cwr)
 {
-       static char flag_buf[MAX_HDR_LEN + PAYLOAD_LEN];
-       static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
-       int payload_len, pkt_size, flag, i;
-       struct tcphdr *tcph;
-
-       payload_len = PAYLOAD_LEN * psh;
-       pkt_size = total_hdr_len + payload_len;
-       flag = NUM_PACKETS / 2;
-
-       create_packet(flag_buf, flag * payload_len, 0, payload_len, 0);
-
-       tcph = (struct tcphdr *)(flag_buf + tcp_offset);
        tcph->psh = psh;
        tcph->syn = syn;
        tcph->rst = rst;
        tcph->urg = urg;
+       if (cwr)
+               tcph->th_flags |= TH_CWR;
+       else
+               tcph->th_flags &= ~TH_CWR;
        tcph->check = 0;
        tcph->check = tcp_checksum(tcph, payload_len);
+}
+
+/* send extra flags of the (NUM_PACKETS / 2) and (NUM_PACKETS / 2 - 1)
+ * pkts, not first and not last pkt
+ */
+static void send_flags(int fd, struct sockaddr_ll *daddr, int psh, int syn,
+                      int rst, int urg, int cwr)
+{
+       static char flag_buf[2][MAX_HDR_LEN + PAYLOAD_LEN];
+       static char buf[MAX_HDR_LEN + PAYLOAD_LEN];
+       int payload_len, pkt_size, i;
+       struct tcphdr *tcph;
+       int flag[2];
+
+       payload_len = PAYLOAD_LEN * (psh || cwr);
+       pkt_size = total_hdr_len + payload_len;
+       flag[0] = NUM_PACKETS / 2;
+       flag[1] = NUM_PACKETS / 2 - 1;
+
+       /* Create and configure packets with flags
+        */
+       for (i = 0; i < 2; i++) {
+               if (flag[i] > 0) {
+                       create_packet(flag_buf[i], flag[i] * payload_len, 0,
+                                     payload_len, 0);
+                       tcph = (struct tcphdr *)(flag_buf[i] + tcp_offset);
+                       set_flags(tcph, payload_len, psh, syn, rst, urg, cwr);
+               }
+       }
 
        for (i = 0; i < NUM_PACKETS + 1; i++) {
-               if (i == flag) {
-                       write_packet(fd, flag_buf, pkt_size, daddr);
+               if (i == flag[0]) {
+                       write_packet(fd, flag_buf[0], pkt_size, daddr);
+                       continue;
+               } else if (i == flag[1] && cwr) {
+                       write_packet(fd, flag_buf[1], pkt_size, daddr);
                        continue;
                }
                create_packet(buf, i * PAYLOAD_LEN, 0, PAYLOAD_LEN, 0);
@@ -1021,16 +1047,19 @@ static void gro_sender(void)
                send_ack(txfd, &daddr);
                write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
        } else if (strcmp(testname, "flags") == 0) {
-               send_flags(txfd, &daddr, 1, 0, 0, 0);
+               send_flags(txfd, &daddr, 1, 0, 0, 0, 0);
                write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
 
-               send_flags(txfd, &daddr, 0, 1, 0, 0);
+               send_flags(txfd, &daddr, 0, 1, 0, 0, 0);
                write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
 
-               send_flags(txfd, &daddr, 0, 0, 1, 0);
+               send_flags(txfd, &daddr, 0, 0, 1, 0, 0);
                write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
 
-               send_flags(txfd, &daddr, 0, 0, 0, 1);
+               send_flags(txfd, &daddr, 0, 0, 0, 1, 0);
+               write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
+
+               send_flags(txfd, &daddr, 0, 0, 0, 0, 1);
                write_packet(txfd, fin_pkt, total_hdr_len, &daddr);
        } else if (strcmp(testname, "tcp") == 0) {
                send_changed_checksum(txfd, &daddr);
@@ -1166,6 +1195,12 @@ static void gro_receiver(void)
 
                printf("urg flag ends coalescing: ");
                check_recv_pkts(rxfd, correct_payload, 3);
+
+               correct_payload[0] = PAYLOAD_LEN;
+               correct_payload[1] = PAYLOAD_LEN * 2;
+               correct_payload[2] = PAYLOAD_LEN * 2;
+               printf("cwr flag ends coalescing: ");
+               check_recv_pkts(rxfd, correct_payload, 3);
        } else if (strcmp(testname, "tcp") == 0) {
                correct_payload[0] = PAYLOAD_LEN;
                correct_payload[1] = PAYLOAD_LEN;
-- 
2.34.1


Reply via email to