1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
|
/*
* SPDX-License-Identifier: GPL-2.0-only
*/
// Network topology
//
// n0 n1 n2 n3
// | | | |
// =================
// LAN
//
// This program demonstrates some basic use of the Object names capability
//
#include "ns3/applications-module.h"
#include "ns3/core-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE("ObjectNamesExample");
/// Counter of the received bytes.
uint32_t bytesReceived = 0;
/**
* Function called when a packet is received.
*
* @param context The context.
* @param packet The received packet.
*/
void
RxEvent(std::string context, Ptr<const Packet> packet)
{
std::cout << Simulator::Now().GetSeconds() << "s " << context << " packet size "
<< packet->GetSize() << std::endl;
bytesReceived += packet->GetSize();
}
int
main(int argc, char* argv[])
{
bool outputValidated = true;
CommandLine cmd(__FILE__);
cmd.Parse(argc, argv);
NodeContainer n;
n.Create(4);
//
// We're going to use the zeroth node in the container as the client, and
// the first node as the server. Add some "human readable" names for these
// nodes. The names below will go into the name system as "/Names/clientZero"
// and "/Names/server", but note that the Add function assumes that if you
// omit the leading "/Names/" the remaining string is assumed to be rooted
// in the "/Names" namespace. The following calls,
//
// Names::Add ("clientZero", n.Get (0));
// Names::Add ("/Names/clientZero", n.Get (0));
//
// will produce identical results.
//
Names::Add("clientZero", n.Get(0));
Names::Add("/Names/server", n.Get(1));
//
// It is possible to rename a node that has been previously named. This is
// useful in automatic name generation. You can automatically generate node
// names such as, "node-0", "node-1", etc., and then go back and change
// the name of some distinguished node to another value -- "access-point"
// for example. We illustrate this by just changing the client's name.
// As is typical of the object name service, you can either provide or elide
// the "/Names" prefix as you choose.
//
Names::Rename("clientZero", "client");
InternetStackHelper internet;
internet.Install(n);
CsmaHelper csma;
csma.SetChannelAttribute("DataRate", DataRateValue(DataRate(5000000)));
csma.SetChannelAttribute("Delay", TimeValue(MilliSeconds(2)));
csma.SetDeviceAttribute("Mtu", UintegerValue(1400));
NetDeviceContainer d = csma.Install(n);
//
// Add some human readable names for the devices we'll be interested in.
// We add the names to the name space "under" the nodes we created above.
// This has the effect of making "/Names/client/eth0" and "/Names/server/eth0".
// In this case, we again omit the "/Names/" prefix on one call to illustrate
// the shortcut.
//
Names::Add("/Names/client/eth0", d.Get(0));
Names::Add("server/eth0", d.Get(1));
//
// You can use the object names that you've assigned in calls to the Config
// system to set Object Attributes. For example, you can set the Mtu
// Attribute of a Csma devices using the object naming service. Note that
// in this case, the "/Names" prefix is always required since the _Config_
// system always expects to see a fully qualified path name.
//
Ptr<CsmaNetDevice> csmaNetDevice = d.Get(0)->GetObject<CsmaNetDevice>();
UintegerValue val;
csmaNetDevice->GetAttribute("Mtu", val);
std::cout << "MTU on device 0 before configuration is " << val.Get() << std::endl;
Config::Set("/Names/client/eth0/Mtu", UintegerValue(1234));
// Check the attribute again
csmaNetDevice->GetAttribute("Mtu", val);
std::cout << "MTU on device 0 after configuration is " << val.Get() << std::endl;
if (val.Get() != 1234)
{
outputValidated = false;
}
//
// You can mix and match names and Attributes in calls to the Config system.
// For example, if "eth0" is a named object, you can get to its parent through
// a different namespace. For example, you could use the NodeList namespace
// to get to the server node, and then continue seamlessly adding named objects
// in the path. This is not nearly as readable as the previous version, but it
// illustrates how you can mix and match object names and Attribute names.
// Note that the config path now begins with a path in the "/NodeList"
// namespace.
//
Config::Set("/NodeList/1/eth0/Mtu", UintegerValue(1234));
Ipv4AddressHelper ipv4;
ipv4.SetBase("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer i = ipv4.Assign(d);
uint16_t port = 9;
UdpEchoServerHelper server(port);
//
// Install the UdpEchoServer application on the server node using its name
// directly.
//
ApplicationContainer apps = server.Install("/Names/server");
apps.Start(Seconds(1));
apps.Stop(Seconds(10));
uint32_t packetSize = 1024;
uint32_t maxPacketCount = 1;
Time interPacketInterval = Seconds(1.);
UdpEchoClientHelper client(i.GetAddress(1), port);
client.SetAttribute("MaxPackets", UintegerValue(maxPacketCount));
client.SetAttribute("Interval", TimeValue(interPacketInterval));
client.SetAttribute("PacketSize", UintegerValue(packetSize));
//
// Install the UdpEchoClient application on the server node using its name
// directly.
//
apps = client.Install("/Names/client");
apps.Start(Seconds(2));
apps.Stop(Seconds(10));
//
// Use the Config system to connect a trace source using the object name
// service to specify the path. Note that in this case, the "/Names"
// prefix is always required since the _Config_ system always expects to
// see a fully qualified path name
//
Config::Connect("/Names/client/eth0/MacRx", MakeCallback(&RxEvent));
//
// Set up some pcap tracing on the CSMA devices. The names of the trace
// files will automatically correspond to the object names if present.
// In this case, you will find trace files called:
//
// object-names-client-eth0.pcap
// object-names-server-eth0.pcap
//
// since those nodes and devices have had names associated with them. You
// will also see:
//
// object-names-2-1.pcap
// object-names-3-1.pcap
//
// since nodes two and three have no associated names.
//
csma.EnablePcapAll("object-names");
//
// We can also create a trace file with a name we completely control by
// overriding a couple of default parameters.
//
csma.EnablePcap("client-device.pcap", d.Get(0), false, true);
std::cout << "Running simulation..." << std::endl;
Simulator::Run();
Simulator::Destroy();
// Expected to see ARP exchange and one packet
// 64 bytes (minimum Ethernet frame size) x 2, plus (1024 + 8 + 20 + 18)
if (bytesReceived != (64 + 64 + 1070))
{
outputValidated = false;
}
if (!outputValidated)
{
std::cerr << "Program internal checking failed; returning with error" << std::endl;
return 1;
}
return 0;
}
|