internet: Add GlobalRoutingProtocol testcase

This commit is contained in:
shashwat
2025-06-19 16:23:00 +05:30
committed by Tommaso Pecorella
parent d1134f2b43
commit 91717fd8d1

View File

@@ -5,11 +5,13 @@
#include "ns3/boolean.h"
#include "ns3/bridge-helper.h"
#include "ns3/config.h"
#include "ns3/global-route-manager.h"
#include "ns3/inet-socket-address.h"
#include "ns3/internet-stack-helper.h"
#include "ns3/ipv4-address-helper.h"
#include "ns3/ipv4-global-routing-helper.h"
#include "ns3/ipv4-global-routing.h"
#include "ns3/ipv4-interface.h"
#include "ns3/ipv4-l3-protocol.h"
#include "ns3/ipv4-packet-info-tag.h"
#include "ns3/ipv4-routing-protocol.h"
@@ -31,7 +33,6 @@
#include "ns3/uinteger.h"
#include <vector>
using namespace ns3;
NS_LOG_COMPONENT_DEFINE("Ipv4GlobalRoutingTestSuite");
@@ -1396,6 +1397,369 @@ EcmpRouteCalculationTestCase::DoRun()
Simulator::Destroy();
}
/**
* @ingroup internet-test
*
* @brief TestCase to check calls to GlobalRoutingProtocol API. This TestCase Checks the output
* returned by the GlobalRoutingProtocol API to Ipv4L3 Layer.
*/
class GlobalRoutingProtocolTestCase : public TestCase
{
public:
GlobalRoutingProtocolTestCase();
~GlobalRoutingProtocolTestCase() override;
private:
void DoSetup() override;
void DoRun() override;
/**
* @brief Checks the Path taken by packets by calling RouteInput() and RouteOutput() APIs of
* GlobalRoutingProtocol. This mimics how Ipv4L3Protocol calls these APIs.
* @param pathNodes Vector of nodes in the path. This includes the source node,Intermediate
* nextHop nodes and the destination node.
* @param path Vector of Ipv4Addresses in the path. This includes the source egress IpAddress,
* destination ingress IpAddress and intermediate nextHop Node's ingress Ipaddress that we need
* to check.It does not include the egress addresses for intermediate nodes.
*/
void CheckPath(std::vector<Ptr<Node>> pathNodes, std::vector<Ipv4Address> path);
/**
* @brief Callback function for RouteInput() API of GlobalRoutingProtocol.
* @param route Route to be used for forwarding
* @param packet Packet to be forwarded
* @param header IPv4 header of the packet
*/
void MyUnicastCallback(Ptr<Ipv4Route> route,
Ptr<const Packet> packet,
const Ipv4Header& header);
/**
* @brief Callback function for RouteInput() API of GlobalRoutingProtocol.
* @param packet Packet to be locally delivered
* @param header IPv4 header of the packet
* @param iif Ingress Interface index
*/
void MyLocalDeliverCallback(Ptr<const Packet> packet, const Ipv4Header& header, uint32_t iif);
/**
* @brief Callback function for RouteInput() API of GlobalRoutingProtocol.
* @param packet Packet to be locally delivered
* @param header IPv4 header of the packet
* @param errno_ Socket error number
*/
void MyErrorCallback(Ptr<const Packet> packet,
const Ipv4Header& header,
Socket::SocketErrno errno_);
NodeContainer nodes; //!< Nodes used in the test.
Ptr<Ipv4Route> m_lastRoute; //!< Route to be tested.
Ipv4RoutingProtocol::UnicastForwardCallback m_ucb; ///< Unicast forward callback
Ipv4RoutingProtocol::MulticastForwardCallback m_mcb; ///< Multicast forward callback
Ipv4RoutingProtocol::LocalDeliverCallback m_lcb; ///< Local delivery callback
Ipv4RoutingProtocol::ErrorCallback m_ecb; ///< Error callback
};
// Signature: void (Ptr<Ipv4Route> route, Ptr<const Packet> packet, const Ipv4Header &header)
void
GlobalRoutingProtocolTestCase::MyUnicastCallback(Ptr<Ipv4Route> route,
Ptr<const Packet> packet,
const Ipv4Header& header)
{
NS_LOG_DEBUG("Unicast Forward Callback called.");
m_lastRoute = route;
}
// Signature: void (Ptr<const Packet>, const Ipv4Header&, uint32_t)
void
GlobalRoutingProtocolTestCase::MyLocalDeliverCallback(Ptr<const Packet> packet,
const Ipv4Header& header,
uint32_t iif)
{
NS_LOG_DEBUG("Local Deliver Callback called.");
}
// Signature: void (Ptr<const Packet>, const Ipv4Header&, Socket::SocketErrno)
void
GlobalRoutingProtocolTestCase::MyErrorCallback(Ptr<const Packet> packet,
const Ipv4Header& header,
Socket::SocketErrno errno_)
{
NS_LOG_DEBUG("Error Callback called.");
// Fail the test if this callback is called
NS_TEST_ASSERT_MSG_EQ(1, 1, "Error Callback called in RouteInput");
}
GlobalRoutingProtocolTestCase::GlobalRoutingProtocolTestCase()
: TestCase("Test API calls to GlobalRoutingProtocol")
{
m_ucb = MakeCallback(&GlobalRoutingProtocolTestCase::MyUnicastCallback, this);
m_lcb = MakeCallback(&GlobalRoutingProtocolTestCase::MyLocalDeliverCallback, this);
m_ecb = MakeCallback(&GlobalRoutingProtocolTestCase::MyErrorCallback, this);
// Multicast callback is not used in unicast test, can bind to null or dummy
Ipv4RoutingProtocol::MulticastForwardCallback mcb;
}
GlobalRoutingProtocolTestCase::~GlobalRoutingProtocolTestCase()
{
}
void
GlobalRoutingProtocolTestCase::CheckPath(std::vector<Ptr<Node>> pathNodes,
std::vector<Ipv4Address> path)
{
uint32_t pathSize = path.size();
Ptr<Ipv4L3Protocol> ip = pathNodes[0]->GetObject<Ipv4L3Protocol>();
NS_TEST_ASSERT_MSG_NE(ip, nullptr, "Error-- no Ipv4 object at source node");
Ptr<Ipv4RoutingProtocol> routing = ip->GetRoutingProtocol();
NS_TEST_ASSERT_MSG_NE(routing,
nullptr,
"Error-- no Ipv4 routing protocol object at source node");
Ptr<Ipv4GlobalRouting> globalRouting = routing->GetObject<Ipv4GlobalRouting>();
NS_TEST_ASSERT_MSG_NE(globalRouting,
nullptr,
"Error-- no Ipv4GlobalRouting object at source node");
Socket::SocketErrno errno_;
Ptr<NetDevice> oif(nullptr);
Ptr<Packet> packet = Create<Packet>();
Ipv4Header ipHeader;
ipHeader.SetSource(path[0]);
ipHeader.SetDestination(path[pathSize - 1]);
// for the source node we need to call RouteOutput()
m_lastRoute = globalRouting->RouteOutput(packet, ipHeader, oif, errno_);
// for the rest of the nodes we need to call RouteInput()
for (uint32_t i = 1; i < pathSize; i++)
{
// for each iteration except the last one check that the UnicastForward Callback is called.
// For the last node that is the destination node LocalDelivery Callback will be called.
if (i != pathSize - 1)
{
NS_TEST_ASSERT_MSG_EQ(m_lastRoute->GetGateway(), path[i], "Error-- wrong gateway");
}
ip = pathNodes[i]->GetObject<Ipv4L3Protocol>();
NS_TEST_ASSERT_MSG_NE(ip, nullptr, "Error-- no Ipv4 object at node");
routing = ip->GetRoutingProtocol();
NS_TEST_ASSERT_MSG_NE(routing, nullptr, "Error-- no Ipv4 routing protocol object at node");
globalRouting = routing->GetObject<Ipv4GlobalRouting>();
NS_TEST_ASSERT_MSG_NE(globalRouting,
nullptr,
"Error-- no Ipv4GlobalRouting object at node");
Ptr<Ipv4Interface> interf = ip->GetInterface(ip->GetInterfaceForAddress(path[i]));
Ptr<NetDevice> idevice = interf->GetDevice();
// call RouteInput() for the next node in the path
globalRouting->RouteInput(packet, ipHeader, idevice, m_ucb, m_mcb, m_lcb, m_ecb);
}
}
void
GlobalRoutingProtocolTestCase::DoSetup()
{
/**
* This test case is designed to test the overall functionality of the GlobalRoutingProtocol.
* It tests the calls to the GlobalRoutingProtocol's RouteOutput() and RouteInput() APIs.
* It mimics how Ipv4L3Protocol calls these APIs. The topology covers most of the cases
* that are expected to be handled by the GlobalRoutingProtocol.
*/
//
//
// Network topology
//
// n0
// \ p-p
// \ (shared csma/cd)
// n2 -------------------------n3
// / | |
// / p-p n4 n5 ---------- n6-------n7----Bridge-n8--------n9
// n1 p-p | 10.1.4.0/24
// | |
// ----------------------------------------
// p-p
//
//
//
nodes.Create(10);
NodeContainer n2345 = NodeContainer(nodes.Get(2), nodes.Get(3), nodes.Get(4), nodes.Get(5));
// We create the channels first without any IP addressing information
SimpleNetDeviceHelper devHelper;
devHelper.SetNetDevicePointToPointMode(true);
Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel>();
NetDeviceContainer d0d2 = devHelper.Install(nodes.Get(0), channel1);
d0d2.Add(devHelper.Install(nodes.Get(2), channel1));
Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel>();
NetDeviceContainer d1d6 = devHelper.Install(nodes.Get(1), channel2);
d1d6.Add(devHelper.Install(nodes.Get(6), channel2));
Ptr<SimpleChannel> channel3 = CreateObject<SimpleChannel>();
NetDeviceContainer d1d2 = devHelper.Install(nodes.Get(1), channel3);
d1d2.Add(devHelper.Install(nodes.Get(2), channel3));
Ptr<SimpleChannel> channel4 = CreateObject<SimpleChannel>();
NetDeviceContainer d5d6 = devHelper.Install(nodes.Get(5), channel4);
d5d6.Add(devHelper.Install(nodes.Get(6), channel4));
Ptr<SimpleChannel> channel5 = CreateObject<SimpleChannel>();
devHelper.SetNetDevicePointToPointMode(false);
NetDeviceContainer d6d7 = devHelper.Install(nodes.Get(6), channel5);
d6d7.Add(devHelper.Install(nodes.Get(7), channel5));
devHelper.SetNetDevicePointToPointMode(false);
NetDeviceContainer d2345 = devHelper.Install(n2345);
// handle the bridge
// connect node 7 to node 8(Switch)
Ptr<SimpleChannel> channel6 = CreateObject<SimpleChannel>();
NetDeviceContainer d78 = devHelper.Install(nodes.Get(7), channel6);
d78.Add(devHelper.Install(nodes.Get(8), channel6));
// connect node 8(switch) to node 9
Ptr<SimpleChannel> channel7 = CreateObject<SimpleChannel>();
NetDeviceContainer d89 = devHelper.Install(nodes.Get(8), channel7);
d89.Add(devHelper.Install(nodes.Get(9), channel7));
NetDeviceContainer bridgeFacingDevices;
NetDeviceContainer switchDevices;
bridgeFacingDevices.Add(d78.Get(0));
switchDevices.Add(d78.Get(1));
bridgeFacingDevices.Add(d89.Get(1));
switchDevices.Add(d89.Get(0));
Ptr<Node> switchNode = nodes.Get(8);
BridgeHelper bridge;
bridge.Install(switchNode, switchDevices);
InternetStackHelper internet;
Ipv4GlobalRoutingHelper glbrouting;
internet.SetRoutingHelper(glbrouting);
internet.Install(nodes.Get(0));
internet.Install(nodes.Get(1));
internet.Install(nodes.Get(2));
internet.Install(nodes.Get(3));
internet.Install(nodes.Get(4));
internet.Install(nodes.Get(5));
internet.Install(nodes.Get(6));
internet.Install(nodes.Get(7));
// node 8 is a bridge node
internet.Install(nodes.Get(9));
// Later, we add IP addresses.
Ipv4AddressHelper ipv4;
ipv4.SetBase("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer i0d2 = ipv4.Assign(d0d2);
ipv4.SetBase("10.1.2.0", "255.255.255.0");
Ipv4InterfaceContainer i1d2 = ipv4.Assign(d1d2);
ipv4.SetBase("10.1.3.0", "255.255.255.0");
Ipv4InterfaceContainer i5i6 = ipv4.Assign(d5d6);
ipv4.SetBase("10.250.1.0", "255.255.255.0");
Ipv4InterfaceContainer i2345 = ipv4.Assign(d2345);
ipv4.SetBase("172.16.1.0", "255.255.255.0");
Ipv4InterfaceContainer i1i6 = ipv4.Assign(d1d6);
ipv4.SetBase("10.1.4.0", "255.255.255.0");
Ipv4InterfaceContainer i67 = ipv4.Assign(d6d7);
ipv4.SetBase("10.1.5.0", "255.255.255.0");
Ipv4InterfaceContainer i79 = ipv4.Assign(bridgeFacingDevices);
}
void
GlobalRoutingProtocolTestCase::DoRun()
{
// Create router nodes, initialize routing database and set up the routing
// tables in the nodes.
GlobalRouteManager::ResetRouterId();
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
// tests-------------------------
// test 1:check path from n0 to n6
// test 2:check path from n1 to n5
// test 3:check path from n1 to n9
// test 4:check path from n8 to n0
// Test 1: check path from n0 to n6
std::vector<Ipv4Address>
pathToCheck1; // includes the source egress destination ingress and intermediate next hops
// addresses that we need to check.It does not include the egress addresses
// for intermediate nodes.
pathToCheck1.emplace_back("10.1.1.1");
pathToCheck1.emplace_back("10.1.1.2");
pathToCheck1.emplace_back("10.1.2.1");
pathToCheck1.emplace_back("172.16.1.2");
std::vector<Ptr<Node>>
pathNodes1; // nodes in the path. Includes the source node and the destination node.
pathNodes1.push_back(nodes.Get(0));
pathNodes1.push_back(nodes.Get(2));
pathNodes1.push_back(nodes.Get(1));
pathNodes1.push_back(nodes.Get(6));
CheckPath(pathNodes1, pathToCheck1);
// Test 2:check path from n1 to n5
std::vector<Ipv4Address> pathToCheck2;
pathToCheck2.emplace_back("10.1.2.1");
pathToCheck2.emplace_back("10.1.2.2");
pathToCheck2.emplace_back("10.250.1.4");
std::vector<Ptr<Node>> pathNodes2;
pathNodes2.push_back(nodes.Get(1));
pathNodes2.push_back(nodes.Get(2));
pathNodes2.push_back(nodes.Get(5));
CheckPath(pathNodes2, pathToCheck2);
// Test 3:check path from n1 to n9
std::vector<Ipv4Address> pathToCheck3;
pathToCheck3.emplace_back("172.16.1.1");
pathToCheck3.emplace_back("172.16.1.2");
pathToCheck3.emplace_back("10.1.4.2");
pathToCheck3.emplace_back("10.1.5.2");
std::vector<Ptr<Node>> pathNodes3;
pathNodes3.push_back(nodes.Get(1));
pathNodes3.push_back(nodes.Get(6));
pathNodes3.push_back(nodes.Get(7));
pathNodes3.push_back(nodes.Get(9));
CheckPath(pathNodes3, pathToCheck3);
// Test 4:check path from n9 to n0
std::vector<Ipv4Address> pathToCheck4;
pathToCheck4.emplace_back("10.1.5.2");
pathToCheck4.emplace_back("10.1.5.1");
pathToCheck4.emplace_back("10.1.4.1");
pathToCheck4.emplace_back("10.1.3.1");
pathToCheck4.emplace_back("10.250.1.1");
pathToCheck4.emplace_back("10.1.1.1");
std::vector<Ptr<Node>> pathNodes4;
pathNodes4.push_back(nodes.Get(9));
pathNodes4.push_back(nodes.Get(7));
pathNodes4.push_back(nodes.Get(6));
pathNodes4.push_back(nodes.Get(5));
pathNodes4.push_back(nodes.Get(2));
pathNodes4.push_back(nodes.Get(0));
CheckPath(pathNodes4, pathToCheck4);
Simulator::Run();
Simulator::Stop(Seconds(10));
Simulator::Destroy();
}
/**
* @ingroup internet-test
*
@@ -1419,6 +1783,7 @@ Ipv4GlobalRoutingTestSuite::Ipv4GlobalRoutingTestSuite()
AddTestCase(new Ipv4DynamicGlobalRoutingTestCase, TestCase::Duration::QUICK);
AddTestCase(new Ipv4GlobalRoutingSlash32TestCase, TestCase::Duration::QUICK);
AddTestCase(new EcmpRouteCalculationTestCase, TestCase::Duration::QUICK);
AddTestCase(new GlobalRoutingProtocolTestCase, TestCase::Duration::QUICK);
}
static Ipv4GlobalRoutingTestSuite