Implementing VNAODV and VNLayer in NS-3

129 views
Skip to first unread message

Víctor Saiáns Vázquez

unread,
Sep 15, 2014, 8:24:53 AM9/15/14
to ns-3-...@googlegroups.com
Hello!

I am trying to implement a routing protocol on the network simulator NS3 and I have some doubts about how to start with my implementation and I hope you could help me.

The scenario is the next: I have to modify the AODV routing protocol for VANETs. First at all I have to add a new protocol layer (called VNLayer) to the protocol stack. This new layer have to be set between the AODV layer and the physical layer. When I achieve this, I have to modify AODV in order to interact with VNLayer converting it to VNAODV. The stack should be like this: Application --> UDP --> VNAODV --> VNLayer --> IEEE 802.11. How should I add the new layer? I have seen how to create a new routing protocol and how to add it to the protocol stack with InternetStackHelper::SetRoutingHelper(), but the Routing protocol is separated in the "step in packet sending process" described here: http://www.nsnam.org/docs/release/3.18/models/html/internet-stack.html#example-path-of-a-packet , and I don't know where I should to add my new Layer. I don't find any information and I am stuck with this.

I have these protocols implemented for NS-2, but I don't know how to add the new VNLayer in the ns-3 stack protocol.

Thanks in advance.

Tommaso Pecorella

unread,
Sep 15, 2014, 2:08:37 PM9/15/14
to ns-3-...@googlegroups.com
Hi,

in your scheme you forgot the IP layer, which is quite important.

As you noted, in the figure the routing protocol is not in between the application and the NetDevice, and tbh the figure is not even totally correct. The RouteOutput function is called many times for each packet to send, both at L4 (TCP, UDP) and lower layers (IP).
Anyway, routing protocol are usually not in "between", they are on the side of the transmission chain. 
In the VN stuff, VNAODV should be on the side of something, probably of the VNLayer. However, I'd really like to know where the VNLayer authors did put the IP layer... I guess you'll first have to find out this.

About ns2 implementation, remember that ns2 allowed with minimal effort to do stuff that is next to impossible in ns-3. This is not a real limitation, as the kind of things that have become increasingly complex to do are also the ones that are next to impossible to do in a real network. In other terms, it's far more difficult to do magic tricks to hide a very bad design or an impossible assumption (e.g., let's assume to know how many packets are in the Tx queues of the surrounding nodes).

Cheers,

T.

Víctor Saiáns Vázquez

unread,
Sep 16, 2014, 5:03:55 AM9/16/14
to ns-3-...@googlegroups.com
Thank you very much for your answer Tommaso. You showed me a way to start.

I asked my tutor where should be the IP layer, and he answer me that in ns-2 they didn't use it, the routing work was done only by AODV or VNAODV, but if in ns-3 there is a prefixed IP layer it shouldn't matter (It only provide IP adressing), and the VNLayer should be between the Ipv4L3Protocol and the ArpIpv4Interface in the "step in packet sending process".

Now I will try to add an empty layer at this level. And when I achieved it I will try to adapt the ns-2 VNLayer implementation and communicate this layer with the routing layer.

Víctor Saiáns Vázquez

unread,
Sep 17, 2014, 10:06:48 AM9/17/14
to ns-3-...@googlegroups.com
I'll need some help with this, I have copied the files ipv4-l3-protocol.cc and ipv4-l3-protocol.h, and I have renamed them to vn-layer-protocol.cc and vn-layer-protocol.h.
Now I am looking for the functions which I have to change in my new class and in the upper and down layers (ipv4-l3-protocol.cc/.h and ipv4-interface.cc/.h) in order to link the packet flow through my new layer. But really I'm not sure about what functions are that. Anybody knows how this classes work? I will appreciate any help with this.

Tommaso Pecorella

unread,
Sep 17, 2014, 10:31:28 AM9/17/14
to ns-3-...@googlegroups.com
Hi,

it's far more complex. Check the sixlowpan module, it does more or less the same you're talking about (even if for IPv6).

Cheers,

T.

Víctor Saiáns Vázquez

unread,
Sep 22, 2014, 7:54:34 AM9/22/14
to ns-3-...@googlegroups.com
Thank you very much Tommaso, now I have achieved to implement my empty VNLayer, which yet only adds/removes a new VNLayer-header to the packets from the closer layers.
The next thing that I want my VNLayer does is sending his own packets according to a state machine controlled by timers. I am thinking about adding a Start() function to my VirtualLayerNetDevice class (equivalent to your SixLowPanNetDevice) in order to initialize the state of the state machine and start the protocol. Something similar to the AODV's Start() function. But I don't know if this new function will be automatically called or if I have to call it explicitly from my simulation script once I had created the topology and configured all the nodes and devices properly.

