Skip to content
Snippets Groups Projects
Commit 397ef82b authored by Olivier SOLDANO's avatar Olivier SOLDANO Committed by Guillaume Roguez
Browse files

fix asymetric IPV4/IPV6 mtu discovery


when the remote (server) has a IPV6 interface selected by ICE,
and local (client) has a IPV4 selected, the path MTU discovery triggers
errors for packets too big on server side because of different
IP headers overhead.
Hence we have to signal to the TLS session to reduce the MTU discovery
packets payload size on client side accordingly.

[GR: use GenericSocket class to export local/remote address]

Change-Id: I724b97c9ccd5e7240a87fb60ef000b4485710131
Signed-off-by: default avatarGuillaume Roguez <guillaume.roguez@savoirfairelinux.com>
Reviewed-by: default avatarGuillaume Roguez <guillaume.roguez@savoirfairelinux.com>
parent 5130bbcf
Branches
No related tags found
No related merge requests found
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#pragma once #pragma once
#include "ip_utils.h"
#include <functional> #include <functional>
#include <vector> #include <vector>
#include <system_error> #include <system_error>
...@@ -100,6 +102,16 @@ public: ...@@ -100,6 +102,16 @@ public:
return res; return res;
} }
/// Return the local IP address if known.
/// \note The address is not valid (addr.isUnspecified() returns true) if it's not known
/// or not available.
virtual IpAddr localAddr() const { return {}; }
/// Return the remote IP address if known.
/// \note The address is not valid (addr.isUnspecified() returns true) if it's not known
/// or not available.
virtual IpAddr remoteAddr() const { return {}; }
protected: protected:
GenericSocket() = default; GenericSocket() = default;
}; };
......
...@@ -87,6 +87,10 @@ public: ...@@ -87,6 +87,10 @@ public:
void setOnRecv(RecvCb&& cb) override; void setOnRecv(RecvCb&& cb) override;
IpAddr localAddr() const override;
IpAddr remoteAddr() const override;
private: private:
const int compId_; const int compId_;
std::shared_ptr<IceTransport> ice_; std::shared_ptr<IceTransport> ice_;
......
...@@ -1226,6 +1226,18 @@ IceSocketTransport::read(ValueType* buf, std::size_t len, std::error_code& ec) ...@@ -1226,6 +1226,18 @@ IceSocketTransport::read(ValueType* buf, std::size_t len, std::error_code& ec)
return res; return res;
} }
IpAddr
IceSocketTransport::localAddr() const
{
return ice_->getLocalAddress(compId_);
}
IpAddr
IceSocketTransport::remoteAddr() const
{
return ice_->getRemoteAddress(compId_);
}
//============================================================================== //==============================================================================
void void
......
...@@ -68,6 +68,7 @@ static constexpr auto HEARTBEAT_RETRANS_TIMEOUT = std::chrono::milliseconds(700) ...@@ -68,6 +68,7 @@ static constexpr auto HEARTBEAT_RETRANS_TIMEOUT = std::chrono::milliseconds(700)
static constexpr auto HEARTBEAT_TOTAL_TIMEOUT = HEARTBEAT_RETRANS_TIMEOUT * HEARTBEAT_TRIES; // gnutls heartbeat time limit for heartbeat procedure (in milliseconds) static constexpr auto HEARTBEAT_TOTAL_TIMEOUT = HEARTBEAT_RETRANS_TIMEOUT * HEARTBEAT_TRIES; // gnutls heartbeat time limit for heartbeat procedure (in milliseconds)
static constexpr int MISS_ORDERING_LIMIT = 32; // maximal accepted distance of out-of-order packet (note: must be a signed type) static constexpr int MISS_ORDERING_LIMIT = 32; // maximal accepted distance of out-of-order packet (note: must be a signed type)
static constexpr auto RX_OOO_TIMEOUT = std::chrono::milliseconds(1500); static constexpr auto RX_OOO_TIMEOUT = std::chrono::milliseconds(1500);
static constexpr int ASYMETRIC_TRANSPORT_MTU_OFFSET = 20; // when client, if your local IP is IPV4 and server is IPV6; you must reduce your MTU to avoid packet too big error on server side. the offset is the difference in size of IP headers
// Helper to cast any duration into an integer number of milliseconds // Helper to cast any duration into an integer number of milliseconds
template <class Rep, class Period> template <class Rep, class Period>
...@@ -923,13 +924,26 @@ TlsSession::TlsSessionImpl::pathMtuHeartbeat() ...@@ -923,13 +924,26 @@ TlsSession::TlsSessionImpl::pathMtuHeartbeat()
HEARTBEAT_TOTAL_TIMEOUT.count()); HEARTBEAT_TOTAL_TIMEOUT.count());
int errno_send = GNUTLS_E_SUCCESS; int errno_send = GNUTLS_E_SUCCESS;
int mtuOffset = 0;
// when the remote (server) has a IPV6 interface selected by ICE, and local (client) has a IPV4 selected,
// the path MTU discovery triggers errors for packets too big on server side because of different IP headers overhead.
// Hence we have to signal to the TLS session to reduce the MTU on client size accordingly.
if (transport_.localAddr().isIpv4() and transport_.remoteAddr().isIpv6()) {
mtuOffset = ASYMETRIC_TRANSPORT_MTU_OFFSET;
RING_WARN() << "[TLS] local/remote IP protocol version not alike, use an MTU offset of "
<< ASYMETRIC_TRANSPORT_MTU_OFFSET << " bytes to compensate";
}
mtuProbe_ = MTUS_[0]; mtuProbe_ = MTUS_[0];
for (auto mtu: MTUS_) { for (auto mtu: MTUS_) {
gnutls_dtls_set_mtu(session_, mtu); gnutls_dtls_set_mtu(session_, mtu);
auto data_mtu = gnutls_dtls_get_data_mtu(session_); auto data_mtu = gnutls_dtls_get_data_mtu(session_);
RING_DBG() << "[TLS] PMTUD: mtu " << mtu RING_DBG() << "[TLS] PMTUD: mtu " << mtu
<< ", payload " << data_mtu; << ", payload " << data_mtu;
auto bytesToSend = data_mtu - 3; // want to know why -3? ask gnutls! auto bytesToSend = data_mtu - mtuOffset - 3; // want to know why -3? ask gnutls!
do { do {
errno_send = gnutls_heartbeat_ping(session_, bytesToSend, HEARTBEAT_TRIES, GNUTLS_HEARTBEAT_WAIT); errno_send = gnutls_heartbeat_ping(session_, bytesToSend, HEARTBEAT_TRIES, GNUTLS_HEARTBEAT_WAIT);
} while (errno_send == GNUTLS_E_AGAIN || errno_send == GNUTLS_E_INTERRUPTED); } while (errno_send == GNUTLS_E_AGAIN || errno_send == GNUTLS_E_INTERRUPTED);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment