From 40fdd921b9d8018cd9567c48627af587a6fec2a6 Mon Sep 17 00:00:00 2001 From: Ycarus Date: Tue, 23 Jan 2018 15:35:00 +0100 Subject: [PATCH] Add mptcp support --- mptcp/Makefile | 73 +++++++++++++ mptcp/files/etc/hotplug.d/iface/30-mptcp | 91 ++++++++++++++++ mptcp/files/etc/hotplug.d/net/03-mptcp | 36 +++++++ mptcp/files/etc/init.d/mptcp | 22 ++++ mptcp/files/etc/uci-defaults/mptcp-defaults | 6 ++ mptcp/files/usr/bin/multipath | 102 ++++++++++++++++++ .../share/omr/post-tracking.d/post-tracking | 45 ++++++++ 7 files changed, 375 insertions(+) create mode 100644 mptcp/Makefile create mode 100644 mptcp/files/etc/hotplug.d/iface/30-mptcp create mode 100755 mptcp/files/etc/hotplug.d/net/03-mptcp create mode 100755 mptcp/files/etc/init.d/mptcp create mode 100755 mptcp/files/etc/uci-defaults/mptcp-defaults create mode 100755 mptcp/files/usr/bin/multipath create mode 100755 mptcp/files/usr/share/omr/post-tracking.d/post-tracking diff --git a/mptcp/Makefile b/mptcp/Makefile new file mode 100644 index 000000000..45bcc4878 --- /dev/null +++ b/mptcp/Makefile @@ -0,0 +1,73 @@ +# +# Copyright (C) 2014-2014 OpenWrt.org +# Copyright (C) 2018 Ycarus (Yannick Chabanois) +# +# This is free software, licensed under the GNU General Public License v3 or later. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=mptcp +PKG_VERSION:=3.0 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Ycarus (Yannick Chabanois) +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/mptcp + SECTION:=net + CATEGORY:=Network + TITLE:=Multipath TCP configuration scrips + DEPENDS:=+ip +iptables + KCONFIG:=\ + CONFIG_MPTCP=y \ + CONFIG_MPTCP_BINDER=y \ + CONFIG_MPTCP_FULLMESH=y \ + CONFIG_MPTCP_NDIFFPORTS=y \ + CONFIG_MPTCP_PM_ADVANCED=y \ + CONFIG_MPTCP_REDUNDANT=y \ + CONFIG_MPTCP_ROUNDROBIN=y \ + CONFIG_MPTCP_SCHED_ADVANCED=y \ + CONFIG_DEFAULT_FULLMESH=y \ + CONFIG_DEFAULT_NDIFFPORTS=n \ + CONFIG_DEFAULT_REDUNDANT=n \ + CONFIG_DEFAULT_ROUNDROBIN=n \ + CONFIG_DEFAULT_SCHEDULER=y \ + CONFIG_DEFAULT_BINDER=n \ + CONFIG_DEFAULT_DUMMY=n \ + CONFIG_TCP_CONG_BALIA=y \ + CONFIG_TCP_CONG_LIA=y \ + CONFIG_TCP_CONG_OLIA=y \ + CONFIG_TCP_CONG_WVEGAS=y \ + CONFIG_DEFAULT_OLIA=y \ + CONFIG_DEFAULT_TCP_CONG="olia" + + PKGARCH:=all +endef + +define Package/mptcp/description + MultiPath TCP (MPTCP) is an effort towards enabling the simultaneous use of + several IP-addresses/interfaces by a modification of TCP that presents a regular + TCP interface to applications, while in fact spreading data across several + subflows. Benefits of this include better resource utilization, better throughput + and smoother reaction to failures. +endef + +define Build/Prepare +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/mptcp/install + $(INSTALL_DIR) $(1) + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,mptcp)) diff --git a/mptcp/files/etc/hotplug.d/iface/30-mptcp b/mptcp/files/etc/hotplug.d/iface/30-mptcp new file mode 100644 index 000000000..6015db82d --- /dev/null +++ b/mptcp/files/etc/hotplug.d/iface/30-mptcp @@ -0,0 +1,91 @@ +#!/bin/sh +# +# Load the multipath config +# +# Author: Mario Krueger +# Released under GPL 3 or later + +[ "$ACTION" = ifup -o "$ACTION" = ifupdate ] || exit 0 + +enable=`uci -q get network.globals.multipath` || exit 0 +[ "$enable" = "enable" ] || exit 0 + +. /lib/functions.sh +. /lib/functions/network.sh + +id=0 +count=1 + +set_default() { + local mode + local config="$1" + count=$(($count+1)) + local iface + config_get iface "$config" ifname + [ "$iface" = "$INTERFACE" ] && id=$count + config_get mode "$config" multipath + [ "$mode" = "master" ] && { + local gateway + network_get_gateway gateway $config || { + logger -t multipath master device $DEVICE has no gateway! + #Fallback: use upcomming interface... + network_get_gateway gateway $INTERFACE + config=$INTERFACE + } + local iface + config_get iface "$config" ifname + ip route del default + ip route add default scope global nexthop via $gateway dev $iface || { + #Fallback: use upcomming interface... + network_get_gateway gateway $INTERFACE + ip route add default scope global nexthop via $gateway dev $INTERFACE + logger -t multipath Faild to set default multipath device! Use $INTERFACE as fallback... + } + } +} + +config_load network +config_foreach set_default interface +[ $id = 0 ] && { + logger -t multipath device $INTERFACE not fount! + echo device $INTERFACE not fount! + exit 1 +} + +mode=`uci -q get network.$INTERFACE.multipath` || mode='off' + +case "$mode" in + "off") + multipath $DEVICE off + exit 0;; + "master") + mode="on";; + "on");; + "backup");; + "handover");; + *) + logger -t multipath Wrong multipath value for device $DEVICE + exit 1;; +esac + +# Update kernel flags +multipath $DEVICE $mode + +# IPv4 Updates: + +local ipaddr +local gateway +local network +local netmask +network_get_ipaddr ipaddr $INTERFACE +network_get_gateway gateway $INTERFACE +network_get_subnet network $INTERFACE +__network_ifstatus netmask $INTERFACE "['ipv4-address'][0]['mask']" +network=`ipcalc.sh $network | sed -n '/NETWORK=/{;s/.*=//;s/ .*//;p;}'` + +ip rule del table $id +ip route flush $id +ip rule add from $ipaddr table $id +ip route add $network/$netmask dev $DEVICE scope link table $id +ip route add default via $gateway dev $DEVICE table $id +ip route flush $id diff --git a/mptcp/files/etc/hotplug.d/net/03-mptcp b/mptcp/files/etc/hotplug.d/net/03-mptcp new file mode 100755 index 000000000..2c3f2a9c4 --- /dev/null +++ b/mptcp/files/etc/hotplug.d/net/03-mptcp @@ -0,0 +1,36 @@ +#!/bin/sh +# vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : + +. /lib/functions.sh + +multipath= +mptcp_path_manager= +mptcp_schdeduler= +congestion= +multipath_status=0 +config_load network +config_get multipath globals multipath +config_get mptcp_path_manager globals mptcp_path_manager +config_get mptcp_scheduler globals mptcp_scheduler +config_get congestion globals congestion +[ "$multipath" = "enable" ] && multipath_status=1 + +# Global MPTCP configuration +sysctl -qw net.mptcp.mptcp_enabled="$multipath_status" +[ "$multipath_status" = "0" ] && exit 0 +[ -z "$mptcp_path_manager" ] || sysctl -qw net.mptcp.mptcp_path_manager="$mptcp_path_manager" +[ -z "$mptcp_scheduler" ] || sysctl -qw net.mptcp.mptcp_scheduler="$mptcp_scheduler" +[ -z "$congestion" ] || sysctl -qw net.ipv4.tcp_congestion_control="$congestion" + +# Configuration by interface +_setup_interface() { + device= + config_get device "$1" ifname + [ -z "$device" ] && return 0 + + if_multipath= + config_get if_multipath "$1" multipath "off" + [ "$if_multipath" = "master" ] && if_multipath="on" + multipath "$device" "$if_multipath" +} +config_foreach _setup_interface interface diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp new file mode 100755 index 000000000..c6849d30c --- /dev/null +++ b/mptcp/files/etc/init.d/mptcp @@ -0,0 +1,22 @@ +#!/bin/sh /etc/rc.common + +START=20 +STOP=90 + +USE_PROCD=1 + +start_service() { + procd_open_instance + procd_set_param command hotplug-call net + procd_set_param respawn + procd_set_param watch network.globals + procd_close_instance +} + +reload_service() { + ubus call network reload +} + +service_running() { + ubus -t 30 wait_for network +} diff --git a/mptcp/files/etc/uci-defaults/mptcp-defaults b/mptcp/files/etc/uci-defaults/mptcp-defaults new file mode 100755 index 000000000..61146c99b --- /dev/null +++ b/mptcp/files/etc/uci-defaults/mptcp-defaults @@ -0,0 +1,6 @@ +#!/bin/sh +uci -q batch < +# Released under GPL 3 or later + +if [ -d "/proc/sys/net/mptcp" ]; then + if [ `cat /proc/sys/net/mptcp/mptcp_enabled` = 0 ]; then + echo "MPTCP is disabled!" + echo "Please set net.mptcp.mptcp_enabled = 1" + exit 1 + fi +else + echo "Your device don't support multipath-TCP." + echo "You have to install the pached kernel to use MPTCP." + echo "See http://multipath-tcp.org/ for details" + exit 1 +fi + +case $1 in + "-h") + echo " Multipath-TCP configuration tool" + echo "show/update flags:" + echo " multipath [device]" + echo " multipath device {on | off | backup | handover}" + echo + echo "show established conections: -c" + echo "show mullmesh info: -f" + echo "show kernel config: -k" + echo + echo "Flag on the device, to enable/disable MPTCP for this interface. The backup-flag" + echo "will allow a subflow to be established across this interface, but only be used" + echo "as backup. Handover-flag indicates that his interface is not used at all (even " + echo "no subflow being established), as long as there are other interfaces available." + echo "See http://multipath-tcp.org/ for details" + echo + exit 0 ;; + "-c") + cat /proc/net/mptcp_net/mptcp + exit 0;; + "-f") + cat /proc/net/mptcp_fullmesh + exit 0;; + "-k") + echo Enabled: `cat /proc/sys/net/mptcp/mptcp_enabled` + echo Path Manager: `cat /proc/sys/net/mptcp/mptcp_path_manager` + echo Use checksum: `cat /proc/sys/net/mptcp/mptcp_checksum` + echo Scheduler: `cat /proc/sys/net/mptcp/mptcp_scheduler` + echo Syn retries: `cat /proc/sys/net/mptcp/mptcp_syn_retries` + echo Debugmode: `cat /proc/sys/net/mptcp/mptcp_debug` + echo + echo See http://multipath-tcp.org/ for details + exit 0 ;; + "") + for ifpath in /sys/class/net/*; do + $0 ${ifpath##*/} + done + exit 0;; + *);; +esac + +DEVICE="$1" +TYPE="$2" +#FLAG_PATH=`find /sys/devices/ -path "*/net/$DEVICE/flags"` + +[ -d "/sys/class/net/$DEVICE/" ] || { + echo "Device '$DEVICE' can't found!" + echo "Use the hardware name like in ifconfig" + exit 1 +} + +FLAG_PATH="/sys/class/net/$DEVICE/flags" +IFF=`cat $FLAG_PATH` + +IFF_OFF="0x80000" +IFF_ON="0x00" +IFF_BACKUP="0x100000" +IFF_HANDOVER="0x200000" +IFF_MASK="0x380000" + +case $TYPE in + "off") FLAG=$IFF_OFF;; + "on") FLAG=$IFF_ON;; + "backup") FLAG=$IFF_BACKUP;; + "handover") FLAG=$IFF_HANDOVER;; + "") + IFF=`printf "0x%02x" $(($IFF&$IFF_MASK))` + case "$IFF" in + $IFF_OFF) echo $DEVICE is deactivated;; + $IFF_ON) echo $DEVICE is in default mode;; + $IFF_BACKUP) echo $DEVICE is in backup mode;; + $IFF_HANDOVER) echo $DEVICE is in handover mode;; + *) echo "Unkown state!" && exit 1;; + esac + exit 0;; + *) echo "Unkown flag! Use 'multipath -h' for help" && exit 1;; +esac + +printf "0x%02x" $(($(($IFF^$(($IFF&$IFF_MASK))))|$FLAG)) > $FLAG_PATH + + diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking new file mode 100755 index 000000000..78bc28d9a --- /dev/null +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -0,0 +1,45 @@ +# vim: set ft=sh noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : + +SETROUTE=false +set_route() { + local multipath_config interface_gw interface_if + INTERFACE=$1 + multipath_config=$(uci -q get "network.$INTERFACE.multipath" || echo "off") + #multipath_current_config=$(multipath $INTERFACE | grep deactivated) + #if [ "$multipath_config" != "off" ] && [ "$SETROUTE" != true ] && [ "$multipath_current_config" = "" ]; then + if [ "$multipath_config" != "off" ] && [ "$SETROUTE" != true ]; then + interface_gw=$(uci -q get "network.$INTERFACE.gateway") + interface_if=$(uci -q get "network.$INTERFACE.ifname") + ip route replace default scope global nexthop via $interface_gw dev $interface_if && SETROUTE=true + fi +} + + +# Get the current multipath status +multipath_status="off" +case "$(multipath "$OMR_TRACKER_DEVICE")" in + *default*) multipath_status="on" ;; + *backup*) multipath_status="backup" ;; + *handover*) multipath_status="handover" ;; +esac + +default_gw=$(ip route show default | grep -v metric | awk '/default/ {print $3}') +current_interface_gw=$(uci -q get "network.$OMR_TRACKER_INTERFACE.gateway") + +# An interface in error will never be used in MPTCP +if [ "$OMR_TRACKER_STATUS" = "ERROR" ]; then + [ "$multipath_status" = "off" ] && exit 0 + _log "$OMR_TRACKER_DEVICE switched off" + multipath "$OMR_TRACKER_DEVICE" off + if [ "$default_gw" = "$current_interface_gw" ] || [ "$default_gw" = "" ]; then + config_load network + config_foreach set_route interface + fi + exit 0 +fi + +multipath_config=$(uci -q get "network.$OMR_TRACKER_INTERFACE.multipath" || echo "off") +[ "$multipath_config" = "master" ] && multipath_config="on" +[ "$multipath_status" = "$multipath_config" ] && exit 0 +_log "$OMR_TRACKER_DEVICE switched to $multipath_config" +multipath "$OMR_TRACKER_DEVICE" "$multipath_config"