Giter Site home page Giter Site logo

kavarenshko / plp-mtu-discovery Goto Github PK

View Code? Open in Web Editor NEW
22.0 1.0 9.0 22 KB

Perform Path MTU Discovery without relying on ICMP errors, which are often not delivered.

License: MIT License

C 98.62% Python 1.38%
icmp icmp-header ip ipv4 mtu path-mtu-discovery ping udp fragmentation

plp-mtu-discovery's Introduction

plp-mtu-discovery

Perform Path MTU Discovery without relying on ICMP errors, which are often not delivered.

This program performs Packetization Layer Path MTU Discovery as described in RFC 4821, which is a more reliable way to detect MTU size in presence of ICMP black holes.

Rationale

While TCP connections automatically adjust MTU size over time depending on various indicators (network performance, packet loss, ICMP error messages, ...), this is not the case for connection-less protocols.

When performance is essential, throughput, packet fragmentation and route reliability are three key indicators to analyze in order to optimize stream performance. Since route reliability does not always depend on us, we should strive to maximize throughput while NOT performing packet fragmentation, which can severely degrade performance[1].

The original proposal for Path MTU Discovery relied on ICMP Fragmentation Needed packets to be delivered when a IPv4 packet with Don't Fragment field set was too large to be propagated. Unfortunately, some routers do not generate these kind of errors but choose to silently ignore large packets instead. A client has no way to determine the cause of the packet loss.

A safer approach

Since all hosts are mandated to support ICMP_ECHO queries, we can exploit the fact that ICMP messages accept an arbitrary amount of data and send different-sized packets to our server. If we turn on the Don't Fragment field in the IPv4 packet and listen for a response, we are de facto waiting for an ACK (in the form of an ICMP_ECHOREPLY packet) confirming that this MTU size is valid.

Now we just have to perform a binary search in respect to the size of the packets in order to find the maximum MTU size supported by this route.

ICMP mode

When in ICMP mode, some ICMP_ECHO requests of different sizes are generated.

  • If a response from the server is received, that MTU size is considered valid and the threshold is raised.
  • If no response is received after several attempts or some kind of error is received (e.g.ICMP Fragmentation Needed), that MTU size is declared invalid and the threshold is lowered.

The only requirement of ICMP mode is that the host must be capable to reply to ping messages.

UDP mode

The same algorithm applies to UDP packets, but you need to run a server (udp_server.py) on your receiving host in order to send back acknowledgment messages.

Compiling & Running

This program should run fine on most Linux distributions and OSX.

gcc -Wall -Wextra mtu_discovery.c mtu.c -o plpmtu

It should not report warnings/errors. If it does, please open an issue.

If you want to run in ICMP mode type:

sudo ./plpmtu -p icmp -s <server-ipaddr>

If you want to run UDP mode instead:

sudo ./plpmtu -p udp -s <server-ipaddr:port>

Admin rights are required in order to use raw sockets.

Command line arguments

Specifier Description
-p {icmp/udp} Select in which mode to operate.
-s <addr[:port]> Specify server's address. If running in UDP mode, you must also specify the destination port by appending ':port' (e.g. -s 8.8.8.8:12345)
-l <addr:port> Optional. Select on which address to bind(); used in UDP mode; might be removed.
-t <timeout> Optional. Select the maximum time to wait for a response from the server, default is 1 second; time is expressed in milliseconds.
-r <max-reqs> Optional. Select the maximum number of failed attempts needed to declare a MTU size invalid, default is 3 attempts.

Examples

sudo ./plpmtu -p icmp -s 184.12.26.131

Perform MTU discovery (ICMP mode) with 184.12.26.131.

sudo ./plpmtu -p udp -s 184.12.26.131:24000 -t 1500 -r 5

Perform MTU discovery (UDP mode) with 184.12.26.131 on port 24000. If a response is not received within 1.5 seconds for 5 times in a row, reduce MTU threshold.

Docs

plp-mtu-discovery's People

Contributors

kavarenshko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

plp-mtu-discovery's Issues

compile error for OpenWRT

I'm trying to put together a package for a mt7621 openwrt router and running into similar compile errors as #3. This applies to both ARM and MIPS that I have tested.

Below is the error:

