Uploaded image for project: 'Fast Datapath Product'
  1. Fast Datapath Product
  2. FDP-136

Userspace conntrack doesn't NAT inner packet if it's fragmented

    • Icon: Task Task
    • Resolution: Unresolved
    • Icon: Normal Normal
    • None
    • rhel-9
    • openvswitch3.2
    • None
    • 8
    • False
    • Hide

      None

      Show
      None
    • False
    • Hide

      Given a system administrator using OVS with the userspace conntrack datapath,

      When a fragmented packet requires NAT, 

      Then the NAT rules should still apply and the flow should be correctly tracked and translated as long as fragments are valid and complete.

      Show
      Given a system administrator using OVS with the userspace conntrack datapath, When a fragmented packet requires NAT,  Then the NAT rules should still apply and the flow should be correctly tracked and translated as long as fragments are valid and complete.
    • openvswitch3.2-3.2.0-135.el9fdp
    • rhel-10
    • None
    • rhel-net-ovs-dpdk
    • ssg_networking
    • OVS/DPDK - FDP-25.D
    • 1

      This can be reproduced by applying the following diff for system-tests:

      diff --git a/tests/system-traffic.at b/tests/system-traffic.at
      index 375a8aa2f..78ab7d7de 100644
      --- a/tests/system-traffic.at
      +++ b/tests/system-traffic.at
      @@ -7786,26 +7786,13 @@ AT_CHECK([ovs-ofctl packet-out br0 "in_port=ovs-client,\
       packet=00000000102000000000201008004500001C000040000A11C762C0A8140AC0A814140001000200080000,actions=resubmit(,0)"])
       dnl Send UDP response server->client
       AT_CHECK([ovs-ofctl packet-out br0 "in_port=ovs-server,\
      -packet=00000000201000000000102008004500001C000040000A11D162C0A80A14C0A8140A0002000100080000,actions=resubmit(,0)"])
      +packet=00000000201000000000102008004500001C000020000A11D162C0A80A14C0A8140A0002000100080000,actions=resubmit(,0)"])
       dnl Fake router sending ICMP need frag router->server
       AT_CHECK([ovs-ofctl packet-out br0 "in_port=ovs-client,\
      -packet=000000001020000000002000080045000038011F0000FF011140C0A81401C0A814140304F778000005784500001C000040000A11C762C0A81414C0A8140A0002000100080000,\
      +packet=000000001020000000002000080045000038011F0000FF011140C0A81401C0A814140304f778000005784500001C000020000A11e762C0A81414C0A8140A0002000100080000,\
       actions=resubmit(,0)"
       ])
       
      -AT_CHECK([ovs-appctl revalidator/purge], [0])
      -AT_CHECK([ovs-ofctl -O OpenFlow15 dump-flows br0 | ofctl_strip | sort ], [0], [dnl
      - n_packets=3, n_bytes=154, reset_counts ip actions=ct(table=1,zone=42,nat)
      - table=1, n_packets=1, n_bytes=42, reset_counts ct_state=+new+trk,ip,in_port=1 actions=ct(commit,table=2,zone=42,nat(dst=192.168.10.20))
      - table=1, n_packets=1, n_bytes=42, reset_counts ip actions=resubmit(,2)
      - table=1, n_packets=1, n_bytes=70, reset_counts ct_state=+rel-rpl+trk,icmp actions=ct(commit,table=2,zone=42,nat)
      - table=2, n_packets=1, n_bytes=42, reset_counts ct_state=+new+trk,ip,in_port=1 actions=output:2
      - table=2, n_packets=1, n_bytes=42, reset_counts ct_state=+rpl+trk,ip,in_port=2 actions=output:1
      - table=2, n_packets=1, n_bytes=70, reset_counts ct_state=+rel+trk,icmp,in_port=1 actions=output:2
      - table=2, reset_counts ct_state=+rel+trk,icmp,in_port=2 actions=output:1
      -OFPST_FLOW reply (OF1.5):
      -])
      -
       AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "192.168.20.10"], [0], [dnl
       udp,orig=(src=192.168.20.10,dst=192.168.20.20,sport=1,dport=2),reply=(src=192.168.10.20,dst=192.168.20.10,sport=2,dport=1),zone=42
       ])
      @@ -7813,7 +7800,7 @@ udp,orig=(src=192.168.20.10,dst=192.168.20.20,sport=1,dport=2),reply=(src=192.16
       OVS_WAIT_UNTIL([ovs-pcap server.pcap | grep 000000001020000000002000])
       
       AT_CHECK([ovs-pcap server.pcap | grep 000000001020000000002000], [0], [dnl
      -000000001020000000002000080045000038011f0000ff011b40c0a81401c0a80a140304f778000005784500001c000040000a11d162c0a80a14c0a8140a0002000100080000
      +000000001020000000002000080045000038011f0000ff011b40c0a81401c0a80a140304f778000005784500001c000020000a11f162c0a80a14c0a8140a0002000100080000
       ])
       
       dnl Check the ICMP error in reply direction
      @@ -7832,19 +7819,6 @@ packet=000000002010000000002000080045000038011F0000FF01114AC0A81401C0A8140A0304F
       actions=resubmit(,0)"
       ])
       
      -AT_CHECK([ovs-appctl revalidator/purge], [0])
      -AT_CHECK([ovs-ofctl -O OpenFlow15 dump-flows br0 | ofctl_strip | sort ], [0], [dnl
      - n_packets=5, n_bytes=266, reset_counts ip actions=ct(table=1,zone=42,nat)
      - table=1, n_packets=1, n_bytes=70, reset_counts ct_state=+rel-rpl+trk,icmp actions=ct(commit,table=2,zone=42,nat)
      - table=1, n_packets=2, n_bytes=112, reset_counts ip actions=resubmit(,2)
      - table=1, n_packets=2, n_bytes=84, reset_counts ct_state=+new+trk,ip,in_port=1 actions=ct(commit,table=2,zone=42,nat(dst=192.168.10.20))
      - table=2, n_packets=1, n_bytes=42, reset_counts ct_state=+rpl+trk,ip,in_port=2 actions=output:1
      - table=2, n_packets=1, n_bytes=70, reset_counts ct_state=+rel+trk,icmp,in_port=1 actions=output:2
      - table=2, n_packets=1, n_bytes=70, reset_counts ct_state=+rel+trk,icmp,in_port=2 actions=output:1
      - table=2, n_packets=2, n_bytes=84, reset_counts ct_state=+new+trk,ip,in_port=1 actions=output:2
      -OFPST_FLOW reply (OF1.5):
      -])
      -
       AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "192.168.20.10"], [0], [dnl
       udp,orig=(src=192.168.20.10,dst=192.168.20.20,sport=1,dport=2),reply=(src=192.168.10.20,dst=192.168.20.10,sport=2,dport=1),zone=42
       ])
      

      Which will pass after the following code adjustment:

      diff --git a/lib/conntrack.c b/lib/conntrack.c
      index b533dd3df..5d78975cb 100644
      --- a/lib/conntrack.c
      +++ b/lib/conntrack.c
      @@ -1523,10 +1523,6 @@ extract_l3_ipv4(struct conn_key *key, const void *data, size_t size,
               return false;
           }
       
      -    if (IP_IS_FRAGMENT(ip->ip_frag_off)) {
      -        return false;
      -    }
      -
           if (validate_checksum && csum(data, ip_len) != 0) {
               COVERAGE_INC(conntrack_l3csum_err);
               return false;
      

      However I'm not sure if that's the right thing to do.

              rh-ee-mpattric Mike Pattrick
              amusil@redhat.com Ales Musil
              Hekai Wang Hekai Wang
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated: