Explorar el Código

Moderate efficiency improvement on multicast gather result parsing, and go ahead and keep track of total known peers.

Adam Ierymenko hace 11 años
padre
commit
22d8aa4dc9
Se han modificado 3 ficheros con 37 adiciones y 20 borrados
  1. 2 13
      node/IncomingPacket.cpp
  2. 16 4
      node/Multicaster.cpp
  3. 19 3
      node/Multicaster.hpp

+ 2 - 13
node/IncomingPacket.cpp

@@ -892,20 +892,9 @@ void IncomingPacket::_sendErrorNeedCertificate(const RuntimeEnvironment *RR,cons
 
 void IncomingPacket::_parseGatherResults(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer,uint64_t nwid,const MulticastGroup &mg,unsigned int offset)
 {
-	//unsigned int totalKnown = at<uint32_t>(offset);
+	unsigned int totalKnown = at<uint32_t>(offset);
 	unsigned int count = at<uint16_t>(offset + 4);
-	const unsigned char *p = (const unsigned char *)data() + offset + 6;
-	const unsigned char *e = (const unsigned char *)data() + size();
-	Address atmp;
-	uint64_t now = Utils::now();
-	for(unsigned int i=0;i<count;++i) {
-		const unsigned char *n = p + ZT_ADDRESS_LENGTH;
-		if (n > e)
-			break;
-		atmp.setTo(p,ZT_ADDRESS_LENGTH);
-		RR->mc->add(now,nwid,mg,peer->address(),atmp);
-		p = n;
-	}
+	RR->mc->addMultiple(Utils::now(),nwid,mg,peer->address(),field(offset + 6,count * 5),count,totalKnown);
 }
 
 } // namespace ZeroTier

+ 16 - 4
node/Multicaster.cpp

@@ -52,6 +52,20 @@ Multicaster::~Multicaster()
 {
 }
 
+void Multicaster::addMultiple(uint64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &learnedFrom,const void *addresses,unsigned int count,unsigned int totalKnown)
+{
+	const unsigned char *p = (const unsigned char *)addresses;
+	const unsigned char *e = p + (5 * count);
+	Mutex::Lock _l(_groups_m);
+	MulticastGroupStatus &gs = _groups[std::pair<uint64_t,MulticastGroup>(nwid,mg)];
+	while (p != e) {
+		_add(now,nwid,mg,gs,learnedFrom,Address(p,5));
+		p += 5;
+	}
+	if (RR->topology->isSupernode(learnedFrom))
+		gs.totalKnownMembers = totalKnown;
+}
+
 unsigned int Multicaster::gather(const Address &queryingPeer,uint64_t nwid,const MulticastGroup &mg,Packet &appendTo,unsigned int limit) const
 {
 	unsigned char *p;
@@ -337,7 +351,7 @@ void Multicaster::clean(uint64_t now)
 				 * learned peers. For peers with no active Peer record, we use the time we last learned
 				 * about them minus one day (a large constant) to put these at the bottom of the list.
 				 * List is sorted in ascending order of rank and multicasts are sent last-to-first. */
-				if (writer->learnedFrom) {
+				if (writer->learnedFrom != writer->address) {
 					SharedPtr<Peer> p(RR->topology->getPeer(writer->learnedFrom));
 					if (p)
 						writer->rank = (RR->topology->amSupernode() ? p->lastDirectReceive() : p->lastUnicastFrame()) - ZT_MULTICAST_LIKE_EXPIRE;
@@ -381,9 +395,7 @@ void Multicaster::_add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,Multi
 	// Update timestamp and learnedFrom if existing
 	for(std::vector<MulticastGroupMember>::iterator m(gs.members.begin());m!=gs.members.end();++m) {
 		if (m->address == member) {
-			// learnedFrom is NULL (zero) if we've learned this directly via MULTICAST_LIKE, at which
-			// point this becomes a first-order connection.
-			if (m->learnedFrom)
+			if (m->learnedFrom != member) // once we learn it directly, remember this forever
 				m->learnedFrom = learnedFrom;
 			m->timestamp = now;
 			return;

+ 19 - 3
node/Multicaster.hpp

@@ -62,7 +62,7 @@ private:
 		MulticastGroupMember(const Address &a,const Address &lf,uint64_t ts) : address(a),learnedFrom(lf),timestamp(ts),rank(0) {}
 
 		Address address;
-		Address learnedFrom; // NULL/0 for addresses directly learned from LIKE
+		Address learnedFrom;
 		uint64_t timestamp; // time of last LIKE/OK(GATHER)
 		uint64_t rank; // used by sorting algorithm in clean()
 
@@ -72,9 +72,10 @@ private:
 
 	struct MulticastGroupStatus
 	{
-		MulticastGroupStatus() : lastExplicitGather(0) {}
+		MulticastGroupStatus() : lastExplicitGather(0),totalKnownMembers(0) {}
 
 		uint64_t lastExplicitGather;
+		unsigned int totalKnownMembers; // 0 if unknown
 		std::list<OutboundMulticast> txQueue; // pending outbound multicasts
 		std::vector<MulticastGroupMember> members; // members of this group
 	};
@@ -89,7 +90,7 @@ public:
 	 * @param now Current time
 	 * @param nwid Network ID
 	 * @param mg Multicast group
-	 * @param learnedFrom Address from which we learned this member or NULL/0 Address if direct
+	 * @param learnedFrom Address from which we learned this member
 	 * @param member New member address
 	 */
 	inline void add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &learnedFrom,const Address &member)
@@ -98,6 +99,21 @@ public:
 		_add(now,nwid,mg,_groups[std::pair<uint64_t,MulticastGroup>(nwid,mg)],learnedFrom,member);
 	}
 
+	/**
+	 * Add multiple addresses from a binary array of 5-byte address fields
+	 *
+	 * It's up to the caller to check bounds on the array before calling this.
+	 *
+	 * @param now Current time
+	 * @param nwid Network ID
+	 * @param mg Multicast group
+	 * @param learnedFrom Peer from which we received this list
+	 * @param addresses Raw binary addresses in big-endian format, as a series of 5-byte fields
+	 * @param count Number of addresses
+	 * @param totalKnown Total number of known addresses as reported by peer
+	 */
+	void addMultiple(uint64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &learnedFrom,const void *addresses,unsigned int count,unsigned int totalKnown);
+
 	/**
 	 * Append gather results to a packet by choosing registered multicast recipients at random
 	 *