From a390629371970be9dffa9db7cd8af2a7004ee50c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 18 Nov 2020 22:06:17 -0500 Subject: [PATCH 1/9] Try another optimization in LinuxEthernetTap. --- osdep/LinuxEthernetTap.cpp | 112 ++++++++++++++----------------------- osdep/LinuxEthernetTap.hpp | 1 - 2 files changed, 43 insertions(+), 70 deletions(-) diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 25ed52edf..4659df556 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -182,14 +182,7 @@ LinuxEthernetTap::LinuxEthernetTap( _dev = ifr.ifr_name; ::fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC); - (void)::pipe(_shutdownSignalPipe); - _tapReaderThread = std::thread([this]{ - fd_set readfds,nullfds; - int n,nfds,r; - void *buf = nullptr; - std::vector buffers; - { struct ifreq ifr; memset(&ifr,0,sizeof(ifr)); @@ -232,67 +225,51 @@ LinuxEthernetTap::LinuxEthernetTap( return; } - fcntl(_fd,F_SETFL,O_NONBLOCK); - ::close(sock); } - FD_ZERO(&readfds); - FD_ZERO(&nullfds); - nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1; - - r = 0; - for(;;) { - FD_SET(_shutdownSignalPipe[0],&readfds); - FD_SET(_fd,&readfds); - select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0); - - if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread - break; - - if (FD_ISSET(_fd,&readfds)) { - for(;;) { // read until there are no more packets, then return to outer select() loop - if (!buf) { - // To reduce use of the mutex, we keep a local buffer vector and - // swap (which is a pointer swap) with the global one when it's - // empty. This retrieves a batch of buffers to use. - if (buffers.empty()) { - std::lock_guard l(_buffers_l); - buffers.swap(_buffers); - } - if (buffers.empty()) { - buf = malloc(ZT_TAP_BUF_SIZE); - if (!buf) - break; - } else { - buf = buffers.back(); - buffers.pop_back(); - } - } - - n = (int)::read(_fd,reinterpret_cast(buf) + r,ZT_TAP_BUF_SIZE - r); - - if (n > 0) { - // Some tap drivers like to send the ethernet frame and the - // payload in two chunks, so handle that by accumulating - // data until we have at least a frame. - r += n; - if (r > 14) { - if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms - r = _mtu + 14; - - if (_enabled) { - _tapq.post(std::pair(buf,r)); - buf = nullptr; - } - - r = 0; - } - } else { - r = 0; - break; - } + std::vector buffers; + void *buf = nullptr; + for(int r=0;;) { + if (!buf) { + // To reduce use of the mutex, we keep a local buffer vector and + // swap (which is a pointer swap) with the global one when it's + // empty. This retrieves a batch of buffers to use. + if (buffers.empty()) { + std::lock_guard l(_buffers_l); + buffers.swap(_buffers); } + if (buffers.empty()) { + buf = malloc(ZT_TAP_BUF_SIZE); + if (!buf) + break; + } else { + buf = buffers.back(); + buffers.pop_back(); + } + } + + const int n = (int)::read(_fd,reinterpret_cast(buf) + r,ZT_TAP_BUF_SIZE - r); + + if (n > 0) { + // Some tap drivers like to send the ethernet frame and the + // payload in two chunks, so handle that by accumulating + // data until we have at least a frame. + r += n; + if (r > 14) { + if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms + r = _mtu + 14; + + if (_enabled) { + _tapq.post(std::pair(buf,r)); + buf = nullptr; + } + + r = 0; + } + } else { + r = 0; + break; } } }); @@ -320,12 +297,9 @@ LinuxEthernetTap::LinuxEthernetTap( LinuxEthernetTap::~LinuxEthernetTap() { - (void)::write(_shutdownSignalPipe[1],"\0",1); // causes reader thread to exit - _tapq.post(std::pair(nullptr,0)); // causes processor thread to exit - + _tapq.post(std::pair(nullptr,0)); + ::shutdown(_fd, SHUT_RDWR); ::close(_fd); - ::close(_shutdownSignalPipe[0]); - ::close(_shutdownSignalPipe[1]); _tapReaderThread.join(); _tapProcessorThread.join(); diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index 9e9206ead..f296ec693 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -68,7 +68,6 @@ private: std::vector _multicastGroups; unsigned int _mtu; int _fd; - int _shutdownSignalPipe[2]; std::atomic_bool _enabled; std::thread _tapReaderThread; std::thread _tapProcessorThread; From 11545bdb5d37b2df26fc5fdd00cadd05878de094 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 18 Nov 2020 22:13:06 -0500 Subject: [PATCH 2/9] Shutdown fix. --- osdep/LinuxEthernetTap.cpp | 8 ++++++-- osdep/LinuxEthernetTap.hpp | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 4659df556..ad96eb9ed 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -92,7 +92,8 @@ LinuxEthernetTap::LinuxEthernetTap( _homePath(homePath), _mtu(mtu), _fd(0), - _enabled(true) + _enabled(true), + _running(true) { static std::mutex s_tapCreateLock; char procpath[128],nwids[32]; @@ -267,7 +268,7 @@ LinuxEthernetTap::LinuxEthernetTap( r = 0; } - } else { + } else if ((errno != EINTR)||(!_running.load())) { r = 0; break; } @@ -297,9 +298,12 @@ LinuxEthernetTap::LinuxEthernetTap( LinuxEthernetTap::~LinuxEthernetTap() { + _running = false; + _tapq.post(std::pair(nullptr,0)); ::shutdown(_fd, SHUT_RDWR); ::close(_fd); + pthread_kill(_tapReaderThread.native_handle(), SIGUSR1); _tapReaderThread.join(); _tapProcessorThread.join(); diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index f296ec693..771b27980 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -69,6 +69,7 @@ private: unsigned int _mtu; int _fd; std::atomic_bool _enabled; + std::atomic_bool _running; std::thread _tapReaderThread; std::thread _tapProcessorThread; std::mutex _buffers_l; From 3712f9b318dc3a47b97bcc717266c4c0b100d4f8 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 18 Nov 2020 22:24:09 -0500 Subject: [PATCH 3/9] Revert "Shutdown fix." This reverts commit 11545bdb5d37b2df26fc5fdd00cadd05878de094. --- osdep/LinuxEthernetTap.cpp | 8 ++------ osdep/LinuxEthernetTap.hpp | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index ad96eb9ed..4659df556 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -92,8 +92,7 @@ LinuxEthernetTap::LinuxEthernetTap( _homePath(homePath), _mtu(mtu), _fd(0), - _enabled(true), - _running(true) + _enabled(true) { static std::mutex s_tapCreateLock; char procpath[128],nwids[32]; @@ -268,7 +267,7 @@ LinuxEthernetTap::LinuxEthernetTap( r = 0; } - } else if ((errno != EINTR)||(!_running.load())) { + } else { r = 0; break; } @@ -298,12 +297,9 @@ LinuxEthernetTap::LinuxEthernetTap( LinuxEthernetTap::~LinuxEthernetTap() { - _running = false; - _tapq.post(std::pair(nullptr,0)); ::shutdown(_fd, SHUT_RDWR); ::close(_fd); - pthread_kill(_tapReaderThread.native_handle(), SIGUSR1); _tapReaderThread.join(); _tapProcessorThread.join(); diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index 771b27980..f296ec693 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -69,7 +69,6 @@ private: unsigned int _mtu; int _fd; std::atomic_bool _enabled; - std::atomic_bool _running; std::thread _tapReaderThread; std::thread _tapProcessorThread; std::mutex _buffers_l; From ca428233ba1957e93edf778cb7a38aaa484c15ce Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 18 Nov 2020 22:24:18 -0500 Subject: [PATCH 4/9] Revert "Try another optimization in LinuxEthernetTap." This reverts commit a390629371970be9dffa9db7cd8af2a7004ee50c. --- osdep/LinuxEthernetTap.cpp | 102 +++++++++++++++++++++++-------------- osdep/LinuxEthernetTap.hpp | 1 + 2 files changed, 65 insertions(+), 38 deletions(-) diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 4659df556..25ed52edf 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -182,7 +182,14 @@ LinuxEthernetTap::LinuxEthernetTap( _dev = ifr.ifr_name; ::fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC); + (void)::pipe(_shutdownSignalPipe); + _tapReaderThread = std::thread([this]{ + fd_set readfds,nullfds; + int n,nfds,r; + void *buf = nullptr; + std::vector buffers; + { struct ifreq ifr; memset(&ifr,0,sizeof(ifr)); @@ -225,51 +232,67 @@ LinuxEthernetTap::LinuxEthernetTap( return; } + fcntl(_fd,F_SETFL,O_NONBLOCK); + ::close(sock); } - std::vector buffers; - void *buf = nullptr; - for(int r=0;;) { - if (!buf) { - // To reduce use of the mutex, we keep a local buffer vector and - // swap (which is a pointer swap) with the global one when it's - // empty. This retrieves a batch of buffers to use. - if (buffers.empty()) { - std::lock_guard l(_buffers_l); - buffers.swap(_buffers); - } - if (buffers.empty()) { - buf = malloc(ZT_TAP_BUF_SIZE); - if (!buf) - break; - } else { - buf = buffers.back(); - buffers.pop_back(); - } - } + FD_ZERO(&readfds); + FD_ZERO(&nullfds); + nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1; - const int n = (int)::read(_fd,reinterpret_cast(buf) + r,ZT_TAP_BUF_SIZE - r); + r = 0; + for(;;) { + FD_SET(_shutdownSignalPipe[0],&readfds); + FD_SET(_fd,&readfds); + select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0); - if (n > 0) { - // Some tap drivers like to send the ethernet frame and the - // payload in two chunks, so handle that by accumulating - // data until we have at least a frame. - r += n; - if (r > 14) { - if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms - r = _mtu + 14; + if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread + break; - if (_enabled) { - _tapq.post(std::pair(buf,r)); - buf = nullptr; + if (FD_ISSET(_fd,&readfds)) { + for(;;) { // read until there are no more packets, then return to outer select() loop + if (!buf) { + // To reduce use of the mutex, we keep a local buffer vector and + // swap (which is a pointer swap) with the global one when it's + // empty. This retrieves a batch of buffers to use. + if (buffers.empty()) { + std::lock_guard l(_buffers_l); + buffers.swap(_buffers); + } + if (buffers.empty()) { + buf = malloc(ZT_TAP_BUF_SIZE); + if (!buf) + break; + } else { + buf = buffers.back(); + buffers.pop_back(); + } } - r = 0; + n = (int)::read(_fd,reinterpret_cast(buf) + r,ZT_TAP_BUF_SIZE - r); + + if (n > 0) { + // Some tap drivers like to send the ethernet frame and the + // payload in two chunks, so handle that by accumulating + // data until we have at least a frame. + r += n; + if (r > 14) { + if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms + r = _mtu + 14; + + if (_enabled) { + _tapq.post(std::pair(buf,r)); + buf = nullptr; + } + + r = 0; + } + } else { + r = 0; + break; + } } - } else { - r = 0; - break; } } }); @@ -297,9 +320,12 @@ LinuxEthernetTap::LinuxEthernetTap( LinuxEthernetTap::~LinuxEthernetTap() { - _tapq.post(std::pair(nullptr,0)); - ::shutdown(_fd, SHUT_RDWR); + (void)::write(_shutdownSignalPipe[1],"\0",1); // causes reader thread to exit + _tapq.post(std::pair(nullptr,0)); // causes processor thread to exit + ::close(_fd); + ::close(_shutdownSignalPipe[0]); + ::close(_shutdownSignalPipe[1]); _tapReaderThread.join(); _tapProcessorThread.join(); diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index f296ec693..9e9206ead 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -68,6 +68,7 @@ private: std::vector _multicastGroups; unsigned int _mtu; int _fd; + int _shutdownSignalPipe[2]; std::atomic_bool _enabled; std::thread _tapReaderThread; std::thread _tapProcessorThread; From 414c248cc5052bc219fcc695ed559b929045f8b0 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 18 Nov 2020 22:26:06 -0500 Subject: [PATCH 5/9] Try another approach... --- osdep/LinuxEthernetTap.cpp | 200 +++++++++++++++++++------------------ 1 file changed, 102 insertions(+), 98 deletions(-) diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 25ed52edf..04871193f 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -184,118 +184,122 @@ LinuxEthernetTap::LinuxEthernetTap( (void)::pipe(_shutdownSignalPipe); - _tapReaderThread = std::thread([this]{ - fd_set readfds,nullfds; - int n,nfds,r; - void *buf = nullptr; - std::vector buffers; + for(unsigned int t=0;t<2;++t) { + _tapReaderThread = std::thread([this, t]{ + fd_set readfds,nullfds; + int n,nfds,r; + void *buf = nullptr; + std::vector buffers; - { - struct ifreq ifr; - memset(&ifr,0,sizeof(ifr)); - strcpy(ifr.ifr_name,_dev.c_str()); + if (t == 0) { + struct ifreq ifr; + memset(&ifr,0,sizeof(ifr)); + strcpy(ifr.ifr_name,_dev.c_str()); - const int sock = socket(AF_INET,SOCK_DGRAM,0); - if (sock <= 0) - return; + const int sock = socket(AF_INET,SOCK_DGRAM,0); + if (sock <= 0) + return; + + if (ioctl(sock,SIOCGIFFLAGS,(void *)&ifr) < 0) { + ::close(sock); + printf("WARNING: ioctl() failed setting up Linux tap device (bring interface up)\n"); + return; + } + ifr.ifr_flags |= IFF_UP; + if (ioctl(sock,SIOCSIFFLAGS,(void *)&ifr) < 0) { + ::close(sock); + printf("WARNING: ioctl() failed setting up Linux tap device (bring interface up)\n"); + return; + } + + // Some kernel versions seem to require you to yield while the device comes up + // before they will accept MTU and MAC. For others it doesn't matter, but is + // harmless. This was moved to the worker thread though so as not to block the + // main ZeroTier loop. + usleep(500000); + + ifr.ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_ETHER; + _mac.copyTo(ifr.ifr_ifru.ifru_hwaddr.sa_data,6); + if (ioctl(sock,SIOCSIFHWADDR,(void *)&ifr) < 0) { + ::close(sock); + printf("WARNING: ioctl() failed setting up Linux tap device (set MAC)\n"); + return; + } + + ifr.ifr_ifru.ifru_mtu = (int)_mtu; + if (ioctl(sock,SIOCSIFMTU,(void *)&ifr) < 0) { + ::close(sock); + printf("WARNING: ioctl() failed setting up Linux tap device (set MTU)\n"); + return; + } + + fcntl(_fd,F_SETFL,O_NONBLOCK); - if (ioctl(sock,SIOCGIFFLAGS,(void *)&ifr) < 0) { ::close(sock); - printf("WARNING: ioctl() failed setting up Linux tap device (bring interface up)\n"); - return; - } - ifr.ifr_flags |= IFF_UP; - if (ioctl(sock,SIOCSIFFLAGS,(void *)&ifr) < 0) { - ::close(sock); - printf("WARNING: ioctl() failed setting up Linux tap device (bring interface up)\n"); - return; + } else { + usleep(1500000); } - // Some kernel versions seem to require you to yield while the device comes up - // before they will accept MTU and MAC. For others it doesn't matter, but is - // harmless. This was moved to the worker thread though so as not to block the - // main ZeroTier loop. - usleep(500000); + FD_ZERO(&readfds); + FD_ZERO(&nullfds); + nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1; - ifr.ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_ETHER; - _mac.copyTo(ifr.ifr_ifru.ifru_hwaddr.sa_data,6); - if (ioctl(sock,SIOCSIFHWADDR,(void *)&ifr) < 0) { - ::close(sock); - printf("WARNING: ioctl() failed setting up Linux tap device (set MAC)\n"); - return; - } + r = 0; + for(;;) { + FD_SET(_shutdownSignalPipe[0],&readfds); + FD_SET(_fd,&readfds); + select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0); - ifr.ifr_ifru.ifru_mtu = (int)_mtu; - if (ioctl(sock,SIOCSIFMTU,(void *)&ifr) < 0) { - ::close(sock); - printf("WARNING: ioctl() failed setting up Linux tap device (set MTU)\n"); - return; - } + if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread + break; - fcntl(_fd,F_SETFL,O_NONBLOCK); - - ::close(sock); - } - - FD_ZERO(&readfds); - FD_ZERO(&nullfds); - nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1; - - r = 0; - for(;;) { - FD_SET(_shutdownSignalPipe[0],&readfds); - FD_SET(_fd,&readfds); - select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0); - - if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread - break; - - if (FD_ISSET(_fd,&readfds)) { - for(;;) { // read until there are no more packets, then return to outer select() loop - if (!buf) { - // To reduce use of the mutex, we keep a local buffer vector and - // swap (which is a pointer swap) with the global one when it's - // empty. This retrieves a batch of buffers to use. - if (buffers.empty()) { - std::lock_guard l(_buffers_l); - buffers.swap(_buffers); - } - if (buffers.empty()) { - buf = malloc(ZT_TAP_BUF_SIZE); - if (!buf) - break; - } else { - buf = buffers.back(); - buffers.pop_back(); - } - } - - n = (int)::read(_fd,reinterpret_cast(buf) + r,ZT_TAP_BUF_SIZE - r); - - if (n > 0) { - // Some tap drivers like to send the ethernet frame and the - // payload in two chunks, so handle that by accumulating - // data until we have at least a frame. - r += n; - if (r > 14) { - if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms - r = _mtu + 14; - - if (_enabled) { - _tapq.post(std::pair(buf,r)); - buf = nullptr; + if (FD_ISSET(_fd,&readfds)) { + for(;;) { // read until there are no more packets, then return to outer select() loop + if (!buf) { + // To reduce use of the mutex, we keep a local buffer vector and + // swap (which is a pointer swap) with the global one when it's + // empty. This retrieves a batch of buffers to use. + if (buffers.empty()) { + std::lock_guard l(_buffers_l); + buffers.swap(_buffers); + } + if (buffers.empty()) { + buf = malloc(ZT_TAP_BUF_SIZE); + if (!buf) + break; + } else { + buf = buffers.back(); + buffers.pop_back(); } - - r = 0; } - } else { - r = 0; - break; + + n = (int)::read(_fd,reinterpret_cast(buf) + r,ZT_TAP_BUF_SIZE - r); + + if (n > 0) { + // Some tap drivers like to send the ethernet frame and the + // payload in two chunks, so handle that by accumulating + // data until we have at least a frame. + r += n; + if (r > 14) { + if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms + r = _mtu + 14; + + if (_enabled) { + _tapq.post(std::pair(buf,r)); + buf = nullptr; + } + + r = 0; + } + } else { + r = 0; + break; + } } } } - } - }); + }); + } _tapProcessorThread = std::thread([this] { MAC to,from; From f934a09baaa360de742d96bf359f7de8472b4702 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 18 Nov 2020 22:32:57 -0500 Subject: [PATCH 6/9] Build fix. --- osdep/LinuxEthernetTap.cpp | 7 ++++--- osdep/LinuxEthernetTap.hpp | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 04871193f..8a557c077 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -185,7 +185,7 @@ LinuxEthernetTap::LinuxEthernetTap( (void)::pipe(_shutdownSignalPipe); for(unsigned int t=0;t<2;++t) { - _tapReaderThread = std::thread([this, t]{ + _tapReaderThread[t] = std::thread([this, t]{ fd_set readfds,nullfds; int n,nfds,r; void *buf = nullptr; @@ -324,14 +324,15 @@ LinuxEthernetTap::LinuxEthernetTap( LinuxEthernetTap::~LinuxEthernetTap() { - (void)::write(_shutdownSignalPipe[1],"\0",1); // causes reader thread to exit + (void)::write(_shutdownSignalPipe[1],"\0",1); // causes reader thread(s) to exit _tapq.post(std::pair(nullptr,0)); // causes processor thread to exit ::close(_fd); ::close(_shutdownSignalPipe[0]); ::close(_shutdownSignalPipe[1]); - _tapReaderThread.join(); + _tapReaderThread[0].join(); + _tapReaderThread[1].join(); _tapProcessorThread.join(); for(std::vector::iterator i(_buffers.begin());i!=_buffers.end();++i) diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index 9e9206ead..a21a53a2c 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -70,7 +70,7 @@ private: int _fd; int _shutdownSignalPipe[2]; std::atomic_bool _enabled; - std::thread _tapReaderThread; + std::thread _tapReaderThread[2]; std::thread _tapProcessorThread; std::mutex _buffers_l; std::vector _buffers; From 7b14aeb53e20727d304f97de33739c69770f2119 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 18 Nov 2020 22:42:00 -0500 Subject: [PATCH 7/9] Tune thread count based on hardware concurrency. --- osdep/LinuxEthernetTap.cpp | 12 ++++++------ osdep/LinuxEthernetTap.hpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 8a557c077..aeffede06 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -184,14 +184,14 @@ LinuxEthernetTap::LinuxEthernetTap( (void)::pipe(_shutdownSignalPipe); - for(unsigned int t=0;t<2;++t) { - _tapReaderThread[t] = std::thread([this, t]{ + for(unsigned int tn=0,tc=(unsigned int)std::thread::hardware_concurrency();tn<=tc;++tn) { + _tapReaderThreads.push_back(std::thread([this, tn]{ fd_set readfds,nullfds; int n,nfds,r; void *buf = nullptr; std::vector buffers; - if (t == 0) { + if (tn == 0) { struct ifreq ifr; memset(&ifr,0,sizeof(ifr)); strcpy(ifr.ifr_name,_dev.c_str()); @@ -298,7 +298,7 @@ LinuxEthernetTap::LinuxEthernetTap( } } } - }); + })); } _tapProcessorThread = std::thread([this] { @@ -331,8 +331,8 @@ LinuxEthernetTap::~LinuxEthernetTap() ::close(_shutdownSignalPipe[0]); ::close(_shutdownSignalPipe[1]); - _tapReaderThread[0].join(); - _tapReaderThread[1].join(); + for(std::vector::iterator t(_tapReaderThreads.begin());t!=_tapReaderThreads.end();++t) + t->join(); _tapProcessorThread.join(); for(std::vector::iterator i(_buffers.begin());i!=_buffers.end();++i) diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index a21a53a2c..8a3890bcb 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -70,7 +70,7 @@ private: int _fd; int _shutdownSignalPipe[2]; std::atomic_bool _enabled; - std::thread _tapReaderThread[2]; + std::vector _tapReaderThreads; std::thread _tapProcessorThread; std::mutex _buffers_l; std::vector _buffers; From a0c78da1ad3e388da219a7d3f065d43d4118b898 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 18 Nov 2020 22:54:05 -0500 Subject: [PATCH 8/9] Revert "Tune thread count based on hardware concurrency." This reverts commit 7b14aeb53e20727d304f97de33739c69770f2119. --- osdep/LinuxEthernetTap.cpp | 12 ++++++------ osdep/LinuxEthernetTap.hpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index aeffede06..8a557c077 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -184,14 +184,14 @@ LinuxEthernetTap::LinuxEthernetTap( (void)::pipe(_shutdownSignalPipe); - for(unsigned int tn=0,tc=(unsigned int)std::thread::hardware_concurrency();tn<=tc;++tn) { - _tapReaderThreads.push_back(std::thread([this, tn]{ + for(unsigned int t=0;t<2;++t) { + _tapReaderThread[t] = std::thread([this, t]{ fd_set readfds,nullfds; int n,nfds,r; void *buf = nullptr; std::vector buffers; - if (tn == 0) { + if (t == 0) { struct ifreq ifr; memset(&ifr,0,sizeof(ifr)); strcpy(ifr.ifr_name,_dev.c_str()); @@ -298,7 +298,7 @@ LinuxEthernetTap::LinuxEthernetTap( } } } - })); + }); } _tapProcessorThread = std::thread([this] { @@ -331,8 +331,8 @@ LinuxEthernetTap::~LinuxEthernetTap() ::close(_shutdownSignalPipe[0]); ::close(_shutdownSignalPipe[1]); - for(std::vector::iterator t(_tapReaderThreads.begin());t!=_tapReaderThreads.end();++t) - t->join(); + _tapReaderThread[0].join(); + _tapReaderThread[1].join(); _tapProcessorThread.join(); for(std::vector::iterator i(_buffers.begin());i!=_buffers.end();++i) diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index 8a3890bcb..a21a53a2c 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -70,7 +70,7 @@ private: int _fd; int _shutdownSignalPipe[2]; std::atomic_bool _enabled; - std::vector _tapReaderThreads; + std::thread _tapReaderThread[2]; std::thread _tapProcessorThread; std::mutex _buffers_l; std::vector _buffers; From 565bef05afd7bf8fd8bf80d7bc0dace9bd2b67f0 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 19 Nov 2020 13:24:30 -0500 Subject: [PATCH 9/9] Release notes and version bumps. --- RELEASE-NOTES.md | 22 ++++++++++++++++++++++ debian/changelog | 6 ++++++ ext/installfiles/mac/ZeroTier One.pkgproj | 2 +- windows/WinUI/AboutView.xaml | 2 +- zerotier-one.spec | 5 ++++- 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 4e6364013..30b8a872c 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,6 +1,28 @@ ZeroTier Release Notes ====== +# 2020-11-19 -- Version 1.6.0 + +Version 1.6.0 is a major release that incorporates back-ported features from the 2.0 branch, which is still under development. It also fixes a number of issues. + +New features and improvements (including those listed under 1.5.0): + + * **Apple Silicon** (MacOS ARM64) native support via universal binary. ZeroTier now requires the very latest Xcode to build. + * **Linux performance improvements** for up to 25% faster tun/tap I/O performance on multi-core systems. + * **Multipath support** with modes modeled after the Linux kernel's bonding driver. This includes active-passive and active-active modes with fast failover and load balancing. See section 2.1.5 of the manual. + * **DNS configuration** push from network controllers to end nodes, with locally configurable permissions for whether or not push is allowed. + * **AES-GMAC-SIV** encryption mode, which is both somewhat more secure and significantly faster than the old Salsa20/12-Poly1305 mode on hardware that supports AES acceleration. This includes virtually all X86-64 chips and most ARM64. This mode is based on AES-SIV and has been audited by Trail of Bits to ensure that it is equivalent security-wise. + +Bug fixes: + + * **Managed route assignment fixes** to eliminate missing routes on Linux and what we believe to be the source of sporadic high CPU usage on MacOS. + * **Hang on shutdown** issues should be fixed. + * **Sporadic multicast outages** should be fixed. + +Known remaining issues: + + * AES hardware acceleration is not yet supported on 32-bit ARM, PowerPC (32 or 64), or MIPS (32 or 64) systems. Currently supported are X86-64 and ARM64/AARCH64 with crypto extensions. + # 2020-10-05 -- Version 1.5.0 (actually 1.6.0-beta1) Version 1.6.0 (1.5.0 is a beta!) is a significant release that incorporates a number of back-ported fixes and features from the ZeroTier 2.0 tree. diff --git a/debian/changelog b/debian/changelog index 417e7168a..f921505dd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +zerotier-one (1.6.0) unstable; urgency=medium + + * See RELEASE-NOTES.md for release notes. + + -- Adam Ierymenko Thu, 19 Nov 2020 01:00:00 -0700 + zerotier-one (1.5.0) unstable; urgency=medium * Version 1.5.0 is actually 1.6.0-beta1 diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index ad9aa0604..42a377d83 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -689,7 +689,7 @@ USE_HFS+_COMPRESSION VERSION - 1.5.0 + 1.6.0 TYPE 0 diff --git a/windows/WinUI/AboutView.xaml b/windows/WinUI/AboutView.xaml index d693c51da..f57c15c95 100644 --- a/windows/WinUI/AboutView.xaml +++ b/windows/WinUI/AboutView.xaml @@ -19,7 +19,7 @@ - + diff --git a/zerotier-one.spec b/zerotier-one.spec index a1cf24c25..452b3b5c1 100644 --- a/zerotier-one.spec +++ b/zerotier-one.spec @@ -1,5 +1,5 @@ Name: zerotier-one -Version: 1.5.0 +Version: 1.6.0 Release: 1%{?dist} Summary: ZeroTier One network virtualization service @@ -145,6 +145,9 @@ esac %endif %changelog +* Thu Nov 19 2020 Adam Ierymenko - 1.6.0-0.1 +- see https://github.com/zerotier/ZeroTierOne for release notes + * Mon Oct 05 2020 Adam Ierymenko - 1.6.0-beta1 - see https://github.com/zerotier/ZeroTierOne for release notes