make -j1 V=s package/utils/plp-mtu-discovery/compile
time: target/linux/prereq#0.17#0.03#0.21
make[1]: Entering directory '/home/dwood/openwrt'
make[2]: Entering directory '/home/dwood/openwrt/package/libs/toolchain'
echo "libc" >> /home/dwood/openwrt/staging_dir/target-mipsel_24kc_musl/pkginfo/toolchain.default.install
echo "libgcc" >> /home/dwood/openwrt/staging_dir/target-mipsel_24kc_musl/pkginfo/toolchain.default.install
echo "libpthread" >> /home/dwood/openwrt/staging_dir/target-mipsel_24kc_musl/pkginfo/toolchain.default.install
make[2]: Leaving directory '/home/dwood/openwrt/package/libs/toolchain'
time: package/libs/toolchain/compile#0.27#0.16#0.41
make[2]: Entering directory '/home/dwood/openwrt/package/utils/plp-mtu-discovery'
rm -f /home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/.built
touch /home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/.built_check
mipsel-openwrt-linux-musl-gcc -I/home/dwood/openwrt/staging_dir/target-mipsel_24kc_musl/usr/include -I/home/dwood/openwrt/staging_dir/target-mipsel_24kc_musl/include -I/home/dwood/openwrt/staging_dir/toolchain-mipsel_24kc_gcc-7.4.0_musl/usr/include -I/home/dwood/openwrt/staging_dir/toolchain-mipsel_24kc_gcc-7.4.0_musl/include/fortify -I/home/dwood/openwrt/staging_dir/toolchain-mipsel_24kc_gcc-7.4.0_musl/include -Os -pipe -mno-branch-likely -mips32r2 -mtune=24kc -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -msoft-float -mips16 -minterlink-mips16 -iremap/home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery:plp-mtu-discovery -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -o /home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/plp-mtu-discovery -Wall -Wextra /home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/mtu_discovery.c /home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/mtu.c
/home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/mtu.c: In function '_checkPacket':
/home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/mtu.c:62:28: error: 'struct udphdr' has no member named 'source'
    if (p->proto_hdr.udp_hdr.source != dest->sin_port) // same host but different port
                            ^
/home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/mtu.c: In function 'mtu_discovery':
/home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/mtu.c:218:24: error: 'struct udphdr' has no member named 'source'
     s.proto_hdr.udp_hdr.source = source->sin_port; // filled in by the kernel
                        ^
/home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/mtu.c:219:24: error: 'struct udphdr' has no member named 'dest'
     s.proto_hdr.udp_hdr.dest = dest->sin_port;
                        ^
/home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/mtu.c:269:24: error: 'struct udphdr' has no member named 'len'
     s.proto_hdr.udp_hdr.len = htons(mtu_current - MTU_IPSIZE);
                        ^
/home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/mtu.c:270:24: error: 'struct udphdr' has no member named 'check'
     s.proto_hdr.udp_hdr.check = 0; // checksum must be set to 0 before calculating it
                        ^
Makefile:36: recipe for target '/home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/.built' failed
make[2]: *** [/home/dwood/openwrt/build_dir/target-mipsel_24kc_musl/plp-mtu-discovery/.built] Error 1
make[2]: Leaving directory '/home/dwood/openwrt/package/utils/plp-mtu-discovery'
time: package/utils/plp-mtu-discovery/compile#0.45#0.21#0.62
package/Makefile:107: recipe for target 'package/utils/plp-mtu-discovery/compile' failed
make[1]: *** [package/utils/plp-mtu-discovery/compile] Error 2
make[1]: Leaving directory '/home/dwood/openwrt'
/home/dwood/openwrt/include/toplevel.mk:216: recipe for target 'package/utils/plp-mtu-discovery/compile' failed
make: *** [package/utils/plp-mtu-discovery/compile] Error 2

On ARM:

