public Rerr(Rerr rerr) { N = rerr.N; UnreachableDestinations = new List <UnreachableDestination>(); //Deep copy of list content foreach (var ud in rerr.UnreachableDestinations) { UnreachableDestinations.Add(new UnreachableDestination(ud)); } }
/// <summary> /// Sends a new DATA message. Looks up the next-hop in the routing table, and passes message to link-layer. /// </summary> /// <param name="msg"></param> public void SendDataMessage(Message msg) { var outgoingMessage = new Message(msg); if (outgoingMessage.Type != MessageType.Data) { throw new ArgumentException("Sorry mate, DATA-messages only."); } LinkLayerResult result = null; //If this is a broadcast-packet, no table-lookup is necessary (and will fail) if (outgoingMessage.DestinationAddress == SimulationConstants.BroadcastAddress) //RREQs will always fall into this one, even those processed by me, since destination=broadcast { result = _linkLayer.SendMessage(outgoingMessage, SimulationConstants.BroadcastAddress); //Broadcasts cannot miss a neighbour } //If an active route valid for forwarding exists, find next-hop and send message if (_aodvHelper.RoutingTable.ActiveRouteExists(outgoingMessage.DestinationAddress)) { //Find route to destination, to acquire next-hop var destinationEntry = _aodvHelper.RoutingTable.GetEntry(outgoingMessage.DestinationAddress); //Update lifetime of active route to destination when it's used per section 6.2 ending. _aodvHelper.RoutingTable.SetRouteActive(destinationEntry.DestinationAddress); //Update lifetime of route to next-hop per section 6.2 ending. var nextHopRoute = _aodvHelper.RoutingTable.GetEntry(destinationEntry.NextHop); if (nextHopRoute != null) { _aodvHelper.RoutingTable.SetRouteActive(nextHopRoute.DestinationAddress); } //Update lifetime of route to originator of data (if it was not sent by me) per section 6.2 ending. if (outgoingMessage.SourceAddress != _localAddress) { var sourceRoute = _aodvHelper.RoutingTable.GetEntry(outgoingMessage.SourceAddress); if (sourceRoute != null) { _aodvHelper.RoutingTable.SetRouteActive(sourceRoute.DestinationAddress); } } //Update lifetime of route to previous hop (if it was not sent by me) per section 6.2 ending. if (outgoingMessage.PreviousHop != _localAddress) { var previousHopRoute = _aodvHelper.RoutingTable.GetEntry(outgoingMessage.PreviousHop); if (previousHopRoute != null) { _aodvHelper.RoutingTable.SetRouteActive(previousHopRoute.DestinationAddress); } } result = _linkLayer.SendMessage(outgoingMessage, destinationEntry.NextHop); //Send message along route towards destination. If it fails, routes updated above are invalidated, no worries. } //If active route does not exist, but a RREQ has been sent for this destination and are not expired yet else if (!_aodvHelper.RoutingTable.ActiveRouteExists(outgoingMessage.DestinationAddress) && _aodvHelper.RreqAttemptExist(outgoingMessage.DestinationAddress, _localAddress)) { ParkMessage(new Message(outgoingMessage)); //Park message and wait for RREP return; } //If any kind of route does NOT exist, OR existing route is invalid/expired, send a new RREQ for the destination else if (!_aodvHelper.RoutingTable.RouteExists(outgoingMessage.DestinationAddress) || (!_aodvHelper.RoutingTable.GetEntry(outgoingMessage.DestinationAddress)?.Valid ?? true)) { ParkMessage(new Message(outgoingMessage)); _statistics.RoutingRequestGenerated(); var rreqMsg = _aodvHelper.GenerateInitialRreqMessage(outgoingMessage.DestinationAddress); _statistics.AddAodvMessageSent(rreqMsg); result = _linkLayer.SendMessage(rreqMsg, SimulationConstants.BroadcastAddress); //No need to check for missing neighbour in result } if (result.Result == LinkLayerResultType.NextHopNotFound) { //This is a clear Section 6.11 (i): Link break for next hop of active route while transmiting data (hehe) //_statistics.AddMessageDropped(e.DroppedMessage); _statistics.AddDataMessageDroppedNextHopUnavailable(result.DroppedMessage); //Get a list of all unreachable destinations, because of this link-failure. This also updates and invalidates entries in routing tables. var unreachableDestinations = _aodvHelper.RoutingTable.HandleAndGetUnreachableDestinations(result.MissingNeighbour); var rerr = new Rerr(unreachableDestinations); //If any destinations were affected by this link-failure if (unreachableDestinations.Count > 0) { //Get all nodes that use the now missing link as a part of their route var precursors = _aodvHelper.RoutingTable.GetEntry(unreachableDestinations[0].UnreachableDestinationAddress).Precursors; foreach (var precursor in precursors) { //Send RERR to precursors if any is available var rerrMsg = new Message(new Rerr(rerr), precursors[0], _localAddress, _conf.MessageTtlValue); SendAodvMessage(rerrMsg, precursor); } } } }