Просмотр исходного кода

Merge branch 'dev' of http://git.int.zerotier.com/zerotier/ZeroTierOne into dev

Adam Ierymenko 4 лет назад
Родитель
Сommit
45b092532e

+ 22 - 0
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.

+ 6 - 0
debian/changelog

@@ -1,3 +1,9 @@
+zerotier-one (1.6.0) unstable; urgency=medium
+
+  * See RELEASE-NOTES.md for release notes.
+
+ -- Adam Ierymenko <[email protected]>  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

+ 1 - 1
ext/installfiles/mac/ZeroTier One.pkgproj

@@ -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>

+ 102 - 97
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<void *> buffers;
-
-		{
-			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;
+	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;
+
+			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;
+
+				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;
+				}
 
-			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;
+				}
 
-			// 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_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;
+				}
 
-			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;
-			}
+				fcntl(_fd,F_SETFL,O_NONBLOCK);
 
-			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;
+			} else {
+				usleep(1500000);
 			}
 
-			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();
+			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);
+						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 (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 (_enabled) {
+									_tapq.post(std::pair<void *,int>(buf,r));
+									buf = nullptr;
+								}
 
+								r = 0;
+							}
+						} else {
 							r = 0;
+							break;
 						}
-					} 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)

+ 1 - 1
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<void *> _buffers;

+ 1 - 1
windows/WinUI/AboutView.xaml

@@ -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/>

+ 4 - 1
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 <[email protected]> - 1.6.0-0.1
+- see https://github.com/zerotier/ZeroTierOne for release notes
+
 * Mon Oct 05 2020 Adam Ierymenko <[email protected]> - 1.6.0-beta1
 - see https://github.com/zerotier/ZeroTierOne for release notes