Network now calls port config function as per new API.

This commit is contained in:
Adam Ierymenko 2015-04-06 16:52:52 -07:00
parent a86300c58f
commit 8001b2c0cb
6 changed files with 157 additions and 70 deletions

View File

@ -78,6 +78,21 @@ extern "C" {
*/
#define ZT1_MAX_MTU 2800
/**
* Maximum length of network short name
*/
#define ZT1_MAX_NETWORK_SHORT_NAME_LENGTH 255
/**
* Maximum number of statically assigned IP addresses per network endpoint using ZT address management (not DHCP)
*/
#define ZT1_MAX_ZT_ASSIGNED_ADDRESSES 16
/**
* Maximum number of multicast group subscriptions per network
*/
#define ZT1_MAX_NETWORK_MULTICAST_SUBSCRIPTIONS 8194
/**
* Feature flag: this is an official ZeroTier, Inc. binary build (built with ZT_OFFICIAL_RELEASE)
*/
@ -272,7 +287,7 @@ enum ZT1_VirtualNetworkStatus
/**
* Initialization of network failed or other internal error
*/
ZT1_NETWORK_STATUS_INITIALIZATION_FAILED = 4
ZT1_NETWORK_STATUS_PORT_ERROR = 4
};
/**
@ -322,6 +337,11 @@ typedef struct
*/
uint64_t mac;
/**
* Network name (from network configuration master)
*/
char name[ZT1_MAX_NETWORK_SHORT_NAME_LENGTH + 1];
/**
* Network configuration request status
*/
@ -359,6 +379,11 @@ typedef struct
*/
int broadcastEnabled;
/**
* If the network is in PORT_ERROR state, this is the error most recently returned by the port config callback
*/
int portError;
/**
* Network config revision as reported by netconf master
*
@ -366,6 +391,21 @@ typedef struct
*/
unsigned long netconfRevision;
/**
* Number of multicast group subscriptions
*/
unsigned int multicastSubscriptionCount;
/**
* Multicast group subscriptions
*/
ZT1_MulticastGroup multicastSubscriptions[ZT1_MAX_NETWORK_MULTICAST_SUBSCRIPTIONS];
/**
* Number of assigned addresses
*/
unsigned int assignedAddressCount;
/**
* ZeroTier-assigned addresses (in sockaddr_storage structures)
*
@ -376,27 +416,7 @@ typedef struct
* This is only used for ZeroTier-managed address assignments sent by the
* virtual network's configuration master.
*/
const struct sockaddr_storage *assignedAddresses;
/**
* Number of assigned addresses
*/
unsigned int assignedAddressCount;
/**
* Multicast group subscriptions
*/
ZT1_MulticastGroup *multicastSubscriptions;
/**
* Number of multicast group subscriptions
*/
unsigned int multicastSubscriptionCount;
/**
* Network name (from network configuration master)
*/
const char *networkName;
struct sockaddr_storage assignedAddresses[ZT1_MAX_ZT_ASSIGNED_ADDRESSES];
} ZT1_VirtualNetworkConfig;
/**
@ -539,8 +559,12 @@ typedef void ZT1_Node;
*
* The supplied config pointer is not guaranteed to remain valid, so make
* a copy if you want one.
*
* This must return 0 on success. It can return any OS-dependent error code
* on failure, and this results in the network being placed into the
* PORT_ERROR state.
*/
typedef void (*ZT1_VirtualNetworkConfigCallback)(ZT1_Node *,uint64_t,const ZT1_VirtualNetworkConfig *);
typedef int (*ZT1_VirtualNetworkConfigFunction)(ZT1_Node *,uint64_t,const ZT1_VirtualNetworkConfig *);
/**
* Callback for status messages
@ -622,7 +646,7 @@ typedef void (*ZT1_VirtualNetworkFrameFunction)(ZT1_Node *,uint64_t,uint64_t,uin
* @param now Current clock in milliseconds
* @param dataStoreGetFunction Function called to get objects from persistent storage
* @param dataStorePutFunction Function called to put objects in persistent storage
* @param virtualNetworkConfigCallback Function to be called when virtual LANs are created, deleted, or their config parameters change
* @param virtualNetworkConfigFunction Function to be called when virtual LANs are created, deleted, or their config parameters change
* @param statusCallback Function to receive status updates and non-fatal error notices
* @return OK (0) or error code if a fatal error condition has occurred
*/
@ -633,7 +657,7 @@ enum ZT1_ResultCode ZT1_Node_new(
ZT1_DataStorePutFunction dataStorePutFunction,
ZT1_WirePacketSendFunction wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT1_VirtualNetworkConfigCallback virtualNetworkConfigCallback,
ZT1_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
ZT1_StatusCallback statusCallback);
/**

View File

@ -49,7 +49,8 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid) :
_enabled(true),
_lastConfigUpdate(0),
_destroyed(false),
_netconfFailure(NETCONF_FAILURE_NONE)
_netconfFailure(NETCONF_FAILURE_NONE),
_portError(0)
{
char confn[128],mcdbn[128];
Utils::snprintf(confn,sizeof(confn),"networks.d/%.16llx.conf",_id);
@ -96,10 +97,16 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid) :
}
requestConfiguration();
ZT1_VirtualNetworkConfig ctmp;
_externalConfig(&ctmp);
_portError = RR->node->configureVirtualNetworkPort(_id,&ctmp);
}
Network::~Network()
{
RR->node->configureVirtualNetworkPort(_id,(const ZT1_VirtualNetworkConfig *)0);
char n[128];
if (_destroyed) {
Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
@ -179,6 +186,11 @@ bool Network::applyConfiguration(const SharedPtr<NetworkConfig> &conf)
_config = conf;
_lastConfigUpdate = RR->node->now();
_netconfFailure = NETCONF_FAILURE_NONE;
ZT1_VirtualNetworkConfig ctmp;
_externalConfig(&ctmp);
_portError = RR->node->configureVirtualNetworkPort(_id,&ctmp);
return true;
} else {
LOG("ignored invalid configuration for network %.16llx (configuration contains mismatched network ID or issued-to address)",(unsigned long long)_id);
@ -368,21 +380,6 @@ void Network::clean()
}
}
ZT1_VirtualNetworkStatus Network::status() const
{
Mutex::Lock _l(_lock);
switch(_netconfFailure) {
case NETCONF_FAILURE_ACCESS_DENIED:
return ZT1_NETWORK_STATUS_ACCESS_DENIED;
case NETCONF_FAILURE_NOT_FOUND:
return ZT1_NETWORK_STATUS_NOT_FOUND;
case NETCONF_FAILURE_NONE:
return ((_lastConfigUpdate > 0) ? ZT1_NETWORK_STATUS_OK : ZT1_NETWORK_STATUS_REQUESTING_CONFIGURATION);
default:
return ZT1_NETWORK_STATUS_INITIALIZATION_FAILED;
}
}
void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
{
Mutex::Lock _l(_lock);
@ -421,4 +418,53 @@ void Network::destroy()
_destroyed = true;
}
ZT1_VirtualNetworkStatus Network::_status() const
{
// assumes _lock is locked
if (_portError)
return ZT1_NETWORK_STATUS_PORT_ERROR;
switch(_netconfFailure) {
case NETCONF_FAILURE_ACCESS_DENIED:
return ZT1_NETWORK_STATUS_ACCESS_DENIED;
case NETCONF_FAILURE_NOT_FOUND:
return ZT1_NETWORK_STATUS_NOT_FOUND;
case NETCONF_FAILURE_NONE:
return ((_lastConfigUpdate > 0) ? ZT1_NETWORK_STATUS_OK : ZT1_NETWORK_STATUS_REQUESTING_CONFIGURATION);
default:
return ZT1_NETWORK_STATUS_PORT_ERROR;
}
}
void Network::_externalConfig(ZT1_VirtualNetworkConfig *ec) const
{
// assumes _lock is locked
ec->nwid = _id;
ec->mac = MAC(RR->identity.address(),_id);
if (_config)
Utils::scopy(ec->name,sizeof(ec->name),_config->name().c_str());
else ec->name[0] = (char)0;
ec->status = _status();
ec->type = (_config) ? (_config->isPrivate() ? ZT1_NETWORK_TYPE_PRIVATE : ZT1_NETWORK_TYPE_PUBLIC) : ZT1_NETWORK_TYPE_PRIVATE;
ec->mtu = ZT_IF_MTU;
ec->dhcp = 0;
ec->bridge = (_config) ? ((_config->allowPassiveBridging() || (std::find(_config->activeBridges().begin(),_config->activeBridges().end(),RR->identity.address()) != _config->activeBridges().end())) ? 1 : 0) : 0;
ec->broadcastEnabled = (_config) ? (_config->enableBroadcast() ? 1 : 0) : 0;
ec->portError = _portError;
ec->netconfRevision = (_config) ? (unsigned long)_config->revision() : 0;
ec->multicastSubscriptionCount = std::max((unsigned int)_myMulticastGroups.size(),(unsigned int)ZT1_MAX_NETWORK_MULTICAST_SUBSCRIPTIONS);
for(unsigned int i=0;i<ec->multicastSubscriptionCount;++i) {
ec->multicastSubscriptions[i].mac = _myMulticastGroups[i].mac().toInt();
ec->multicastSubscriptions[i].adi = _myMulticastGroups[i].adi();
}
if (_config) {
ec->assignedAddressCount = (unsigned int)_config->staticIps().size();
for(unsigned long i=0;i<ZT1_MAX_ZT_ASSIGNED_ADDRESSES;++i) {
if (i < _config->staticIps().size())
memcpy(&(ec->assignedAddresses[i]),&(_config->staticIps()[i]),sizeof(struct sockaddr_storage));
}
} else ec->assignedAddressCount = 0;
}
} // namespace ZeroTier

View File

@ -192,7 +192,20 @@ public:
/**
* @return Status of this network
*/
ZT1_VirtualNetworkStatus status() const;
inline ZT1_VirtualNetworkStatus status() const
{
Mutex::Lock _l(_lock);
return _status();
}
/**
* @param ec Buffer to fill with externally-visible network configuration
*/
inline void externalConfig(ZT1_VirtualNetworkConfig *ec) const
{
Mutex::Lock _l(_lock);
_externalConfig(ec);
}
/**
* Update and check multicast rate balance for a multicast group
@ -321,6 +334,9 @@ public:
void destroy();
private:
ZT1_VirtualNetworkStatus _status() const;
void _externalConfig(ZT1_VirtualNetworkConfig *ec) const; // assumes _lock is locked
const RuntimeEnvironment *RR;
uint64_t _id;
MAC _mac; // local MAC address
@ -340,12 +356,13 @@ private:
volatile bool _destroyed;
volatile enum {
enum {
NETCONF_FAILURE_NONE,
NETCONF_FAILURE_ACCESS_DENIED,
NETCONF_FAILURE_NOT_FOUND,
NETCONF_FAILURE_INIT_FAILED
} _netconfFailure;
int _portError; // return value from port config callback
Mutex _lock;

View File

@ -125,6 +125,8 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
_private = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE,one).c_str()) != 0);
_enableBroadcast = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST,one).c_str()) != 0);
_name = d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME);
if (_name.length() > ZT1_MAX_NETWORK_SHORT_NAME_LENGTH)
throw std::invalid_argument("network short name too long (max: 255 characters)");
_description = d.get(ZT_NETWORKCONFIG_DICT_KEY_DESC,std::string());
// In dictionary IPs are split into V4 and V6 addresses, but we don't really
@ -156,6 +158,8 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
}
_staticIps.push_back(addr);
}
if (_staticIps.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES)
throw std::invalid_argument("too many ZT-assigned IP addresses");
std::sort(_staticIps.begin(),_staticIps.end());
std::unique(_staticIps.begin(),_staticIps.end());

View File

@ -54,14 +54,14 @@ Node::Node(
ZT1_DataStorePutFunction dataStorePutFunction,
ZT1_WirePacketSendFunction wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT1_VirtualNetworkConfigCallback virtualNetworkConfigCallback,
ZT1_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
ZT1_StatusCallback statusCallback) :
RR(new RuntimeEnvironment(this)),
_dataStoreGetFunction(dataStoreGetFunction),
_dataStorePutFunction(dataStorePutFunction),
_wirePacketSendFunction(wirePacketSendFunction),
_virtualNetworkFrameFunction(virtualNetworkFrameFunction),
_virtualNetworkConfigCallback(virtualNetworkConfigCallback),
_virtualNetworkConfigFunction(virtualNetworkConfigFunction),
_statusCallback(statusCallback),
_networks(),
_networks_m(),
@ -217,12 +217,12 @@ enum ZT1_ResultCode ZT1_Node_new(
ZT1_DataStorePutFunction dataStorePutFunction,
ZT1_WirePacketSendFunction wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT1_VirtualNetworkConfigCallback virtualNetworkConfigCallback,
ZT1_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
ZT1_StatusCallback statusCallback)
{
*node = (ZT1_Node *)0;
try {
*node = reinterpret_cast<ZT1_Node *>(new ZeroTier::Node(now,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigCallback,statusCallback));
*node = reinterpret_cast<ZT1_Node *>(new ZeroTier::Node(now,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigFunction,statusCallback));
return ZT1_RESULT_OK;
} catch (std::bad_alloc &exc) {
return ZT1_RESULT_FATAL_ERROR_OUT_OF_MEMORY;

View File

@ -61,7 +61,7 @@ public:
ZT1_DataStorePutFunction dataStorePutFunction,
ZT1_WirePacketSendFunction wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT1_VirtualNetworkConfigCallback virtualNetworkConfigCallback,
ZT1_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
ZT1_StatusCallback statusCallback);
~Node();
@ -115,16 +115,12 @@ public:
*/
inline bool putPacket(const InetAddress &addr,const void *data,unsigned int len,unsigned int desperation)
{
try {
return (_wirePacketSendFunction(
reinterpret_cast<ZT1_Node *>(this),
reinterpret_cast<const struct sockaddr_storage *>(&addr),
desperation,
data,
len) == 0);
} catch ( ... ) { // callbacks should not throw
return false;
}
return (_wirePacketSendFunction(
reinterpret_cast<ZT1_Node *>(this),
reinterpret_cast<const struct sockaddr_storage *>(&addr),
desperation,
data,
len) == 0);
}
/**
@ -140,17 +136,15 @@ public:
*/
inline void putFrame(uint64_t nwid,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
{
try {
_virtualNetworkFrameFunction(
reinterpret_cast<ZT1_Node *>(this),
nwid,
source.toInt(),
dest.toInt(),
etherType,
vlanId,
data,
len);
} catch ( ... ) {} // callbacks should not throw
_virtualNetworkFrameFunction(
reinterpret_cast<ZT1_Node *>(this),
nwid,
source.toInt(),
dest.toInt(),
etherType,
vlanId,
data,
len);
}
inline SharedPtr<Network> network(uint64_t nwid)
@ -167,6 +161,8 @@ public:
inline void postEvent(ZT1_Event ev) { _statusCallback(reinterpret_cast<ZT1_Node *>(this),ev); }
inline int configureVirtualNetworkPort(uint64_t nwid,const ZT1_VirtualNetworkConfig *nc) { return _virtualNetworkConfigFunction(reinterpret_cast<ZT1_Node *>(this),nwid,nc); }
void postNewerVersionIfNewer(unsigned int major,unsigned int minor,unsigned int rev);
private:
@ -176,7 +172,7 @@ private:
ZT1_DataStorePutFunction _dataStorePutFunction;
ZT1_WirePacketSendFunction _wirePacketSendFunction;
ZT1_VirtualNetworkFrameFunction _virtualNetworkFrameFunction;
ZT1_VirtualNetworkConfigCallback _virtualNetworkConfigCallback;
ZT1_VirtualNetworkConfigFunction _virtualNetworkConfigFunction;
ZT1_StatusCallback _statusCallback;
//Dictionary _localConfig; // persisted as local.conf