Search code examples
network-programmingns-3

how to extract ip address from QueueDiscItem in ns3?


I'm new to NS3 and i was trying to extract ip address of a packet from QueueDiscItem,

when i have: Ptr< QueueDiscItem > item initiated and call:

item->Print(std::cout);

the output i get is
"tos 0x0 DSCP Default ECN Not-ECT ttl 63 id 265 protocol 6 offset (bytes) 0 flags [none] length: 76 10.1.4.2 > 10.1.2.1 0x7fffc67ec880 Dst addr 02-06-ff:ff:ff:ff:ff:ff proto 2048 txq"

but when i call:

Ipv4Header header;
item->GetPacket()->PeekHeader(header);
header.Print(std::cout);

the output i get is
"tos 0x0 DSCP Default ECN Not-ECT ttl 0 id 0 protocol 0 offset (bytes) 0 flags [none] length: 20 102.102.102.102 > 102.102.102.102"


Solution

  • How to get the Header data

    According to the list of TraceSources, the TraceSources associated with QueueDiscItems are for Queues. I'm guessing you were trying to attach to one of those TraceSources.

    A QueueDiscItem encapsulates several things: a Ptr<Packet>, a MAC address, and several more things. Since you are using IPv4, the QueueDiscItem is actually an Ipv4QueueDiscItem (the latter is a subclass of the former). So, let's start by casting the QueueDiscItem to an Ipv4QueueDiscItem by

    Ptr<const Ipv4QueueDiscItem> ipItem = DynamicCast<const Ipv4QueueDiscItem>(item);
    

    Next, you need to know that at this point in the simulation, the Ipv4Header has not been added to the Ptr<Packet> yet. This is probably a design choice (that I don't understand). So, how can we get this information? Well, the Ipv4QueueDiscItem encapsulates the Ipv4Header, and at some point before passing the Ptr<Packet> to L2, the header is added to the packet. This Header can be retrieved by

    const Ipv4Header ipHeader = ipItem->GetHeader();
    

    So, now we have the Ipv4Header of the packet you're interested in. Now, we can safely get the address from the Ipv4QueueDiscItem by

    ipHeader.GetSource();
    ipHeader.GetDestination();
    

    In summary, your TraceSource function should look something like this:

    void
    EnqueueTrace (Ptr<const QueueDiscItem> item) {
        Ptr<const Ipv4QueueDiscItem> ipItem = DynamicCast<const Ipv4QueueDiscItem>(item);
        const Ipv4Header ipHeader = ipItem->GetHeader();
        NS_LOG_UNCOND("Packet received at " << Simulator::Now() << " going from " << ipHeader.GetSource() << " to " << ipHeader.GetDestination());
    }
    

    Why does item->Print(std::cout); work?

    All of the above makes sense, but why does

    item->Print(std::cout);
    

    print the correct addresses? First, it is important to realize that here Print() is a function of the QueueDiscItem, not the Packet. If we go to the source of this function, we find that Print() just prints the Header if it has already been added.