Search code examples
c++routesns-3

How to use multi-path routing in NS-3


I'm a beginner of NS-3, I want to configure multi-path routing in my network by NS-3, here is the code:

#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/ipv4-global-routing-helper.h"

using namespace ns3;
using namespace std;

NS_LOG_COMPONENT_DEFINE ("TestRoutingExample");

int main(int argc, char *argv[]) 
{
    LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
    LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);

    Ptr<Node> n0 = CreateObject<Node>();
    Ptr<Node> n1 = CreateObject<Node>();
    Ptr<Node> n2 = CreateObject<Node>();
    Ptr<Node> n3 = CreateObject<Node>();
    Ptr<Node> n4 = CreateObject<Node>();

    Names::Add("n0", n0);
    Names::Add("n1", n1);
    Names::Add("n2", n2);
    Names::Add("n3", n3);
    Names::Add("n4", n4);

    NodeContainer n0n1(n0, n1);
    NodeContainer n1n2(n1, n2);
    NodeContainer n1n3(n1, n3);
    NodeContainer n3n4(n3, n4);
    NodeContainer n2n4(n2, n4);

    NodeContainer global(n0, n1, n2, n3, n4);

    // create link
    PointToPointHelper p2p;
    p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
    p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
    NetDeviceContainer d0d1 = p2p.Install(n0n1);
    NetDeviceContainer d1d2 = p2p.Install(n1n2);
    NetDeviceContainer d1d3 = p2p.Install(n1n3);
    NetDeviceContainer d2d4 = p2p.Install(n2n4);
    NetDeviceContainer d3d4 = p2p.Install(n3n4);
    // create internet stack
    InternetStackHelper internet;
    internet.Install (global);

    Ipv4AddressHelper ipv4;

    ipv4.SetBase ("10.0.0.0", "255.255.255.0");
    Ipv4InterfaceContainer i0i1 = ipv4.Assign (d0d1);

    ipv4.SetBase ("10.1.1.0", "255.255.255.0");
    Ipv4InterfaceContainer i1i2 = ipv4.Assign (d1d2);

    ipv4.SetBase ("10.2.2.0", "255.255.255.0");
    Ipv4InterfaceContainer i1i3 = ipv4.Assign (d1d3);

    ipv4.SetBase ("10.3.3.0", "255.255.255.0");
    Ipv4InterfaceContainer i2i4 = ipv4.Assign (d2d4);

    ipv4.SetBase ("10.4.4.0", "255.255.255.0");
    Ipv4InterfaceContainer i3i4 = ipv4.Assign (d3d4);


    Config::SetDefault("ns3::Ipv4GlobalRouting::RandomEcmpRouting",     BooleanValue(true)); // enable multi-path routing
    Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

    // install application
    UdpEchoServerHelper echoServer1(9999);
    ApplicationContainer serverApps1 = echoServer1.Install (n4);
    serverApps1.Start (Seconds (1.0));
    serverApps1.Stop (Seconds (1000.0));

    // n0 -> n4
    UdpEchoClientHelper echoClient1(i2i4.GetAddress (1), 9999);
    echoClient1.SetAttribute ("MaxPackets", UintegerValue (200));
    echoClient1.SetAttribute ("Interval", TimeValue (Seconds (1)));
    echoClient1.SetAttribute ("PacketSize", UintegerValue (1024));
    ApplicationContainer clientApps1 = echoClient1.Install (n0);
    clientApps1.Start (Seconds (2.0));
    clientApps1.Stop (Seconds (10.0));

    // dump config
    p2p.EnablePcapAll ("test");

    Simulator::Run ();
    Simulator::Destroy ();

    return 0;
}

The topology is as follows:

topology

n0 will periodically send UDP packets to n4, but I find all the packets take the path: n0→n1→n2→n4 by checking the .pcap file, Why?


Solution

  • Take a look at dynamic-global-routing.cc example. Basically you can do this by enabling RespondToInterfaceEvents:

    Config::SetDefault ("ns3::Ipv4GlobalRouting::RespondToInterfaceEvents", BooleanValue (true));
    

    RespondToInterfaceEvents: Set to true if you want to dynamically recompute the global routes upon Interface notification events (up/down, or add/remove address)

    And shutting down one of the interfaces on either node n1 or n4 (since both of them have two interfaces in your case). So it should look something like this:

    Ptr<Ipv4> ipv41 = n1->GetObject<Ipv4> ();
    // The first ifIndex is 0 for loopback, then the first p2p is numbered 1,
    // then the next p2p is numbered 2
    uint32_t ipv4ifIndex1 = 1; // since you first installed d1d2
    
    Simulator::Schedule (Seconds(4), &Ipv4::SetDown, ipv41, ipv4ifIndex1);
    Simulator::Schedule (Seconds(6), &Ipv4::SetUp, ipv41, ipv4ifIndex1);    
    

    Following this approach you can extend it and randomly fire SetDown and SetUp events. I hope this helps.


    Update: If you want to use RandomEcmpRouting you have to move the SetDefault call on top (before you create the interfaces).