I am not sure if this is the best method to add the virtual network protocol functionality to this new VirtualLayerNetDevice. I would appreciate very much your opinion at this point of the implementation.

Thanks in advance.

Victor.

Tommaso Pecorella

unread,
Sep 22, 2014, 2:06:25 PM9/22/14
to ns-3-...@googlegroups.com
Hi,

no opinions, it's a design choice. Personally I like that each protocol in each node have its own behaviour, and not to rely on other node's infos. I.e., to have the Start method called as soon as the interfaces are up. Sill, it's a design choice. Other developers can do what they feel right, provided that the end result is the same.

Cheers,

T.

Víctor Saiáns Vázquez

unread,
Sep 30, 2014, 8:07:05 AM9/30/14
to ns-3-...@googlegroups.com
Hello another time (I hope this is the last one),

I have achieved to implement the state machine controlled by some timers, and start the protocol from my simulation script. But now I have a trouble when the protocol has to send a packet to a certain IP address. My first idea was calling this function:

m_netDevice->Send(pkt, hardwareDestination, Ipv4L3Protocol::PROT_NUMBER);

Exactly how the SixLowPanNetDevice::DoSend() function does (The VirtualLayerNetDevice::DoSend() in my case). The problem is that I don't have the destination MAC Address like in the case in which the upper layers generated the packet. Then I thought that I could make an ARP query, something like this:

if (this->NeedsArp()) {
            NS_LOG_LOGIC("Needs ARP" << " " << dst);
            Ptr<ArpL3Protocol> arp = m_node->GetObject<ArpL3Protocol> ();

            Address hardwareDestination;
            bool found = false;
            if (dst.IsBroadcast()) {
                NS_LOG_LOGIC("All-network Broadcast");
                hardwareDestination = m_netDevice->GetBroadcast();
                found = true;
            } else if (dst.IsMulticast()) {
                NS_LOG_LOGIC("IsMulticast");
                NS_ASSERT_MSG(m_netDevice->IsMulticast(),
                        "ArpIpv4Interface::SendTo (): Sending multicast packet over "
                        "non-multicast device");

                hardwareDestination = m_netDevice->GetMulticast(dst);
                found = true;
            } else {

                if (dst.IsSubnetDirectedBroadcast(m_node->GetObject<Ipv4Interface>()->GetAddress(1).GetMask())) {
                    NS_LOG_LOGIC("Subnetwork Broadcast");
                    hardwareDestination = m_netDevice->GetBroadcast();
                    found = true;
                } else {
                    NS_LOG_LOGIC("ARP Lookup");
                    found = arp->Lookup(pkt, dst, m_netDevice, m_node->GetObject<Ipv4Interface>()->GetArpCache(), &hardwareDestination);
                }
            }

            if (found) {
                NS_LOG_LOGIC("Address Resolved.  Send.");

                m_txTrace(pkt, m_node->GetObject<VirtualLayerNetDevice> (), GetIfIndex());

                NS_LOG_DEBUG("VirtualLayerNetDevice::Send " << m_node->GetId() << " " << *pkt);

                m_netDevice->Send(pkt, hardwareDestination, Ipv4L3Protocol::PROT_NUMBER);
            }
        } else {
            NS_LOG_LOGIC("Doesn't need ARP");

            m_txTrace(pkt, m_node->GetObject<VirtualLayerNetDevice> (), GetIfIndex());

            NS_LOG_DEBUG("VirtualLayerNetDevice::Send " << m_node->GetId() << " " << *pkt);

            m_netDevice->Send(pkt, m_netDevice->GetBroadcast(), Ipv4L3Protocol::PROT_NUMBER);
        }

But the compilator return the next error when I call to the arp->Lookup():

[1949/2401] cxx: src/virtual-layer/model/virtual-layer-net-device.cc -> build/src/virtual-layer/model/virtual-layer-net-device.cc.1.o
In file included from ./ns3/object.h:27:0,
                 from ./ns3/channel.h:22,
                 from ../src/virtual-layer/model/virtual-layer-net-device.cc:3:
