summaryrefslogtreecommitdiff
path: root/regress/sys/netinet/pmtu/tcp_atomicfrag6.py
diff options
context:
space:
mode:
Diffstat (limited to 'regress/sys/netinet/pmtu/tcp_atomicfrag6.py')
-rwxr-xr-xregress/sys/netinet/pmtu/tcp_atomicfrag6.py78
1 files changed, 78 insertions, 0 deletions
diff --git a/regress/sys/netinet/pmtu/tcp_atomicfrag6.py b/regress/sys/netinet/pmtu/tcp_atomicfrag6.py
new file mode 100755
index 00000000000..d0646b544d5
--- /dev/null
+++ b/regress/sys/netinet/pmtu/tcp_atomicfrag6.py
@@ -0,0 +1,78 @@
+#!/usr/local/bin/python2.7
+
+import os
+from addr import *
+from scapy.all import *
+
+e=Ether(src=LOCAL_MAC, dst=REMOTE_MAC)
+ip6=IPv6(src=FAKE_NET_ADDR6, dst=REMOTE_ADDR6)
+port=os.getpid() & 0xffff
+
+print "Send SYN packet, receive SYN+ACK."
+syn=TCP(sport=port, dport='chargen', seq=1, flags='S', window=(2**16)-1)
+synack=srp1(e/ip6/syn, iface=LOCAL_IF, timeout=5)
+
+if synack is None:
+ print "ERROR: no SYN+ACK from chargen server received"
+ exit(1)
+
+print "Send ACK packet, receive chargen data."
+ack=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='A',
+ ack=synack.seq+1, window=(2**16)-1)
+data=srp1(e/ip6/ack, iface=LOCAL_IF, timeout=5)
+
+if data is None:
+ print "ERROR: no data from chargen server received"
+ exit(1)
+
+print "Fill our receive buffer."
+time.sleep(1)
+
+print "Send ICMP6 packet too big packet with MTU 1272."
+icmp6=ICMPv6PacketTooBig(mtu=1272)/data.payload
+sendp(e/IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/icmp6, iface=LOCAL_IF)
+
+print "Path MTU discovery will resend first data with length 1272."
+# srp1 cannot be used, fragment answer will not match on outgoing udp packet
+if os.fork() == 0:
+ time.sleep(1)
+ sendp(e/ip6/ack, iface=LOCAL_IF)
+ os._exit(0)
+
+ans=sniff(iface=LOCAL_IF, timeout=3, filter=
+ "ip6 and src "+ip6.dst+" and dst "+ip6.src+" and proto ipv6-frag")
+
+for a in ans:
+ fh=a.payload.payload
+ if fh.offset != 0 or fh.nh != (ip6/syn).nh:
+ continue
+ th=fh.payload
+ if th.sport != syn.dport or th.dport != syn.sport:
+ continue
+ frag=a
+ break
+else:
+ print "ERROR: no fragement retransmit from chargen server received"
+ exit(1)
+
+print "Cleanup the other's socket with a reset packet."
+rst=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='AR',
+ ack=synack.seq+1)
+sendp(e/ip6/rst, iface=LOCAL_IF)
+
+if frag.offset != 0:
+ print "ERROR: TCP fragment is not atomic, offset is %d." % frag.offset
+ exit(1)
+
+if frag.m != 0:
+ print "ERROR: TCP fragment is not atomic, more fragment bit is set."
+ exit(1)
+
+print "Atomic fragment contains 8 octet header, so expected len is 1280"
+flen = frag.plen + len(IPv6())
+print "flen=%d" % flen
+if flen != 1280:
+ print "ERROR: TCP atomic fragment len is %d, expected 1280." % flen
+ exit(1)
+
+exit(0)