Moar build fixes, clock perf improvement.

This commit is contained in:
Adam Ierymenko 2020-03-23 16:12:45 -07:00
parent 2da096944d
commit 490b9c4d79
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
13 changed files with 87 additions and 92 deletions

View file

@ -27,7 +27,7 @@ A ZeroTier identity is comprised of one or more cryptographic public keys and a
#### Identity Types and Corresponding Algorithms #### Identity Types and Corresponding Algorithms
* **Type 0** (v1.x and v2.x): one Curve25519 key for elliptic curve Diffie-Hellman and one Ed25519 key for Ed25519 signatures, with the address and fingerprint computed from a hash of both. * **Type 0** (v1.x and v2.x): one Curve25519 key for elliptic curve Diffie-Hellman and one Ed25519 key for Ed25519 signatures, with the address and fingerprint computed from a hash of both.
* **Type 1** (v2.x only): Curve25519, Ed25519, and NIST P-384 public keys, with the latter being used for signatures (the Ed25519 key is still there but is presently unused) and with *both* keys being used for elliptic curve Diffie-Hellman key agreement. In key agreement the resulting raw secret keys are hashed together using SHA-384 to combine them and yield a single session key. * **Type 1** (v2.x only): Curve25519, Ed25519, and NIST P-384 public keys, with the latter being used for signatures (the Ed25519 key is still there but is presently unused) and with *both* Curve25519 and NIST P-384 being used for elliptic curve Diffie-Hellman key agreement. In key agreement the resulting raw secret keys are hashed together using SHA-384 to combine them and yield a single session key.
Session keys resulting from identity key exchange and agreement are *long-lived keys* that remain static for the lifetime of a particular pair of identities. A different mechanism is used for ephemeral key negotiation. Session keys resulting from identity key exchange and agreement are *long-lived keys* that remain static for the lifetime of a particular pair of identities. A different mechanism is used for ephemeral key negotiation.
@ -52,6 +52,8 @@ bzg7fc3sn46fzyxcxw2ev4c4m2u5fyisb3o4wz5hfmvexbzwk6et3fsglkdcn6nnjobxi3bq7hgxqox3
These are too large to type but not to copy/paste, store in databases, or use in scripts and APIs. These are too large to type but not to copy/paste, store in databases, or use in scripts and APIs.
Once a device has joined a network, network controllers will remember and check its full identity or identity fingerprint (depending on implementation) rather than just the device's ZeroTier address.
## VL1 Wire Protocol ## VL1 Wire Protocol
ZeroTier's wire protocol is packet based with packets having the following format: ZeroTier's wire protocol is packet based with packets having the following format:

View file

@ -0,0 +1,4 @@
package main
func main() {
}

View file

@ -37,7 +37,6 @@ Global Options:
Commands: Commands:
help Show this help help Show this help
version Print version version Print version
selftest Run internal tests
service Start as service service Start as service
status Show ZeroTier status and config status Show ZeroTier status and config
peers Show VL1 peers and link information peers Show VL1 peers and link information

View file

@ -1,29 +0,0 @@
/*
* Copyright (c)2013-2020 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: 2024-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.
*/
/****/
package cli
import (
"fmt"
"os"
"zerotier/pkg/zerotier"
)
func SelfTest() {
if !zerotier.SelfTest() {
fmt.Println("FAILED: at least one ZeroTier self-test reported failure.")
os.Exit(1)
}
os.Exit(0)
}

View file

