mirror of
https://github.com/Ysurac/openmptcprouter-feeds.git
synced 2025-02-15 03:51:51 +00:00
commit
85822a58cf
8 changed files with 782 additions and 67 deletions
|
@ -65,10 +65,13 @@ end
|
|||
|
||||
-- if tonumber(uname.release:sub(1,4)) >= 5.15 then
|
||||
if uname.release:sub(1,4) == "5.15" or uname.release:sub(1,1) == "6" then
|
||||
o = s:option(ListValue, "mptcp_pm_type", translate("Path Manager type"))
|
||||
o:value(0, translate("In-kernel path manager"))
|
||||
o:value(1, translate("Userspace path manager"))
|
||||
o.default = 0
|
||||
if uname.release:sub(1,1) == "6" then
|
||||
-- Only available since 5.19
|
||||
o = s:option(ListValue, "mptcp_pm_type", translate("Path Manager type"))
|
||||
o:value(0, translate("In-kernel path manager"))
|
||||
o:value(1, translate("Userspace path manager"))
|
||||
o.default = 0
|
||||
end
|
||||
|
||||
o = s:option(Value, "mptcp_subflows", translate("Max subflows"),translate("specifies the maximum number of additional subflows allowed for each MPTCP connection"))
|
||||
o.datatype = "uinteger"
|
||||
|
|
|
@ -457,7 +457,7 @@ function wizard_add()
|
|||
end
|
||||
ucic:set("openmptcprouter",intf,"testspeed",testspeed)
|
||||
if testspeed == "1" then
|
||||
ucic:set("openmptcprouter",intf,"testspeed_lc")
|
||||
ucic:delete("openmptcprouter",intf,"testspeed_lc")
|
||||
end
|
||||
if downloadspeed ~= "0" and downloadspeed ~= "" then
|
||||
if sqmautorate == "1" and (ucic:get("network",intf,"downloadspeed") ~= downloadspeed or ucic:get("sqm",intf,"max_download") == "" or ucic:get("sqm",intf,"download") == "0") then
|
||||
|
|
|
@ -53,16 +53,16 @@ pinger_binary=$(uci -q get sqm.${INTERFACE}.pinger || echo 'tsping')
|
|||
# so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially
|
||||
# and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad
|
||||
# a bad reflector will go to the back of the queue on reflector rotation
|
||||
#reflectors=$(uci -q get omr-tracker.defaults.hosts)
|
||||
reflectors=(
|
||||
"1.1.1.1" "1.0.0.1" # Cloudflare
|
||||
"8.8.8.8" "8.8.4.4" # Google
|
||||
"9.9.9.9" "9.9.9.10" "9.9.9.11" # Quad9
|
||||
"94.140.14.15" "94.140.14.140" "94.140.14.141" "94.140.15.15" "94.140.15.16" # AdGuard
|
||||
"64.6.65.6" "156.154.70.1" "156.154.70.2" "156.154.70.3" "156.154.70.4" "156.154.70.5" "156.154.71.1" "156.154.71.2" "156.154.71.3" "156.154.71.4" "156.154.71.5" # Neustar
|
||||
"208.67.220.2" "208.67.220.123" "208.67.220.220" "208.67.222.2" "208.67.222.123" # OpenDNS
|
||||
"185.228.168.9" "185.228.168.10" # CleanBrowsing
|
||||
)
|
||||
reflectors=( $(uci -q get omr-tracker.defaults.hosts) )
|
||||
#reflectors=(
|
||||
#"1.1.1.1" "1.0.0.1" # Cloudflare
|
||||
#"8.8.8.8" "8.8.4.4" # Google
|
||||
#"9.9.9.9" "9.9.9.10" "9.9.9.11" # Quad9
|
||||
#"94.140.14.15" "94.140.14.140" "94.140.14.141" "94.140.15.15" "94.140.15.16" # AdGuard
|
||||
#"64.6.65.6" "156.154.70.1" "156.154.70.2" "156.154.70.3" "156.154.70.4" "156.154.70.5" "156.154.71.1" "156.154.71.2" "156.154.71.3" "156.154.71.4" "156.154.71.5" # Neustar
|
||||
#"208.67.220.2" "208.67.220.123" "208.67.220.220" "208.67.222.2" "208.67.222.123" # OpenDNS
|
||||
#"185.228.168.9" "185.228.168.10" # CleanBrowsing
|
||||
#)
|
||||
|
||||
randomize_reflectors=1 # enable (1) or disable (0) randomization of reflectors on startup
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ global_multipath_settings() {
|
|||
config_get mptcp_rr_num_segments globals mptcp_rr_num_segments
|
||||
config_get mptcp_version globals mptcp_version "0"
|
||||
config_get mptcp_stale_loss_cnt globals mptcp_stale_loss_cnt "4"
|
||||
config_get mptcp_pm_type globals mptcp_pm_type "1"
|
||||
|
||||
[ "$multipath" = "enable" ] && multipath_status=1
|
||||
|
||||
|
@ -52,11 +53,10 @@ global_multipath_settings() {
|
|||
ip mptcp limits set add_addr_accepted $mptcp_add_addr_accepted subflows $mptcp_subflows 2>&1 >/dev/null
|
||||
#[ -z "$mptcp_debug" ] || sysctl -qew net.mptcp.mptcp_debug="$mptcp_debug"
|
||||
[ -z "$mptcp_checksum" ] || sysctl -qew net.mptcp.mptcp_checksum="$mptcp_checksum"
|
||||
[ -z "$mptcp_path_manager" ] || sysctl -qew net.mptcp.mptcp_path_manager="$mptcp_path_manager"
|
||||
[ -z "$mptcp_scheduler" ] || sysctl -qew net.mptcp.mptcp_scheduler="$mptcp_scheduler"
|
||||
[ -z "$mptcp_add_addr_timeout" ] || sysctl -qew net.mptcp.add_addr_timeout="$mptcp_add_addr_timeout"
|
||||
[ -z "$mptcp_checksum" ] || sysctl -qew net.mptcp.checksum_enabled="$mptcp_checksum"
|
||||
[ -z "$mptcp_stale_loss_cnt" ] || sysctl -qew net.mptcp.stale_loss_cnt="$mptcp_stale_loss_cnt"
|
||||
[ -z "$mptcp_pm_type" ] || sysctl -qew net.mptcp.pm_type="$mptcp_pm_type"
|
||||
fi
|
||||
[ -z "$congestion" ] || sysctl -qew net.ipv4.tcp_congestion_control="$congestion"
|
||||
}
|
||||
|
@ -195,10 +195,12 @@ interface_multipath_settings() {
|
|||
|
||||
#echo "îface: $iface"
|
||||
|
||||
if [ "$mode" = "master" ]; then
|
||||
if [ "$(uci -q get openmptcprouter.settings.force_multipath)" != "0" ]; then
|
||||
if [ "$mode" = "master" ]; then
|
||||
multipath "$iface" "on"
|
||||
else
|
||||
multipath "$iface" "$mode"
|
||||
else
|
||||
multipath "$iface" "$mode"
|
||||
fi
|
||||
fi
|
||||
#[ "$mode" = "off" ] && {
|
||||
# ip rule del table $id > /dev/null 2>&1
|
||||
|
|
|
@ -1291,7 +1291,7 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && ([ "$multipath_config" = "on" ] || [ "$mul
|
|||
config_load openmptcprouter
|
||||
config_foreach glorytunudppath server
|
||||
fi
|
||||
[ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && {
|
||||
[ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" != "1" ] && [ "$(uci -q get openmptcprouter.settings.force_multipath)" != "0" ] && {
|
||||
[ "$multipath_status" = "$multipath_config" ] || {
|
||||
if [ "$(sysctl -qen net.mptcp.mptcp_enabled | tr -d '\n')" = "1" ] || [ "$(sysctl -qen net.mptcp.enabled | tr -d '\n')" = "1" ]; then
|
||||
if [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.force_link)" != "0" ]; then
|
||||
|
@ -1610,48 +1610,55 @@ if [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then
|
|||
fi
|
||||
|
||||
if [ "$(pgrep -f omr-test-speed-server)" = "" ] && [ "$(uci -q get openmptcprouter.${OMR_TRACKER_INTERFACE}.testspeed)" = "1" ] && [ -z "$(uci -q get openmptcprouter.${OMR_TRACKER_INTERFACE}.testspeed_lc)" ]; then
|
||||
download_speed=$(/bin/omr-test-speed-server vps ${OMR_TRACKER_DEVICE} fasttest)
|
||||
download_speed2=$(/bin/omr-test-speed-server vps ${OMR_TRACKER_DEVICE} fasttest)
|
||||
download_speed3=$(/bin/omr-test-speed-server vps ${OMR_TRACKER_DEVICE} fasttest)
|
||||
[ "$download_speed2" -gt "$download_speed" ] && download_speed=${download_speed2}
|
||||
[ "$download_speed3" -gt "$download_speed" ] && download_speed=${download_speed3}
|
||||
download_speed=$((download_speed/1000))
|
||||
if [ -n "$download_speed" ] && [ "$download_speed" != "0" ]; then
|
||||
upload_speed=$(/bin/omr-test-speed-server vps ${OMR_TRACKER_DEVICE} fasttest upload)
|
||||
upload_speed2=$(/bin/omr-test-speed-server vps ${OMR_TRACKER_DEVICE} fasttest upload)
|
||||
upload_speed3=$(/bin/omr-test-speed-server vps ${OMR_TRACKER_DEVICE} fasttest upload)
|
||||
[ "$upload_speed2" -gt "$upload_speed" ] && upload_speed=${upload_speed2}
|
||||
[ "$upload_speed3" -gt "$upload_speed" ] && upload_speed=${upload_speed3}
|
||||
|
||||
# Set Download speed settings
|
||||
if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ]; then
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.download=$((download_speed*65/100))
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.max_download=${download_speed}
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.min_download=$((download_speed*10/100))
|
||||
else
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.download=$((download_speed*95/100))
|
||||
fi
|
||||
_log "Calculated ${OMR_TRACKER_INTERFACE} download speed: ${download_speed}"
|
||||
uci -q set network.${OMR_TRACKER_INTERFACE}.downloadspeed=${download_speed}
|
||||
launch_speedtest() {
|
||||
local server=$1
|
||||
[ "$(uci -q get openmptcprouter.${server}.current)" != "1" ] && return
|
||||
download_speed=$(/bin/omr-test-speed-server ${server} ${OMR_TRACKER_DEVICE} fasttest)
|
||||
download_speed2=$(/bin/omr-test-speed-server ${server} ${OMR_TRACKER_DEVICE} fasttest)
|
||||
download_speed3=$(/bin/omr-test-speed-server ${server} ${OMR_TRACKER_DEVICE} fasttest)
|
||||
[ "$download_speed2" -gt "$download_speed" ] && download_speed=${download_speed2}
|
||||
[ "$download_speed3" -gt "$download_speed" ] && download_speed=${download_speed3}
|
||||
download_speed=$((download_speed/1000))
|
||||
if [ -n "$download_speed" ] && [ "$download_speed" != "0" ]; then
|
||||
upload_speed=$(/bin/omr-test-speed-server ${server} ${OMR_TRACKER_DEVICE} fasttest upload)
|
||||
upload_speed2=$(/bin/omr-test-speed-server ${server} ${OMR_TRACKER_DEVICE} fasttest upload)
|
||||
upload_speed3=$(/bin/omr-test-speed-server ${server} ${OMR_TRACKER_DEVICE} fasttest upload)
|
||||
[ "$upload_speed2" -gt "$upload_speed" ] && upload_speed=${upload_speed2}
|
||||
[ "$upload_speed3" -gt "$upload_speed" ] && upload_speed=${upload_speed3}
|
||||
|
||||
# Set Upload speed settings
|
||||
upload_speed=$((upload_speed/1000))
|
||||
if [ -n "$upload_speed" ] && [ "$upload_speed" != "0" ]; then
|
||||
# Set Download speed settings
|
||||
if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ]; then
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.upload=$((upload_speed*65/100))
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.max_upload=${upload_speed}
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.min_upload=$((upload_speed*10/100))
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.download=$((download_speed*65/100))
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.max_download=${download_speed}
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.min_download=$((download_speed*10/100))
|
||||
else
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.upload=$((upload_speed*95/100))
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.download=$((download_speed*95/100))
|
||||
fi
|
||||
_log "Calculated ${OMR_TRACKER_INTERFACE} download speed: ${download_speed}"
|
||||
uci -q set network.${OMR_TRACKER_INTERFACE}.downloadspeed=${download_speed}
|
||||
|
||||
# Set Upload speed settings
|
||||
upload_speed=$((upload_speed/1000))
|
||||
if [ -n "$upload_speed" ] && [ "$upload_speed" != "0" ]; then
|
||||
if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ]; then
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.upload=$((upload_speed*65/100))
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.max_upload=${upload_speed}
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.min_upload=$((upload_speed*10/100))
|
||||
else
|
||||
uci -q set sqm.${OMR_TRACKER_INTERFACE}.upload=$((upload_speed*95/100))
|
||||
fi
|
||||
_log "Calculated ${OMR_TRACKER_INTERFACE} upload speed: ${upload_speed}"
|
||||
uci -q set network.${OMR_TRACKER_INTERFACE}.uploadspeed=${upload_speed}
|
||||
uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.testspeed_lc=$(date +"%s")
|
||||
uci commit network
|
||||
uci commit sqm
|
||||
uci commit openmptcprouter
|
||||
fi
|
||||
_log "Calculated ${OMR_TRACKER_INTERFACE} upload speed: ${upload_speed}"
|
||||
uci -q set network.${OMR_TRACKER_INTERFACE}.uploadspeed=${upload_speed}
|
||||
fi
|
||||
uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.testspeed_lc=$(date +"%s")
|
||||
uci commit network
|
||||
uci commit sqm
|
||||
uci commit openmptcprouter
|
||||
fi
|
||||
}
|
||||
config_load openmptcprouter
|
||||
config_foreach launch_speedtest server
|
||||
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (C) 2020-2022 Ycarus (Yannick Chabanois) <ycarus@zugaina.org> for OpenMPTCProuter project
|
||||
# Copyright (C) 2020-2023 Ycarus (Yannick Chabanois) <ycarus@zugaina.org> for OpenMPTCProuter project
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
|
@ -9,9 +9,9 @@ include $(TOPDIR)/rules.mk
|
|||
|
||||
PKG_NAME:=mptcpd
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/intel/mptcpd.git
|
||||
PKG_SOURCE_VERSION:=88bea6802379ee1cdbcba4817351b63fd1489537
|
||||
PKG_VERSION:=0.9-$(PKG_SOURCE_VERSION)
|
||||
PKG_SOURCE_URL:=https://github.com/multipath-tcp/mptcpd.git
|
||||
PKG_SOURCE_VERSION:=863e83f255f55dfd0ba9325d816bd99f6d9da0c2
|
||||
PKG_VERSION:=0.12-$(PKG_SOURCE_VERSION)
|
||||
PKG_RELEASE:=1
|
||||
PKG_MAINTAINER:=Ycarus (Yannick Chabanois) <ycarus@zugaina.org>
|
||||
|
||||
|
|
703
mptcpd/patches/ndiffports.patch
Normal file
703
mptcpd/patches/ndiffports.patch
Normal file
|
@ -0,0 +1,703 @@
|
|||
From f127effabdb5aa1114613b637c96b212a603c57a Mon Sep 17 00:00:00 2001
|
||||
From: Mat Martineau <mathew.j.martineau@linux.intel.com>
|
||||
Date: Tue, 14 Jun 2022 16:35:18 -0700
|
||||
Subject: [PATCH] plugins: Add ndiffports plugin
|
||||
|
||||
This plugin creates N different subflows for each MPTCP connection, all
|
||||
using the same single interface on each peer. Only the original local
|
||||
and remote IP addresses are used, but with unique port numbers for each
|
||||
subflow.
|
||||
---
|
||||
plugins/path_managers/Makefile.am | 17 +-
|
||||
plugins/path_managers/ndiffports.c | 647 +++++++++++++++++++++++++++++
|
||||
2 files changed, 663 insertions(+), 1 deletion(-)
|
||||
create mode 100644 plugins/path_managers/ndiffports.c
|
||||
|
||||
diff --git a/plugins/path_managers/Makefile.am b/plugins/path_managers/Makefile.am
|
||||
index 50719921..8320b750 100644
|
||||
--- a/plugins/path_managers/Makefile.am
|
||||
+++ b/plugins/path_managers/Makefile.am
|
||||
@@ -7,7 +7,7 @@ include $(top_srcdir)/aminclude_static.am
|
||||
MPTCPD_PLUGIN_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include -I$(top_builddir)/include
|
||||
|
||||
-pkglib_LTLIBRARIES = addr_adv.la sspi.la
|
||||
+pkglib_LTLIBRARIES = addr_adv.la ndiffports.la sspi.la
|
||||
|
||||
sspi_la_SOURCES = sspi.c
|
||||
sspi_la_CPPFLAGS = $(MPTCPD_PLUGIN_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS)
|
||||
@@ -24,6 +24,21 @@ sspi_la_LIBADD = \
|
||||
$(top_builddir)/lib/libmptcpd.la \
|
||||
$(CODE_COVERAGE_LIBS)
|
||||
|
||||
+ndiffports_la_SOURCES = ndiffports.c
|
||||
+ndiffports_la_CPPFLAGS = $(MPTCPD_PLUGIN_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS)
|
||||
+ndiffports_la_CFLAGS = \
|
||||
+ $(ELL_CFLAGS) \
|
||||
+ $(MPTCPD_PLUGIN_CFLAGS) \
|
||||
+ $(CODE_COVERAGE_CFLAGS)
|
||||
+ndiffports_la_LDFLAGS = \
|
||||
+ -no-undefined \
|
||||
+ -module \
|
||||
+ -avoid-version \
|
||||
+ $(ELL_LIBS)
|
||||
+ndiffports_la_LIBADD = \
|
||||
+ $(top_builddir)/lib/libmptcpd.la \
|
||||
+ $(CODE_COVERAGE_LIBS)
|
||||
+
|
||||
addr_adv_la_SOURCES = addr_adv.c
|
||||
addr_adv_la_CPPFLAGS = $(MPTCPD_PLUGIN_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS)
|
||||
addr_adv_la_CFLAGS = \
|
||||
diff --git a/plugins/path_managers/ndiffports.c b/plugins/path_managers/ndiffports.c
|
||||
new file mode 100644
|
||||
index 00000000..f217dbbd
|
||||
--- /dev/null
|
||||
+++ b/plugins/path_managers/ndiffports.c
|
||||
@@ -0,0 +1,647 @@
|
||||
+// SPDX-License-Identifier: BSD-3-Clause
|
||||
+/**
|
||||
+ * @file ndiffports.c
|
||||
+ *
|
||||
+ * @brief MPTCP n-different-ports path manager plugin.
|
||||
+ *
|
||||
+ * This plugin creates N different subflows for each MPTCP connection,
|
||||
+ * all using the same single interface on each peer. Only the original
|
||||
+ * local and remote IP addresses are used, but with unique port numbers
|
||||
+ * for each subflow.
|
||||
+ *
|
||||
+ * Copyright (c) 2022, Intel Corporation
|
||||
+ */
|
||||
+
|
||||
+#ifdef HAVE_CONFIG_H
|
||||
+# include <mptcpd/private/config.h> // For NDEBUG and mptcpd VERSION.
|
||||
+#endif
|
||||
+
|
||||
+#include <assert.h>
|
||||
+#include <stddef.h> // For NULL.
|
||||
+#include <limits.h>
|
||||
+
|
||||
+#include <netinet/in.h>
|
||||
+
|
||||
+#pragma GCC diagnostic push
|
||||
+#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
+#include <ell/util.h> // For L_STRINGIFY needed by l_error().
|
||||
+#include <ell/log.h>
|
||||
+#include <ell/hashmap.h>
|
||||
+#include <ell/time.h>
|
||||
+#pragma GCC diagnostic pop
|
||||
+
|
||||
+#include <mptcpd/network_monitor.h>
|
||||
+#include <mptcpd/path_manager.h>
|
||||
+#include <mptcpd/plugin.h>
|
||||
+#include <mptcpd/id_manager.h>
|
||||
+
|
||||
+/*
|
||||
+ * Development notes
|
||||
+ *
|
||||
+ * - Need config file value for N in Ndiffports
|
||||
+ * - Track both local and remote port to allow for remote-initiated subflows
|
||||
+ * - Subflow request timeout (clear pending flag?)
|
||||
+ *
|
||||
+ * Questions
|
||||
+ * - Is subflow close "reason code" available on the genl api?
|
||||
+ *
|
||||
+ * Longer-term ideas
|
||||
+ *
|
||||
+ * - Accept advertisements for remote ports with the same remote address
|
||||
+ * as the initial subflow.
|
||||
+ * - Advertise multiple local listening ports
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * @brief Number of subflows to allow.
|
||||
+ *
|
||||
+ * Compile-time constant as a temporary measure, until plugins have access
|
||||
+ * to config file values.
|
||||
+ */
|
||||
+#define NDIFFPORTS_LIMIT 2
|
||||
+
|
||||
+/**
|
||||
+ * @brief Time threshold for detecting subflows rejected by the peer
|
||||
+ *
|
||||
+ * Subflows with a lifetime under this number of second are considered an
|
||||
+ * indication of hitting the remote peer's subflow limit.
|
||||
+ */
|
||||
+#define NDIFFPORTS_REJECT_TIME 10
|
||||
+
|
||||
+/**
|
||||
+ * @struct ndiffports_subflow_info
|
||||
+ *
|
||||
+ * @brief Per-subflow information.
|
||||
+ *
|
||||
+ * Each connection tracks this information for each subflow it uses.
|
||||
+ * With ndiffports, all local and remote addresses are the same so only
|
||||
+ * port information is required to identify a specific subflow.
|
||||
+ *
|
||||
+ * Other fields track the state of the subflow.
|
||||
+ */
|
||||
+struct ndiffports_subflow_info
|
||||
+{
|
||||
+ /// Local port number for this subflow
|
||||
+ in_port_t local_port;
|
||||
+
|
||||
+ /// Subflow slot is free or in use
|
||||
+ bool in_use;
|
||||
+
|
||||
+ /// Timestamp for tracking last change to subflow state
|
||||
+ uint64_t timestamp;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * @struct ndiffports_connection_info
|
||||
+ *
|
||||
+ * @brief Per-connection information.
|
||||
+ *
|
||||
+ * Instances of this structure are stored in the ndiffports_connections
|
||||
+ * hashmap, indexed by token. They are created when a connection is
|
||||
+ * established and freed when the connection is closed or the plugin
|
||||
+ * exits.
|
||||
+ */
|
||||
+struct ndiffports_connection_info
|
||||
+{
|
||||
+ /// Local address for all subflows. Port number ignored.
|
||||
+ struct sockaddr_storage laddr;
|
||||
+
|
||||
+ /// Remote address for all subflows.
|
||||
+ struct sockaddr_storage raddr;
|
||||
+
|
||||
+ /// Server (vs client) side
|
||||
+ bool server_side;
|
||||
+
|
||||
+ /// Active subflow count
|
||||
+ int active_subflows;
|
||||
+
|
||||
+ /// Max subflow count
|
||||
+ int max_subflows;
|
||||
+
|
||||
+ /// Peer rejected subflows
|
||||
+ int peer_rejected_consecutive;
|
||||
+
|
||||
+ /// Subflow was requested, but no new_subflow event yet
|
||||
+ bool pending_request;
|
||||
+
|
||||
+ /// Subflow info
|
||||
+ struct ndiffports_subflow_info subflow[NDIFFPORTS_LIMIT];
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * Hashmap of @c ndiffports_connection_info objects that track the
|
||||
+ * active MPTCP connections and associated state.
|
||||
+ */
|
||||
+static struct l_hashmap *ndiffports_connections;
|
||||
+
|
||||
+// ----------------------------------------------------------------
|
||||
+// Helper functions
|
||||
+// ----------------------------------------------------------------
|
||||
+
|
||||
+/**
|
||||
+ * @brief Extract local port information from a @c sockaddr
|
||||
+ *
|
||||
+ * @param[in] addr A @c struct @c sockaddr with an IPv4 or IPv6 address+port
|
||||
+ *
|
||||
+ * @return @c sin_port or @c sin6_port from the @a addr, or @c 0 if
|
||||
+ * an invalid @c sa_family was detected.
|
||||
+ *
|
||||
+ */
|
||||
+static in_port_t get_port(struct sockaddr const *addr)
|
||||
+{
|
||||
+ in_port_t port = 0;
|
||||
+
|
||||
+ if (addr->sa_family == AF_INET) {
|
||||
+ port = ((struct sockaddr_in const *) addr)->sin_port;
|
||||
+ } else if (addr->sa_family == AF_INET6) {
|
||||
+ port = ((struct sockaddr_in6 const *) addr)->sin6_port;
|
||||
+ }
|
||||
+
|
||||
+ return port;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief Set the port number to 0 in a @c struct @c sockaddr.
|
||||
+ *
|
||||
+ * @param[in] addr A @c struct @c sockaddr to modify
|
||||
+ */
|
||||
+static void clear_port(struct sockaddr *addr)
|
||||
+{
|
||||
+ if (addr->sa_family == AF_INET) {
|
||||
+ ((struct sockaddr_in *) addr)->sin_port = 0;
|
||||
+ } else if (addr->sa_family == AF_INET6) {
|
||||
+ ((struct sockaddr_in6 *) addr)->sin6_port = 0;
|
||||
+ } else {
|
||||
+ l_error("Unexpected sockaddr family %d", addr->sa_family);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief Locate an unused subflow slot
|
||||
+ *
|
||||
+ * Each @c struct @c ndiffports_connection_info contains an array of @c
|
||||
+ * struct @c ndiffports_subflow_info objects. Find the first subflow
|
||||
+ * object that is not in use.
|
||||
+ *
|
||||
+ * @param[in] info A @c struct @c ndiffports_connection_info
|
||||
+ *
|
||||
+ * @return Pointer to the first available object, or NULL if none available
|
||||
+ */
|
||||
+static struct ndiffports_subflow_info *
|
||||
+find_empty_subflow(struct ndiffports_connection_info *info)
|
||||
+{
|
||||
+ for (int i = 0; i < NDIFFPORTS_LIMIT && i < info->max_subflows; i++) {
|
||||
+ if (!info->subflow[i].in_use) {
|
||||
+ return &info->subflow[i];
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief Find an existing subflow matching the provided local endpoint
|
||||
+ *
|
||||
+ * Look up a subflow object and return a pointer to it, using the
|
||||
+ * local port number. Address values are assumed to be validated already.
|
||||
+ *
|
||||
+ * @param[in] info A @c struct @c ndiffports_connection_info
|
||||
+ * @param[in] laddr A @c struct @c sockaddr containing the port number
|
||||
+ *
|
||||
+ * @return Pointer to the subflow object if found, or @c NULL if not found.
|
||||
+ */
|
||||
+static struct ndiffports_subflow_info *
|
||||
+find_subflow(struct ndiffports_connection_info *info,
|
||||
+ struct sockaddr const *laddr)
|
||||
+{
|
||||
+ in_port_t lport = get_port(laddr);
|
||||
+
|
||||
+ for (int i = 0; i < NDIFFPORTS_LIMIT && i < info->max_subflows; i++) {
|
||||
+ struct ndiffports_subflow_info *sub = &info->subflow[i];
|
||||
+
|
||||
+ if (sub->in_use && sub->local_port == lport) {
|
||||
+ return &info->subflow[i];
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief Initiate a new subflow
|
||||
+ *
|
||||
+ * @param[in] pm Path manager object to act on
|
||||
+ * @param[in] token Token for the connection where the subflow will be added
|
||||
+ * @param[in] info Connection object where the subflow will be added
|
||||
+ */
|
||||
+static void add_new_subflow(struct mptcpd_pm *pm, mptcpd_token_t token,
|
||||
+ struct ndiffports_connection_info *info)
|
||||
+{
|
||||
+ if (info->pending_request) {
|
||||
+ l_warn("New subflow request while previous request is pending");
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ info->pending_request = true;
|
||||
+
|
||||
+ mptcpd_pm_add_subflow(pm, token, 1, 0,
|
||||
+ (struct sockaddr *)&info->laddr,
|
||||
+ (struct sockaddr *)&info->raddr,
|
||||
+ false);
|
||||
+
|
||||
+ /* TODO: start a timer to retry subflow creation */
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief Check two @c sockaddr objects for equality.
|
||||
+ *
|
||||
+ * Addresses are equal if the @c sa_family and @c sin_addr / @c sin6_addr
|
||||
+ * fields match. Port numbers are ignored.
|
||||
+ *
|
||||
+ * @param[in] addr1 Address to compare
|
||||
+ * @param[in] addr2 Address to compare
|
||||
+ *
|
||||
+ * @return @c true if the network addresses match (including address
|
||||
+ * family). @false if the address family or address values don't match.
|
||||
+ */
|
||||
+static bool addrs_equal(struct sockaddr const *addr1,
|
||||
+ struct sockaddr const *addr2)
|
||||
+{
|
||||
+ if (addr1->sa_family != addr2->sa_family) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (addr1->sa_family == AF_INET) {
|
||||
+ struct sockaddr_in const *const addr1_in =
|
||||
+ (struct sockaddr_in const *) addr1;
|
||||
+ struct sockaddr_in const *const addr2_in =
|
||||
+ (struct sockaddr_in const *) addr2;
|
||||
+
|
||||
+ return addr1_in->sin_addr.s_addr == addr2_in->sin_addr.s_addr;
|
||||
+ } else {
|
||||
+ struct sockaddr_in6 const *const addr1_in6 =
|
||||
+ (struct sockaddr_in6 const *) addr1;
|
||||
+ struct sockaddr_in6 const *const addr2_in6 =
|
||||
+ (struct sockaddr_in6 const *) addr2;
|
||||
+
|
||||
+ return 0 == memcmp(&addr1_in6->sin6_addr, &addr2_in6->sin6_addr,
|
||||
+ sizeof(addr1_in6->sin6_addr));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief Validate addresses on a new subflow
|
||||
+ *
|
||||
+ * With ndiffports, all subflows are expected to use the same local and
|
||||
+ * remote addresses as the initial subflow. Valid subflows will have
|
||||
+ * both addresses match (port numbers are ignored).
|
||||
+ *
|
||||
+ * @param[in] info Connection to validate against
|
||||
+ * @param[in] laddr Local address for new subflow
|
||||
+ * @param[in] raddr Remote address for new subflow
|
||||
+ *
|
||||
+ * @return @c true if local/remote addresses for the connection match
|
||||
+ * those in the new subflow. @c false if either pair differs.
|
||||
+ */
|
||||
+static bool validate_addrs(struct ndiffports_connection_info *info,
|
||||
+ struct sockaddr const *laddr,
|
||||
+ struct sockaddr const *raddr)
|
||||
+{
|
||||
+ return (addrs_equal((struct sockaddr*)&info->laddr, laddr) &&
|
||||
+ addrs_equal((struct sockaddr*)&info->raddr, raddr));
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief Calculate how many seconds ago a timestamp was
|
||||
+ *
|
||||
+ * @param[in] timestamp Timestamp in the past
|
||||
+ *
|
||||
+ * @return Number of seconds since the @c timestamp. 0 if timestamp is in
|
||||
+ * the future.
|
||||
+ */
|
||||
+static uint64_t seconds_elapsed(uint64_t timestamp)
|
||||
+{
|
||||
+ uint64_t now = l_time_now();
|
||||
+
|
||||
+ return (now > timestamp) ? l_time_to_secs(now - timestamp) : 0;
|
||||
+}
|
||||
+
|
||||
+// ----------------------------------------------------------------
|
||||
+// Mptcpd Plugin Operations
|
||||
+// ----------------------------------------------------------------
|
||||
+
|
||||
+/**
|
||||
+ * @brief Connection established event handler
|
||||
+ *
|
||||
+ * When a new connection is created, set up data structures to track
|
||||
+ * connection-related info and track the initial subflow.
|
||||
+ *
|
||||
+ * If additional subflows need to be established and this peer initiated
|
||||
+ * the connection, initiate one new subflow.
|
||||
+ *
|
||||
+ * @param[in] token MPTCP connection token for this new connection
|
||||
+ * @param[in] laddr Local address and port for the initial subflow
|
||||
+ * @param[in] raddr Remote address and port for the initial subflow
|
||||
+ * @param[in] server_side @c true if this peer was the listener (server),
|
||||
+ * @c false if this peer initiated the connection.
|
||||
+ * @param[in] pm Path manager object
|
||||
+ */
|
||||
+static void ndiffports_connection_established(mptcpd_token_t token,
|
||||
+ struct sockaddr const *laddr,
|
||||
+ struct sockaddr const *raddr,
|
||||
+ bool server_side,
|
||||
+ struct mptcpd_pm *pm)
|
||||
+{
|
||||
+ struct ndiffports_subflow_info *first_subflow;
|
||||
+ struct ndiffports_connection_info *new_entry;
|
||||
+ in_port_t local_port = get_port(laddr);
|
||||
+ void *old_entry;
|
||||
+
|
||||
+ if (!local_port) {
|
||||
+ l_error("Invalid local port");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ new_entry = l_new(struct ndiffports_connection_info, 1);
|
||||
+
|
||||
+ memcpy(&new_entry->laddr, laddr, sizeof(new_entry->laddr));
|
||||
+ memcpy(&new_entry->raddr, raddr, sizeof(new_entry->raddr));
|
||||
+ new_entry->server_side = server_side;
|
||||
+ new_entry->active_subflows = 1;
|
||||
+ new_entry->max_subflows = NDIFFPORTS_LIMIT;
|
||||
+
|
||||
+ /* Zero out the port number on the local addr so it's assigned
|
||||
+ * at connect time for new subflows
|
||||
+ */
|
||||
+ clear_port((struct sockaddr *)&new_entry->laddr);
|
||||
+
|
||||
+ first_subflow = &new_entry->subflow[0];
|
||||
+ first_subflow->local_port = local_port;
|
||||
+ first_subflow->timestamp = l_time_now();
|
||||
+
|
||||
+ if (!l_hashmap_replace(ndiffports_connections, L_UINT_TO_PTR(token),
|
||||
+ new_entry, &old_entry)) {
|
||||
+ l_error("Unable to store connection info");
|
||||
+ }
|
||||
+
|
||||
+ if (old_entry) {
|
||||
+ /* Unexpected: token already exists.
|
||||
+ * The kernel enforces unique tokens so assume it's stale
|
||||
+ * data from an old connection that no longer exists.
|
||||
+ */
|
||||
+ l_warn("Found old entry for token %08x", token);
|
||||
+ l_free(old_entry);
|
||||
+ }
|
||||
+
|
||||
+ if (!server_side &&
|
||||
+ new_entry->active_subflows < new_entry->max_subflows) {
|
||||
+ add_new_subflow(pm, token, new_entry);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief Connection closed event handler
|
||||
+ *
|
||||
+ * When a connection is closed, delete the tracking information for
|
||||
+ * that connection.
|
||||
+ *
|
||||
+ * @param[in] token MPTCP connection token for this new connection
|
||||
+ * @param[in] pm Path manager object (unused)
|
||||
+ */
|
||||
+static void ndiffports_connection_closed(mptcpd_token_t token,
|
||||
+ struct mptcpd_pm *pm)
|
||||
+{
|
||||
+ struct ndiffports_connection_info *entry;
|
||||
+ (void) pm;
|
||||
+
|
||||
+ entry = l_hashmap_remove(ndiffports_connections, L_UINT_TO_PTR(token));
|
||||
+
|
||||
+ if (!entry) {
|
||||
+ l_warn("Missing entry for token %08x", token);
|
||||
+ }
|
||||
+
|
||||
+ l_free(entry);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief New subflow event handler
|
||||
+ *
|
||||
+ * When a new subflow is created, track the subflow information within
|
||||
+ * the corresponding connection entry.
|
||||
+ *
|
||||
+ * If additional subflows need to be established and this peer initiated
|
||||
+ * the overall MPTCP connection, initiate one new subflow.
|
||||
+ *
|
||||
+ * @param[in] token MPTCP connection token for this new connection
|
||||
+ * @param[in] laddr Local address and port for new subflow
|
||||
+ * @param[in] raddr Remote address and port for new subflow
|
||||
+ * @param[in] backup @c true if this is backup subflow, @c false for
|
||||
+ * regular priority. (not used)
|
||||
+ * @param[in] pm Path manager object
|
||||
+ */
|
||||
+static void ndiffports_new_subflow(mptcpd_token_t token,
|
||||
+ struct sockaddr const *laddr,
|
||||
+ struct sockaddr const *raddr,
|
||||
+ bool backup,
|
||||
+ struct mptcpd_pm *pm)
|
||||
+{
|
||||
+ struct ndiffports_subflow_info *sub;
|
||||
+ struct ndiffports_connection_info *entry;
|
||||
+
|
||||
+ (void) backup;
|
||||
+
|
||||
+ entry = l_hashmap_lookup(ndiffports_connections, L_UINT_TO_PTR(token));
|
||||
+
|
||||
+ if (!entry) {
|
||||
+ l_warn("New subflow for unmanaged token %08x", token);
|
||||
+
|
||||
+ mptcpd_pm_remove_subflow(pm, token, laddr, raddr);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!validate_addrs(entry, laddr, raddr) ||
|
||||
+ entry->active_subflows >= entry->max_subflows) {
|
||||
+ goto reject;
|
||||
+ }
|
||||
+
|
||||
+ sub = find_subflow(entry, laddr);
|
||||
+
|
||||
+ if (sub) {
|
||||
+ l_warn("Unexpected event from established subflow");
|
||||
+
|
||||
+ // TODO: stop timer.
|
||||
+ } else {
|
||||
+ sub = find_empty_subflow(entry);
|
||||
+ if (!sub) {
|
||||
+ goto reject;
|
||||
+ }
|
||||
+
|
||||
+ sub->in_use = true;
|
||||
+ sub->timestamp = l_time_now();
|
||||
+
|
||||
+ entry->active_subflows++;
|
||||
+
|
||||
+ sub->local_port = get_port(laddr);
|
||||
+ }
|
||||
+
|
||||
+ sub->timestamp = l_time_now();
|
||||
+ entry->pending_request = false;
|
||||
+
|
||||
+ /* TODO: start timer to clear consecutive_reject counter */
|
||||
+
|
||||
+ if (!entry->server_side &&
|
||||
+ entry->active_subflows < entry->max_subflows) {
|
||||
+ add_new_subflow(pm, token, entry);
|
||||
+ }
|
||||
+
|
||||
+ return;
|
||||
+
|
||||
+reject:
|
||||
+ mptcpd_pm_remove_subflow(pm, token, laddr, raddr);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief Subflow closed event handler
|
||||
+ *
|
||||
+ * When a subflow is closed, clear related information. If the number of
|
||||
+ * subflows is below the expected count and this peer initiated the
|
||||
+ * original connection, request a new subflow to replace the closed one.
|
||||
+ *
|
||||
+ * @param[in] token MPTCP connection token for this new connection
|
||||
+ * @param[in] laddr Local address and port for new subflow
|
||||
+ * @param[in] raddr Remote address and port for new subflow
|
||||
+ * @param[in] backup @c true if this is backup subflow, @c false for
|
||||
+ * regular priority. (not used)
|
||||
+ * @param[in] pm Path manager object
|
||||
+ */
|
||||
+static void ndiffports_subflow_closed(mptcpd_token_t token,
|
||||
+ struct sockaddr const *laddr,
|
||||
+ struct sockaddr const *raddr,
|
||||
+ bool backup,
|
||||
+ struct mptcpd_pm *pm)
|
||||
+{
|
||||
+ struct ndiffports_connection_info *entry;
|
||||
+ struct ndiffports_subflow_info *sub;
|
||||
+
|
||||
+ (void) backup;
|
||||
+
|
||||
+ entry = l_hashmap_lookup(ndiffports_connections, L_UINT_TO_PTR(token));
|
||||
+
|
||||
+ if (!entry) {
|
||||
+ l_warn("Closed subflow for unmanaged token %08x", token);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!validate_addrs(entry, laddr, raddr)) {
|
||||
+ l_warn("Address/token mismatch for token %08x", token);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ sub = find_subflow(entry, laddr);
|
||||
+
|
||||
+ if (sub) {
|
||||
+ if (seconds_elapsed(sub->timestamp) < NDIFFPORTS_REJECT_TIME) {
|
||||
+ entry->peer_rejected_consecutive++;
|
||||
+ }
|
||||
+
|
||||
+ sub->in_use = false;
|
||||
+ sub->timestamp = l_time_now();
|
||||
+
|
||||
+ if (entry->active_subflows > 0) {
|
||||
+ entry->active_subflows--;
|
||||
+ } else {
|
||||
+ l_error("Underflow when adjusting subflow count");
|
||||
+ }
|
||||
+ } else {
|
||||
+ l_warn("Untracked subflow was closed");
|
||||
+ }
|
||||
+
|
||||
+ if (!entry->server_side &&
|
||||
+ entry->active_subflows < entry->max_subflows) {
|
||||
+ add_new_subflow(pm, token, entry);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Plugin ops to register with the mptcpd core
|
||||
+ */
|
||||
+static struct mptcpd_plugin_ops const pm_ops = {
|
||||
+ .connection_established = ndiffports_connection_established,
|
||||
+ .connection_closed = ndiffports_connection_closed,
|
||||
+ .new_subflow = ndiffports_new_subflow,
|
||||
+ .subflow_closed = ndiffports_subflow_closed,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * @brief Ndiffports plugin init hook
|
||||
+ *
|
||||
+ * Set up the hashmap for tracking connections.
|
||||
+ *
|
||||
+ * @param[in] pm Path manager object (not used)
|
||||
+ */
|
||||
+static int ndiffports_init(struct mptcpd_pm *pm)
|
||||
+{
|
||||
+ (void) pm;
|
||||
+
|
||||
+ static char const name[] = "ndiffports";
|
||||
+
|
||||
+ if (!mptcpd_plugin_register_ops(name, &pm_ops)) {
|
||||
+ l_error("Failed to initialize "
|
||||
+ "n-different-ports "
|
||||
+ "path manager plugin.");
|
||||
+
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ ndiffports_connections = l_hashmap_new();
|
||||
+
|
||||
+ l_info("MPTCP n-different-ports "
|
||||
+ "path manager initialized.");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief Helper for cleaning up connection info
|
||||
+ *
|
||||
+ * Delete one connection entry.
|
||||
+ *
|
||||
+ * @param[in] pm Path manager object (not used)
|
||||
+ */
|
||||
+static void ndiffports_connection_destroy(void *value)
|
||||
+{
|
||||
+ struct ndiffports_connection_info *info = value;
|
||||
+
|
||||
+ l_free(info);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @brief Ndiffports plugin exit hook
|
||||
+ *
|
||||
+ * Delete the hashmap for tracking connections.
|
||||
+ *
|
||||
+ * @param[in] pm Path manager object (not used)
|
||||
+ */
|
||||
+static void ndiffports_exit(struct mptcpd_pm *pm)
|
||||
+{
|
||||
+ (void) pm;
|
||||
+
|
||||
+ l_hashmap_destroy(ndiffports_connections,
|
||||
+ ndiffports_connection_destroy);
|
||||
+ ndiffports_connections = NULL;
|
||||
+ l_info("MPTCP n-different-ports path manager exited.");
|
||||
+}
|
||||
+
|
||||
+MPTCPD_PLUGIN_DEFINE(ndiffports,
|
||||
+ "N-different-ports path manager",
|
||||
+ MPTCPD_PLUGIN_PRIORITY_DEFAULT,
|
||||
+ ndiffports_init,
|
||||
+ ndiffports_exit)
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ Local Variables:
|
||||
+ c-file-style: "linux"
|
||||
+ End:
|
||||
+*/
|
|
@ -19,7 +19,7 @@ INTERFACE="$i"
|
|||
exit 0
|
||||
}
|
||||
|
||||
[ "$FASTTEST" ] || echo "Select best test server..."
|
||||
[ "$FASTTEST" = true ] || echo "Select best test server..."
|
||||
HOSTLST="http://scaleway.testdebit.info/10G.iso http://bordeaux.testdebit.info/10G.iso http://aix-marseille.testdebit.info/10G.iso http://lyon.testdebit.info/10G.iso http://lille.testdebit.info/10G.iso http://paris.testdebit.info/10G.iso http://appliwave.testdebit.info/10G/10G.iso http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 https://speed.hetzner.de/10GB.bin http://ipv4.bouygues.testdebit.info/10G.iso http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://speedtest.milkywan.fr/files/10G.iso"
|
||||
bestping="9999"
|
||||
for pinghost in $HOSTLST; do
|
||||
|
@ -29,7 +29,7 @@ for pinghost in $HOSTLST; do
|
|||
else
|
||||
ping=$(ping -4 -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n')
|
||||
fi
|
||||
[ "$FASTTEST" ] || echo "host: $domain - ping: $ping"
|
||||
[ "$FASTTEST" = true ] || echo "host: $domain - ping: $ping"
|
||||
if [ -n "$ping" ] && [ "$ping" -lt "$bestping" ]; then
|
||||
bestping=$ping
|
||||
HOST=$pinghost
|
||||
|
@ -38,7 +38,7 @@ done
|
|||
|
||||
[ -z "$HOST" ] && HOST="https://speed.hetzner.de/10GB.bin"
|
||||
|
||||
[ "$FASTTEST" ] || echo "Best server is $HOST, running test:"
|
||||
[ "$FASTTEST" = true ] || echo "Best server is $HOST, running test:"
|
||||
trap : HUP INT TERM
|
||||
if [ -z "$INTERFACE" ]; then
|
||||
curl -4 -o /dev/null $HOST || echo
|
||||
|
@ -51,11 +51,11 @@ else
|
|||
ipset add ss_rules_dst_bypass_all $ip
|
||||
done
|
||||
fi
|
||||
if [ "$FASTTEST" ]; then
|
||||
if [ "$FASTTEST" = true ]; then
|
||||
avg_speed=$(curl -4 --max-time 10 -o /dev/null -qfsS -w '%{speed_download}' --interface $INTERFACE $HOST 2>/dev/null)
|
||||
echo "$avg_speed"
|
||||
else
|
||||
curl -4 --max-time 4 -o /dev/null --interface $INTERFACE $HOST || echo
|
||||
curl -4 -o /dev/null --interface $INTERFACE $HOST || echo
|
||||
fi
|
||||
if [ -n "$(ipset list 2>/dev/null | grep ss_rules)" ]; then
|
||||
for ip in $hostip; do
|
||||
|
|
Loading…
Reference in a new issue