/// <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);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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);
            }
        }
Пример #6
0
 /// <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);
 }