Revert "Try another optimization in LinuxEthernetTap."

This reverts commit a390629371.
This commit is contained in:
Adam Ierymenko 2020-11-18 22:24:18 -05:00
parent 3712f9b318
commit ca428233ba
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
2 changed files with 65 additions and 38 deletions

View file

@ -182,7 +182,14 @@ 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));
@ -225,51 +232,67 @@ LinuxEthernetTap::LinuxEthernetTap(
return; return;
} }
fcntl(_fd,F_SETFL,O_NONBLOCK);
::close(sock); ::close(sock);
} }
std::vector<void *> buffers; FD_ZERO(&readfds);
void *buf = nullptr; FD_ZERO(&nullfds);
for(int r=0;;) { nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1;
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();
}
}
const int n = (int)::read(_fd,reinterpret_cast<uint8_t *>(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) { if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread
// Some tap drivers like to send the ethernet frame and the break;
// 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) { if (FD_ISSET(_fd,&readfds)) {
_tapq.post(std::pair<void *,int>(buf,r)); for(;;) { // read until there are no more packets, then return to outer select() loop
buf = nullptr; 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; 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;
}
} }
} else {
r = 0;
break;
} }
} }
}); });
@ -297,9 +320,12 @@ LinuxEthernetTap::LinuxEthernetTap(
LinuxEthernetTap::~LinuxEthernetTap() LinuxEthernetTap::~LinuxEthernetTap()
{ {
_tapq.post(std::pair<void *,int>(nullptr,0)); (void)::write(_shutdownSignalPipe[1],"\0",1); // causes reader thread to exit
::shutdown(_fd, SHUT_RDWR); _tapq.post(std::pair<void *,int>(nullptr,0)); // causes processor thread to exit
::close(_fd); ::close(_fd);
::close(_shutdownSignalPipe[0]);
::close(_shutdownSignalPipe[1]);
_tapReaderThread.join(); _tapReaderThread.join();
_tapProcessorThread.join(); _tapProcessorThread.join();

View file

@ -68,6 +68,7 @@ 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;