如何在NS3中aodv的路由协议(aodv-routing-protocol)里添加能量(energy)的模块?

因为做毕设的原因,需要在aodv路由协议中,在节点收到rreq包的时候,顺便记录下当前节点的剩余能量,之前是在NS2上做过,但是才接触NS3没多久,所以不太会,在网上以及NS3给的example中也没有看懂查看的方法,所以想来咨询下有关于能量模块的具体实现方式,energy module以及energy helper有大佬可以帮我解惑一下么- -谢谢了!

RoutingProtocol::RecvRequest (Ptr p, Ipv4Address receiver, Ipv4Address src)
// src is neigbor's IP
{
NS_LOG_FUNCTION (this);
RreqHeader rreqHeader;
p->RemoveHeader (rreqHeader);

// A node ignores all RREQs received from any node in its blacklist
RoutingTableEntry toPrev;
if (m_routingTable.LookupRoute (src, toPrev))
{
if (toPrev.IsUnidirectional ())
{
NS_LOG_DEBUG ("Ignoring RREQ from node in blacklist");
return;
}
}

uint32_t id = rreqHeader.GetId ();
Ipv4Address origin = rreqHeader.GetOrigin (); // Originator is not always neighbor (RREQ forwarding)

NS_LOG_DEBUG ("Recv RREQ [ID=" << rreqHeader.GetId () << ",OriginSeqNo=" << rreqHeader.GetOriginSeqno () << "]: " << src << " --> " << receiver << ", originator " << origin << " dst " << rreqHeader.GetDst ());

// Increment RREQ hop count
uint8_t hop = rreqHeader.GetHopCount () + 1;
rreqHeader.SetHopCount (hop);

// Add in RREQ ETX metrix for last hop from neighbor to this node
// Now RREQ contains ETX from origin to this node
uint32_t etx = m_nbEtx.GetEtxForNeighbor (src); // src is always neighbor, origin maybe isn't
if (etx == NeighborEtx::EtxMaxValue ())
{ // this should never happen because neighbor has limited ETX, but it is better to check!
NS_LOG_DEBUG ("ETX -> oo !!! ");
rreqHeader.SetEtx (etx);
}
else
{
rreqHeader.SetEtx (etx + rreqHeader.GetEtx ());
}

NS_LOG_DEBUG ("Recv RREQ header: hop " << int(hop) << ", ETX " << rreqHeader.GetEtx ());

/*

  • Node checks to determine whether it has received a RREQ with the same Originator IP Address and RREQ ID.
  • If such a RREQ has been received, the node silently discards the newly received RREQ.
  • This is modified to include ETX, so RREQ is discarded only if etx of previously received RREQ is beter (smaller) then this one
    */

    if (m_rreqIdCache.IsDuplicate (origin, id))
    {
    RoutingTableEntry rte;
    if (m_routingTable.LookupRoute (origin, rte))
    {
    if (rte.GetEtx () <= rreqHeader.GetEtx ())
    {
    NS_LOG_DEBUG ("Ignoring RREQ due to duplicate, previous RREQ had better ETX.");
    NS_LOG_DEBUG ("Duplicate, IGNORE previous RREQ had better ETX.");
    return;
    }
    NS_LOG_DEBUG ("Duplicate, but better ETX. Continue...");
    }
    NS_LOG_DEBUG ("Duplicate, but no route in the table. Continue...");
    }
    else
    NS_LOG_DEBUG ("Not found duplicate. Continue...");

    // This should be solved by previous if due to duplicate RREQ, but it is not?!
    if (receiver == rreqHeader.GetOrigin ())
    {
    NS_LOG_DEBUG ("This is my own RREQ, so drop!");
    return;
    }

    /*

  • When the reverse route is created or updated, the following actions on the route are also carried out:

    1. the Originator Sequence Number from the RREQ is compared to the corresponding destination sequence number
  • in the route table entry and copied if greater than the existing value there
    
    1. the valid sequence number field is set to true;
    1. the next hop in the routing table becomes the node from which the RREQ was received
    1. the hop count is copied from the Hop Count in the RREQ message;
    1. the Lifetime is set to be the maximum of (ExistingLifetime, MinimalLifetime), where
  • MinimalLifetime = current time + 2*NetTraversalTime - 2*HopCount*NodeTraversalTime
    
    1. ETX is copied from the RREQ message / RoutingTableEntry toOrigin; if (!m_routingTable.LookupRoute (origin, toOrigin)) { // There is no route in the routing table Ptr dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)); RoutingTableEntry newEntry (/*device=/ dev, /*dst=*/ origin, /*validSeno=*/ true, /*seqNo=*/ rreqHeader.GetOriginSeqno (), /*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0), /*hops=*/ hop, /*nextHop*/ src, /*timeLife=*/ Time ((2 * m_netTraversalTime - 2 * hop * m_nodeTraversalTime)), /*etx*/ rreqHeader.GetEtx ()); m_routingTable.AddRoute (newEntry); } else { // Update existing route if (toOrigin.GetValidSeqNo ()) { if (int32_t (rreqHeader.GetOriginSeqno ()) - int32_t (toOrigin.GetSeqNo ()) > 0) toOrigin.SetSeqNo (rreqHeader.GetOriginSeqno ()); // update sequence number with newer one } else toOrigin.SetSeqNo (rreqHeader.GetOriginSeqno ()); toOrigin.SetValidSeqNo (true); toOrigin.SetNextHop (src); toOrigin.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver))); toOrigin.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0)); toOrigin.SetHop (hop); toOrigin.SetLifeTime (std::max (Time (2 * m_netTraversalTime - 2 * hop * m_nodeTraversalTime), toOrigin.GetLifeTime ())); toOrigin.SetEtx (rreqHeader.GetEtx ()); m_routingTable.Update (toOrigin); }

    RoutingTableEntry toNeighbor;
    if (!m_routingTable.LookupRoute (src, toNeighbor))
    { // Nenad: No rute in routing table, this should never happen since the route for neighbor is created in RecvAodv ()
    NS_LOG_DEBUG ("Neighbor:" << src << " not found in routing table. Creating an entry");
    Ptr dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));
    RoutingTableEntry newEntry (dev, src, false, rreqHeader.GetOriginSeqno (), /* Nenad: not clear to me why seqno is not valid? /
    m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),
    1, src, m_activeRouteTimeout,
    /*etx
    / m_nbEtx.GetEtxForNeighbor (src));
    m_routingTable.AddRoute (newEntry);
    }
    else
    { // Update existing route
    toNeighbor.SetLifeTime (m_activeRouteTimeout);
    toNeighbor.SetValidSeqNo (false); // Nenad: not clear to me why seqno is not valid?
    toNeighbor.SetSeqNo (rreqHeader.GetOriginSeqno ());
    toNeighbor.SetFlag (VALID);
    toNeighbor.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)));
    toNeighbor.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0));
    toNeighbor.SetHop (1);
    toNeighbor.SetNextHop (src);
    toNeighbor.SetEtx (m_nbEtx.GetEtxForNeighbor (src));
    m_routingTable.Update (toNeighbor);
    }

    // Update neighbors
    m_nb.Update (src, Time (m_allowedHelloLoss * m_helloInterval));

    NS_LOG_LOGIC (receiver << " receive RREQ with hop count " << static_cast(rreqHeader.GetHopCount ())
    << " ID " << rreqHeader.GetId ()
    << " to destination " << rreqHeader.GetDst ());

    // A node generates a RREP if either:
    // (i) it is itself the destination,
    if (IsMyOwnAddress (rreqHeader.GetDst ()))
    {
    m_routingTable.LookupRoute (origin, toOrigin);
    NS_LOG_DEBUG ("Send reply since I am the destination");
    SendReply (rreqHeader, toOrigin);
    return;
    }
    /*

  • (ii) or it has an active route to the destination, the destination sequence number in the node's existing route table entry for the destination

  •  is valid and greater than or equal to the Destination Sequence Number of the RREQ, and the "destination only" flag is NOT set.
    

    /
    RoutingTableEntry toDst;
    Ipv4Address dst = rreqHeader.GetDst ();
    if (m_routingTable.LookupRoute (dst, toDst))
    {
    /

    • Drop RREQ, This node RREP wil make a loop. / if (toDst.GetNextHop () == src) { NS_LOG_DEBUG ("Drop RREQ from " << src << ", dest next hop " << toDst.GetNextHop ()); return; } /
    • The Destination Sequence number for the requested destination is set to the maximum of the corresponding value
    • received in the RREQ message, and the destination sequence value currently maintained by the node for the requested destination.
    • However, the forwarding node MUST NOT modify its maintained value for the destination sequence number, even if the value
    • received in the incoming RREQ is larger than the value currently maintained by the forwarding node. */ if ((rreqHeader.GetUnknownSeqno () || (int32_t (toDst.GetSeqNo ()) - int32_t (rreqHeader.GetDstSeqno ()) >= 0)) && toDst.GetValidSeqNo () ) { if (!rreqHeader.GetDestinationOnly () && toDst.GetFlag () == VALID) { m_routingTable.LookupRoute (origin, toOrigin); SendReplyByIntermediateNode (toDst, toOrigin, rreqHeader.GetGratuitousRrep ()); return; } // Update seqno and valid fileds in the RREQ packet for forwarding rreqHeader.SetDstSeqno (toDst.GetSeqNo ()); rreqHeader.SetUnknownSeqno (false); } }

    // Forward RREQ
    SocketIpTtlTag tag;
    p->RemovePacketTag (tag);
    if (tag.GetTtl () < 2)
    {
    NS_LOG_DEBUG ("TTL exceeded. Drop RREQ origin " << src << " destination " << dst );
    return;
    }

    for (std::map, Ipv4InterfaceAddress>::const_iterator j =
    m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
    {
    Ptr socket = j->first;
    Ipv4InterfaceAddress iface = j->second;
    Ptr packet = Create ();
    SocketIpTtlTag ttl;
    ttl.SetTtl (tag.GetTtl () - 1);
    packet->AddPacketTag (ttl);
    packet->AddHeader (rreqHeader);
    TypeHeader tHeader (AODVTYPE_RREQ);
    packet->AddHeader (tHeader);
    // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise
    Ipv4Address destination;
    if (iface.GetMask () == Ipv4Mask::GetOnes ())
    {
    destination = Ipv4Address ("255.255.255.255");
    }
    else
    {
    destination = iface.GetBroadcast ();
    }
    m_lastBcastTime = Simulator::Now ();
    Simulator::Schedule (Time (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 10))), &RoutingProtocol::SendTo, this, socket, packet, destination);

    }
    }