Small refactoring; Split horizon loop break.
This commit is contained in:
		| @@ -264,7 +264,7 @@ func (n *network) processNetChan(client transport.Client, listener tunnel.Listen | |||||||
| 				} | 				} | ||||||
| 				if ok := n.node.AddPeer(peer); !ok { | 				if ok := n.node.AddPeer(peer); !ok { | ||||||
| 					log.Debugf("Network peer exists, refreshing: %s", peer.id) | 					log.Debugf("Network peer exists, refreshing: %s", peer.id) | ||||||
| 					// update lastSeen time for the peer | 					// update lastSeen time for the existing node | ||||||
| 					if ok := n.RefreshPeer(peer.id, now); !ok { | 					if ok := n.RefreshPeer(peer.id, now); !ok { | ||||||
| 						log.Debugf("Network failed refreshing peer: %s", peer.id) | 						log.Debugf("Network failed refreshing peer: %s", peer.id) | ||||||
| 					} | 					} | ||||||
| @@ -314,7 +314,7 @@ func (n *network) processNetChan(client transport.Client, listener tunnel.Listen | |||||||
| 				if ok := n.RefreshPeer(pbNetPeer.Node.Id, now); !ok { | 				if ok := n.RefreshPeer(pbNetPeer.Node.Id, now); !ok { | ||||||
| 					log.Debugf("Network failed refreshing peer: %s", pbNetPeer.Node.Id) | 					log.Debugf("Network failed refreshing peer: %s", pbNetPeer.Node.Id) | ||||||
| 				} | 				} | ||||||
| 				// NOTE: we don't uunpack MaxDepth toplogy | 				// NOTE: we don't unpack MaxDepth toplogy | ||||||
| 				peer = UnpackPeerTopology(pbNetPeer, now, MaxDepth-1) | 				peer = UnpackPeerTopology(pbNetPeer, now, MaxDepth-1) | ||||||
| 				log.Debugf("Network updating topology of node: %s", n.node.id) | 				log.Debugf("Network updating topology of node: %s", n.node.id) | ||||||
| 				if ok := n.node.UpdatePeer(peer); !ok { | 				if ok := n.node.UpdatePeer(peer); !ok { | ||||||
| @@ -539,34 +539,23 @@ func (n *network) processCtrlChan(client transport.Client, listener tunnel.Liste | |||||||
| 				if pbRtrAdvert.Id == n.options.Id { | 				if pbRtrAdvert.Id == n.options.Id { | ||||||
| 					continue | 					continue | ||||||
| 				} | 				} | ||||||
| 				log.Debugf("Network received advert message from: %s", pbRtrAdvert.Id) | 				log.Debugf("Network received advert message with %d events from: %s", len(pbRtrAdvert.Events), pbRtrAdvert.Id) | ||||||
| 				// loookup advertising node in our peers | 				// loookup advertising node in our peer topology | ||||||
| 				advertNode := n.node.GetPeer(pbRtrAdvert.Id) | 				advertNode := n.node.GetPeerNode(pbRtrAdvert.Id) | ||||||
| 				// if we dont recognize the node as our peer we skip processing its adverts |  | ||||||
| 				if advertNode == nil { | 				if advertNode == nil { | ||||||
|  | 					// if we can't find the node in our topology (MaxDepth) we skipp prcessing adverts | ||||||
| 					log.Debugf("Network skipping advert message from unknown peer: %s", pbRtrAdvert.Id) | 					log.Debugf("Network skipping advert message from unknown peer: %s", pbRtrAdvert.Id) | ||||||
| 					continue | 					continue | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				var events []*router.Event | 				var events []*router.Event | ||||||
| 				for _, event := range pbRtrAdvert.Events { | 				for _, event := range pbRtrAdvert.Events { | ||||||
| 					// set the address of the advertising node |  | ||||||
| 					// we know Route.Gateway is the address of advertNode |  | ||||||
| 					// NOTE: this is true only when advertNode had not been registered |  | ||||||
| 					// as our peer when we received the advert from it |  | ||||||
| 					if advertNode.address == "" { |  | ||||||
| 						advertNode.address = event.Route.Gateway |  | ||||||
| 						if ok := n.node.UpdatePeer(advertNode); !ok { |  | ||||||
| 							log.Debugf("Network failed to update peer: %s", advertNode.id) |  | ||||||
| 							continue |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 					// if advertising node id is not the same as Route.Router |  | ||||||
| 					// we know the advertising node is not the origin of the route | 					// we know the advertising node is not the origin of the route | ||||||
| 					if advertNode.id != event.Route.Router { | 					if pbRtrAdvert.Id != event.Route.Router { | ||||||
| 						// if the origin router is not the advertising node peer | 						// if the origin router is not the advertising node peer | ||||||
| 						// we can't rule out potential routing loops so we bail here | 						// we can't rule out potential routing loops so we bail here | ||||||
| 						if peer := advertNode.GetPeer(event.Route.Router); peer == nil { | 						if !advertNode.HasPeer(event.Route.Router) { | ||||||
|  | 							log.Debugf("Network skipping advert message from peer: %s", pbRtrAdvert.Id) | ||||||
| 							continue | 							continue | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| @@ -676,14 +665,13 @@ func (n *network) advertise(client transport.Client, advertChan <-chan *router.A | |||||||
|  |  | ||||||
| // Connect connects the network | // Connect connects the network | ||||||
| func (n *network) Connect() error { | func (n *network) Connect() error { | ||||||
| 	n.RLock() | 	n.Lock() | ||||||
| 	// return if already connected | 	// return if already connected | ||||||
| 	if n.connected { | 	if n.connected { | ||||||
| 		n.RUnlock() | 		n.Unlock() | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	n.Lock() |  | ||||||
| 	// try to resolve network nodes | 	// try to resolve network nodes | ||||||
| 	nodes, err := n.resolveNodes() | 	nodes, err := n.resolveNodes() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -831,8 +819,6 @@ func (n *network) Close() error { | |||||||
| 		// unlock the lock otherwise we'll deadlock sending the close | 		// unlock the lock otherwise we'll deadlock sending the close | ||||||
| 		n.Unlock() | 		n.Unlock() | ||||||
|  |  | ||||||
| 		// send close message only if we managed to connect to NetworkChannel |  | ||||||
| 		log.Debugf("Sending close message from: %s", n.options.Id) |  | ||||||
| 		msg := &pbNet.Close{ | 		msg := &pbNet.Close{ | ||||||
| 			Node: &pbNet.Node{ | 			Node: &pbNet.Node{ | ||||||
| 				Id:      n.options.Id, | 				Id:      n.options.Id, | ||||||
|   | |||||||
							
								
								
									
										114
									
								
								network/node.go
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								network/node.go
									
									
									
									
									
								
							| @@ -43,7 +43,7 @@ func (n *node) Network() Network { | |||||||
| 	return n.network | 	return n.network | ||||||
| } | } | ||||||
|  |  | ||||||
| // AddPeer adds a new peer to node | // AddPeer adds a new peer to node topology | ||||||
| // It returns false if the peer already exists | // It returns false if the peer already exists | ||||||
| func (n *node) AddPeer(peer *node) bool { | func (n *node) AddPeer(peer *node) bool { | ||||||
| 	n.Lock() | 	n.Lock() | ||||||
| @@ -57,33 +57,6 @@ func (n *node) AddPeer(peer *node) bool { | |||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  |  | ||||||
| // GetPeer returns a peer if it exists |  | ||||||
| // It returns nil if the peer was not found |  | ||||||
| func (n *node) GetPeer(id string) *node { |  | ||||||
| 	n.RLock() |  | ||||||
| 	defer n.RUnlock() |  | ||||||
|  |  | ||||||
| 	p, ok := n.peers[id] |  | ||||||
| 	if !ok { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	peer := &node{ |  | ||||||
| 		id:       p.id, |  | ||||||
| 		address:  p.address, |  | ||||||
| 		peers:    make(map[string]*node), |  | ||||||
| 		network:  p.network, |  | ||||||
| 		lastSeen: p.lastSeen, |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// TODO: recursively retrieve all of its peers |  | ||||||
| 	for id, pop := range p.peers { |  | ||||||
| 		peer.peers[id] = pop |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return peer |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // UpdatePeer updates a peer if it exists | // UpdatePeer updates a peer if it exists | ||||||
| // It returns false if the peer does not exist | // It returns false if the peer does not exist | ||||||
| func (n *node) UpdatePeer(peer *node) bool { | func (n *node) UpdatePeer(peer *node) bool { | ||||||
| @@ -106,7 +79,17 @@ func (n *node) DeletePeer(id string) { | |||||||
| 	delete(n.peers, id) | 	delete(n.peers, id) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Refresh updates node timestamp | // HasPeer returns true if node has peer with given id | ||||||
|  | func (n *node) HasPeer(id string) bool { | ||||||
|  | 	n.RLock() | ||||||
|  | 	defer n.RUnlock() | ||||||
|  |  | ||||||
|  | 	_, ok := n.peers[id] | ||||||
|  | 	return ok | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // RefreshPeer updates node timestamp | ||||||
|  | // It returns false if the peer has not been found. | ||||||
| func (n *node) RefreshPeer(id string, now time.Time) bool { | func (n *node) RefreshPeer(id string, now time.Time) bool { | ||||||
| 	n.Lock() | 	n.Lock() | ||||||
| 	defer n.Unlock() | 	defer n.Unlock() | ||||||
| @@ -123,13 +106,7 @@ func (n *node) RefreshPeer(id string, now time.Time) bool { | |||||||
| 	return true | 	return true | ||||||
| } | } | ||||||
|  |  | ||||||
| // Nodes returns a slice if all nodes in node topology | func (n *node) walk(until func(peer *node) bool) map[string]*node { | ||||||
| func (n *node) Nodes() []Node { |  | ||||||
| 	// we need to freeze the network graph here |  | ||||||
| 	// otherwise we might get inconsisten results |  | ||||||
| 	n.RLock() |  | ||||||
| 	defer n.RUnlock() |  | ||||||
|  |  | ||||||
| 	// track the visited nodes | 	// track the visited nodes | ||||||
| 	visited := make(map[string]*node) | 	visited := make(map[string]*node) | ||||||
| 	// queue of the nodes to visit | 	// queue of the nodes to visit | ||||||
| @@ -151,11 +128,31 @@ func (n *node) Nodes() []Node { | |||||||
| 				visited[id] = node | 				visited[id] = node | ||||||
| 				queue.PushBack(node) | 				queue.PushBack(node) | ||||||
| 			} | 			} | ||||||
|  | 			if until(node) { | ||||||
|  | 				return visited | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		// remove the node from the queue | 		// remove the node from the queue | ||||||
| 		queue.Remove(qnode) | 		queue.Remove(qnode) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	return visited | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Nodes returns a slice if all nodes in node topology | ||||||
|  | func (n *node) Nodes() []Node { | ||||||
|  | 	// we need to freeze the network graph here | ||||||
|  | 	// otherwise we might get inconsisten results | ||||||
|  | 	n.RLock() | ||||||
|  | 	defer n.RUnlock() | ||||||
|  |  | ||||||
|  | 	// NOTE: this should never be true | ||||||
|  | 	untilNoMorePeers := func(n *node) bool { | ||||||
|  | 		return n == nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	visited := n.walk(untilNoMorePeers) | ||||||
|  |  | ||||||
| 	var nodes []Node | 	var nodes []Node | ||||||
| 	// collect all the nodes and return them | 	// collect all the nodes and return them | ||||||
| 	for _, node := range visited { | 	for _, node := range visited { | ||||||
| @@ -165,8 +162,34 @@ func (n *node) Nodes() []Node { | |||||||
| 	return nodes | 	return nodes | ||||||
| } | } | ||||||
|  |  | ||||||
| // topology returns node topology down to given depth | // GetPeerNode returns a peer from node topology i.e. up to MaxDepth | ||||||
| func (n *node) topology(depth uint) *node { | // It returns nil if the peer was not found in the node topology | ||||||
|  | func (n *node) GetPeerNode(id string) *node { | ||||||
|  | 	n.RLock() | ||||||
|  | 	defer n.RUnlock() | ||||||
|  |  | ||||||
|  | 	// get node topology up to MaxDepth | ||||||
|  | 	top := n.Topology(MaxDepth) | ||||||
|  |  | ||||||
|  | 	untilFoundPeer := func(n *node) bool { | ||||||
|  | 		return n.id == id | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	visited := top.walk(untilFoundPeer) | ||||||
|  |  | ||||||
|  | 	peerNode, ok := visited[id] | ||||||
|  | 	if !ok { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return peerNode | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Topology returns a copy of th node topology down to given depth | ||||||
|  | func (n *node) Topology(depth uint) *node { | ||||||
|  | 	n.RLock() | ||||||
|  | 	defer n.RUnlock() | ||||||
|  |  | ||||||
| 	// make a copy of yourself | 	// make a copy of yourself | ||||||
| 	node := &node{ | 	node := &node{ | ||||||
| 		id:       n.id, | 		id:       n.id, | ||||||
| @@ -186,7 +209,7 @@ func (n *node) topology(depth uint) *node { | |||||||
|  |  | ||||||
| 	// iterate through our peers and update the node peers | 	// iterate through our peers and update the node peers | ||||||
| 	for _, peer := range n.peers { | 	for _, peer := range n.peers { | ||||||
| 		nodePeer := peer.topology(depth) | 		nodePeer := peer.Topology(depth) | ||||||
| 		if _, ok := node.peers[nodePeer.id]; !ok { | 		if _, ok := node.peers[nodePeer.id]; !ok { | ||||||
| 			node.peers[nodePeer.id] = nodePeer | 			node.peers[nodePeer.id] = nodePeer | ||||||
| 		} | 		} | ||||||
| @@ -195,15 +218,16 @@ func (n *node) topology(depth uint) *node { | |||||||
| 	return node | 	return node | ||||||
| } | } | ||||||
|  |  | ||||||
| // Peers returns node peers | // Peers returns node peers up to MaxDepth | ||||||
| func (n *node) Peers() []Node { | func (n *node) Peers() []Node { | ||||||
| 	n.RLock() | 	n.RLock() | ||||||
|  | 	defer n.RUnlock() | ||||||
|  |  | ||||||
| 	var peers []Node | 	var peers []Node | ||||||
| 	for _, nodePeer := range n.peers { | 	for _, nodePeer := range n.peers { | ||||||
| 		peer := nodePeer.topology(MaxDepth) | 		peer := nodePeer.Topology(MaxDepth) | ||||||
| 		peers = append(peers, peer) | 		peers = append(peers, peer) | ||||||
| 	} | 	} | ||||||
| 	n.RUnlock() |  | ||||||
|  |  | ||||||
| 	return peers | 	return peers | ||||||
| } | } | ||||||
| @@ -236,7 +260,7 @@ func UnpackPeerTopology(pbPeer *pb.Peer, lastSeen time.Time, depth uint) *node { | |||||||
| 	return peerNode | 	return peerNode | ||||||
| } | } | ||||||
|  |  | ||||||
| func peerTopology(peer Node, depth uint) *pb.Peer { | func peerProtoTopology(peer Node, depth uint) *pb.Peer { | ||||||
| 	node := &pb.Node{ | 	node := &pb.Node{ | ||||||
| 		Id:      peer.Id(), | 		Id:      peer.Id(), | ||||||
| 		Address: peer.Address(), | 		Address: peer.Address(), | ||||||
| @@ -257,7 +281,7 @@ func peerTopology(peer Node, depth uint) *pb.Peer { | |||||||
|  |  | ||||||
| 	// iterate through peers of peers aka pops | 	// iterate through peers of peers aka pops | ||||||
| 	for _, pop := range peer.Peers() { | 	for _, pop := range peer.Peers() { | ||||||
| 		peer := peerTopology(pop, depth) | 		peer := peerProtoTopology(pop, depth) | ||||||
| 		pbPeers.Peers = append(pbPeers.Peers, peer) | 		pbPeers.Peers = append(pbPeers.Peers, peer) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -278,7 +302,7 @@ func PeersToProto(node Node, depth uint) *pb.Peer { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, peer := range node.Peers() { | 	for _, peer := range node.Peers() { | ||||||
| 		pbPeer := peerTopology(peer, depth) | 		pbPeer := peerProtoTopology(peer, depth) | ||||||
| 		pbPeers.Peers = append(pbPeers.Peers, pbPeer) | 		pbPeers.Peers = append(pbPeers.Peers, pbPeer) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -117,6 +117,12 @@ func TestNodes(t *testing.T) { | |||||||
| 			t.Errorf("Expected to find %s node", node.Id()) | 			t.Errorf("Expected to find %s node", node.Id()) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// this is a leaf node | ||||||
|  | 	id := "peer11" | ||||||
|  | 	if nodePeer := node.GetPeerNode(id); nodePeer == nil { | ||||||
|  | 		t.Errorf("Expected to find %s node", id) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func collectPeerIds(peer Node, ids map[string]bool) map[string]bool { | func collectPeerIds(peer Node, ids map[string]bool) map[string]bool { | ||||||
|   | |||||||
| @@ -337,6 +337,7 @@ func (r *router) advertiseTable() error { | |||||||
|  |  | ||||||
| 			// advertise all routes as Update events to subscribers | 			// advertise all routes as Update events to subscribers | ||||||
| 			if len(events) > 0 { | 			if len(events) > 0 { | ||||||
|  | 				log.Debugf("Network router flushing table with %d events: %s", len(events), r.options.Id) | ||||||
| 				r.advertWg.Add(1) | 				r.advertWg.Add(1) | ||||||
| 				go r.publishAdvert(RouteUpdate, events) | 				go r.publishAdvert(RouteUpdate, events) | ||||||
| 			} | 			} | ||||||
| @@ -668,11 +669,13 @@ func (r *router) Process(a *Advert) error { | |||||||
| 	for _, event := range events { | 	for _, event := range events { | ||||||
| 		// skip if the router is the origin of this route | 		// skip if the router is the origin of this route | ||||||
| 		if event.Route.Router == r.options.Id { | 		if event.Route.Router == r.options.Id { | ||||||
|  | 			log.Debugf("Network router skipping processing its own route: %s", r.options.Id) | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		// create a copy of the route | 		// create a copy of the route | ||||||
| 		route := event.Route | 		route := event.Route | ||||||
| 		action := event.Type | 		action := event.Type | ||||||
|  | 		log.Debugf("Network router processing route action %s: %s", action, r.options.Id) | ||||||
| 		if err := r.manageRoute(route, fmt.Sprintf("%s", action)); err != nil { | 		if err := r.manageRoute(route, fmt.Sprintf("%s", action)); err != nil { | ||||||
| 			return fmt.Errorf("failed applying action %s to routing table: %s", action, err) | 			return fmt.Errorf("failed applying action %s to routing table: %s", action, err) | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -110,8 +110,12 @@ func (t *table) Update(r Route) error { | |||||||
| 	if _, ok := t.routes[service][sum]; !ok { | 	if _, ok := t.routes[service][sum]; !ok { | ||||||
| 		t.routes[service][sum] = r | 		t.routes[service][sum] = r | ||||||
| 		go t.sendEvent(&Event{Type: Update, Timestamp: time.Now(), Route: r}) | 		go t.sendEvent(&Event{Type: Update, Timestamp: time.Now(), Route: r}) | ||||||
|  | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	t.routes[service][sum] = r | ||||||
|  | 	go t.sendEvent(&Event{Type: Update, Timestamp: time.Now(), Route: r}) | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user