make -j1 V=s package/utils/plp-mtu-discovery/compile
time: target/linux/prereq#0.12#0.02#0.14
make[1]: Entering directory '/home/dwood/openwrt'
make[2]: Entering directory '/home/dwood/openwrt/package/libs/toolchain'
echo "libc" >> /home/dwood/openwrt/staging_dir/target-arm_cortex-a9_musl_eabi/pkginfo/toolchain.default.install
echo "libgcc" >> /home/dwood/openwrt/staging_dir/target-arm_cortex-a9_musl_eabi/pkginfo/toolchain.default.install
echo "libpthread" >> /home/dwood/openwrt/staging_dir/target-arm_cortex-a9_musl_eabi/pkginfo/toolchain.default.install
make[2]: Leaving directory '/home/dwood/openwrt/package/libs/toolchain'
time: package/libs/toolchain/compile#0.14#0.03#0.17
make[2]: Entering directory '/home/dwood/openwrt/package/utils/plp-mtu-discovery'
touch /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/.prepared_59045236a38c18f902e74310b5fbaa65_6664517399ebbbc92a37c5bb081b5c53_check
rm -Rf /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery
git clone https://github.com/Kavarenshko/plp-mtu-discovery.git /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery
Cloning into '/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 64 (delta 0), reused 0 (delta 0), pack-reused 61
Unpacking objects: 100% (64/64), done.
touch /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/.prepared_59045236a38c18f902e74310b5fbaa65_6664517399ebbbc92a37c5bb081b5c53
rm -f /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/.configured_*
rm -f /home/dwood/openwrt/staging_dir/target-arm_cortex-a9_musl_eabi/stamp/.plp-mtu-discovery_installed
(cd /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/./; if [ -x ./configure ]; then find /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/ -name config.guess | xargs -r chmod u+w; find /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/ -name config.guess | xargs -r -n1 cp --remove-destination /home/dwood/openwrt/scripts/config.guess; find /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/ -name config.sub | xargs -r chmod u+w; find /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/ -name config.sub | xargs -r -n1 cp --remove-destination /home/dwood/openwrt/scripts/config.sub; AR="arm-openwrt-linux-muslgnueabi-gcc-ar" AS="arm-openwrt-linux-muslgnueabi-gcc -c -Os -pipe -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -mfloat-abi=soft -iremap/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery:plp-mtu-discovery -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro" LD=arm-openwrt-linux-muslgnueabi-ld NM="arm-openwrt-linux-muslgnueabi-gcc-nm" CC="arm-openwrt-linux-muslgnueabi-gcc" GCC="arm-openwrt-linux-muslgnueabi-gcc" CXX="arm-openwrt-linux-muslgnueabi-g++" RANLIB="arm-openwrt-linux-muslgnueabi-gcc-ranlib" STRIP=arm-openwrt-linux-muslgnueabi-strip OBJCOPY=arm-openwrt-linux-muslgnueabi-objcopy OBJDUMP=arm-openwrt-linux-muslgnueabi-objdump SIZE=arm-openwrt-linux-muslgnueabi-size CFLAGS="-Os -pipe -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -mfloat-abi=soft -iremap/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery:plp-mtu-discovery -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro " CXXFLAGS="-Os -pipe -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -mfloat-abi=soft -iremap/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery:plp-mtu-discovery -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro " CPPFLAGS="-I/home/dwood/openwrt/staging_dir/target-arm_cortex-a9_musl_eabi/usr/include -I/home/dwood/openwrt/staging_dir/target-arm_cortex-a9_musl_eabi/include -I/home/dwood/openwrt/staging_dir/toolchain-arm_cortex-a9_gcc-7.4.0_musl_eabi/usr/include -I/home/dwood/openwrt/staging_dir/toolchain-arm_cortex-a9_gcc-7.4.0_musl_eabi/include/fortify -I/home/dwood/openwrt/staging_dir/toolchain-arm_cortex-a9_gcc-7.4.0_musl_eabi/include " LDFLAGS="-L/home/dwood/openwrt/staging_dir/target-arm_cortex-a9_musl_eabi/usr/lib -L/home/dwood/openwrt/staging_dir/target-arm_cortex-a9_musl_eabi/lib -L/home/dwood/openwrt/staging_dir/toolchain-arm_cortex-a9_gcc-7.4.0_musl_eabi/usr/lib -L/home/dwood/openwrt/staging_dir/toolchain-arm_cortex-a9_gcc-7.4.0_musl_eabi/lib -znow -zrelro "   ./configure --target=arm-openwrt-linux --host=arm-openwrt-linux --build=x86_64-pc-linux-gnu --program-prefix="" --program-suffix="" --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdir=/usr/lib --sysconfdir=/etc --datadir=/usr/share --localstatedir=/var --mandir=/usr/man --infodir=/usr/info --disable-nls  ; fi; )
touch /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/.configured_68b329da9893e34099c7d8ad5cb9c940
rm -f /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/.built
touch /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/.built_check
arm-openwrt-linux-muslgnueabi-gcc -I/home/dwood/openwrt/staging_dir/target-arm_cortex-a9_musl_eabi/usr/include -I/home/dwood/openwrt/staging_dir/target-arm_cortex-a9_musl_eabi/include -I/home/dwood/openwrt/staging_dir/toolchain-arm_cortex-a9_gcc-7.4.0_musl_eabi/usr/include -I/home/dwood/openwrt/staging_dir/toolchain-arm_cortex-a9_gcc-7.4.0_musl_eabi/include/fortify -I/home/dwood/openwrt/staging_dir/toolchain-arm_cortex-a9_gcc-7.4.0_musl_eabi/include -Os -pipe -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -mfloat-abi=soft -iremap/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery:plp-mtu-discovery -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -o /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/plp-mtu-discovery -Wall -Wextra /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/mtu_discovery.c /home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/mtu.c
/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/mtu.c: In function '_checkPacket':
/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/mtu.c:62:28: error: 'struct udphdr' has no member named 'source'
    if (p->proto_hdr.udp_hdr.source != dest->sin_port) // same host but different port
                            ^
