Here are some caveats and clarifications on the IPv6 fragmentation. First and foremost, make sure that you can make and send an unfragmented ICMPv6 echo request packet with Scapy, and receive a reply. Don't skip this step---even though your tunnelbroker or miredo tunnel may be working well enough for ping6 to succeed, your Scapy setup may have problems using it, as we discovered to be the case on MacOS Yosemite (cf. http://www.cs.dartmouth.edu/~sergey/netreads/miredo-scapy-macosx-issue.txt) Second, remember that the checksum (chksum) field of the ICMPv6 header must contain the correct checksum for the _unfragmented_ packet of the desired contents after reassembly, because this checksum will be checked after the fragmented packet is fully reassembled, and it has to match the full content, not that of any particular fragment. This is also true for UDP and TCP checksum fields. So you will need to compute it, and set it to that hard value as you build your packet. Remember, Scapy will compute the checksum fields if you set them to None and call build() or hexdump() on them. You will then find the checksum in the hexdump. Thirdly, remember that the ICMP or UDP or TCP checksum is calculated using elements of the IPv6 header such as the source and destination IPv6 addresses. If you try to compute it over just the ICMP or UDP or TCP layer alone, you will get a warning "WARNING: No IPv6 underlayer to compute checksum. Leaving null." meaning that the chksum calculation was skipped: >>> ICMPv6EchoRequest().build() WARNING: No IPv6 underlayer to compute checksum. Leaving null. '\x80\x00\x00\x00\x00\x00\x00\x00' ^^^^^^^^ chksum not calculated >>> (IPv6(dst='2604:5f00:ffff:fe00::1:53')/ICMPv6EchoRequest(data='sergey')).build() '`\x00\x00\x00\x00\x0e:@ \x01\x00\x00S\xaa\x06L\x14\x18>\xd1\xb8\x00W\xb7&\x04_\x00\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x01\x00S\x80\x00\xd4~\x00\x00\x00\x00sergey' ^^^^^ [Checksum calculated; or, better:] >>> hexdump(IPv6(dst='2604:5f00:ffff:fe00::1:53')/ICMPv6EchoRequest(data='sergey')) 0000 60 00 00 00 00 0E 3A 40 20 01 00 00 53 AA 06 4C `.....:@ ...S..L 0010 14 18 3E D1 B8 00 57 B7 26 04 5F 00 FF FF FE 00 ..>...W.&._..... 0020 00 00 00 00 00 01 00 53 80 00 D4 7E 00 00 00 00 .......S...~.... ^^^^^ 0030 73 65 72 67 65 79 sergey [Checksum calculated, but only correct for my src address, dst address, and payload.] [If you wonder, the ASCII code for ~ is 7E] So you must make sure to call build() or show2() on a packet that has the correct IPv6 layer already completed, otherwise your checksum will be incorrect and the packet will be rejected. Finally, miredo tunnels tend to lose packets, especially the first packet you send. So I recommend sending some expendable packet first to prime the tunnel. Otherwise you will see some ICMPv6 Time Exceeded packets arriving apparently out of order, because one of the fragments was lost, and the rest of the arrived fragments had to be discarded. This is why for my tests on MacOS I used >>> ll = [fh/unfragmented_ping_tested_to_work, fh/ping_fragment1, >>> fh/ping_fragment2] >>> sendp( ll , iface='tun0') to test my miredo-based solution; fh is the magic string '\x00\x00\x00\x1e' that miredo requires on my Yosemite (see miredo-scapy-macosx-issue.txt).