./ns3/ptr.h: En el destructor ‘ns3::Ptr<T>::~Ptr() [with T = ns3::ArpCache]’:
../src/virtual-layer/model/virtual-layer-net-device.cc:971:112:   instanciado desde aquí
./ns3/ptr.h:457:7: error: uso inválido del tipo incompleto ‘struct ns3::ArpCache’
./ns3/ipv4-interface.h:36:7: error: declaración adelantada de ‘struct ns3::ArpCache’
./ns3/ptr.h: En la función miembro ‘void ns3::Ptr<T>::Acquire() const [with T = ns3::ArpCache]’:
./ns3/ptr.h:442:3:   instanciado desde ‘ns3::Ptr<T>::Ptr(const ns3::Ptr<T>&) [with T = ns3::ArpCache, ns3::Ptr<T> = ns3::Ptr<ns3::ArpCache>]’
../src/virtual-layer/model/virtual-layer-net-device.cc:971:135:   instanciado desde aquí
./ns3/ptr.h:411:7: error: uso inválido del tipo incompleto ‘struct ns3::ArpCache’
./ns3/ipv4-interface.h:36:7: error: declaración adelantada de ‘struct ns3::ArpCache’
Waf: Leaving directory `/home/victor/Escritorio/ns-3-allinone/ns-3-dev/build'
Build failed
 -> task in 'ns3-virtual-layer' failed (exit status 1):
    {task 56934096: cxx virtual-layer-net-device.cc -> virtual-layer-net-device.cc.1.o}
['/usr/bin/g++', '-O0', '-ggdb', '-g3', '-Wall', '-Werror', '-Wno-error=deprecated-declarations', '-fstrict-aliasing', '-Wstrict-aliasing', '-fPIC', '-pthread', '-Isrc/virtual-layer', '-I../src/virtual-layer', '-I.', '-I..', '-DNS3_ASSERT_ENABLE', '-DNS3_LOG_ENABLE', '-DHAVE_SYS_IOCTL_H=1', '-DHAVE_IF_NETS_H=1', '-DHAVE_NET_ETHERNET_H=1', '-DHAVE_PACKET_H=1', '-DHAVE_SQLITE3=1', '-DHAVE_IF_TUN_H=1', '-DHAVE_GSL=1', '../src/virtual-layer/model/virtual-layer-net-device.cc', '-c', '-o', 'src/virtual-layer/model/virtual-layer-net-device.cc.1.o']
make: *** [all] Error 1

Maybe this isn't the correct way of making an ARP query at this layer. Do you know how to do this?

Thanks a lot in advance.

Víctor

Tommaso Pecorella

unread,
Sep 30, 2014, 10:55:21 AM9/30/14
to ns-3-...@googlegroups.com
Hi,

don't worry to ask stuff if you need.

The problems are... many. I have also to confess that I knew in advance that you was going to hit them, but I left you to find 'em by yourself. That because I'm evil and because I think that only if one bash his/her head on a problem can fully understand it.

The most obvious is how you're trying to find the ArpCache. ArpCache*s* to be precise. There is one ArpCache for each Ipv4Interface, i.e., one for each NetDevice. You can't simply call node->GetObject.
You can, of course, call GetObject and find the Ipv4L4Protocol, then ask for the Ipv4Interface corresponding to your NetDevice, then ask for the ArpCache.

The second problem is... it will not work. You could make it work, but it will not work on the long run.
The problem is: you are using a L3+ service from a layer that is BELOW it.
If your goal is to [completely] decouple the IP later from the network by placing a VNLayer in between, adding a dependency between the VNLayer and the IP ARP is exactly something to avoid.
You should, instead, have your own pseudo-ARP at your layer, even defining different interfaces for the IP layer. Otherwise it's not virtual, it's real...

It's funny how implementing something one can discover the amount of things that are needed but not mentioned in the papers. Or, if you want to be more cynic, it's all bells and whistles on the papers, and when you try to implement them it's all bubblegum and kicking asses (and the bubblegums are finished).

Cheers,

T.


PS: there's a solution, but the overhead would be... quite high. Dunno if you are ready to face it.

Víctor Saiáns Vázquez

unread,
Oct 1, 2014, 8:20:48 AM10/1/14
to ns-3-...@googlegroups.com
Hello,

first at all, thank you very much for your replies, you are being really helpful.

Regarding the ARP theme, the first thing I have tried is to make it work accessing to the ArpCache corresponding to the m_netDevice to which the VirtualLayerNetDevice is attached. Doing this:

m_ifIndex = m_node->GetObject<Ipv4L3Protocol>()->GetInterfaceForDevice(m_netDevice);

if (this->NeedsArp()) {
            NS_LOG_INFO("Needs ARP" << " " << dst);

            Ptr<ArpL3Protocol> arp = m_node->GetObject<ArpL3Protocol> ();

            Address hardwareDestination;
            bool found = false;
            if (dst.IsBroadcast()) {
                NS_LOG_INFO("All-network Broadcast");

                hardwareDestination = m_netDevice->GetBroadcast();
                found = true;
            } else if (dst.IsMulticast()) {
                NS_LOG_LOGIC("IsMulticast");
                NS_ASSERT_MSG(m_netDevice->IsMulticast(),
                        "ArpIpv4Interface::SendTo (): Sending multicast packet over "
                        "non-multicast device");

                hardwareDestination = m_netDevice->GetMulticast(dst);
                found = true;
            } else {

                NS_LOG_INFO("ARP Lookup");

                found = arp->Lookup(pkt, dst, m_netDevice, m_node->GetObject<Ipv4L3Protocol>()->GetInterface(m_ifIndex)->GetArpCache(), &hardwareDestination);

            }

            if (found) {
                NS_LOG_INFO("Address Resolved: " << hardwareDestination << ", sending...");


                m_txTrace(pkt, m_node->GetObject<VirtualLayerNetDevice> (), GetIfIndex());

                NS_LOG_DEBUG("VirtualLayerNetDevice::Send " << m_node->GetId() << " " << *pkt);

                m_netDevice->Send(pkt, hardwareDestination, Ipv4L3Protocol::PROT_NUMBER);
            }
        } else {
            NS_LOG_LOGIC("Doesn't need ARP");

            m_txTrace(pkt, m_node->GetObject<VirtualLayerNetDevice> (), GetIfIndex());

            NS_LOG_DEBUG("VirtualLayerNetDevice::Send " << m_node->GetId() << " " << *pkt);

            m_netDevice->Send(pkt, m_netDevice->GetBroadcast(), Ipv4L3Protocol::PROT_NUMBER);
        }

The program compiles, but when I execute my simulation script and the LookUp() method is called it crashes:

Needs ARP 10.1.1.2
ARP Lookup
Command ['/home/victor/Escritorio/ns-3-allinone/ns-3-dev/build/scratch/wave_ex'] terminated with signal SIGSEGV. Run it under a debugger to get more information (./waf --run <program> --command-template="gdb --args %s <args>").

I couldn't make it work.

You are in the true when you said that I shouldn't add a dependency between the VNLayer and the IP ARP. But I don't understand what do you refer to exactly when you said: "your own pseudo-ARP at your layer, even defining different interfaces for the IP layer. Otherwise it's not virtual, it's real...".
I have tried to create my own ARP cache doing this:

        m_ifIndex = m_node->GetObject<Ipv4L3Protocol>()->GetInterfaceForDevice(m_netDevice);

        Ptr<ArpL3Protocol> arp = m_node->GetObject<ArpL3Protocol> ();
        m_cache = arp->CreateCache(m_netDevice, m_node->GetObject<Ipv4L3Protocol>()->GetInterface(m_ifIndex));

But this doesn't eliminate the dependency. And using this new ArpCache when I call to the LookUp() function the result is this:

        found = arp->Lookup(pkt, dst, m_netDevice, m_cache, &hardwareDestination);

But the result is this:

ARP Lookup
assert failed. cond="i >= 0", msg="No device found on node", file=../src/internet/model/ipv4-l3-protocol.cc, line=1055
terminate called without an active exception
Command ['/home/victor/Escritorio/ns-3-allinone/ns-3-dev/build/scratch/wave_ex'] terminated with signal SIGIOT. Run it under a debugger to get more information (./waf --run <program> --command-template="gdb --args %s <args>").

The only solution that I found is sending the MAC address in the header of my VNLayer packets and store it in order to using it when the VNLayer needs to send a packet to a certain IP Address. I think that it could work, but it doesn't seem the best solution.

Could you give me a clue about how to add my own ARP to the VNLayer?


Thanks a lot in advance.

Víctor

Tommaso Pecorella

unread,
Oct 1, 2014, 12:17:49 PM10/1/14
to ns-3-...@googlegroups.com
The ARP cache must NOT be created again. It must be found.
http://www.nsnam.org/docs/doxygen/classns3_1_1_ipv4_interface.html#ab9f56e353b93795c8918cd7aafcf92d9

The other problem is... I'm sorry to say, but I think that the whole "Virtual Node" concept is flawed. You are trying to use a protocol deeply rooted in the upper layer (ARP) in a bottom layer (VNLayer), and the bottom layer aims at provide an abstraction to the upper layer.... there's something wrong. I'm not a blind follower of the Separation of Concerns and Information Hiding principles, but violating them is always something to be carefully evaluated.

I can't tell you what to do to not to do, it's your research. However I see only problems in calling ARP from below.
As a side note, there is one thing to observe: if you're below IP, and your network layer is acting as a NetDevice, then the Ip layer will always send packets WITH the correct destination MAC address.

  /**
   * \param packet packet sent from above down to Network Device
   * \param dest mac address of the destination (already resolved)
   * \param protocolNumber identifies the type of payload contained in
   *        this packet. Used to call the right L3Protocol when the packet
   *        is received.
   *
   *  Called from higher layer to send packet into Network Device
   *  to the specified destination Address
   *
   * \return whether the Send operation succeeded
   */

 
virtual bool Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber) = 0;


"dest" is always correctly filled. No need to ask ARP again.

Cheers,

T.
Reply all
Reply to author
Forward
0 new messages