浏览代码

Try another optimization in LinuxEthernetTap.

Adam Ierymenko 4 年之前
父节点
当前提交
a390629371
共有 2 个文件被更改,包括 38 次插入65 次删除
  1. 38 64
      osdep/LinuxEthernetTap.cpp
  2. 0 1
      osdep/LinuxEthernetTap.hpp

+ 38 - 64
osdep/LinuxEthernetTap.cpp

@@ -182,14 +182,7 @@ LinuxEthernetTap::LinuxEthernetTap(
 	_dev = ifr.ifr_name;
 	_dev = ifr.ifr_name;
 	::fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC);
 	::fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC);
 
 
-	(void)::pipe(_shutdownSignalPipe);
-
 	_tapReaderThread = std::thread([this]{
 	_tapReaderThread = std::thread([this]{
-		fd_set readfds,nullfds;
-		int n,nfds,r;
-		void *buf = nullptr;
-		std::vector<void *> buffers;
-
 		{
 		{
 			struct ifreq ifr;
 			struct ifreq ifr;
 			memset(&ifr,0,sizeof(ifr));
 			memset(&ifr,0,sizeof(ifr));
@@ -232,67 +225,51 @@ LinuxEthernetTap::LinuxEthernetTap(
 				return;
 				return;
 			}
 			}
 
 
-			fcntl(_fd,F_SETFL,O_NONBLOCK);
-
 			::close(sock);
 			::close(sock);
 		}
 		}
 
 
-		FD_ZERO(&readfds);
-		FD_ZERO(&nullfds);
-		nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1;
+		std::vector<void *> 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<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;
-		for(;;) {
-			FD_SET(_shutdownSignalPipe[0],&readfds);
-			FD_SET(_fd,&readfds);
-			select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0);
+			const int n = (int)::read(_fd,reinterpret_cast<uint8_t *>(buf) + r,ZT_TAP_BUF_SIZE - r);
 
 
-			if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread
-				break;
+			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(_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();
-						}
+					if (_enabled) {
+						_tapq.post(std::pair<void *,int>(buf,r));
+						buf = nullptr;
 					}
 					}
 
 
-					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;
-					}
+					r = 0;
 				}
 				}
+			} else {
+				r = 0;
+				break;
 			}
 			}
 		}
 		}
 	});
 	});
@@ -320,12 +297,9 @@ LinuxEthernetTap::LinuxEthernetTap(
 
 
 LinuxEthernetTap::~LinuxEthernetTap()
 LinuxEthernetTap::~LinuxEthernetTap()
 {
 {
-	(void)::write(_shutdownSignalPipe[1],"\0",1); // causes reader thread to exit
-	_tapq.post(std::pair<void *,int>(nullptr,0)); // causes processor thread to exit
-
+	_tapq.post(std::pair<void *,int>(nullptr,0));
+	::shutdown(_fd, SHUT_RDWR);
 	::close(_fd);
 	::close(_fd);
-	::close(_shutdownSignalPipe[0]);
-	::close(_shutdownSignalPipe[1]);
 
 
 	_tapReaderThread.join();
 	_tapReaderThread.join();
 	_tapProcessorThread.join();
 	_tapProcessorThread.join();

+ 0 - 1
osdep/LinuxEthernetTap.hpp

@@ -68,7 +68,6 @@ private:
 	std::vector<MulticastGroup> _multicastGroups;
 	std::vector<MulticastGroup> _multicastGroups;
 	unsigned int _mtu;
 	unsigned int _mtu;
 	int _fd;
 	int _fd;
-	int _shutdownSignalPipe[2];
 	std::atomic_bool _enabled;
 	std::atomic_bool _enabled;
 	std::thread _tapReaderThread;
 	std::thread _tapReaderThread;
 	std::thread _tapProcessorThread;
 	std::thread _tapProcessorThread;