direct-code-execution / ns-3-dce

Run real programs in the discrete time simulator ns3
http://www.nsnam.org/projects/direct-code-execution/
75 stars 46 forks source link

dce-iperf Linux stack GetAddress derefferences null ptr #125

Closed ParthPratim closed 2 years ago

ParthPratim commented 2 years ago

Description of the problem

The dce-iperf script works fine when using the InternetStackHelper implemented in ns-3-dev, but fails with the below error when using the LinuxStackHelper implemented in DCE.

assert failed. cond="m_ptr", msg="Attempted to dereference zero pointer", +0.000000000s -1 file=/home/parth27/project/template/bake/build/include/ns3-dev/ns3/ptr.h, line=630

Steps to reproduce

Run the following command to enable the Linux stack in dce-iperf

./waf --run "dce-iperf --stack=linux"

Issue Location in Code

The issue is with the line :

https://github.com/direct-code-execution/ns-3-dce/blob/4bca774a84d55c981cddff2187702a5573134d2f/example/dce-iperf.cc#L119

The Ipv4Linux::GetAddress() implementation cannot seem to reference the 1st index as it exceeds the size of the m_interfaces stack.

ParthPratim commented 2 years ago

https://github.com/direct-code-execution/ns-3-dce/blob/4bca774a84d55c981cddff2187702a5573134d2f/example/dce-iperf.cc#L118-L122

To find a quick fix, I commented out the serverIp string computation code segment, and then replaced the line 122, with the actual server IP address i.e 10.1.1.2. And it worked fine with accurate iperf reports in the file-* folder.

So, As a temporary fix we can have this patch.

But, I was thinking of why Ipv4's GetAddress(...) function works differently in LinuxStackHelper as compared to InternetStackHelper.

After a bit of debugging, I arrived at this conclusion.

The Assign() [1] call of Ipv4InterfaceContainer, calls the AddInterface of the Ipv4 protocol implementation, which in case of LinuxStackHelper, maps to Ipv4Linux::AddInterface() of DCE, and it's implementation was similar to how Ipv4L3Protocol works, the only difference is ns-3's implementation maintains a reverse map from interface-device => interface's-stack-index, for accessing later in GetInterfaceForDevice(). So, now since everything is the same, there has to be something different in the initial m_interface stack.

https://github.com/direct-code-execution/ns-3-dce/blob/4bca774a84d55c981cddff2187702a5573134d2f/helper/linux-stack-helper.cc#L62-L76

The actual difference was between the Install function of LinuxStackHelper and InternetStackHelper[2]. In InternetStackHelper we also aggregate a Ipv4L3Protocol object[3], which goes on to call Ipv4L3Protocol::NotifyNewAggregate (), and further Ipv4L3Protocol::SetNode (Ptr<Node> node), which will further call Ipv4L3Protocol::SetupLoopback (void), which will add an additional LoopbackNetDevice to the Ipv4 interfaces list m_interfaces here [4]. And this is why the size of m_interfaces is 2, and thus accessing the 1th index in the stack is possible, and doesn't throw a null ptr dereference error.

[1] : https://www.nsnam.org/doxygen/ipv4-address-helper_8cc_source.html#l00135 [2] : https://www.nsnam.org/doxygen/internet-stack-helper_8cc_source.html#l00292 [3] : https://www.nsnam.org/doxygen/internet-stack-helper_8cc_source.html#l00304 [4] : https://www.nsnam.org/doxygen/ipv4-l3-protocol_8cc_source.html#l00372

This is probably the cause behind this issue.

tomhenderson commented 2 years ago

Suggested patch to fix: https://github.com/direct-code-execution/ns-3-dce/pull/126