|
@@ -188,6 +188,7 @@ LinuxEthernetTap::LinuxEthernetTap(
|
|
|
fd_set readfds,nullfds;
|
|
|
int n,nfds,r;
|
|
|
void *buf = nullptr;
|
|
|
+ std::vector buffers;
|
|
|
|
|
|
{
|
|
|
struct ifreq ifr;
|
|
@@ -252,14 +253,20 @@ 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<std::mutex> l(_buffers_l);
|
|
|
- if (_buffers.empty()) {
|
|
|
+ // 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();
|
|
|
+ buf = buffers.back();
|
|
|
+ buffers.pop_back();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -302,7 +309,9 @@ LinuxEthernetTap::LinuxEthernetTap(
|
|
|
_handler(_arg, nullptr, _nwid, from, to, etherType, 0, (const void *)(b + 14),(unsigned int)(qi.second - 14));
|
|
|
{
|
|
|
std::lock_guard<std::mutex> l(_buffers_l);
|
|
|
- _buffers.push_back(qi.first);
|
|
|
+ if (_buffers.size() < 128)
|
|
|
+ _buffers.push_back(qi.first);
|
|
|
+ else free(qi.first);
|
|
|
}
|
|
|
} else break;
|
|
|
}
|