File: object-names.cc

package info (click to toggle)
ns3 3.47-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 106,848 kB
  • sloc: cpp: 633,577; python: 15,491; ansic: 6,773; makefile: 1,959; sh: 1,021; pascal: 632; javascript: 167; perl: 102
file content (213 lines) | stat: -rw-r--r-- 7,323 bytes parent folder | download | duplicates (2)
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;
}