diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 9306dc34c..b7ecdfe10 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -92,12 +92,17 @@ LinuxEthernetTap::LinuxEthernetTap( _homePath(homePath), _mtu(mtu), _fd(0), - _enabled(true) + _enabled(true), + _bufferReadPtr(0), + _bufferWritePtr(0) { static std::mutex s_tapCreateLock; char procpath[128],nwids[32]; struct stat sbuf; + for(unsigned long i=0;i tapCreateLock(s_tapCreateLock); @@ -252,15 +257,14 @@ LinuxEthernetTap::LinuxEthernetTap( if (FD_ISSET(_fd,&readfds)) { for(;;) { // read until there are no more packets, then return to outer select() loop if (!buf) { - std::lock_guard l(_buffers_l); - if (_buffers.empty()) { - buf = malloc(ZT_TAP_BUF_SIZE); - if (!buf) + for(unsigned int k=0;k(_buffers[_bufferReadPtr++ & ZT_BUFFER_POOL_MASK].exchange(0)); + if (buf) break; - } else { - buf = _buffers.back(); - _buffers.pop_back(); } + buf = malloc(ZT_TAP_BUF_SIZE); + if (!buf) + continue; } n = (int)::read(_fd,reinterpret_cast(buf) + r,ZT_TAP_BUF_SIZE - r); @@ -294,16 +298,22 @@ LinuxEthernetTap::LinuxEthernetTap( MAC to,from; std::pair qi; while (_tapq.get(qi)) { - uint8_t *const b = reinterpret_cast(qi.first); + uint8_t *b = reinterpret_cast(qi.first); if (b) { to.setTo(b, 6); from.setTo(b + 6, 6); unsigned int etherType = Utils::ntoh(((const uint16_t *)b)[6]); _handler(_arg, nullptr, _nwid, from, to, etherType, 0, (const void *)(b + 14),(unsigned int)(qi.second - 14)); - { - std::lock_guard l(_buffers_l); - _buffers.push_back(qi.first); + + for(unsigned int k=0;k(b))) { + b = nullptr; + break; + } } + if (b) + free(b); } else break; } }); @@ -321,8 +331,11 @@ LinuxEthernetTap::~LinuxEthernetTap() _tapReaderThread.join(); _tapProcessorThread.join(); - for(std::vector::iterator i(_buffers.begin());i!=_buffers.end();++i) - free(*i); + for(unsigned int k=0;k(_buffers[k].load()); + if (p) + free(p); + } std::vector< std::pair > dv(_tapq.drain()); for(std::vector< std::pair >::iterator i(dv.begin());i!=dv.end();++i) { if (i->first) diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index 9e9206ead..f56477af6 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -28,6 +28,9 @@ #include "EthernetTap.hpp" #include "BlockingQueue.hpp" +#define ZT_BUFFER_POOL_SIZE 64 +#define ZT_BUFFER_POOL_MASK 63U + namespace ZeroTier { class LinuxEthernetTap : public EthernetTap @@ -73,7 +76,8 @@ private: std::thread _tapReaderThread; std::thread _tapProcessorThread; std::mutex _buffers_l; - std::vector _buffers; + std::atomic _buffers[ZT_BUFFER_POOL_SIZE]; + std::atomic _bufferReadPtr,_bufferWritePtr; BlockingQueue< std::pair > _tapq; };