1
0
forked from 0ad/0ad

Use a lower default MTU for ENet hosts, and make it configurable.

This fixes packet loss issues on some VPN solutions.

Patch By: sera
Differential Revision: https://code.wildfiregames.com/D4967
This was SVN commit r27599.
This commit is contained in:
Nicolas Auvray 2023-04-10 08:21:07 +00:00
parent ac3d187dcd
commit ef71533d70
6 changed files with 117 additions and 11 deletions

View File

@ -525,6 +525,7 @@ lateobservers = everyone ; Allow observers to join the game after it st
observerlimit = 8 ; Prevent further observer joins in running games if this limit is reached
observermaxlag = -1 ; Make clients wait for observers if they lag more than X turns behind. -1 means "never wait for observers".
autocatchup = true ; Auto-accelerate the sim rate if lagging behind (as an observer).
enetmtu = 1372 ; Lower ENet protocol MTU in case packets get further fragmented on the UDP layer which may cause drops.
[overlay]
fps = "false" ; Show frames per second in top right corner

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -20,6 +20,7 @@
#include "NetClient.h"
#include "NetClientTurnManager.h"
#include "NetEnet.h"
#include "NetMessage.h"
#include "NetSession.h"
@ -247,7 +248,7 @@ bool CNetClient::TryToConnect(const CStr& hostJID, bool localNetwork)
}
ENetAddress hostAddr{ ENET_HOST_ANY, ENET_PORT_ANY };
ENetHost* enetClient = enet_host_create(&hostAddr, 1, 1, 0, 0);
ENetHost* enetClient = PS::Enet::CreateHost(&hostAddr, 1, 1);
if (!enetClient)
{

View File

@ -0,0 +1,62 @@
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "NetEnet.h"
#include "ps/ConfigDB.h"
#include "ps/containers/Span.h"
namespace PS
{
namespace Enet
{
// ENet protocol MTU
// ENet by default uses 1400 as ENet packet fragment max size, adding ICMP and
// IPv4 headers this may exceed the MTU for some VPN solutions [1], so provide
// a lower default.
// MTU negotiation server-side needs [2], which was merged after enet-1.3.17,
// so the user configured value may be ignored on older versions.
// [1] https://github.com/lsalzman/enet/issues/132
// [2] https://github.com/lsalzman/enet/pull/222
constexpr enet_uint32 HOST_DEFAULT_MTU = 1372;
ENetHost* CreateHost(const ENetAddress* address, size_t peerCount, size_t channelLimit)
{
// TODO: Maybe allow user to set rate limits?
ENetHost* host = enet_host_create(address, peerCount, channelLimit, 0, 0);
if (!host)
return nullptr;
// Public ENet API doesn't offer a means to change MTU, so do it in a
// way least likely to break with ENet updates.
enet_uint32 mtu = HOST_DEFAULT_MTU;
CFG_GET_VAL("network.enetmtu", mtu);
host->mtu = mtu;
for (ENetPeer& p : PS::span{host->peers, host->peerCount})
enet_peer_reset(&p);
return host;
}
} // namespace Enet
} // namespace PS

44
source/network/NetEnet.h Normal file
View File

@ -0,0 +1,44 @@
/* Copyright (C) 2023 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef INCLUDED_NETENET
#define INCLUDED_NETENET
#include "lib/external_libraries/enet.h"
namespace PS
{
namespace Enet
{
/**
* Wrapper for enet_host_create setting default values and custom mtu, taking
* care of user configuration.
*/
ENetHost* CreateHost(const ENetAddress* address, size_t peerCount, size_t channelLimit);
} // namespace Enet
} // namespace PS
#endif // #ifndef INCLUDED_NETENET

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -20,6 +20,7 @@
#include "NetServer.h"
#include "NetClient.h"
#include "NetEnet.h"
#include "NetMessage.h"
#include "NetSession.h"
#include "NetServerTurnManager.h"
@ -223,7 +224,7 @@ bool CNetServerWorker::SetupConnection(const u16 port)
addr.port = port;
// Create ENet server
m_Host = enet_host_create(&addr, MAX_CLIENTS, CHANNEL_COUNT, 0, 0);
m_Host = PS::Enet::CreateHost(&addr, MAX_CLIENTS, CHANNEL_COUNT);
if (!m_Host)
{
LOGERROR("Net server: enet_host_create failed");

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games.
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -20,6 +20,7 @@
#include "NetSession.h"
#include "NetClient.h"
#include "NetEnet.h"
#include "NetMessage.h"
#include "NetServer.h"
#include "NetStats.h"
@ -60,12 +61,8 @@ bool CNetClientSession::Connect(const CStr& server, const u16 port, ENetHost* en
ENSURE(!m_Host);
ENSURE(!m_Server);
// Create ENet host
ENetHost* host;
if (enetClient != nullptr)
host = enetClient;
else
host = enet_host_create(NULL, 1, CHANNEL_COUNT, 0, 0);
// Create ENet host if necessary.
ENetHost* host = enetClient != nullptr ? enetClient : PS::Enet::CreateHost(nullptr, 1, CHANNEL_COUNT);
if (!host)
return false;