New Layer Implementation Between TCP and IP. Is it Possible Without Changing TCP Socket Implementation Code ?

165 views
Skip to first unread message

Faris Syariati

unread,
Jun 14, 2016, 10:38:10 PM6/14/16
to ns-3-users
Hi. 
I am new to ns3, and now I am doing a research related to new layer between TCP and IP for a certain purpose.
For some time, I am using IPRawSocket implementation to design the new layer, so I can implementing directly on the Application for both sender and sink. However, after digging deep to the TCP Socket implementation on ns3, it seems to possible to implements the new layer on the tcp socket before and after moving it to the IP layer. 

My question is, is it possible to add the layer between TCP and IP without changing any TCP Socket Implementation code? Like by creating a helper and install the layer to the stack. Is there any callback function when the TCP socket send and received data from IP layer? Or should I create a new socket implementation ? 

Thank You.

Tommaso Pecorella

unread,
Jun 15, 2016, 4:49:21 AM6/15/16
to ns-3-users
Hi,

it should be possible to add a shim layer. I.e., one that present itself as an IpL4Protocol to IP and like IP (v4 or v6) to the real L4 protocols.
It's a matter of registering the right callbacks during the setup. SixLowPan uses this trick, check there.

T.

Faris Syariati

unread,
Jun 15, 2016, 10:10:39 AM6/15/16
to ns-3-users
Hi. Thank you for replying. 
I have a follow up question. I opened the example for 6LowPan, an the implementation somehow quite straightforward as what I expected, though it is between IP and CSMA.
On 6Lowpan Net Device I found this one

m_node->RegisterProtocolHandler (MakeCallback (&SixLowPanNetDevice::ReceiveFromDevice, this), protocolType, device, false);


So, does it mean if I make use similar with code above by using type id from IPL4Protocol or TcpL4 I can directly make a callback to the send or received event ? I wonder if I can make use of this one so I can create a similar implementation to registering a callback between them. 

Thank You.

Tommaso Pecorella

unread,
Jun 15, 2016, 10:17:42 AM6/15/16
to ns-3-users
Yes and no.

No because IP uses a different method. Yes because the idea is the same.

T.

Faris Syariati

unread,
Jun 15, 2016, 11:03:08 AM6/15/16
to ns-3-users
Ah. I see. RegisterProtocolHandler's protocolType is for ethernet.
Okay, I am still try to find out. I will read some docs for the protocol implementation. Thanks for the support. 

Faris Syariati

unread,
Jun 15, 2016, 11:43:50 AM6/15/16
to ns-3-users
For additional I am going to try add the callback using TraceConnectWithoutContext for tcp socket on Tx and Rx. hopefully it can intercept the packet on right place. 

Nat P

unread,
Jun 20, 2016, 5:10:30 AM6/20/16
to ns-3-users
Hi,

unfortunately the easy answer is no. There's no callback between IP and TCP. The node Handler is for the communication between NetDevice and IP (please see the documentation on Traffic Control Layer that explains it very well). Inside the Internet module, there are no callback, only inheritance. But....

If you are motivated, you can try to subclass TcpL4Protocol and then implement the Send and Receive method. These are the point of communication with L3.

Just for information purpose, directed to any C++ lovers out there: inheritance IS EVIL, and should be used with CARE. In this case, thanks to inheritance-based design, for implementing something that is logically between IP and TCP, you should subclass the TCP code:

IP ----> [NEW LAYER] ----> TCP     Logically
IP ----> TCP ----> [NEW LAYER]     In the code.

right now we can't do much, but please remember that for your new project or code: IS-A (inheritance) is different from USE-A (store a pointer, or a callback, and use it)

Nat

Tommaso Pecorella

unread,
Jun 20, 2016, 10:55:16 AM6/20/16
to ns-3-users
Hi,

sorry but I disagree with Nat. Not on the Inheritance part, I disagree on HOW to add a shim layer between L4 and L3: inheritance is not needed.

