summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--controller/EmbeddedNetworkController.cpp8
-rw-r--r--include/ZeroTierOne.h18
-rw-r--r--node/Capability.hpp7
-rw-r--r--node/Network.cpp4
4 files changed, 33 insertions, 4 deletions
diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp
index c60f7322..d656bad3 100644
--- a/controller/EmbeddedNetworkController.cpp
+++ b/controller/EmbeddedNetworkController.cpp
@@ -260,6 +260,11 @@ static json _renderRule(ZT_VirtualNetworkRule &rule)
r["start"] = (unsigned int)rule.v.frameSize[0];
r["end"] = (unsigned int)rule.v.frameSize[1];
break;
+ case ZT_NETWORK_RULE_MATCH_RANDOM:
+ r["type"] = "MATCH_RANDOM";
+ r["not"] = ((rule.t & 0x80) != 0);
+ r["probability"] = (unsigned long)rule.v.randomProbability;
+ break;
case ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE:
r["type"] = "MATCH_TAGS_DIFFERENCE";
r["not"] = ((rule.t & 0x80) != 0);
@@ -441,6 +446,9 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule)
rule.v.frameSize[0] = (uint16_t)(_jI(r["start"],0ULL) & 0xffffULL);
rule.v.frameSize[1] = (uint16_t)(_jI(r["end"],(uint64_t)rule.v.frameSize[0]) & 0xffffULL);
return true;
+ } else if (t == "MATCH_RANDOM") {
+ rule.t |= ZT_NETWORK_RULE_MATCH_RANDOM;
+ rule.v.randomProbability = (uint32_t)(_jI(r["probability"],0ULL) & 0xffffffffULL);
} else if (t == "MATCH_TAGS_DIFFERENCE") {
rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE;
rule.v.tag.id = (uint32_t)(_jI(r["id"],0ULL) & 0xffffffffULL);
diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h
index c66b9079..ee03c3b1 100644
--- a/include/ZeroTierOne.h
+++ b/include/ZeroTierOne.h
@@ -634,24 +634,29 @@ enum ZT_VirtualNetworkRuleType
ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE = 50,
/**
+ * Random match with selectable probability
+ */
+ ZT_NETWORK_RULE_MATCH_RANDOM = 51,
+
+ /**
* Match if local and remote tags differ by no more than value, use 0 to check for equality
*/
- ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE = 51,
+ ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE = 52,
/**
* Match if local and remote tags ANDed together equal value.
*/
- ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND = 52,
+ ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND = 53,
/**
* Match if local and remote tags ANDed together equal value.
*/
- ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR = 53,
+ ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR = 54,
/**
* Match if local and remote tags XORed together equal value.
*/
- ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR = 54,
+ ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR = 55,
/**
* Maximum ID allowed for a MATCH entry in the rules table
@@ -721,6 +726,11 @@ typedef struct
uint64_t zt;
/**
+ * 0 = never, UINT32_MAX = always
+ */
+ uint32_t randomProbability;
+
+ /**
* 48-bit Ethernet MAC address in big-endian order
*/
uint8_t mac[6];
diff --git a/node/Capability.hpp b/node/Capability.hpp
index 2cf54b5c..e808ad40 100644
--- a/node/Capability.hpp
+++ b/node/Capability.hpp
@@ -249,6 +249,10 @@ public:
b.append((uint16_t)rules[i].v.frameSize[0]);
b.append((uint16_t)rules[i].v.frameSize[1]);
break;
+ case ZT_NETWORK_RULE_MATCH_RANDOM:
+ b.append((uint8_t)4);
+ b.append((uint32_t)rules[i].v.randomProbability);
+ break;
case ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE:
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND:
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
@@ -331,6 +335,9 @@ public:
rules[ruleCount].v.frameSize[0] = b.template at<uint16_t>(p);
rules[ruleCount].v.frameSize[1] = b.template at<uint16_t>(p + 2);
break;
+ case ZT_NETWORK_RULE_MATCH_RANDOM:
+ rules[ruleCount].v.randomProbability = b.template at<uint32_t>(p);
+ break;
case ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE:
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND:
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
diff --git a/node/Network.cpp b/node/Network.cpp
index d38a3fdd..fe899dcc 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -504,6 +504,10 @@ static _doZtFilterResult _doZtFilter(
thisRuleMatches = (uint8_t)((frameLen >= (unsigned int)rules[rn].v.frameSize[0])&&(frameLen <= (unsigned int)rules[rn].v.frameSize[1]));
FILTER_TRACE("%u %s %c %u in %u-%u -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),frameLen,(unsigned int)rules[rn].v.frameSize[0],(unsigned int)rules[rn].v.frameSize[1],(unsigned int)thisRuleMatches);
break;
+ case ZT_NETWORK_RULE_MATCH_RANDOM:
+ thisRuleMatches = (uint8_t)((uint32_t)(RR->node->prng() & 0xffffffffULL) <= rules[rn].v.randomProbability);
+ FILTER_TRACE("%u %s %c -> %u",rn,_rtn(rt),(((rules[rn].t & 0x80) != 0) ? '!' : '='),(unsigned int)thisRuleMatches);
+ break;
case ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE:
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND:
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR: