Packet header manipulation + Packet::Copy()

1,777 views
Skip to first unread message

Grilo

unread,
May 13, 2011, 6:40:56 AM5/13/11
to ns-3-users
I am implementing a transport protocol called DTSN, which needs to
intercept packets at intermediate nodes and eventually to change their
content (e.g. eliminate sequence numbers from NACK packets if the
intermediate nodes have those packets in cache).
What I do is to call a callback function (transport protocol) from
Ipv4L3Protocol::IpForward() at intermediate nodes. So far so good.
However, if I change the contents of the packet inside the callback
function (and notice that IpForward copies the packet with pk->Copy()
before calling the transport callback), afterwards there will
eventually be a "Deserialize" error reported at the lower layers when
forwarding the packet. This is strange.
In fact I've solved the problem by having the callback function return
"false" so that the packet is not forwarded by
Ipv4L3Protocol::IpForward(). Instead, the callback function sends a
changed second (!!!) copy of the packet explicitly with
Ipv4L3Protocol::Send().

And this worked for a long time. Now I'm having a similar problem.
There are some optional headers in my transport protocol, which I
implemented separately. Some of these must be accessed by intermediate
nodes and they are not at the top (in fact, the top header signals
whether those optional headers are present or not). So imagine that in
order to access the third extension header, I do the following within
the callback function:

p->RemoveHeader(topHeader) ;
p->RemoveHeader(secondHeader) ;
p->PeekHeader(thirdHeader) ;

p->AddHeader(secondHeader) ;
p->TopHeader(secondHeader) ;

I'm done! Although the packet 'p' is theoretically the same as in the
beginning, the simulator reports a deserialize error in some
Packet::Print() call at the lower layers. But the funny thing is that
if I call Packet::Print() within the callback before and after the
packet manipulation, the headers seem to be correct and there is no
error using Print().
So, it is obvious that I'm facing some constraints associated with
packet header manipulation.

Has anyone experienced similar problems, or do any of you have a good
explanation for what is happenning?

Regards,
António Grilo


Grilo

unread,
May 13, 2011, 6:45:58 AM5/13/11
to ns-3-users
By the way, some of the headers are not aligned to 32 bits, but I
think this is not a problem, right?

Grilo

unread,
May 13, 2011, 10:04:06 AM5/13/11
to ns-3-users
Funny...

Just discovered that while manipulating the packet copy, I'm also
changing the original packet. How can I make a truly independent
packet copy, which I can change at my discretion?

Gustavo Carneiro

unread,
May 13, 2011, 10:12:48 AM5/13/11
to ns-3-...@googlegroups.com
This shouldn't happen if the modifications in the copy of the packet are all "legal", i.e. do not use PeekData to directly modify the byte buffer.

You should strive to create a minimal example program that reproduces the problem; if you can do that (I know it's not always easy), then it could be a bug in ns-3 itself... 
 

--
You received this message because you are subscribed to the Google Groups "ns-3-users" group.
To post to this group, send email to ns-3-...@googlegroups.com.
To unsubscribe from this group, send email to ns-3-users+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/ns-3-users?hl=en.




--
Gustavo J. A. M. Carneiro
INESC Porto, UTM, WiN, http://win.inescporto.pt/gjc
"The universe is always one step beyond logic." -- Frank Herbert

Grilo

unread,
May 13, 2011, 10:56:54 AM5/13/11
to ns-3-users
In fact I'm not even manipulating data. I've also noticed that if I do
similar changes in the transport protocol receive method, I get a
similar error. However, if I do it in the socket implementation
(endpoint layer) everything goes smooth... The strange thing is that
the Receive method simply calls (*endPoint)->ForwardUp... So it should
be the same to strip headers in the Receive method or already in the
ForwardUp method itself.

I'll try to change the UDP protocol so that I can reproduce the error.

Gustavo, já agora, cumprimentos! ;)
António Grilo
(IST, Lisboa)
> INESC Porto, UTM, WiN,http://win.inescporto.pt/gjc

Cristian

unread,
Oct 28, 2014, 2:52:43 PM10/28/14
to ns-3-...@googlegroups.com
Hi Grilo,

I know this is an old post and might not be fresh in your memory but did you manage to find a solution for manipulating the copied data without modifying the original? I am facing the same problem when I try to modify the destination address of an IPv6 Header. After the copied packet is modified, my original packet is not being sent correctly any more. In the ModifyPacketDestination function, I am setting the Destination Address similar to the Source Address, just for testing purposes.

It seems like the "ipv6Header->Serialize(item.current)" is creating part of the problem but I am not sure. If it is removed, the original packets are sent fine.


Ptr <Packet> ShimLayerRmc::ModifyPacketDestination(Ptr<Packet> packet2)
{
   
    
    // To get a header from Ptr<Packet> packet first, copy the packet 
    Ptr<Packet> q = packet->Copy();
    
    // Use indicator to search the packet
    PacketMetadata::ItemIterator metadataIterator = q->BeginItem();
    PacketMetadata::Item item;
    while (metadataIterator.HasNext())
    {
        item = metadataIterator.Next();
        NS_LOG_FUNCTION("item name: " << item.tid.GetName());
        
        // If we want to have an ip header
        if(item.tid.GetName() == "ns3::Ipv6Header")
        {
           
            Callback<ObjectBase *> constr = item.tid.GetConstructor();
            NS_ASSERT(!constr.IsNull());
            
            // Ptr<> and DynamicCast<> won't work here as all headers are from ObjectBase, not Object
            ObjectBase *instance = constr();
            NS_ASSERT(instance != 0);
            
            Ipv6Header* ipv6Header = dynamic_cast<Ipv6Header*> (instance);
            NS_ASSERT(ipv6Header != 0);
          
            ipv6Header->Deserialize(item.current);
      
            src_ip = ipv6Header->GetSourceAddress();
            
            ipv6Header->SetDestinationAddress(src_ip);
           
            ipv6Header->Serialize(item.current); // if this is commented, then original packet - "packet" - is being received at destination.
            
            delete ipv6Header;
            break;
        }
    }
      return q;
  }

The function call and the Send function is below:
 
Ptr<Packet> g = ModifyPacketDestination(packet); //Packet g is being returned but not used
 ret = m_netDevice->Send (packet, dest, protocolNumber);
 
====> "packet" not being received at destination although not being modified

I have also tried with CreateFragment but same result..

 uint16_t offsetData = 0;
 uint32_t size = packet->GetSize ();   
Ptr<Packet> fragment1 = packet->CreateFragment (offsetData, size);
Ptr<Packet> g = GetPacketSource(fragment1);
 ret = m_netDevice->Send (packet, dest, protocolNumber);

====> "packet" not being received at destination although not modified

Any tip or advice would be great.

Thanks,
Cristian

Tommaso Pecorella

unread,
Oct 29, 2014, 3:52:33 AM10/29/14
to ns-3-...@googlegroups.com
Smart pointers Copy function is a CoW. What your code is doing is, effectively, find the metadata of the header of the ORIGINAL packet, because he copied one wasn't yet done for real.
Please do NOT play with metadata if you do not exactly what you're doing. The above method may work to find if a header is there (and even then, it's unreliable and it may not work in emulation mode).
Changing a header by directly modifying it (i.e., without using RemoveHeader) is causing troubles.

T.

Cristian

unread,
Oct 29, 2014, 7:49:24 AM10/29/14
to ns-3-...@googlegroups.com
Hi Tommaso,

Thanks for your reply.

If my understanding is right, I should therefore:

1. Read and store the contents of the header (assuming the header I need has been added last).
2. Remove the header.
3. Create a new one with the stored contents, and modified values.
4. Add the new header to the packet.

I will try to follow these steps and post the code once I get it working.


Just for my understanding, concerning the CoW, the packet is being copied only when modified. In my method, even if the approach is wrong, an actual modification of the header is made, since the packet is not being received at the destination, but a real copy isn't created. I find it contradictory to the first statement. In what scenario would a real copy be made then?

In my second attempt, that I listed in my previous post, I assumed my CoW copy wasn't functioning correctly, and thus used CreateFragment, thinking it will make a proper copy, but the same results occurred. The conclusion I made is that CreateFragment doesn't make a proper copy either. Am I missing out something here as well?

If there is something available, could you please redirect me towards a document, or an example, where I can understand how to properly copy the packets and modify the headers, to also work in emulation mode?


Thanks.

Regards,
Cristian

Cristian

unread,
Oct 29, 2014, 11:34:26 AM10/29/14
to ns-3-...@googlegroups.com
Hi guys,

Managed to get it working. I got inspired from the 6LoWPan header compression.

My code is below for those who find it helpful:

Ptr<Packet> ShimLayerRmc::ModifyDestinationAddress (Ptr<Packet> packet)
{
    Ptr<Packet> q = packet->Copy();
    
    Ipv6Header ipHeader;
    Ipv6Header ipHeader_new;
       
    if ( q->PeekHeader (ipHeader) != 0 )
    {   
        std::cout << "Have entered the Header Modification loop " << '\n';
        
        q->RemoveHeader (ipHeader);
      
        ipHeader_new.SetTrafficClass (ipHeader.GetTrafficClass ());
        ipHeader_new.SetFlowLabel (ipHeader.GetFlowLabel ());
        ipHeader_new.SetPayloadLength (ipHeader.GetPayloadLength());
        
        uint8_t nextHeader = ipHeader.GetNextHeader ();
        ipHeader_new.SetNextHeader (nextHeader);
        ipHeader_new.SetHopLimit (ipHeader.GetHopLimit());
        
        ipHeader_new.SetSourceAddress(ipHeader.GetSourceAddress());
       // ipHeader_new.SetDestinationAddress(ipHeader.GetDestinationAddress());
        ipHeader_new.SetDestinationAddress(ipHeader.GetSourceAddress()); //Set Source Address as Destination Address (testing purpose)
        
        q->AddHeader (ipHeader_new);
    } 
    
    else
    {
        std::cout << "Header empty" << '\n';
    }
    
    return q;
}


The function call:

Ptr<Packet> g =  ModifyDestinationAddress(packet);   
ret = m_netDevice->Send (packet, dest, protocolNumber);
 
====> The original packet is being sent to the correct destination, even though the destination address of the copied packet has been modified. This was not the case with the previous method.


Thanks again Tommaso for your help.

Regards,
Cristian

Gaurav Gupta

unread,
Nov 6, 2014, 4:25:29 AM11/6/14
to ns-3-...@googlegroups.com
Hi Cristian

I need your help as i am working on something similar kind of work as i have to create one malicious node which will intercept the packet and send it to any other location instead of the proper destination so my question is how can i use your code and where (In which file) i have to perform change. I am working on mobile ipv6 in ns3 dce.

thanks 

gaurav

Cristian

unread,
Nov 6, 2014, 9:03:04 AM11/6/14
to ns-3-...@googlegroups.com
Hi Gaurav,

I would recommend you read the routing overview model [1] to get an understanding of how routing works in ns3. I performed the change in a custom model similar to sixlowpan but in your scenario I think you would be better off modifying it at layer 3 (IP Layer). Concerning the intercept of packets this post [2] might be of help. 

Best wishes,
Cristian

Liwa Hussein

unread,
Mar 25, 2015, 1:58:17 AM3/25/15
to ns-3-...@googlegroups.com
Hello
Sorry for your time
I am now working on a special research to increase the reliability of sensor networks
And  i suggested adding a new feild in the header of each packet to  identified in the event of loss or packet no comparison
I hope you help me set up my own program and apply it on my ns


Liwa
Reply all
Reply to author
Forward
0 new messages