Add buffer life cycle stuff to API for fewer memcpys.

This commit is contained in:
Adam Ierymenko 2020-03-02 17:15:00 -08:00
parent b96ea5ae03
commit b824ea7bcf
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
9 changed files with 78 additions and 36 deletions

View file

@ -96,7 +96,7 @@ struct ZT_GoNode_Impl
static const std::string defaultHomePath(OSUtils::platformDefaultHomePath());
const char *ZT_PLATFORM_DEFAULT_HOMEPATH = defaultHomePath.c_str();
/****************************************************************************/
// --------------------------------------------------------------------------------------------------------------------
/* These functions are implemented in Go in pkg/zerotier/node.go */
extern "C" int goPathCheckFunc(void *,const ZT_Identity *,int,const void *,int);
@ -300,7 +300,7 @@ static int ZT_GoNode_PathLookupFunction(
return 0;
}
/****************************************************************************/
// --------------------------------------------------------------------------------------------------------------------
extern "C" ZT_GoNode *ZT_GoNode_new(const char *workingPath,uintptr_t userPtr)
{

View file

@ -98,7 +98,7 @@ func (lc *LocalConfig) Read(p string, saveDefaultsIfNotExist bool, isTotallyNewN
lc.Network = make(map[NetworkID]NetworkLocalSettings)
if isTotallyNewNode {
lc.Settings.PrimaryPort = 893
lc.Settings.PrimaryPort = 793
} else {
lc.Settings.PrimaryPort = 9993
}

View file

@ -30,7 +30,7 @@ const LogoChar = "⏁"
var Base32StdLowerCase = base32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567").WithPadding(base32.NoPadding)
// unassignedPrivilegedPorts are ports below 1024 that do not appear to be assigned by IANA.
// The new 2.0+ ZeroTier default is 893, which we will eventually seek to have assigned. These
// The new 2.0+ ZeroTier default is 793, which we will eventually seek to have assigned. These
// are searched as backups if this port is already in use on a system.
var unassignedPrivilegedPorts = []int{
4,

View file

@ -635,7 +635,7 @@ func (n *Node) Peers() []*Peer {
return peers
}
//////////////////////////////////////////////////////////////////////////////
// --------------------------------------------------------------------------------------------------------------------
func (n *Node) multicastSubscribe(nwid uint64, mg *MulticastGroup) {
C.ZT_Node_multicastSubscribe(unsafe.Pointer(n.zn), nil, C.uint64_t(nwid), C.uint64_t(mg.MAC), C.ulong(mg.ADI))

View file

@ -16,24 +16,8 @@ package zerotier
//#include "../../native/GoGlue.h"
import "C"
import "fmt"
// SelfTest runs a series of tests on the ZeroTier core and the Go service code, returning true on success.
// Results are sent to stdout.
func SelfTest() bool {
fmt.Print("Running ZeroTier core tests...\n\n")
if C.ZT_TestOther() != 0 {
return false
}
fmt.Println()
if C.ZT_TestCrypto() != 0 {
return false
}
fmt.Println()
if C.ZT_TestIdentity() != 0 {
return false
}
return true
}

View file

@ -69,7 +69,12 @@ extern "C" {
* treat privileged ports in a special way. The old default was 9993 and
* this is likely to be seen in the wild quite a bit.
*/
#define ZT_DEFAULT_PORT 893
#define ZT_DEFAULT_PORT 793
/**
* Size of a standard I/O buffer as returned by getBuffer().
*/
#define ZT_BUF_SIZE 16384
/**
* Minimum MTU allowed on virtual networks
@ -1728,6 +1733,25 @@ struct ZT_Node_Callbacks
ZT_PathLookupFunction pathLookupFunction;
};
/**
* Get a buffer for reading data to be passed back into the core via one of the processX() functions
*
* The size of the returned buffer is 16384 bytes (ZT_BUF_SIZE).
*
* Buffers retrieved with this method MUST be returned to the core via either one of the processX()
* functions (with isZtBuffer set to true) or freeBuffer(). Buffers should not be freed directly using free().
*
* @return Pointer to I/O buffer
*/
ZT_SDK_API void *ZT_getBuffer();
/**
* Free an unused buffer obtained via getBuffer
*
* @param b Buffer to free
*/
ZT_SDK_API void ZT_freeBuffer(void *b);
/**
* Create a new ZeroTier node
*
@ -1766,6 +1790,7 @@ ZT_SDK_API void ZT_Node_delete(ZT_Node *node,void *tptr);
* @param remoteAddress Origin of packet
* @param packetData Packet data
* @param packetLength Packet length
* @param isZtBuffer If non-zero then packetData is a buffer obtained with ZT_getBuffer()
* @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks()
* @return OK (0) or error code if a fatal error condition has occurred
*/
@ -1777,6 +1802,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket(
const struct sockaddr_storage *remoteAddress,
const void *packetData,
unsigned int packetLength,
int isZtBuffer,
volatile int64_t *nextBackgroundTaskDeadline);
/**
@ -1792,6 +1818,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket(
* @param vlanId 10-bit VLAN ID or 0 if none
* @param frameData Frame payload data
* @param frameLength Frame payload length
* @param isZtBuffer If non-zero then packetData is a buffer obtained with ZT_getBuffer()
* @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks()
* @return OK (0) or error code if a fatal error condition has occurred
*/
@ -1806,6 +1833,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
unsigned int vlanId,
const void *frameData,
unsigned int frameLength,
int isZtBuffer,
volatile int64_t *nextBackgroundTaskDeadline);
/**

View file

@ -177,9 +177,9 @@ public:
/**
* Create a new uninitialized buffer with undefined contents (use clear() to zero if needed)
*/
ZT_ALWAYS_INLINE Buf() noexcept {}
ZT_ALWAYS_INLINE Buf() noexcept : __nextInPool(0),__refCount(0) {}
ZT_ALWAYS_INLINE Buf(const Buf &b2) noexcept { memcpy(unsafeData,b2.unsafeData,ZT_BUF_MEM_SIZE); }
ZT_ALWAYS_INLINE Buf(const Buf &b2) noexcept : __nextInPool(0),__refCount(0) { memcpy(unsafeData,b2.unsafeData,ZT_BUF_MEM_SIZE); }
ZT_ALWAYS_INLINE Buf &operator=(const Buf &b2) noexcept
{

View file

@ -30,6 +30,8 @@
#include "Expect.hpp"
#include "VL1.hpp"
#include "VL2.hpp"
#include "Buf.hpp"
namespace ZeroTier {
@ -158,16 +160,12 @@ ZT_ResultCode Node::processWirePacket(
int64_t now,
int64_t localSocket,
const struct sockaddr_storage *remoteAddress,
const void *packetData,
SharedPtr<Buf> &packetData,
unsigned int packetLength,
volatile int64_t *nextBackgroundTaskDeadline)
{
_now = now;
// TODO: add buffer life cycle methods
SharedPtr<Buf> tmp(new Buf());
packetLength &= ZT_BUF_MEM_MASK;
memcpy(tmp->unsafeData,packetData,packetLength);
RR->vl1->onRemotePacket(tPtr,localSocket,(remoteAddress) ? InetAddress::NIL : *asInetAddress(remoteAddress),tmp,packetLength);
RR->vl1->onRemotePacket(tPtr,localSocket,(remoteAddress) ? InetAddress::NIL : *asInetAddress(remoteAddress),packetData,packetLength);
return ZT_RESULT_OK;
}
@ -179,14 +177,14 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
uint64_t destMac,
unsigned int etherType,
unsigned int vlanId,
const void *frameData,
SharedPtr<Buf> &frameData,
unsigned int frameLength,
volatile int64_t *nextBackgroundTaskDeadline)
{
_now = now;
SharedPtr<Network> nw(this->network(nwid));
if (nw) {
//RR->sw->onLocalEthernet(tptr,nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength);
RR->vl2->onLocalEthernet(tPtr,nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength);
return ZT_RESULT_OK;
} else {
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
@ -815,6 +813,21 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des
extern "C" {
void *ZT_getBuffer()
{
try {
return (void *)(new ZeroTier::Buf()); // __refCount is left at zero
} catch ( ... ) {
return nullptr; // can only happen on out of memory condition
}
}
ZT_SDK_API void ZT_freeBuffer(void *b)
{
if (b)
delete ((ZeroTier::Buf *)b);
}
enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now)
{
*node = (ZT_Node *)0;
@ -846,10 +859,18 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
const struct sockaddr_storage *remoteAddress,
const void *packetData,
unsigned int packetLength,
int isZtBuffer,
volatile int64_t *nextBackgroundTaskDeadline)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(tptr,now,localSocket,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline);
ZeroTier::SharedPtr<ZeroTier::Buf> buf;
if (isZtBuffer) {
buf.set((ZeroTier::Buf *)packetData);
} else {
buf.set(new ZeroTier::Buf());
memcpy(buf->unsafeData,packetData,std::min((unsigned int)ZT_BUF_MEM_SIZE,packetLength));
}
return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(tptr,now,localSocket,remoteAddress,buf,packetLength,nextBackgroundTaskDeadline);
} catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) {
@ -868,10 +889,18 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
unsigned int vlanId,
const void *frameData,
unsigned int frameLength,
int isZtBuffer,
volatile int64_t *nextBackgroundTaskDeadline)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->processVirtualNetworkFrame(tptr,now,nwid,sourceMac,destMac,etherType,vlanId,frameData,frameLength,nextBackgroundTaskDeadline);
ZeroTier::SharedPtr<ZeroTier::Buf> buf;
if (isZtBuffer) {
buf.set((ZeroTier::Buf *)frameData);
} else {
buf.set(new ZeroTier::Buf());
memcpy(buf->unsafeData,frameData,std::min((unsigned int)ZT_BUF_MEM_SIZE,frameLength));
}
return reinterpret_cast<ZeroTier::Node *>(node)->processVirtualNetworkFrame(tptr,now,nwid,sourceMac,destMac,etherType,vlanId,buf,frameLength,nextBackgroundTaskDeadline);
} catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch ( ... ) {

View file

@ -24,6 +24,7 @@
#include "Salsa20.hpp"
#include "NetworkController.hpp"
#include "Hashtable.hpp"
#include "Buf.hpp"
#include <cstdio>
#include <cstdlib>
@ -72,7 +73,7 @@ public:
int64_t now,
int64_t localSocket,
const struct sockaddr_storage *remoteAddress,
const void *packetData,
SharedPtr<Buf> &packetData,
unsigned int packetLength,
volatile int64_t *nextBackgroundTaskDeadline);
ZT_ResultCode processVirtualNetworkFrame(
@ -83,7 +84,7 @@ public:
uint64_t destMac,
unsigned int etherType,
unsigned int vlanId,
const void *frameData,
SharedPtr<Buf> &frameData,
unsigned int frameLength,
volatile int64_t *nextBackgroundTaskDeadline);
ZT_ResultCode processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline);