|
|
|
|
@ -798,12 +798,13 @@ public:
|
|
|
|
|
bool _serverThreadRunning; |
|
|
|
|
bool _serverThreadRunningV6; |
|
|
|
|
|
|
|
|
|
unsigned int _rxThreadCount; |
|
|
|
|
BlockingQueue<PacketRecord *> _rxPacketQueue; |
|
|
|
|
std::vector<PacketRecord *> _rxPacketVector; |
|
|
|
|
std::vector<std::thread> _rxPacketThreads; |
|
|
|
|
Mutex _rxPacketVector_m,_rxPacketThreads_m; |
|
|
|
|
bool _enableMulticore; |
|
|
|
|
bool _multicoreEnabled; |
|
|
|
|
bool _cpuPinningEnabled; |
|
|
|
|
unsigned int _concurrency; |
|
|
|
|
|
|
|
|
|
bool _allowTcpFallbackRelay; |
|
|
|
|
bool _forceTcpRelay; |
|
|
|
|
@ -938,89 +939,6 @@ public:
|
|
|
|
|
_ports[1] = 0; |
|
|
|
|
_ports[2] = 0; |
|
|
|
|
|
|
|
|
|
_enableMulticore = false; |
|
|
|
|
char* multicoreVar = std::getenv("ZT_ENABLE_MULTICORE"); |
|
|
|
|
if (multicoreVar) { |
|
|
|
|
int tmp = atoi(multicoreVar); |
|
|
|
|
if (tmp > 0) { |
|
|
|
|
_enableMulticore = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (_enableMulticore) { |
|
|
|
|
bool _enablePinning = false; |
|
|
|
|
char* pinningVar = std::getenv("ZT_CORE_PINNING"); |
|
|
|
|
if (pinningVar) { |
|
|
|
|
int tmp = atoi(pinningVar); |
|
|
|
|
if (tmp > 0) { |
|
|
|
|
_enablePinning = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
char* concurrencyVar = std::getenv("ZT_CONCURRENCY"); |
|
|
|
|
if (concurrencyVar) { |
|
|
|
|
int tmp = atoi(concurrencyVar); |
|
|
|
|
if (tmp > 0) { |
|
|
|
|
_rxThreadCount = tmp; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
_rxThreadCount = std::thread::hardware_concurrency() >= 4 ? 2 : 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
_rxThreadCount = std::thread::hardware_concurrency() >= 4 ? 2 : 1; |
|
|
|
|
} |
|
|
|
|
fprintf(stderr, "using %d rx threads\n", _rxThreadCount); |
|
|
|
|
for (unsigned int i = 0; i < _rxThreadCount; ++i) { |
|
|
|
|
_rxPacketThreads.push_back(std::thread([this, i, _enablePinning]() { |
|
|
|
|
|
|
|
|
|
if (_enablePinning) { |
|
|
|
|
#if defined(__LINUX__) || defined(__FreeBSD__) /* || defined(__APPLE__) */ |
|
|
|
|
int pinCore = i % _rxThreadCount; |
|
|
|
|
fprintf(stderr, "pinning thread %d to core %d\n", i, pinCore); |
|
|
|
|
pthread_t self = pthread_self(); |
|
|
|
|
cpu_set_t cpuset; |
|
|
|
|
CPU_ZERO(&cpuset); |
|
|
|
|
CPU_SET(pinCore, &cpuset); |
|
|
|
|
#endif |
|
|
|
|
#ifdef __LINUX__ |
|
|
|
|
int rc = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset); |
|
|
|
|
#elif __FreeBSD__ |
|
|
|
|
int rc = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset); |
|
|
|
|
#endif |
|
|
|
|
#if defined(__LINUX__) || defined(__FreeBSD__) /* || defined(__APPLE__) */ |
|
|
|
|
if (rc != 0) |
|
|
|
|
{ |
|
|
|
|
fprintf(stderr, "failed to pin rx thread %d to core %d: %s\n", i, pinCore, strerror(errno)); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
PacketRecord* packet = nullptr; |
|
|
|
|
for (;;) { |
|
|
|
|
if (! _rxPacketQueue.get(packet)) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if (! packet) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
const ZT_ResultCode err = _node->processWirePacket(nullptr, packet->now, packet->sock, &(packet->from), packet->data, packet->size, &_nextBackgroundTaskDeadline); |
|
|
|
|
{ |
|
|
|
|
Mutex::Lock l(_rxPacketVector_m); |
|
|
|
|
_rxPacketVector.push_back(packet); |
|
|
|
|
} |
|
|
|
|
if (ZT_ResultCode_isFatal(err)) { |
|
|
|
|
char tmp[256]; |
|
|
|
|
OSUtils::ztsnprintf(tmp, sizeof(tmp), "error processing packet: %d", (int)err); |
|
|
|
|
Mutex::Lock _l(_termReason_m); |
|
|
|
|
_termReason = ONE_UNRECOVERABLE_ERROR; |
|
|
|
|
_fatalErrorMessage = tmp; |
|
|
|
|
this->terminate(); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
})); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
prometheus::simpleapi::saver.set_registry(prometheus::simpleapi::registry_ptr); |
|
|
|
|
prometheus::simpleapi::saver.set_delay(std::chrono::seconds(5)); |
|
|
|
|
prometheus::simpleapi::saver.set_out_file(_homePath + ZT_PATH_SEPARATOR + "metrics.prom"); |
|
|
|
|
@ -1071,6 +989,64 @@ public:
|
|
|
|
|
delete _rc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void setUpMultithreading() |
|
|
|
|
{ |
|
|
|
|
_node->initMultithreading(true, _concurrency, _cpuPinningEnabled); |
|
|
|
|
bool pinning = _cpuPinningEnabled; |
|
|
|
|
|
|
|
|
|
fprintf(stderr, "Starting %d RX threads\n", _concurrency); |
|
|
|
|
for (unsigned int i = 0; i < _concurrency; ++i) { |
|
|
|
|
_rxPacketThreads.push_back(std::thread([this, i, pinning]() { |
|
|
|
|
|
|
|
|
|
if (pinning) { |
|
|
|
|
#if defined(__LINUX__) || defined(__FreeBSD__) /* || defined(__APPLE__) */ |
|
|
|
|
int pinCore = i % _concurrency; |
|
|
|
|
fprintf(stderr, "CPU Pinning enabled. Pinning thread %d to core %d\n", i, pinCore); |
|
|
|
|
pthread_t self = pthread_self(); |
|
|
|
|
cpu_set_t cpuset; |
|
|
|
|
CPU_ZERO(&cpuset); |
|
|
|
|
CPU_SET(pinCore, &cpuset); |
|
|
|
|
#endif |
|
|
|
|
#ifdef __LINUX__ |
|
|
|
|
int rc = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset); |
|
|
|
|
#elif __FreeBSD__ |
|
|
|
|
int rc = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset); |
|
|
|
|
#endif |
|
|
|
|
#if defined(__LINUX__) || defined(__FreeBSD__) /* || defined(__APPLE__) */ |
|
|
|
|
if (rc != 0) |
|
|
|
|
{ |
|
|
|
|
fprintf(stderr, "failed to pin rx thread %d to core %d: %s\n", i, pinCore, strerror(errno)); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
PacketRecord* packet = nullptr; |
|
|
|
|
for (;;) { |
|
|
|
|
if (! _rxPacketQueue.get(packet)) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if (! packet) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
const ZT_ResultCode err = _node->processWirePacket(nullptr, packet->now, packet->sock, &(packet->from), packet->data, packet->size, &_nextBackgroundTaskDeadline); |
|
|
|
|
{ |
|
|
|
|
Mutex::Lock l(_rxPacketVector_m); |
|
|
|
|
_rxPacketVector.push_back(packet); |
|
|
|
|
} |
|
|
|
|
if (ZT_ResultCode_isFatal(err)) { |
|
|
|
|
char tmp[256]; |
|
|
|
|
OSUtils::ztsnprintf(tmp, sizeof(tmp), "error processing packet: %d", (int)err); |
|
|
|
|
Mutex::Lock _l(_termReason_m); |
|
|
|
|
_termReason = ONE_UNRECOVERABLE_ERROR; |
|
|
|
|
_fatalErrorMessage = tmp; |
|
|
|
|
this->terminate(); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
})); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
virtual ReasonForTermination run() |
|
|
|
|
{ |
|
|
|
|
try { |
|
|
|
|
@ -2672,7 +2648,18 @@ public:
|
|
|
|
|
fprintf(stderr,"WARNING: using manually-specified secondary and/or tertiary ports. This can cause NAT issues." ZT_EOL_S); |
|
|
|
|
} |
|
|
|
|
_portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true); |
|
|
|
|
_node->setLowBandwidthMode(OSUtils::jsonBool(settings["lowBandwidthMode"],false)); |
|
|
|
|
_multicoreEnabled = OSUtils::jsonBool(settings["multicoreEnabled"],false); |
|
|
|
|
_concurrency = OSUtils::jsonInt(settings["concurrency"],0); |
|
|
|
|
_cpuPinningEnabled = OSUtils::jsonBool(settings["cpuPinningEnabled"],false); |
|
|
|
|
if (_multicoreEnabled) { |
|
|
|
|
unsigned int maxConcurrency = std::thread::hardware_concurrency(); |
|
|
|
|
if (_concurrency <= 1 || _concurrency >= maxConcurrency) { |
|
|
|
|
unsigned int conservativeDefault = (std::thread::hardware_concurrency() >= 4 ? 2 : 1); |
|
|
|
|
fprintf(stderr, "Concurrency level provided (%d) is invalid, assigning conservative default value of (%d)\n", _concurrency, conservativeDefault); |
|
|
|
|
_concurrency = conservativeDefault; |
|
|
|
|
} |
|
|
|
|
setUpMultithreading(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifndef ZT_SDK |
|
|
|
|
const std::string up(OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT)); |
|
|
|
|
@ -3001,7 +2988,7 @@ public:
|
|
|
|
|
_lastDirectReceiveFromGlobal = now; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_enableMulticore) { |
|
|
|
|
if (_multicoreEnabled) { |
|
|
|
|
PacketRecord* packet; |
|
|
|
|
_rxPacketVector_m.lock(); |
|
|
|
|
if (_rxPacketVector.empty()) { |
|
|
|
|
@ -3018,7 +3005,7 @@ public:
|
|
|
|
|
memcpy(&(packet->from), from, sizeof(struct sockaddr_storage)); |
|
|
|
|
packet->size = (unsigned int)len; |
|
|
|
|
memcpy(packet->data, data, len); |
|
|
|
|
_rxPacketQueue.postLimit(packet, 256 * _rxThreadCount); |
|
|
|
|
_rxPacketQueue.postLimit(packet, 256 * _concurrency); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
const ZT_ResultCode rc = _node->processWirePacket(nullptr,now,reinterpret_cast<int64_t>(sock),reinterpret_cast<const struct sockaddr_storage *>(from),data,len,&_nextBackgroundTaskDeadline); |
|
|
|
|
|