/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/mtu.c: In function 'mtu_discovery':
/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/mtu.c:218:24: error: 'struct udphdr' has no member named 'source'
     s.proto_hdr.udp_hdr.source = source->sin_port; // filled in by the kernel
                        ^
/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/mtu.c:219:24: error: 'struct udphdr' has no member named 'dest'
     s.proto_hdr.udp_hdr.dest = dest->sin_port;
                        ^
/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/mtu.c:269:24: error: 'struct udphdr' has no member named 'len'
     s.proto_hdr.udp_hdr.len = htons(mtu_current - MTU_IPSIZE);
                        ^
/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/mtu.c:270:24: error: 'struct udphdr' has no member named 'check'
     s.proto_hdr.udp_hdr.check = 0; // checksum must be set to 0 before calculating it
                        ^
Makefile:36: recipe for target '/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/.built' failed
make[2]: *** [/home/dwood/openwrt/build_dir/target-arm_cortex-a9_musl_eabi/plp-mtu-discovery/.built] Error 1
make[2]: Leaving directory '/home/dwood/openwrt/package/utils/plp-mtu-discovery'
time: package/utils/plp-mtu-discovery/compile#0.48#0.17#0.88
package/Makefile:107: recipe for target 'package/utils/plp-mtu-discovery/compile' failed
make[1]: *** [package/utils/plp-mtu-discovery/compile] Error 2
make[1]: Leaving directory '/home/dwood/openwrt'
/home/dwood/openwrt/include/toplevel.mk:216: recipe for target 'package/utils/plp-mtu-discovery/compile' failed
make: *** [package/utils/plp-mtu-discovery/compile] Error 2

How to reproduce my cross compile build environment:

git clone https://github.com/openwrt/openwrt.git openwrt
cd openwrt
mkdir -p package/utils/plp-mtu-discovery/
curl https://download.ttl.one/plp-mtu-discovery/ > package/utils/plp-mtu-discovery/Makefile
./scripts/feeds update -a -f; ./scripts/feeds install -a -f
cat > .config << EOF
CONFIG_TARGET_ramips=y
CONFIG_TARGET_ramips_mt7621=y
CONFIG_TARGET_ramips_mt7621_Default=y
EOF
make defconfig && make download && make -j40

# Add package after initial compile to allow full toolchain and such to be setup first.
echo 'CONFIG_PACKAGE_plp-mtu-discovery=y' >> .config

make -j1 V=s package/utils/plp-mtu-discovery/compile

compile error under macOS

gcc -Wall -Wextra mtu_discovery.c mtu.c -o plpmtu

mtu.c:62:29: error: no member named 'source' in 'struct udphdr'
if (p->proto_hdr.udp_hdr.source != dest->sin_port) // same host but different port
~~~~~~~~~~~~~~~~~~~~ ^
mtu.c:218:25: error: no member named 'source' in 'struct udphdr'
s.proto_hdr.udp_hdr.source = source->sin_port; // filled in by the kernel
~~~~~~~~~~~~~~~~~~~ ^
mtu.c:219:25: error: no member named 'dest' in 'struct udphdr'
s.proto_hdr.udp_hdr.dest = dest->sin_port;
~~~~~~~~~~~~~~~~~~~ ^
mtu.c:269:25: error: no member named 'len' in 'struct udphdr'
s.proto_hdr.udp_hdr.len = htons(mtu_current - MTU_IPSIZE);
~~~~~~~~~~~~~~~~~~~ ^
mtu.c:270:25: error: no member named 'check' in 'struct udphdr'
s.proto_hdr.udp_hdr.check = 0; // checksum must be set to 0 before calculating it
~~~~~~~~~~~~~~~~~~~ ^

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.