下面進行源碼註釋:
// End-to-end tests for Ipv4 static routing
#include "ns3/boolean.h"
#include "ns3/config.h"
#include "ns3/inet-socket-address.h"
#include "ns3/internet-stack-helper.h"
#include "ns3/ipv4-address-helper.h"
#include "ns3/ipv4-static-routing-helper.h"
#include "ns3/node.h"
#include "ns3/node-container.h"
#include "ns3/packet.h"
#include "ns3/pointer.h"
#include "ns3/simulator.h"
#include "ns3/string.h"
#include "ns3/test.h"
#include "ns3/uinteger.h"
#include "ns3/simple-net-device.h"
#include "ns3/simple-channel.h"
#include "ns3/simple-net-device-helper.h"
#include "ns3/socket-factory.h"
#include "ns3/udp-socket-factory.h"
using namespace ns3;
/**
* \ingroup internet-test
* \ingroup tests
*
* \brief IPv4 StaticRouting /32 Test
*/
class Ipv4StaticRoutingSlash32TestCase : public TestCase
{
public:
Ipv4StaticRoutingSlash32TestCase ();
virtual ~Ipv4StaticRoutingSlash32TestCase ();
Ptr<Packet> m_receivedPacket; //!< Received packet
/**
* \brief Send data.
* \param socket The sending socket.
* \param to Destination address.
*/
void DoSendData (Ptr<Socket> socket, std::string to);
/**
* \brief Send data.
* \param socket The sending socket.
* \param to Destination address.
*/
void SendData (Ptr<Socket> socket, std::string to);
/**
* \brief Receive data.
* \param socket The receiving socket.
*/
void ReceivePkt (Ptr<Socket> socket);
private:
virtual void DoRun (void);
};
// Add some help text to this case to describe what it is intended to test
Ipv4StaticRoutingSlash32TestCase::Ipv4StaticRoutingSlash32TestCase ()
: TestCase ("Slash 32 static routing example")
{
}
Ipv4StaticRoutingSlash32TestCase::~Ipv4StaticRoutingSlash32TestCase ()
{
}
void
Ipv4StaticRoutingSlash32TestCase::ReceivePkt (Ptr<Socket> socket)
{
uint32_t availableData;
availableData = socket->GetRxAvailable ();
m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
NS_ASSERT (availableData == m_receivedPacket->GetSize ());
//cast availableData to void, to suppress 'availableData' set but not used
//compiler warning
(void) availableData;
}
void
Ipv4StaticRoutingSlash32TestCase::DoSendData (Ptr<Socket> socket, std::string to)
{
Address realTo = InetSocketAddress (Ipv4Address (to.c_str ()), 1234);
NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create<Packet> (123), 0, realTo),
123, "100");
}
void
Ipv4StaticRoutingSlash32TestCase::SendData (Ptr<Socket> socket, std::string to)
{
m_receivedPacket = Create<Packet> ();
Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (60),
&Ipv4StaticRoutingSlash32TestCase::DoSendData, this, socket, to);
Simulator::Stop (Seconds (66));
Simulator::Run ();
}
// Test program for this 3-router scenario, using static routing
//
// (a.a.a.a/32)A<--x.x.x.0/30-->B<--y.y.y.0/30-->C(c.c.c.c/32)
//
void
Ipv4StaticRoutingSlash32TestCase::DoRun (void)
{
//這裏創建三個節點
Ptr<Node> nA = CreateObject<Node> ();
Ptr<Node> nB = CreateObject<Node> ();
Ptr<Node> nC = CreateObject<Node> ();
// 安裝協議棧
NodeContainer c = NodeContainer (nA, nB, nC);
InternetStackHelper internet;
internet.Install (c);
// 創建了2個鏈接
// a-------------b----------------c
// |1.1 1.2 | 1.5 1.6 |
// 172.116.1.1/24 192.168.1.1/24
NodeContainer nAnB = NodeContainer (nA, nB);
NodeContainer nBnC = NodeContainer (nB, nC);
// 路由器A添加一個接入的網卡
Ptr<SimpleNetDevice> deviceA = CreateObject<SimpleNetDevice> ();
deviceA->SetAddress (Mac48Address::Allocate ());
nA->AddDevice (deviceA);
// 路由器C添加一個接入網卡
Ptr<SimpleNetDevice> deviceC = CreateObject<SimpleNetDevice> ();
deviceC->SetAddress (Mac48Address::Allocate ());
nC->AddDevice (deviceC);
// 對AB和BC鏈路分別添加一個網間網的互聯網卡
SimpleNetDeviceHelper devHelper;
NetDeviceContainer dAdB = devHelper.Install (nAnB);
NetDeviceContainer dBdC = devHelper.Install (nBnC);
// AB鏈路網間網地址
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.252");
Ipv4InterfaceContainer iAiB = ipv4.Assign (dAdB);
// BC鏈路的網間網地址
ipv4.SetBase ("10.1.1.4", "255.255.255.252");
Ipv4InterfaceContainer iBiC = ipv4.Assign (dBdC);
// 這裏爲3個路由器分別建立1個路由表,所有後面沒有安裝的函數,
Ptr<Ipv4> ipv4A = nA->GetObject<Ipv4> ();
Ptr<Ipv4> ipv4B = nB->GetObject<Ipv4> ();
Ptr<Ipv4> ipv4C = nC->GetObject<Ipv4> ();
// 路由表A中添加了一個接口,返回了接口的索引
int32_t ifIndexA = ipv4A->AddInterface (deviceA);
Ipv4InterfaceAddress ifInAddrA = Ipv4InterfaceAddress (Ipv4Address ("172.16.1.1"), Ipv4Mask ("/32"));
ipv4A->AddAddress (ifIndexA, ifInAddrA); // 路由表內,將接口和地址綁爲一項
ipv4A->SetMetric (ifIndexA, 1); // 到該端口是幾跳
ipv4A->SetUp (ifIndexA); // 將端口設置爲UP狀態
// 路由表C中添加了一個接口,返回了接口的索引
int32_t ifIndexC = ipv4C->AddInterface (deviceC);
Ipv4InterfaceAddress ifInAddrC = Ipv4InterfaceAddress (Ipv4Address ("192.168.1.1"), Ipv4Mask ("/32"));
ipv4C->AddAddress (ifIndexC, ifInAddrC);
ipv4C->SetMetric (ifIndexC, 1);
ipv4C->SetUp (ifIndexC);
// 靜態路由
Ipv4StaticRoutingHelper ipv4RoutingHelper;
// 從A到C
Ptr<Ipv4StaticRouting> staticRoutingA = ipv4RoutingHelper.GetStaticRouting (ipv4A);
// The ifIndex 是 1; the first p2p link added
// 到C的接入網段地址,需要發送到P2P的AB網間網的B口!!
staticRoutingA->AddHostRouteTo (Ipv4Address ("192.168.1.1"), Ipv4Address ("10.1.1.2"), 1);
// 同樣需要在路由器B上設置相關路由
Ptr<Ipv4StaticRouting> staticRoutingB = ipv4RoutingHelper.GetStaticRouting (ipv4B);
// The ifIndex on 路由器 B 是 2; 0 是 loopback地址, 1 是AB鏈路的接口
// 到C的接入網段地址,需要發送到P2P的BC網間網的C口!!
staticRoutingB->AddHostRouteTo (Ipv4Address ("192.168.1.1"), Ipv4Address ("10.1.1.6"), 2);
// 創建發送UDP數據包的測試
Ptr<SocketFactory> rxSocketFactory = nC->GetObject<UdpSocketFactory> ();
Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (InetSocketAddress (Ipv4Address ("192.168.1.1"), 1234)), 0, "trivial");
rxSocket->SetRecvCallback (MakeCallback (&Ipv4StaticRoutingSlash32TestCase::ReceivePkt, this));
Ptr<SocketFactory> txSocketFactory = nA->GetObject<UdpSocketFactory> ();
Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
txSocket->SetAllowBroadcast (true);
// ------ Now the tests ------------
// Unicast test
SendData (txSocket, "192.168.1.1");
NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 123, "Static routing with /32 did not deliver all packets.");
Simulator::Destroy ();
}
/**
* \ingroup internet-test
* \ingroup tests
*
* \brief IPv4 StaticRouting /32 TestSuite
*/
class Ipv4StaticRoutingTestSuite : public TestSuite
{
public:
Ipv4StaticRoutingTestSuite ();
};
Ipv4StaticRoutingTestSuite::Ipv4StaticRoutingTestSuite ()
: TestSuite ("ipv4-static-routing", UNIT)
{
AddTestCase (new Ipv4StaticRoutingSlash32TestCase, TestCase::QUICK);
}
static Ipv4StaticRoutingTestSuite ipv4StaticRoutingTestSuite; //!< Static variable for test initialization