/// <summary> /// Handles an incoming HELLO packet. /// </summary> /// <param name="incomingPacket"></param> private void HandleHello(Message incomingPacket) { var hello = (Hello)incomingPacket.Payload; var route = new AodvTableEntry { Valid = true, DestinationAddress = hello.DestinationAddress, DestinationSequenceNumber = hello.DestinationSequenceNumber, HopCount = 1, NextHop = incomingPacket.PreviousHop, ValidDestinationSequenceNumberFlag = true, ExpirationTime = new DateTime(hello.Lifetime.Ticks) //Creates an exact copy of the lifetime in DateTime format. }; //Ensure that we have an active route towards the neighbour if (!_aodvHelper.RoutingTable.RouteExists(hello.DestinationAddress)) { _aodvHelper.RoutingTable.AddEntry(route); } else //Route does exist, update what we can infer from the fact that our neighbour send us a HELLO { _aodvHelper.RoutingTable.UpdateEntry(route); } _logger.WriteLine("Processed HELLO from " + hello.DestinationAddress); }
/// <summary> /// Prints the creation or update of a routing entry to the log file. /// </summary> /// <param name="entry"></param> /// <param name="update"></param> private void LogRouteEntry(AodvTableEntry entry, bool update) { var added = update ? "Routing entry updated: " : "Routing entry added: "; var msg = "Destination: " + entry.DestinationAddress + ", DSN: " + entry.DestinationSequenceNumber + ", Valid DSN: " + entry.ValidDestinationSequenceNumberFlag + ", Hop Count: " + entry.HopCount + ", Next Hop: " + entry.NextHop + ", Valid: " + entry.Valid + ", ExpirationTime: " + entry.ExpirationTime.ToLongTimeString(); _logger.WriteLine(added + msg); }
/// <summary> /// Updates an existing routing table entry, with the entry provided. /// </summary> /// <param name="entry"></param> public void UpdateEntry(AodvTableEntry entry) { var destination = entry.DestinationAddress; _table[destination].DestinationAddress = entry.DestinationAddress; _table[destination].DestinationSequenceNumber = entry.DestinationSequenceNumber; _table[destination].ValidDestinationSequenceNumberFlag = entry.ValidDestinationSequenceNumberFlag; _table[destination].HopCount = entry.HopCount; _table[destination].Valid = entry.Valid; _table[destination].NextHop = entry.NextHop; _table[destination].Precursors = entry.Precursors.ToList(); _table[destination].ExpirationTime = entry.ExpirationTime; LogRouteEntry(entry, true); }
/// <summary> /// Handles an incoming RREP packet. /// </summary> /// <param name="incomingPacket"></param> private void HandleRrep(Message incomingPacket) { var rrep = (Rrep)incomingPacket.Payload; //var outgoingMessages = new Dictionary<string, Message>(); //Search routing table for route to previous hop (where RREP was received from), and create it, if it does not exists (may now be used for forwarding) if (!_aodvHelper.RoutingTable.RouteExists(incomingPacket.PreviousHop)) { var route = new AodvTableEntry { Valid = true, DestinationAddress = incomingPacket.PreviousHop, DestinationSequenceNumber = 0, HopCount = 1, NextHop = incomingPacket.PreviousHop, ValidDestinationSequenceNumberFlag = false, ExpirationTime = _time.GetFutureTime(_aodvParameters.ActiveRouteTimeout), Precursors = new List <string> { _aodvHelper.RoutingTable.GetEntry(rrep.OriginatorAddress)?.NextHop } }; _logger.WriteLine("1Adding route entry from received RREP towards previous hop: " + incomingPacket.PreviousHop); _aodvHelper.RoutingTable.AddEntry(route); } else //Route does exist, update what we can infer from the fact that our neighbour forwarded a RREQ to us { var route = _aodvHelper.RoutingTable.GetEntry(incomingPacket.PreviousHop); route.Valid = true; route.HopCount = 1; route.NextHop = incomingPacket.PreviousHop; route.ExpirationTime = _time.GetFutureTime(_aodvParameters.ActiveRouteTimeout); _logger.WriteLine("2Updating existing route entry for previous hop from received RREP: " + incomingPacket.PreviousHop); _aodvHelper.RoutingTable.UpdateEntry(route); } //Increment HopCount, since me receiving the RREP, adds another hop to the path rrep.HopCount = rrep.HopCount + 1; //If route forward in RREP path (towards destination in RREP) does not exist, create it if (!_aodvHelper.RoutingTable.RouteExists(rrep.DestinationAddress)) { var destinationRoute = new AodvTableEntry { Valid = true, DestinationAddress = rrep.DestinationAddress, DestinationSequenceNumber = rrep.DestinationSequenceNumber, HopCount = rrep.HopCount, ValidDestinationSequenceNumberFlag = true, NextHop = incomingPacket.PreviousHop, ExpirationTime = rrep.Lifetime, Precursors = new List <string>() //Precursor added below, per section 6.7 last paragraph }; _logger.WriteLine("Creating route entry for destination from received RREP: " + rrep.DestinationAddress); _aodvHelper.RoutingTable.AddEntry(destinationRoute); //If I'm the originator in the RREP, I now have a route to the destination, yay! } else //Route towards destination in rrep exists { var entry = _aodvHelper.RoutingTable.GetEntry(rrep.DestinationAddress); var identicalDsn = rrep.DestinationSequenceNumber == entry.DestinationSequenceNumber; var update = false; if (!entry.ValidDestinationSequenceNumberFlag) // Section 6.7 (i) { update = true; } else if (rrep.DestinationSequenceNumber > entry.DestinationSequenceNumber && entry.ValidDestinationSequenceNumberFlag) //Section 6.7 (ii) { update = true; } else if (identicalDsn && !entry.Valid) // Section 6.7 (iii) { update = true; } else if (identicalDsn && rrep.HopCount < entry.HopCount) //Section 6.7 (iv) { update = true; } if (update) { entry.Valid = true; entry.ValidDestinationSequenceNumberFlag = true; entry.NextHop = incomingPacket.PreviousHop; entry.HopCount = rrep.HopCount; entry.ExpirationTime = rrep.Lifetime; //Current time + rrep.lifetime entry.DestinationSequenceNumber = rrep.DestinationSequenceNumber; //Precursor added below, per section 6.7 last paragraph _logger.WriteLine("3Updating existing route entry for destination from received RREP: " + rrep.DestinationAddress); _aodvHelper.RoutingTable.UpdateEntry(entry); } } //Removes all buffered RREQs I have sent for this destination _aodvHelper.RemoveLocalBufferedRreq(rrep.DestinationAddress); //If I'm not the originator (i.e. I am not the one who requested the route) if (rrep.OriginatorAddress != _localAddress) { //Verify that I have a route to the destination. Previous-hop has a routing entry that says I do, otherwise he wouldnt have forwarded the RREP to me. if (!_aodvHelper.RoutingTable.ActiveRouteExists(rrep.OriginatorAddress)) { _statistics.AodvDropped_NoActiveForwardingRoute(incomingPacket); //Well, I dont have a route (even though I should - most likely due to a rrep sent back too late) //Send RERR to previous hop var ud = new List <UnreachableDestination> { new UnreachableDestination(rrep.OriginatorAddress, 0) }; var rerrMsg = new Message(new Rerr(ud), incomingPacket.PreviousHop, _localAddress, _conf.MessageTtlValue); SendAodvMessage(rerrMsg, incomingPacket.PreviousHop); return; } //Add next hop towards originator, to precursors of destination (6.7, last paragraph) //Section 6.7, last paragraph //"When any node transmits a RREP, the precursor list for the corresponding DESTINATION node is updated, by adding to it, the next hop node //to which the RREP is forwarded." So, "the next hop node to which the RREP is forwarded" is next hop towards ORIGINATOR. _aodvHelper.RoutingTable.AddPrecursorToEntry(rrep.DestinationAddress, _aodvHelper.RoutingTable.GetEntry(rrep.OriginatorAddress).NextHop); //Update lifetime of reverse route towards originator var reverseRoute = _aodvHelper.RoutingTable.GetEntry(rrep.OriginatorAddress); var future = _time.GetFutureTime(_aodvParameters.ActiveRouteTimeout); reverseRoute.ExpirationTime = reverseRoute.ExpirationTime > future ? reverseRoute.ExpirationTime : future; //Forward RREP to node according to routing table towards the originator var outMsg = new Message(incomingPacket); outMsg.Payload = new Rrep(rrep); SendAodvMessage(outMsg, reverseRoute.NextHop); _logger.WriteLine("4Updating existing route entry for originator from received RREP: " + rrep.OriginatorAddress); _aodvHelper.RoutingTable.UpdateEntry(reverseRoute); } }
/// <summary> /// Handles an incoming RREQ packet. /// </summary> /// <param name="incomingPacket"></param> private void HandleRreq(Message incomingPacket) { //Processing RREQ according to section 6.5 var rreq = (Rreq)incomingPacket.Payload; //Cast message to right type //Check that received RREQ has not been received and processed before if (_aodvHelper.RreqAttemptExist(rreq.DestinationAddress, rreq.OriginatorAddress)) { _logger.WriteLine("Incoming RREQ from " + rreq.OriginatorAddress + " discarded, since it has been processed before."); return; //Discard RREQ } //RREQ not received before, place in buffer with 0 as attempt number _aodvHelper.AddBufferedRreqAttempt(new BufferedRreqAttempt(0, rreq, _conf.AodvConfiguration.PathDiscoveryTime)); //First, create/update route to previous hop. If route to previous hop exists, update lifetime if (_aodvHelper.RoutingTable.ActiveRouteExists(incomingPacket.PreviousHop)) { var prevRoute = _aodvHelper.RoutingTable.GetEntry(incomingPacket.PreviousHop); prevRoute.Valid = true; prevRoute.HopCount = 1; prevRoute.NextHop = incomingPacket.PreviousHop; prevRoute.ExpirationTime = _time.GetFutureTime(_aodvParameters.ActiveRouteTimeout); _logger.WriteLine("RREQ handler: Updating route to previous hop: " + incomingPacket.PreviousHop + " for RREQ #" + rreq.RouteRequestId); _aodvHelper.RoutingTable.UpdateEntry(prevRoute); } else //Route did not exist, so create it { var prevHopEntry = new AodvTableEntry { Valid = true, DestinationAddress = incomingPacket.PreviousHop, DestinationSequenceNumber = 0, ValidDestinationSequenceNumberFlag = false, //(He's my neighbour, so even though I dont know his sequence number, I know that he's there) HopCount = 1, //Only 1 hop to previous neighbour (duh) NextHop = incomingPacket.PreviousHop, ExpirationTime = _time.GetFutureTime(_aodvParameters.ActiveRouteTimeout) }; _logger.WriteLine("RREQ handler: Adding route to previous hop: " + incomingPacket.PreviousHop + " for RREQ #" + rreq.RouteRequestId); _aodvHelper.RoutingTable.AddEntry(prevHopEntry); } //RREQ has not been seen before or was not sent by me, continue to process it. rreq.HopCount = rreq.HopCount + 1; //Increment HopCount in RREQ, since me receiving it, was one hop more //Create or update reverse route to RREQ Originator var oldEntry = _aodvHelper.RoutingTable.GetEntry(rreq.OriginatorAddress); var minimalLifetime = _aodvParameters.MinimalLifetime(rreq.HopCount); //No route to originator exists, create it if (oldEntry == null) { var originatorRoute = new AodvTableEntry { DestinationAddress = rreq.OriginatorAddress, DestinationSequenceNumber = rreq.OriginatorSequenceNumber, ValidDestinationSequenceNumberFlag = true, HopCount = rreq.HopCount, Valid = true, NextHop = incomingPacket.PreviousHop, ExpirationTime = minimalLifetime }; _logger.WriteLine("RREQ handler: Adding route to originator: " + rreq.OriginatorAddress + " for RREQ #" + rreq.RouteRequestId); _aodvHelper.RoutingTable.AddEntry(originatorRoute); } else //Route exists, update existing entry { var originatorRoute = new AodvTableEntry { DestinationAddress = rreq.OriginatorAddress, DestinationSequenceNumber = rreq.OriginatorSequenceNumber > oldEntry.DestinationSequenceNumber ? rreq.OriginatorSequenceNumber : oldEntry.DestinationSequenceNumber, //See section 6.5, action 1. ValidDestinationSequenceNumberFlag = true, HopCount = rreq.HopCount, Valid = true, NextHop = incomingPacket.PreviousHop, ExpirationTime = oldEntry.ExpirationTime > minimalLifetime ? oldEntry.ExpirationTime : minimalLifetime }; _logger.WriteLine("RREQ handler: Updating route to originator: " + rreq.OriginatorAddress + " for RREQ #" + rreq.RouteRequestId); _aodvHelper.RoutingTable.UpdateEntry(originatorRoute); //And now we have a route towards the originator that can be used. neat-o. } //If I am the destination specified in RREQ if (rreq.DestinationAddress == _localAddress) //Section 6.6 (i) and section 6.6.1 { //Increment my sequence number, if DSN in RREQ is 1 larger per secton 6.6.1 if (rreq.DestinationSequenceNumber == _aodvHelper.RoutingTable.SequenceNumber + 1) { _aodvHelper.RoutingTable.IncrementSequenceNumber(); } var rrep = new Rrep { OriginatorAddress = rreq.OriginatorAddress, DestinationAddress = rreq.DestinationAddress, DestinationSequenceNumber = _aodvHelper.RoutingTable.SequenceNumber, HopCount = 0, Lifetime = _time.GetFutureTime(_aodvParameters.MyRouteTimeout) //Section 6.6.1, see also section 10. }; var responseMsg = new Message(rrep, rreq.OriginatorAddress, _localAddress, _conf.MessageTtlValue); SendAodvMessage(responseMsg, incomingPacket.PreviousHop); //Send RREP to previous hop, which is where I received the RREQ from } //If I have an active route to destination, which upholds requirements in section 6.6 (ii), see section 6.6.2 else if (_aodvHelper.RoutingTable.ActiveRouteExists(rreq.DestinationAddress) && //If I have an active route _aodvHelper.RoutingTable.GetEntry(rreq.DestinationAddress).ValidDestinationSequenceNumberFlag && //and the route has a valid dsn _aodvHelper.RoutingTable.GetEntry(rreq.DestinationAddress).DestinationSequenceNumber >= rreq.DestinationSequenceNumber && //and route dsn is >= rreq.dsn !rreq.D) //and rreq must NOT only be answered by destination { var forwardRoute = _aodvHelper.RoutingTable.GetEntry(rreq.DestinationAddress); var rrep = new Rrep { OriginatorAddress = rreq.OriginatorAddress, DestinationAddress = rreq.DestinationAddress, DestinationSequenceNumber = forwardRoute.DestinationSequenceNumber, HopCount = forwardRoute.HopCount, Lifetime = _time.GetFutureTime((forwardRoute.ExpirationTime - _time.CurrentTime).TotalSeconds) //6.6.2, "subtract current time from expiration time in route table entry" }; //Add previous hop of incoming message to precursor list of destination _aodvHelper.RoutingTable.AddPrecursorToEntry(rreq.DestinationAddress, incomingPacket.PreviousHop); //Add next-hop of forward route to precursor list of originator _aodvHelper.RoutingTable.AddPrecursorToEntry(rreq.OriginatorAddress, forwardRoute.NextHop); //Place RREP in outbox var responseMsg = new Message(rrep, rreq.OriginatorAddress, _localAddress, _conf.MessageTtlValue); SendAodvMessage(responseMsg, incomingPacket.PreviousHop); //Send RREP to previous hop, which is where I received the RREQ from //Send gratuitous RREP if required in RREQ, specified in section 6.6.3. Dont send it, if path to destination goes through previousHop if (rreq.G) { var gratuitousRrep = new Rrep { HopCount = _aodvHelper.RoutingTable.GetEntry(rreq.OriginatorAddress).HopCount, DestinationAddress = rreq.OriginatorAddress, DestinationSequenceNumber = rreq.OriginatorSequenceNumber, OriginatorAddress = rreq.DestinationAddress, Lifetime = _time.GetFutureTime((_aodvHelper.RoutingTable.GetEntry(rreq.OriginatorAddress).ExpirationTime - _time.CurrentTime).TotalSeconds) //"Remaining lifetime of route towards RREQ originator, as known by intermediate node" (expiration time - current time = remaining time) }; var gratuitousMsg = new Message(gratuitousRrep, rreq.DestinationAddress, _localAddress, _conf.MessageTtlValue); SendAodvMessage(gratuitousMsg, forwardRoute.NextHop); //Gratuitous RREP sent forward } } //Else, I have no active route and am not the destination else { var outMsg = new Message(incomingPacket); rreq.DestinationSequenceNumber = Math.Max(rreq.DestinationSequenceNumber, _aodvHelper.RoutingTable.GetEntry(rreq.DestinationAddress)?.DestinationSequenceNumber ?? -1); //Set DSN to max of rreq.dsn or table[destination].dsn outMsg.Payload = new Rreq(rreq); outMsg.DestinationAddress = SimulationConstants.BroadcastAddress; SendAodvMessage(outMsg, SimulationConstants.BroadcastAddress); } }
/// <summary> /// Adds a new routing table entry to the routing table /// </summary> /// <param name="entry"></param> public void AddEntry(AodvTableEntry entry) { _table[entry.DestinationAddress] = entry; LogRouteEntry(entry, false); }