下面进行源码注释:
// 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