This section includes the implementation details for the base version of TAG described thus far.
Before each packet begins its journey, the position of its intended destination must be determined. De- pending on the type of network and destination node, the destination position may need to be obtained from a separate location service such as [LJDC+00]. If the destination is a static gateway node, however, the destination’s constant position may already be known by every node. It should be noted, as well, that TAG is able to handle stale destination positions for distant nodes. These stale destination positions are updated by TAG once the packet is within the position exchange range of the destination.
The STARTPACKETfunction initializes the shim header for a new packet at a source node. For each new
packet to be routed, the destination position and ID (Dandd) are added to the shim header, along with the source node (current node) ID. Every packet starts in GREEDY mode (M= GREEDY). The shim header is attached to the packet and then the TAGFORWARDfunction, shown below, is called.
1: functionSTARTPACKET 2: h.M= GREEDY 3: h.s= self.id 4: h.D= destination position 5: h.d= destination id 6: TAGFORWARD(h) 7: end function
TAGFORWARDis the main routing function and is called at each hop along the path. If the packet has reached its destination, the packet is delivered. Otherwise, various methods are called depending on which mode the packet is in, with each method returning the ID of the node to which the packet should be sent next. For packets in GREEDY mode, the GREEDYORREVERTTOFACEfunction is called to either send the packet to the neighbor that is nearest the destination, or revert to face routing if the current node is a local minimum. If the packet is in the FACE-FWD or FACE-REV mode, the FACECOMMONmethod is simply called (detailed later). Lastly, for packets in the FACE-RETURN mode (in which the packet is returning to
the face start node), the next node to be visited while backtracking to the face start node is determined by the RIGHTHANDFORWARDfunction. If, however, the packet has reached the face start node, the boundary circle is expanded and face routing is restarted by (EXPANDANDRESTARTFACE).
1: functionTAGFORWARD(h, incomingIf)
2: ifh.d== self.idthen
3: deliver packet
4: else
5: switchh.M
6: caseGREEDY
7: next = GREEDYORREVERTTOFACE(h)
8: caseFACE-FWD
9: next = FACECOMMON(h, incomingIf)
10: caseFACE-REV
11: next = FACECOMMON(h, incomingIf)
12: caseFACE-RETURN
13: ifh.f == self.idthen
14: next = EXPANDANDRESTARTFACE(h, IncomingIf)
15: else
16: next = RIGHTHANDFORWARD(h, false)
17: end if
18: drop packet on failure, otherwise forward to next and call TAGFORWARD 19: end if
20: end function
1: functionGREEDYORREVERTTOFACE(h)
2: next = GREEDYFORWARD(h)
3: ifnext == failurethen
4: next = STARTFACE(h)
5: end if
6: returnnext
7: end function
1: functionEXPANDANDRESTARTFACE(h, incomingIf)
2: h.r=h.r*ρ
3: returnREVERSETHEDIRECTION(h, incomingIf)
4: end function
The FACECOMMONmethod first determines the proposed next node to be visited according to the right- hand rule. If the packet is (1) in FACE-FWD mode, (2) at the face start node f, and (3) expected to visit nodee next, the packet has made a full loop around the face, and it is dropped because there is no route to the destination. If instead, the packet reaches a node that is nearer the destination than the face
1: functionGREEDYFORWARD(h)
2: N= self.directlyConnectedNeighbors+ self.id
3: nearest =g(N,h.D) .see Equation 4.1
4: ifnearest == self.idthen
5: returnfailure
6: end if
7: returnnearest
8: end function
1: functionRIGHTHANDFORWARD(h, starting)
2: ifstarting == truethen
3: previous =h.D
4: else
5: previous = position of node at previous hop
6: end if
7: current = self.position
8: N= self.directlyConnectedNeighbors
9: incomingBearing =π + atan2(previous.y-current.y, previous.x-current.x) .see Equation 4.2 10: ifh.cw== clockwisethen
11: return fr(N,incomingBearing) .see Equation 4.4
12: else
13: return fl(N,incomingBearing) .see Equation 4.5
14: end if
15: end function
1: functionREVERSETHEDIRECTION(h, incomingIf)
2: ifh.cw== clockwisethen
3: h.cw= counter-clockwise
4: else
5: h.cw= clockwise
6: end if
7: returnnode connected to incomingIf
start node, GREEDYORREVERTTOFACEis called. This method starts greedily routing unless this node is
found to be another local minimum, in which case face routing is started on the face between this node and the destination. Ignoring, for now, the highlighted code, if the proposed next node lies outside the bounding circle, then we REVERSETHEDIRECITONin which the packet is traveling (changing directions, for example, from clockwise to counter-clockwise). If the packet had been in FACE-FWD mode the mode is changed to FACE-REV mode. If instead, the packet is already in FACE-REV mode the mode is changed to FACE-RETURN. In some cases, the packet is already at the face start node so the FACE-RETURN mode is skipped and the bounding circle is immediately expanded (by multiplying it by a bounding circle increase factor) and face routing is restarted with EXPANDANDRESTARTFACE.
Other pseudocode methods are provided for completeness, but are not detailed here.
1: functionFACECOMMON(h, incomingIf)
2: next = RIGHTHANDFORWARD(h, false)
3: ifh.M== FACE-FWD and self.id==h.f and next ==h.ethen
4: returnfailure .No route to destination, drop
5: end if
6: ifDIST(self.position,h.D)<DIST(h.F,h.D)then
7: returnGREEDYORREVERTTOFACE(h) .Fall back to greedy
8: end if
9: ifINTERSECTS(F, D, self.position, next.position)then .only if intersection mode is enabled
10: returnSTARTFACE(h) 11: end if
12: ifDIST(next.position,h.D)>h.rthen
13: next = REVERSETHEDIRECTION(h, incomingIf) 14: ifh.M== FACE-FWDthen
15: h.M= FACE-REV
16: returnnext
17: end if
18: ifh.f == self.idandh.e== nextthen
19: returnEXPANDANDRESTARTFACE(h)
20: end if 21: h.M= FACE-RETURN 22: returnnext 23: end if 24: returnnext 25: end function
1: functionSTARTFACE(h) 2: h.M= FACE-FWD
3: h.f = self.id
4: h.f d= DIST(h.D, self.position)
5: h.F = self.position .used only if intersection mode is enabled
6: nearest = FINDCONNECTEDNODENEARESTPOSITION(h.D) .only if topology-aware enabled 7: h.cw= RIGHTWAYTOREACH(nearest) .if not topology-aware, always clockwise
8: h.r= SMARTRADIUS(nearest,h.D) .if not topology-aware, DIST(F,D) *ρ0 9: next = RIGHTHANDFORWARD(h, true)
10: h.e= next
11: h.tf aceStart= time.Now() 12: returnnext
13: end function