Issue generating TCP RST reply from the switch

8 views
Skip to first unread message

Sergio Gutierrez

unread,
Oct 24, 2022, 12:07:27 PM10/24/22
to p4-dev
Dear all.

As a simple exercise to get familiar with the switch programming, I am trying to implement a simple behavior where the switch replies with a TCP RST packet upon the reception of a TCP SYN.

I am defining my TCP header as follows:

header tcp_t {
   bit<16>  src_port;
   bit<16>  dst_port;
   bit<32>  seq_no;
   bit<32>  ack_no;
   bit<4>   data_offset;
   bit<3>   res;
   bit<3>   ecn;
   bit<1>   urg;
   bit<1>   ack;
   bit<1>   psh;
   bit<1>   rst;
   bit<1>   syn;
   bit<1>   fin;
   bit<16>  window;
   bit<16>  checksum;
   bit<16>  urgent_ptr;    
}

And also, I am defining some fields within the local metadata structure:

struct local_metadata_t {
       @field_list(1)
       port_num_t ingress_port;

       bit<1> isSyn;
       bit<16> tcp_src_port;
       bit<16> tcp_dst_port;

       bit<32> ip_src_addr;
       bit<32> ip_dst_addr;

       bit<48> eth_src_addr;
       bit<48> eth_dst_addr;

       bit<32> tcp_seq;
        

}

Then, in the state where I parse TCP packets, I read some of the values to the local metadata struct:

    state parse_tcp {
       packet.extract(hdr.tcp);

       if(hdr.tcp.syn == 1){
               local_metadata.isSyn = 1;
               local_metadata.tcp_src_port = hdr.tcp.src_port;
               local_metadata.tcp_dst_port = hdr.tcp.dst_port;
               local_metadata.ip_src_addr = hdr.ipv4.src_addr;
               local_metadata.ip_dst_addr = hdr.ipv4.dst_addr;
               local_metadata.eth_src_addr = hdr.ethernet.src_addr;
               local_metadata.eth_dst_addr = hdr.ethernet.dst_addr;
               local_metadata.tcp_seq =hdr.tcp.seq_no;
                
       }
       transition accept;
   }


Finally, in the apply block of my Ingress Pipeline Implementation, I do the following things to build the RST reply:

       if(hdr.tcp.isValid() && hdr.tcp.syn == 1) {
               tcp_sessions.apply();
               hdr.tcp.setInvalid();
               hdr.tcp.setValid();
               hdr.tcp.rst=1;
               hdr.tcp.syn=0;
               hdr.tcp.ack=1;
               hdr.tcp.ack_no = local_metadata.tcp_seq + 1;
               hdr.tcp.seq_no = 0;
               hdr.tcp.window = 0;
               hdr.tcp.data_offset = 5;
               hdr.tcp.src_port = local_metadata.tcp_dst_port;
               hdr.tcp.dst_port = local_metadata.tcp_src_port;
               hdr.ipv4.src_addr = local_metadata.ip_dst_addr;
               hdr.ipv4.dst_addr = local_metadata.ip_src_addr;
               hdr.ethernet.src_addr = local_metadata.eth_dst_addr;
               hdr.ethernet.dst_addr = local_metadata.eth_src_addr;
               standard_metadata.egress_spec = local_metadata.ingress_port;
            }

When I check the reply in the originating host, I see that the TCP RST packet is being replied indeed. However, it seems the packet is not adequately processed since the application does not seem to close the connection but it times out instead. When checking with tcpdump/wireshark, the RST packet contains indeed the 20 bytes that were sent as options in the SYN packet but in the reply these bytes are not recognized as options but they are as RST cause. 

I tried adding the options field to the TCP header (20 bytes) and leaving it blank when setting the other fields in the apply block, but the behavior is the same. 

Comparing my experiment with for instance sending a SYN packet to a closed port, the difference I see is the TCP RST reply packet does not contain the options field but 6 bytes of ethernet padding.

What else should I consider in order to be able to reproduce this behavior on the switch?

Thanks in advance for your attention.

Kind regards,

--
Sergio Gutiérrez

Radostin Stoyanov

unread,
Oct 24, 2022, 12:26:20 PM10/24/22
to Sergio Gutierrez, p4-dev
Dear Sergio,

Would you be able to confirm if the TCP checksum of the response packet is correct? You should be able to check this with Wireshark.

Best wishes,
Radostin

--
You received this message because you are subscribed to the Google Groups "p4-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to p4-dev+un...@lists.p4.org.
To view this discussion on the web visit https://groups.google.com/a/lists.p4.org/d/msgid/p4-dev/CAO7Dj-dju4MKa8gUwrO1fxfNnOLY5CcW6eDkmcb7B%3D31vTtM7A%40mail.gmail.com.

Sergio Gutierrez

unread,
Oct 24, 2022, 12:56:07 PM10/24/22
to Radostin Stoyanov, p4-dev

Thanks for your reply Radostin.

Actually, it seems it is not correct. When checking with wireshark, it reports the checksum is incorrect.

This is how I am updating checksum in the switch:

        update_checksum_with_payload(
           hdr.tcp.isValid(),
           {
               hdr.ipv4.src_addr,
               hdr.ipv4.dst_addr,
               8w0,
               hdr.ipv4.protocol,
               40w0,
               hdr.tcp.src_port,
               hdr.tcp.dst_port,
               hdr.tcp.seq_no,
               hdr.tcp.ack_no,
               hdr.tcp.data_offset,
               hdr.tcp.res,
               hdr.tcp.ecn,
               hdr.tcp.urg,
               hdr.tcp.ack,
               hdr.tcp.psh,
               hdr.tcp.rst,
               hdr.tcp.syn,
               hdr.tcp.fin,
               hdr.tcp.window,
               16w0,
               hdr.tcp.urgent_ptr,
               hdr.tcp.options

           },
           hdr.tcp.checksum, HashAlgorithm.csum16);

   }

Perhaps, am I missing something in this calculation?

Thanks in advance for the attention.
--
Sergio Gutiérrez

hem...@mnkcg.com

unread,
Oct 24, 2022, 1:03:15 PM10/24/22
to sag...@gmail.com, rado...@stoyanov.io, p4-...@lists.p4.org

For any layer-4 checksum issues, please see this test I added to p4c when an incorrect checksum was reported for TCP with options.

 

https://github.com/p4lang/p4c/blob/main/testdata/p4_16_samples/checksum-l4-bmv2.p4

 

Hemant  

Sergio Gutierrez

unread,
Oct 24, 2022, 1:14:54 PM10/24/22
to hem...@mnkcg.com, rado...@stoyanov.io, p4-...@lists.p4.org
Thanks Hemant and Radostin.

Indeed, the problem was the checksum calculation. I fixed according to the code provided by Hemant and now it is working fine.

Best regards,
--
Sergio Gutiérrez
Reply all
Reply to author
Forward
0 new messages