mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-02-20 17:52:46 +00:00
Merge branch 'dev' of http://git.int.zerotier.com/zerotier/ZeroTierOne into dev
This commit is contained in:
commit
45b092532e
@ -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.
|
||||
|
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,3 +1,9 @@
|
||||
zerotier-one (1.6.0) unstable; urgency=medium
|
||||
|
||||
* See RELEASE-NOTES.md for release notes.
|
||||
|
||||
-- Adam Ierymenko <adam.ierymenko@zerotier.com> 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
|
||||
|
@ -689,7 +689,7 @@
|
||||
<key>USE_HFS+_COMPRESSION</key>
|
||||
<false/>
|
||||
<key>VERSION</key>
|
||||
<string>1.5.0</string>
|
||||
<string>1.6.0</string>
|
||||
</dict>
|
||||
<key>TYPE</key>
|
||||
<integer>0</integer>
|
||||
|
@ -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<void *> buffers;
|
||||
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<void *> 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<std::mutex> 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<uint8_t *>(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<void *,int>(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<std::mutex> 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<uint8_t *>(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<void *,int>(buf,r));
|
||||
buf = nullptr;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
}
|
||||
} else {
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_tapProcessorThread = std::thread([this] {
|
||||
MAC to,from;
|
||||
@ -320,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<void *,int>(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<void *>::iterator i(_buffers.begin());i!=_buffers.end();++i)
|
||||
|
@ -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<void *> _buffers;
|
||||
|
@ -19,7 +19,7 @@
|
||||
<Run Text="ZeroTier One"/>
|
||||
</Paragraph>
|
||||
<Paragraph TextAlignment="Center">
|
||||
<Run FontSize="14" Text="Version 1.5.0 (1.6.0-beta1)"/>
|
||||
<Run FontSize="14" Text="Version 1.6.0"/>
|
||||
<LineBreak/>
|
||||
<Run FontSize="14" Text="(c) 2011-2020 ZeroTier, Inc."/>
|
||||
<LineBreak/>
|
||||
|
@ -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 <adam.ierymenko@zerotier.com> - 1.6.0-0.1
|
||||
- see https://github.com/zerotier/ZeroTierOne for release notes
|
||||
|
||||
* Mon Oct 05 2020 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.6.0-beta1
|
||||
- see https://github.com/zerotier/ZeroTierOne for release notes
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user