13 changed files with 236 additions and 22 deletions
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c)2013-2021 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2026-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
#include "PacketMultiplexer.hpp" |
||||
|
||||
#include "Node.hpp" |
||||
#include "RuntimeEnvironment.hpp" |
||||
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
void PacketMultiplexer::putFrame(void* tPtr, uint64_t nwid, void** nuptr, const MAC& source, const MAC& dest, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len, unsigned int flowId) |
||||
{ |
||||
PacketRecord* packet; |
||||
_rxPacketVector_m.lock(); |
||||
if (_rxPacketVector.empty()) { |
||||
packet = new PacketRecord; |
||||
} |
||||
else { |
||||
packet = _rxPacketVector.back(); |
||||
_rxPacketVector.pop_back(); |
||||
} |
||||
_rxPacketVector_m.unlock(); |
||||
|
||||
packet->tPtr = tPtr; |
||||
packet->nwid = nwid; |
||||
packet->nuptr = nuptr; |
||||
packet->source = source.toInt(); |
||||
packet->dest = dest.toInt(); |
||||
packet->etherType = etherType; |
||||
packet->vlanId = vlanId; |
||||
packet->len = len; |
||||
packet->flowId = flowId; |
||||
memcpy(packet->data, data, len); |
||||
|
||||
int bucket = flowId % _concurrency; |
||||
//fprintf(stderr, "bucket=%d\n", bucket);
|
||||
_rxPacketQueues[bucket]->postLimit(packet, 2048); |
||||
} |
||||
|
||||
PacketMultiplexer::PacketMultiplexer(const RuntimeEnvironment* renv) |
||||
{ |
||||
RR = renv; |
||||
bool _enablePinning = false; |
||||
char* pinningVar = std::getenv("ZT_CPU_PINNING"); |
||||
if (pinningVar) { |
||||
int tmp = atoi(pinningVar); |
||||
if (tmp > 0) { |
||||
_enablePinning = true; |
||||
} |
||||
} |
||||
|
||||
_concurrency = 1; |
||||
char* concurrencyVar = std::getenv("ZT_PACKET_PROCESSING_CONCURRENCY"); |
||||
if (concurrencyVar) { |
||||
int tmp = atoi(concurrencyVar); |
||||
if (tmp > 0) { |
||||
_concurrency = tmp; |
||||
} |
||||
else { |
||||
_concurrency = std::max((unsigned int)1, std::thread::hardware_concurrency() / 2); |
||||
} |
||||
} |
||||
else { |
||||
_concurrency = std::max((unsigned int)1, std::thread::hardware_concurrency() / 2); |
||||
} |
||||
|
||||
for (unsigned int i = 0; i < _concurrency; ++i) { |
||||
fprintf(stderr, "reserved queue for thread %d\n", i); |
||||
_rxPacketQueues.push_back(new BlockingQueue<PacketRecord*>()); |
||||
} |
||||
|
||||
// Each thread picks from its own queue to feed into the core
|
||||
for (unsigned int i = 0; i < _concurrency; ++i) { |
||||
_rxThreads.push_back(std::thread([this, i, _enablePinning]() { |
||||
fprintf(stderr, "created post-decode packet ingestion thread %d\n", i); |
||||
|
||||
PacketRecord* packet = nullptr; |
||||
for (;;) { |
||||
if (! _rxPacketQueues[i]->get(packet)) { |
||||
break; |
||||
} |
||||
if (! packet) { |
||||
break; |
||||
} |
||||
|
||||
//fprintf(stderr, "popped packet from queue %d\n", i);
|
||||
|
||||
MAC sourceMac = MAC(packet->source); |
||||
MAC destMac = MAC(packet->dest); |
||||
|
||||
RR->node->putFrame(packet->tPtr, packet->nwid, packet->nuptr, sourceMac, destMac, packet->etherType, 0, (const void*)packet->data, packet->len); |
||||
{ |
||||
Mutex::Lock l(_rxPacketVector_m); |
||||
_rxPacketVector.push_back(packet); |
||||
} |
||||
/*
|
||||
if (ZT_ResultCode_isFatal(err)) { |
||||
char tmp[256]; |
||||
OSUtils::ztsnprintf(tmp, sizeof(tmp), "error processing packet: %d", (int)err); |
||||
Mutex::Lock _l(_termReason_m); |
||||
_termReason = ONE_UNRECOVERABLE_ERROR; |
||||
_fatalErrorMessage = tmp; |
||||
this->terminate(); |
||||
break; |
||||
} |
||||
*/ |
||||
} |
||||
})); |
||||
} |
||||
}; |
||||
|
||||
} // namespace ZeroTier
|
||||
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c)2013-2021 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2026-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
#ifndef ZT_PACKET_MULTIPLEXER_HPP |
||||
#define ZT_PACKET_MULTIPLEXER_HPP |
||||
|
||||
#include "../osdep/BlockingQueue.hpp" |
||||
#include "MAC.hpp" |
||||
#include "Mutex.hpp" |
||||
#include "RuntimeEnvironment.hpp" |
||||
|
||||
#include <thread> |
||||
#include <vector> |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
struct PacketRecord { |
||||
void* tPtr; |
||||
uint64_t nwid; |
||||
void** nuptr; |
||||
uint64_t source; |
||||
uint64_t dest; |
||||
unsigned int etherType; |
||||
unsigned int vlanId; |
||||
uint8_t data[ZT_MAX_MTU]; |
||||
unsigned int len; |
||||
unsigned int flowId; |
||||
}; |
||||
|
||||
class PacketMultiplexer { |
||||
public: |
||||
const RuntimeEnvironment* RR; |
||||
|
||||
PacketMultiplexer(const RuntimeEnvironment* renv); |
||||
|
||||
void putFrame(void* tPtr, uint64_t nwid, void** nuptr, const MAC& source, const MAC& dest, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len, unsigned int flowId); |
||||
|
||||
std::vector<BlockingQueue<PacketRecord*>*> _rxPacketQueues; |
||||
|
||||
unsigned int _concurrency; |
||||
// pool
|
||||
std::vector<PacketRecord*> _rxPacketVector; |
||||
std::vector<std::thread> _rxPacketThreads; |
||||
Mutex _rxPacketVector_m, _rxPacketThreads_m; |
||||
|
||||
std::vector<std::thread> _rxThreads; |
||||
unsigned int _rxThreadCount; |
||||
}; |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // ZT_PACKET_MULTIPLEXER_HPP
|
||||
Loading…
Reference in new issue