diff --git a/docs/architecture.txt b/docs/architecture.txt index f2cfb3b3..a237de61 100644 --- a/docs/architecture.txt +++ b/docs/architecture.txt @@ -1,5 +1,5 @@ Router: - - Starts Topology + - Starts Routes - Starts Connection Maker - Starts TCP Listener - Starts UDP Listener @@ -17,9 +17,9 @@ Router: frames and forwards them to a local peer (or peers) (router.Sniff / router.handleCapturedPacket) -- Topology +- Routes Maintains unicast and broadcast routing tables which can be read - directly from any thread by just obtaining a readlock on topology. + directly from any thread by just obtaining a read lock on Routes. - Unicast answers the question "If I want to send a packet to peer X, which of the peers I'm connected to should I send the packet to?" @@ -27,7 +27,7 @@ Router: the time it reaches me, which of my connected peers is X expecting me to pass the packet to?" Also spawns a thread which runs an actor loop, responding to - requests to encode all peers, or rebuild the routing tables. + requests to rebuild the routing tables. - Connection Maker Spawns a thread which runs an actor loop. This actor loop is passed @@ -55,7 +55,7 @@ Router: router udp listener processes to send traffic to neighbouring peers. This is done directly with read locks. In these methods, we inspect the unicast and broadcast routing tables as generated by - Topology. + Routes. - Connections The connection life cycle is as follows: diff --git a/router/connection.go b/router/connection.go index 0bf360ef..f03d3b9c 100644 --- a/router/connection.go +++ b/router/connection.go @@ -506,7 +506,7 @@ func (conn *LocalConnection) receiveTCP(decoder *gob.Decoder, usingPassword bool return } if len(newUpdate) != 0 { - conn.Router.Topology.RebuildRoutes() + conn.Router.Routes.Recalculate() conn.local.BroadcastTCP(Concat(ProtocolUpdateByte, newUpdate)) } } else if msg[0] == ProtocolPMTUVerified { diff --git a/router/peer.go b/router/peer.go index b27e621d..1298b475 100644 --- a/router/peer.go +++ b/router/peer.go @@ -151,7 +151,7 @@ func (peer *Peer) Broadcast(df bool, frame []byte, dec *EthernetDecoder) error { } func (peer *Peer) Relay(srcPeer, dstPeer *Peer, df bool, frame []byte, dec *EthernetDecoder) error { - relayPeerName, found := peer.Router.Topology.Unicast(dstPeer.Name) + relayPeerName, found := peer.Router.Routes.Unicast(dstPeer.Name) if !found { // Not necessarily an error as there could be a race with the // dst disappearing whilst the frame is in flight @@ -172,7 +172,7 @@ func (peer *Peer) Relay(srcPeer, dstPeer *Peer, df bool, frame []byte, dec *Ethe } func (peer *Peer) RelayBroadcast(srcPeer *Peer, df bool, frame []byte, dec *EthernetDecoder) error { - nextHops := peer.Router.Topology.Broadcast(srcPeer.Name) + nextHops := peer.Router.Routes.Broadcast(srcPeer.Name) if len(nextHops) == 0 { return nil } @@ -395,7 +395,7 @@ func (peer *Peer) handleBroadcastTCP(msg []byte) { } func (peer *Peer) broadcastPeerUpdate(peers ...*Peer) { - peer.Router.Topology.RebuildRoutes() + peer.Router.Routes.Recalculate() peer.handleBroadcastTCP(Concat(ProtocolUpdateByte, EncodePeers(append(peers, peer)...))) } diff --git a/router/router.go b/router/router.go index 7ca8a306..2eb3b7e5 100644 --- a/router/router.go +++ b/router/router.go @@ -53,7 +53,7 @@ func (router *Router) Start() { po, err := NewPcapO(router.Iface.Name) checkFatal(err) router.ConnectionMaker = StartConnectionMaker(router) - router.Topology = StartTopology(router) + router.Routes = StartRoutes(router) router.UDPListener = router.listenUDP(Port, po) router.listenTCP(Port) router.sniff(pio) @@ -65,7 +65,7 @@ func (router *Router) Status() string { buf.WriteString(fmt.Sprintln("Sniffing traffic on", router.Iface)) buf.WriteString(fmt.Sprintf("MACs:\n%s", router.Macs)) buf.WriteString(fmt.Sprintf("Peers:\n%s", router.Peers)) - buf.WriteString(fmt.Sprintf("Topology:\n%s", router.Topology)) + buf.WriteString(fmt.Sprintf("Routes:\n%s", router.Routes)) buf.WriteString(fmt.Sprintf("Reconnects:\n%s", router.ConnectionMaker)) return buf.String() } diff --git a/router/topology.go b/router/routes.go similarity index 64% rename from router/topology.go rename to router/routes.go index 02c3dcbf..2f42bec4 100644 --- a/router/topology.go +++ b/router/routes.go @@ -4,43 +4,52 @@ import ( "bytes" "fmt" "log" + "sync" ) -func (topo *Topology) Unicast(name PeerName) (PeerName, bool) { - topo.RLock() - defer topo.RUnlock() - hop, found := topo.unicast[name] +type Routes struct { + sync.RWMutex + queryChan chan<- *Interaction + unicast map[PeerName]PeerName + broadcast map[PeerName][]PeerName + router *Router +} + +func (routes *Routes) Unicast(name PeerName) (PeerName, bool) { + routes.RLock() + defer routes.RUnlock() + hop, found := routes.unicast[name] return hop, found } -func (topo *Topology) Broadcast(name PeerName) []PeerName { - topo.RLock() - defer topo.RUnlock() - hops, found := topo.broadcast[name] +func (routes *Routes) Broadcast(name PeerName) []PeerName { + routes.RLock() + defer routes.RUnlock() + hops, found := routes.broadcast[name] if !found { return []PeerName{} } return hops } -func (topo *Topology) String() string { +func (routes *Routes) String() string { var buf bytes.Buffer - topo.RLock() - defer topo.RUnlock() + routes.RLock() + defer routes.RUnlock() buf.WriteString(fmt.Sprintln("unicast:")) - for name, hop := range topo.unicast { + for name, hop := range routes.unicast { buf.WriteString(fmt.Sprintf("%s -> %s\n", name, hop)) } buf.WriteString(fmt.Sprintln("broadcast:")) - for name, hops := range topo.broadcast { + for name, hops := range routes.broadcast { buf.WriteString(fmt.Sprintf("%s -> %v\n", name, hops)) } return buf.String() } -func StartTopology(router *Router) *Topology { +func StartRoutes(router *Router) *Routes { queryChan := make(chan *Interaction, ChannelSize) - state := &Topology{ + state := &Routes{ router: router, queryChan: queryChan, unicast: make(map[PeerName]PeerName), @@ -54,32 +63,32 @@ func StartTopology(router *Router) *Topology { // ACTOR client API const ( - TRebuildRoutes = iota + RRecalculate = iota ) // Async. -func (topo *Topology) RebuildRoutes() { - topo.queryChan <- &Interaction{code: TRebuildRoutes} +func (routes *Routes) Recalculate() { + routes.queryChan <- &Interaction{code: RRecalculate} } // ACTOR server -func (topo *Topology) queryLoop(queryChan <-chan *Interaction) { +func (routes *Routes) queryLoop(queryChan <-chan *Interaction) { for { query, ok := <-queryChan if !ok { return } switch query.code { - case TRebuildRoutes: - unicast := topo.buildUnicastRoutes() - broadcast := topo.buildBroadcastRoutes() - topo.Lock() - topo.unicast = unicast - topo.broadcast = broadcast - topo.Unlock() + case RRecalculate: + unicast := routes.calculateUnicast() + broadcast := routes.calculateBroadcast() + routes.Lock() + routes.unicast = unicast + routes.broadcast = broadcast + routes.Unlock() default: - log.Fatal("Unexpected topology query:", query) + log.Fatal("Unexpected routes query:", query) } } } @@ -93,9 +102,9 @@ func (topo *Topology) queryLoop(queryChan <-chan *Interaction) { // any knowledge of the MAC address at all. Thus there's no need // to exchange knowledge of MAC addresses, nor any constraints on // the routes that we construct. -func (topo *Topology) buildUnicastRoutes() map[PeerName]PeerName { - _, routes := topo.router.Ourself.Routes(nil, true) - return routes +func (routes *Routes) calculateUnicast() map[PeerName]PeerName { + _, unicast := routes.router.Ourself.Routes(nil, true) + return unicast } // Calculate all the routes for the question: if we receive a @@ -116,11 +125,11 @@ func (topo *Topology) buildUnicastRoutes() map[PeerName]PeerName { // Y =/= Z /\ X.Routes(Y) <= X.Routes(Z) => // X.Routes(Y) u [P | Y.HasSymmetricConnectionTo(P)] <= X.Routes(Z) // where <= is the subset relationship on keys of the returned map. -func (topo *Topology) buildBroadcastRoutes() map[PeerName][]PeerName { +func (routes *Routes) calculateBroadcast() map[PeerName][]PeerName { broadcast := make(map[PeerName][]PeerName) - ourself := topo.router.Ourself + ourself := routes.router.Ourself - topo.router.Peers.ForEach(func(name PeerName, peer *Peer) { + routes.router.Peers.ForEach(func(name PeerName, peer *Peer) { hops := []PeerName{} if found, reached := peer.Routes(ourself, true); found { ourself.ForEachConnection(func(remoteName PeerName, conn Connection) { diff --git a/router/types.go b/router/types.go index 11835412..53e7e2d3 100644 --- a/router/types.go +++ b/router/types.go @@ -17,7 +17,7 @@ type Router struct { Macs *MacCache Peers *PeerCache UDPListener *net.UDPConn - Topology *Topology + Routes *Routes ConnectionMaker *ConnectionMaker Password *[]byte ConnLimit int @@ -150,14 +150,6 @@ type Interaction struct { resultChan chan<- interface{} } -type Topology struct { - sync.RWMutex - queryChan chan<- *Interaction - unicast map[PeerName]PeerName - broadcast map[PeerName][]PeerName - router *Router -} - type ConnectionMakerInteraction struct { Interaction address string diff --git a/site/troubleshooting.md b/site/troubleshooting.md index 1603b939..c1ec0f61 100644 --- a/site/troubleshooting.md +++ b/site/troubleshooting.md @@ -69,7 +69,7 @@ Peer 7a:16:dd:5b:83:de (v31) (UID 13151318985609435078) -> 7a:f4:56:87:76:3b [37.157.33.76:7195] Peer 7a:f4:56:87:76:3b (v1) (UID 6913268221365110570) -> 7a:16:dd:5b:83:de [191.235.147.190:6783] -Topology: +Routes: unicast: 7a:f4:56:87:76:3b -> 00:00:00:00:00:00 7a:16:dd:5b:83:de -> 7a:16:dd:5b:83:de @@ -105,7 +105,7 @@ number of the connection. In the above example, the local router has connected to its peer using address 191.235.147.190:6783, and its peer sees the same connection as coming from 37.157.33.76:7195. -The 'Topology' section summarised the information for deciding how to +The 'Routes' section summarised the information for deciding how to route packets between peers, which is mostly of interest when the weave network is not fully connected. See the [architecture documentation](https://raw.githubusercontent.com/zettio/weave/master/docs/architecture.txt)