Take for example DSR (it's a routing protocol, but it uses a shim layer). During the protocol creation there's a section that does this:
Ptr<ns3::dsr::DsrRouting> DsrHelper::Create (Ptr<Node> node) const
{
  NS_LOG_FUNCTION
(this);
 
Ptr<ns3::dsr::DsrRouting> agent = m_agentFactory.Create<ns3::dsr::DsrRouting> ();
 
// deal with the downtargets, install UdpL4Protocol, TcpL4Protocol, Icmpv4L4Protocol
 
Ptr<UdpL4Protocol> udp = node->GetObject<UdpL4Protocol> ();
  agent
->SetDownTarget (udp->GetDownTarget ());
  udp
->SetDownTarget (MakeCallback (&dsr::DsrRouting::Send, agent));
 
Ptr<TcpL4Protocol> tcp = node->GetObject<TcpL4Protocol> ();
  tcp
->SetDownTarget (MakeCallback (&dsr::DsrRouting::Send, agent));
 
Ptr<Icmpv4L4Protocol> icmp = node->GetObject<Icmpv4L4Protocol> ();
  icmp
->SetDownTarget (MakeCallback (&dsr::DsrRouting::Send, agent));
  node
->AggregateObject (agent);
 
return agent;
}

The result is the following: all the L4 protocols will use DSR functions to send packets "down" (i.e., to send them).

For the "up" part, in case of DSR it is handled by this:
void DsrRouting::NotifyNewAggregate ()
{
  NS_LOG_FUNCTION
(this << "NotifyNewAggregate");
 
if (m_node == 0)
   
{
     
Ptr<Node> node = this->GetObject<Node> ();
     
if (node != 0)
       
{
          m_ipv4
= this->GetObject<Ipv4L3Protocol> ();
         
if (m_ipv4 != 0)
           
{
             
this->SetNode (node);
              m_ipv4
->Insert (this);
             
this->SetDownTarget (MakeCallback (&Ipv4L3Protocol::Send, m_ipv4));
           
}


          m_ip
= node->GetObject<Ipv4> ();
         
if (m_ip != 0)
           
{
              NS_LOG_DEBUG
("Ipv4 started");
           
}
       
}
   
}
 
IpL4Protocol::NotifyNewAggregate ();
 
Simulator::ScheduleNow (&DsrRouting::Start, this);
}

The "m_ipv4->Insert (this);" will tell IPv4 that it will have to use that class instance as the "up" target for packets that have a protocol number specified by "int DsrRouting::GetProtocolNumber (void) const" (in the DSR case).
If you want to make a real shim layer you can simply override all the protocol numbers that you added earlier. In this way IP will send you all the protocols you want.

At this point it's better to point out what DSR does. It wraps all the packets in its own headers with its own protocol number. Upon receiving the packet it restores the original element.

Anyway, as you can see it is totally possible to add a shim layer without complex inheritances.
Your shim layer need ONLY to subclass IpL4Protocol. Nothing more.

Cheers,

T.


PS: yes, it's a kind of magic.

Faris Syariati

unread,
Jun 20, 2016, 11:34:15 AM6/20/16
to ns-3-users
Dear All.
Thank you for your feedback.

Actually I did to do the similar flow with what Mr. Tomasso explain, not entirely the successful and same way because when I use SetDownTraget in my context, it override all the callback function for TcpL4Protocol down target which is Ipv4::Send. So I have another question, is it possible to still use Ipv4::Send  whilst I only add another line of codes?
Furthermore, I still need implementing Ipv4::Send because I only need to add a new header and do some scheduling on that part. The implementation of DSR seems very similar with my requirement however it replace all down target.  I did also using TxTrace and RxTrace but well I think it is read only (please CMIIW) so it is unlikely.

For now, Unfortunately, my solution still very dirty, on IpV4L3Protocol I add 2 TraceCallback which are placed on Send and Receive function, then I set the callback from outside so before it sen down and up, I can modify the packet freely there. 

m_ipV4->TraceConnectWithoutContext("MpTx", MakeCallback(&MpTransmissionProtocol::SendMpPacket, this));




Ipv4L3Protocol::Send(Ptr<Packet> packet, Ipv4Address source, Ipv4Address destination, uint8_t protocol, Ptr<Ipv4Route> route)

{

m_mpTxTrace(packet, destination);




        NS_LOG_FUNCTION(this << packet << source << destination << uint32_t (protocol) << route);




        Ipv4Header ipHeader;



Faris Syariati

unread,
Jun 20, 2016, 11:45:40 AM6/20/16
to ns-3-users
Hi Nat.

My solution is still dirty because I still not finding the best fit implementation for my necessity. Based on my last reply, I am still doing a another workaround, it is a minimal, but still changing the code on Ipv4L3Protocol using TraceCallback.

Actually, using DownTarget is possible, It is just, the workaround will be complicated since I need to rewrite the Ipv4::Send implementation on my own (In tcpL4Protocol context). Unless my professor asks a very clean implementation, I am thinking to use this current implementation, but I will very glad to find the best way without changing it. I think there IS a way. But maybe not as simple as a, b, c.

Looking forward for another input. I will stay update with my own finding.

Faris 

Tommaso Pecorella

unread,
Jun 20, 2016, 5:15:00 PM6/20/16
to ns-3-users
Hi Faris,

I don't know your exact requirements, so I don't know if the "clean" implementation is easier or not.
I can tell you that on the long run the clean implementations are always better. They require you to re-do some stuff after a first attempt, but the code is far better and you'll avoid a long list of possible problems (and you'll fix faster the bug).

About your question, it's always possible to call directly Ipv4::Send. The whole point of the down target was to NOT do that, otherwise you'd do exactly what Nat was saying: a strong coupling between classes.
Moreover, to prevent your question, the answer is yes. The "shim layer" thing I posted can be done for a single protocol, i.e., you can have your class sitting in between IP and TCP and not between IP and ICMP, for example.

Cheers,

T.

Faris Syariati

unread,
Jun 21, 2016, 1:16:46 AM6/21/16
to ns-3-users
Dear Tomasso,

I got your point.
This is the skeleton how I use the DownTarget to use Ipv4 Send, it works fine so far. 

Ptr<TcpL4Protocol> tcp = nodes.Get(0)->GetObject<TcpL4Protocol>();

Ptr<Ipv4> ipv4 = nodes.Get(0)->GetObject<Ipv4>();tcp->SetDownTarget(MakeBoundCallback(&NewDownTagetCb, ipv4));

tcp->SetDownTarget(MakeBoundCallback(&NewDownTagetCb, ipv4));


void NewDownTagetCb(Ptr<Ipv4> ipv4, Ptr<Packet> packet, Ipv4Address source, Ipv4Address destination, uint8_t protocol, Ptr<Ipv4Route> route)

{

  //Do Something here

   ipv4->Send(packet, source, destination, protocol, route);

}



Thank You.  
Reply all
Reply to author
Forward
0 new messages