@ -123,9 +123,6 @@ func main() {
case "version": case "version":
fmt.Printf("%d.%d.%d\n", zerotier.CoreVersionMajor, zerotier.CoreVersionMinor, zerotier.CoreVersionRevision) fmt.Printf("%d.%d.%d\n", zerotier.CoreVersionMajor, zerotier.CoreVersionMinor, zerotier.CoreVersionRevision)
os.Exit(0) os.Exit(0)
case "selftest":
cli.SelfTest()
os.Exit(0)
case "service": case "service":
cli.Service(basePath, authToken, cmdArgs) cli.Service(basePath, authToken, cmdArgs)
case "status": case "status":

View file

@ -46,7 +46,7 @@ type Identity struct {
idtype int idtype int
publicKey []byte publicKey []byte
privateKey []byte privateKey []byte
cid unsafe.Pointer cid unsafe.Pointer // ZT_Identity
} }
func identityFinalizer(obj interface{}) { func identityFinalizer(obj interface{}) {

View file

@ -45,10 +45,10 @@ type ExternalAddress struct {
// LocalConfigSettings contains node settings // LocalConfigSettings contains node settings
type LocalConfigSettings struct { type LocalConfigSettings struct {
// PrimaryPort is the main UDP port and must be set (defaults to 9993) // PrimaryPort is the main UDP port and must be set.
PrimaryPort int `json:"primaryPort"` PrimaryPort int `json:"primaryPort"`
// SecondaryPort is the secondary UDP port, set to 0 to disbale (picked at random by default) // SecondaryPort is the secondary UDP port, set to 0 to disable (picked at random by default)
SecondaryPort int `json:"secondaryPort"` SecondaryPort int `json:"secondaryPort"`
// PortSearch causes ZeroTier to try other ports automatically if it can't bind to configured ports // PortSearch causes ZeroTier to try other ports automatically if it can't bind to configured ports
@ -100,6 +100,10 @@ func (lc *LocalConfig) Read(p string, saveDefaultsIfNotExist bool, isTotallyNewN
if isTotallyNewNode { if isTotallyNewNode {
lc.Settings.PrimaryPort = 793 lc.Settings.PrimaryPort = 793
} else { } else {
// For legacy reasons we keep nodes that already existed prior to 2.0 (upgraded nodes)
// at 9993 by default if there is no existing primary port configured. This is for
// principle of least surprise since some admins may have special firewall rules for
// this port.
lc.Settings.PrimaryPort = 9993 lc.Settings.PrimaryPort = 9993
} }
lc.Settings.SecondaryPort = unassignedPrivilegedPorts[randomUInt()%uint(len(unassignedPrivilegedPorts))] lc.Settings.SecondaryPort = unassignedPrivilegedPorts[randomUInt()%uint(len(unassignedPrivilegedPorts))]

View file

@ -899,7 +899,7 @@ void AES::CTR::finish() noexcept
// Software AES and AES key expansion --------------------------------------------------------------------------------- // Software AES and AES key expansion ---------------------------------------------------------------------------------
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
static inline uint32_t readuint32_t(const void *in) static ZT_INLINE uint32_t readuint32_t(const void *in)
{ {
uint32_t v = ((const uint8_t *)in)[0]; uint32_t v = ((const uint8_t *)in)[0];
v <<= 8; v <<= 8;
@ -910,7 +910,7 @@ static inline uint32_t readuint32_t(const void *in)
v |= ((const uint8_t *)in)[3]; v |= ((const uint8_t *)in)[3];
return v; return v;
} }
static inline void writeuint32_t(void *out,const uint32_t v) static ZT_INLINE void writeuint32_t(void *out,const uint32_t v)
{ {
((uint8_t *)out)[0] = (uint8_t)(v >> 24); ((uint8_t *)out)[0] = (uint8_t)(v >> 24);
((uint8_t *)out)[1] = (uint8_t)(v >> 16); ((uint8_t *)out)[1] = (uint8_t)(v >> 16);

View file

@ -24,6 +24,8 @@ namespace ZeroTier {
/** /**
* A ZeroTier address * A ZeroTier address
*
* This is merely a 40-bit short address packed into a uint64_t and wrapped with methods.
*/ */
class Address : public TriviallyCopyable class Address : public TriviallyCopyable
{ {

View file

@ -1,26 +0,0 @@
/*
* Copyright (c)2013-2020 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: 2024-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_LZ4_HPP
#define ZT_LZ4_HPP
#include "Constants.hpp"
namespace ZeroTier {
int LZ4_compress_fast(const char *source,char *dest,int inputSize,int maxOutputSize,int acceleration = 1) noexcept;
int LZ4_decompress_safe(const char *source,char *dest,int compressedSize,int maxDecompressedSize) noexcept;
} // namespace ZeroTier
#endif

View file

@ -36,6 +36,13 @@ namespace ZeroTier {
namespace { namespace {
/**
* All core objects of a ZeroTier node.
*
* This is just a box that allows us to allocate all core objects
* and data structures at once for a bit of memory saves and improved
* cache adjacency.
*/
struct _NodeObjects struct _NodeObjects
{ {
ZT_INLINE _NodeObjects(RuntimeEnvironment *const RR,void *const tPtr) : ZT_INLINE _NodeObjects(RuntimeEnvironment *const RR,void *const tPtr) :
@ -190,11 +197,17 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
} }
} }
struct _processBackgroundTasks_ping_eachPeer struct _processBackgroundTasks_eachPeer
{ {
int64_t now; ZT_INLINE _processBackgroundTasks_eachPeer(const int64_t now_,Node *const parent_,void *const tPtr_) :
Node *parent; now(now_),
void *tPtr; parent(parent_),
tPtr(tPtr_),
online(false),
rootsNotOnline() {}
const int64_t now;
Node *const parent;
void *const tPtr;
bool online; bool online;
std::vector<Address> rootsNotOnline; std::vector<Address> rootsNotOnline;
ZT_INLINE void operator()(const SharedPtr<Peer> &peer,const bool isRoot) ZT_INLINE void operator()(const SharedPtr<Peer> &peer,const bool isRoot)
@ -209,22 +222,25 @@ struct _processBackgroundTasks_ping_eachPeer
} }
} }
}; };
struct _processBackgroundTasks_eachPath
static uint8_t keepAlivePayload = 0; // junk payload for keepalive packets
struct _processBackgroundTasks_path_keepalive
{ {
int64_t now; ZT_INLINE _processBackgroundTasks_eachPath(const int64_t now_,const RuntimeEnvironment *const RR_,void *const tPtr_) :
RuntimeEnvironment *RR; now(now_),
void *tPtr; RR(RR_),
tPtr(tPtr_),
keepAlivePayload((uint8_t)now_) {}
const int64_t now;
const RuntimeEnvironment *const RR;
void *const tPtr;
uint8_t keepAlivePayload;
ZT_INLINE void operator()(const SharedPtr<Path> &path) ZT_INLINE void operator()(const SharedPtr<Path> &path)
{ {
if ((now - path->lastOut()) >= ZT_PATH_KEEPALIVE_PERIOD) { if ((now - path->lastOut()) >= ZT_PATH_KEEPALIVE_PERIOD) {
++keepAlivePayload; ++keepAlivePayload;
path->send(RR,tPtr,&keepAlivePayload,1,now); path->send(RR,tPtr,&keepAlivePayload,sizeof(keepAlivePayload),now);
} }
} }
}; };
ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline) ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline)
{ {
_now = now; _now = now;
@ -233,12 +249,8 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int
if ((now - _lastPing) >= ZT_PEER_PING_PERIOD) { if ((now - _lastPing) >= ZT_PEER_PING_PERIOD) {
_lastPing = now; _lastPing = now;
try { try {
_processBackgroundTasks_ping_eachPeer pf; _processBackgroundTasks_eachPeer pf(now,this,tPtr);
pf.now = now; RR->topology->eachPeerWithRoot<_processBackgroundTasks_eachPeer &>(pf);
pf.parent = this;
pf.tPtr = tPtr;
pf.online = false;
RR->topology->eachPeerWithRoot<_processBackgroundTasks_ping_eachPeer &>(pf);
if (pf.online != _online) { if (pf.online != _online) {
_online = pf.online; _online = pf.online;
@ -300,11 +312,8 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int
if ((now - _lastPathKeepaliveCheck) >= ZT_PATH_KEEPALIVE_PERIOD) { if ((now - _lastPathKeepaliveCheck) >= ZT_PATH_KEEPALIVE_PERIOD) {
_lastPathKeepaliveCheck = now; _lastPathKeepaliveCheck = now;
_processBackgroundTasks_path_keepalive pf; _processBackgroundTasks_eachPath pf(now,RR,tPtr);
pf.now = now; RR->topology->eachPath<_processBackgroundTasks_eachPath &>(pf);
pf.RR = RR;
pf.tPtr = tPtr;
RR->topology->eachPath<_processBackgroundTasks_path_keepalive &>(pf);
} }
int64_t earliestAlarmAt = 0x7fffffffffffffffLL; int64_t earliestAlarmAt = 0x7fffffffffffffffLL;

View file

@ -30,6 +30,16 @@
namespace ZeroTier { namespace ZeroTier {
#ifdef __APPLE__
static clock_serv_t _machGetRealtimeClock() noexcept
{
clock_serv_t c;
host_get_clock_service(mach_host_self(),CALENDAR_CLOCK,&c);
return c;
}
static clock_serv_t s_machRealtimeClock = _machGetRealtimeClock();
#endif
unsigned int OSUtils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...) unsigned int OSUtils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...)
{ {
va_list ap; va_list ap;

View file

@ -32,6 +32,12 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#ifdef __APPLE__
#include <mach/mach.h>
#include <mach/clock.h>
#include <mach/mach_time.h>
#endif
#ifndef OMIT_JSON_SUPPORT #ifndef OMIT_JSON_SUPPORT
#include "../ext/json/json.hpp" #include "../ext/json/json.hpp"
#endif #endif
@ -43,6 +49,11 @@ namespace ZeroTier {
*/ */
class OSUtils class OSUtils
{ {
private:
#ifdef __APPLE__
static clock_serv_t s_machRealtimeClock;
#endif
public: public:
/** /**
* Variant of snprintf that is portable and throws an exception * Variant of snprintf that is portable and throws an exception
@ -161,14 +172,26 @@ public:
tmp.LowPart = ft.dwLowDateTime; tmp.LowPart = ft.dwLowDateTime;
tmp.HighPart = ft.dwHighDateTime; tmp.HighPart = ft.dwHighDateTime;
return (int64_t)( ((tmp.QuadPart - 116444736000000000LL) / 10000L) + st.wMilliseconds ); return (int64_t)( ((tmp.QuadPart - 116444736000000000LL) / 10000L) + st.wMilliseconds );
#else
#ifdef __LINUX__
timespec ts;
#ifdef CLOCK_REALTIME_COARSE
clock_gettime(CLOCK_REALTIME_COARSE,&ts);
#else
clock_gettime(CLOCK_REALTIME,&ts);
#endif
return ( (1000LL * (int64_t)ts.tv_sec) + ((int64_t)(ts.tv_nsec / 1000000)) );
#else
#ifdef __APPLE__
mach_timespec_t mts;
clock_get_time(s_machRealtimeClock,&mts);
return ( (1000LL * (int64_t)mts.tv_sec) + ((int64_t)(mts.tv_nsec / 1000000)) );
#else #else
timeval tv; timeval tv;
// #ifdef __LINUX__
// syscall(SYS_gettimeofday,&tv,0); /* fix for musl libc broken gettimeofday bug */
// #else
gettimeofday(&tv,(struct timezone *)0); gettimeofday(&tv,(struct timezone *)0);
// #endif
return ( (1000LL * (int64_t)tv.tv_sec) + (int64_t)(tv.tv_usec / 1000) ); return ( (1000LL * (int64_t)tv.tv_sec) + (int64_t)(tv.tv_usec / 1000) );
#endif
#endif
#endif #endif
}; };