Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0
0003 
0004 # Kselftest framework requirement - SKIP code is 4.
0005 ksft_skip=4
0006 
0007 # Conntrack needs to reassemble fragments in order to have complete
0008 # packets for rule matching.  Reassembly can lead to packet loss.
0009 
0010 # Consider the following setup:
0011 #            +--------+       +---------+       +--------+
0012 #            |Router A|-------|Wanrouter|-------|Router B|
0013 #            |        |.IPIP..|         |..IPIP.|        |
0014 #            +--------+       +---------+       +--------+
0015 #           /                  mtu 1400                   \
0016 #          /                                               \
0017 #+--------+                                                 +--------+
0018 #|Client A|                                                 |Client B|
0019 #|        |                                                 |        |
0020 #+--------+                                                 +--------+
0021 
0022 # Router A and Router B use IPIP tunnel interfaces to tunnel traffic
0023 # between Client A and Client B over WAN. Wanrouter has MTU 1400 set
0024 # on its interfaces.
0025 
0026 rnd=$(mktemp -u XXXXXXXX)
0027 rx=$(mktemp)
0028 
0029 r_a="ns-ra-$rnd"
0030 r_b="ns-rb-$rnd"
0031 r_w="ns-rw-$rnd"
0032 c_a="ns-ca-$rnd"
0033 c_b="ns-cb-$rnd"
0034 
0035 checktool (){
0036         if ! $1 > /dev/null 2>&1; then
0037                 echo "SKIP: Could not $2"
0038                 exit $ksft_skip
0039         fi
0040 }
0041 
0042 checktool "iptables --version" "run test without iptables"
0043 checktool "ip -Version" "run test without ip tool"
0044 checktool "which socat" "run test without socat"
0045 checktool "ip netns add ${r_a}" "create net namespace"
0046 
0047 for n in ${r_b} ${r_w} ${c_a} ${c_b};do
0048         ip netns add ${n}
0049 done
0050 
0051 cleanup() {
0052         for n in ${r_a} ${r_b} ${r_w} ${c_a} ${c_b};do
0053                 ip netns del ${n}
0054         done
0055         rm -f ${rx}
0056 }
0057 
0058 trap cleanup EXIT
0059 
0060 test_path() {
0061         msg="$1"
0062 
0063         ip netns exec ${c_b} socat -t 3 - udp4-listen:5000,reuseaddr > ${rx} < /dev/null &
0064 
0065         sleep 1
0066         for i in 1 2 3; do
0067                 head -c1400 /dev/zero | tr "\000" "a" | \
0068                         ip netns exec ${c_a} socat -t 1 -u STDIN UDP:192.168.20.2:5000
0069         done
0070 
0071         wait
0072 
0073         bytes=$(wc -c < ${rx})
0074 
0075         if [ $bytes -eq 1400 ];then
0076                 echo "OK: PMTU $msg connection tracking"
0077         else
0078                 echo "FAIL: PMTU $msg connection tracking: got $bytes, expected 1400"
0079                 exit 1
0080         fi
0081 }
0082 
0083 # Detailed setup for Router A
0084 # ---------------------------
0085 # Interfaces:
0086 # eth0: 10.2.2.1/24
0087 # eth1: 192.168.10.1/24
0088 # ipip0: No IP address, local 10.2.2.1 remote 10.4.4.1
0089 # Routes:
0090 # 192.168.20.0/24 dev ipip0    (192.168.20.0/24 is subnet of Client B)
0091 # 10.4.4.1 via 10.2.2.254      (Router B via Wanrouter)
0092 # No iptables rules at all.
0093 
0094 ip link add veth0 netns ${r_a} type veth peer name veth0 netns ${r_w}
0095 ip link add veth1 netns ${r_a} type veth peer name veth0 netns ${c_a}
0096 
0097 l_addr="10.2.2.1"
0098 r_addr="10.4.4.1"
0099 ip netns exec ${r_a} ip link add ipip0 type ipip local ${l_addr} remote ${r_addr} mode ipip || exit $ksft_skip
0100 
0101 for dev in lo veth0 veth1 ipip0; do
0102     ip -net ${r_a} link set $dev up
0103 done
0104 
0105 ip -net ${r_a} addr add 10.2.2.1/24 dev veth0
0106 ip -net ${r_a} addr add 192.168.10.1/24 dev veth1
0107 
0108 ip -net ${r_a} route add 192.168.20.0/24 dev ipip0
0109 ip -net ${r_a} route add 10.4.4.0/24 via 10.2.2.254
0110 
0111 ip netns exec ${r_a} sysctl -q net.ipv4.conf.all.forwarding=1 > /dev/null
0112 
0113 # Detailed setup for Router B
0114 # ---------------------------
0115 # Interfaces:
0116 # eth0: 10.4.4.1/24
0117 # eth1: 192.168.20.1/24
0118 # ipip0: No IP address, local 10.4.4.1 remote 10.2.2.1
0119 # Routes:
0120 # 192.168.10.0/24 dev ipip0    (192.168.10.0/24 is subnet of Client A)
0121 # 10.2.2.1 via 10.4.4.254      (Router A via Wanrouter)
0122 # No iptables rules at all.
0123 
0124 ip link add veth0 netns ${r_b} type veth peer name veth1 netns ${r_w}
0125 ip link add veth1 netns ${r_b} type veth peer name veth0 netns ${c_b}
0126 
0127 l_addr="10.4.4.1"
0128 r_addr="10.2.2.1"
0129 
0130 ip netns exec ${r_b} ip link add ipip0 type ipip local ${l_addr} remote ${r_addr} mode ipip || exit $ksft_skip
0131 
0132 for dev in lo veth0 veth1 ipip0; do
0133         ip -net ${r_b} link set $dev up
0134 done
0135 
0136 ip -net ${r_b} addr add 10.4.4.1/24 dev veth0
0137 ip -net ${r_b} addr add 192.168.20.1/24 dev veth1
0138 
0139 ip -net ${r_b} route add 192.168.10.0/24 dev ipip0
0140 ip -net ${r_b} route add 10.2.2.0/24 via 10.4.4.254
0141 ip netns exec ${r_b} sysctl -q net.ipv4.conf.all.forwarding=1 > /dev/null
0142 
0143 # Client A
0144 ip -net ${c_a} addr add 192.168.10.2/24 dev veth0
0145 ip -net ${c_a} link set dev lo up
0146 ip -net ${c_a} link set dev veth0 up
0147 ip -net ${c_a} route add default via 192.168.10.1
0148 
0149 # Client A
0150 ip -net ${c_b} addr add 192.168.20.2/24 dev veth0
0151 ip -net ${c_b} link set dev veth0 up
0152 ip -net ${c_b} link set dev lo up
0153 ip -net ${c_b} route add default via 192.168.20.1
0154 
0155 # Wan
0156 ip -net ${r_w} addr add 10.2.2.254/24 dev veth0
0157 ip -net ${r_w} addr add 10.4.4.254/24 dev veth1
0158 
0159 ip -net ${r_w} link set dev lo up
0160 ip -net ${r_w} link set dev veth0 up mtu 1400
0161 ip -net ${r_w} link set dev veth1 up mtu 1400
0162 
0163 ip -net ${r_a} link set dev veth0 mtu 1400
0164 ip -net ${r_b} link set dev veth0 mtu 1400
0165 
0166 ip netns exec ${r_w} sysctl -q net.ipv4.conf.all.forwarding=1 > /dev/null
0167 
0168 # Path MTU discovery
0169 # ------------------
0170 # Running tracepath from Client A to Client B shows PMTU discovery is working
0171 # as expected:
0172 #
0173 # clienta:~# tracepath 192.168.20.2
0174 # 1?: [LOCALHOST]                      pmtu 1500
0175 # 1:  192.168.10.1                                          0.867ms
0176 # 1:  192.168.10.1                                          0.302ms
0177 # 2:  192.168.10.1                                          0.312ms pmtu 1480
0178 # 2:  no reply
0179 # 3:  192.168.10.1                                          0.510ms pmtu 1380
0180 # 3:  192.168.20.2                                          2.320ms reached
0181 # Resume: pmtu 1380 hops 3 back 3
0182 
0183 # ip netns exec ${c_a} traceroute --mtu 192.168.20.2
0184 
0185 # Router A has learned PMTU (1400) to Router B from Wanrouter.
0186 # Client A has learned PMTU (1400 - IPIP overhead = 1380) to Client B
0187 # from Router A.
0188 
0189 #Send large UDP packet
0190 #---------------------
0191 #Now we send a 1400 bytes UDP packet from Client A to Client B:
0192 
0193 # clienta:~# head -c1400 /dev/zero | tr "\000" "a" | socat -u STDIN UDP:192.168.20.2:5000
0194 test_path "without"
0195 
0196 # The IPv4 stack on Client A already knows the PMTU to Client B, so the
0197 # UDP packet is sent as two fragments (1380 + 20). Router A forwards the
0198 # fragments between eth1 and ipip0. The fragments fit into the tunnel and
0199 # reach their destination.
0200 
0201 #When sending the large UDP packet again, Router A now reassembles the
0202 #fragments before routing the packet over ipip0. The resulting IPIP
0203 #packet is too big (1400) for the tunnel PMTU (1380) to Router B, it is
0204 #dropped on Router A before sending.
0205 
0206 ip netns exec ${r_a} iptables -A FORWARD -m conntrack --ctstate NEW
0207 test_path "with"