25 // Lan0 |
25 // Lan0 |
26 // |
26 // |
27 // - Multicast source is at node n0; |
27 // - Multicast source is at node n0; |
28 // - Multicast forwarded by node n2 onto LAN1; |
28 // - Multicast forwarded by node n2 onto LAN1; |
29 // - Nodes n0, n1, n2, n3, and n4 receive the multicast frame. |
29 // - Nodes n0, n1, n2, n3, and n4 receive the multicast frame. |
30 // - Node n4 listens for the data (actual listener not yet implementted) |
30 // - Node n4 listens for the data |
31 |
31 |
32 #include "ns3/command-line.h" |
32 #include "ns3/core-module.h" |
33 #include "ns3/ptr.h" |
33 #include "ns3/helper-module.h" |
34 #include "ns3/random-variable.h" |
34 #include "ns3/simulator-module.h" |
35 #include "ns3/log.h" |
|
36 #include "ns3/simulator.h" |
|
37 #include "ns3/nstime.h" |
|
38 #include "ns3/data-rate.h" |
|
39 #include "ns3/ascii-trace.h" |
35 #include "ns3/ascii-trace.h" |
40 #include "ns3/pcap-trace.h" |
36 #include "ns3/pcap-trace.h" |
41 #include "ns3/internet-node.h" |
37 |
42 #include "ns3/csma-channel.h" |
|
43 #include "ns3/csma-net-device.h" |
|
44 #include "ns3/csma-topology.h" |
|
45 #include "ns3/csma-ipv4-topology.h" |
|
46 #include "ns3/mac48-address.h" |
|
47 #include "ns3/ipv4-address.h" |
|
48 #include "ns3/inet-socket-address.h" |
|
49 #include "ns3/ipv4.h" |
|
50 #include "ns3/socket.h" |
|
51 #include "ns3/ipv4-route.h" |
|
52 #include "ns3/onoff-application.h" |
|
53 #include "ns3/packet-sink.h" |
|
54 #include "ns3/uinteger.h" |
|
55 |
38 |
56 using namespace ns3; |
39 using namespace ns3; |
57 |
40 |
58 NS_LOG_COMPONENT_DEFINE ("CsmaMulticastExample"); |
41 NS_LOG_COMPONENT_DEFINE ("CsmaMulticastExample"); |
59 |
42 |
60 int |
43 int |
61 main (int argc, char *argv[]) |
44 main (int argc, char *argv[]) |
62 { |
45 { |
63 // |
46 // |
64 // Users may find it convenient to turn on explicit debugging |
47 // Users may find it convenient to turn on explicit debugging |
65 // for selected modules; the below lines suggest how to do this |
48 // for selected modules; the below lines suggest how to do this |
66 // |
49 // |
67 #if 0 |
50 // LogComponentEnable ("CsmaMulticastExample", LOG_LEVEL_INFO); |
68 LogComponentEnable ("CsmaMulticastExample", LOG_LEVEL_INFO); |
|
69 |
51 |
70 LogComponentEnable("Object", LOG_LEVEL_ALL); |
52 // |
71 LogComponentEnable("Queue", LOG_LEVEL_ALL); |
53 // Set up default values for the simulation. |
72 LogComponentEnable("DropTailQueue", LOG_LEVEL_ALL); |
54 // |
73 LogComponentEnable("Channel", LOG_LEVEL_ALL); |
55 // Select Ethernet II-style encapsulation (no LLC/Snap header) |
74 LogComponentEnable("CsmaChannel", LOG_LEVEL_ALL); |
56 Config::SetDefault ("ns3::CsmaNetDevice::EncapsulationMode", String ("IpArp")); |
75 LogComponentEnable("NetDevice", LOG_LEVEL_ALL); |
|
76 LogComponentEnable("CsmaNetDevice", LOG_LEVEL_ALL); |
|
77 LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL); |
|
78 LogComponentEnable("PacketSocket", LOG_LEVEL_ALL); |
|
79 LogComponentEnable("Socket", LOG_LEVEL_ALL); |
|
80 LogComponentEnable("UdpSocket", LOG_LEVEL_ALL); |
|
81 LogComponentEnable("UdpL4Protocol", LOG_LEVEL_ALL); |
|
82 LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL); |
|
83 LogComponentEnable("Ipv4StaticRouting", LOG_LEVEL_ALL); |
|
84 LogComponentEnable("Ipv4Interface", LOG_LEVEL_ALL); |
|
85 LogComponentEnable("ArpIpv4Interface", LOG_LEVEL_ALL); |
|
86 LogComponentEnable("Ipv4LoopbackInterface", LOG_LEVEL_ALL); |
|
87 LogComponentEnable("OnOffApplication", LOG_LEVEL_ALL); |
|
88 LogComponentEnable("PacketSinkApplication", LOG_LEVEL_ALL); |
|
89 LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_ALL); |
|
90 LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_ALL); |
|
91 LogComponentEnable("PacketSinkApplication", LOG_LEVEL_ALL); |
|
92 #endif |
|
93 // |
|
94 // Set up default values for the simulation. Use the DefaultValue::Bind() |
|
95 |
57 |
96 // Allow the user to override any of the defaults and the above Bind() at |
58 // Allow the user to override any of the defaults at |
97 // run-time, via command-line arguments |
59 // run-time, via command-line arguments |
98 // |
|
99 CommandLine cmd; |
60 CommandLine cmd; |
100 cmd.Parse (argc, argv); |
61 cmd.Parse (argc, argv); |
101 // |
62 |
102 // Explicitly create the nodes required by the topology (shown above). |
|
103 // |
|
104 NS_LOG_INFO ("Create nodes."); |
63 NS_LOG_INFO ("Create nodes."); |
105 Ptr<Node> n0 = CreateObject<InternetNode> (); |
64 NodeContainer c; |
106 Ptr<Node> n1 = CreateObject<InternetNode> (); |
65 c.Create (5); |
107 Ptr<Node> n2 = CreateObject<InternetNode> (); |
66 // We will later want two subcontainers of these nodes, for the two LANs |
108 Ptr<Node> n3 = CreateObject<InternetNode> (); |
67 NodeContainer c0 = NodeContainer (c.Get (0), c.Get (1), c.Get (2)); |
109 Ptr<Node> n4 = CreateObject<InternetNode> (); |
68 NodeContainer c1 = NodeContainer (c.Get (2), c.Get (3), c.Get (4)); |
|
69 |
|
70 NS_LOG_INFO ("Build Topology."); |
|
71 CsmaHelper csma; |
|
72 csma.SetChannelParameter ("BitRate", DataRate (5000000)); |
|
73 csma.SetChannelParameter ("Delay", MilliSeconds (2)); |
|
74 |
|
75 // We will use these NetDevice containers later, for IP addressing |
|
76 NetDeviceContainer nd0 = csma.Build (c0); // First LAN |
|
77 NetDeviceContainer nd1 = csma.Build (c1); // Second LAN |
110 |
78 |
111 NS_LOG_INFO ("Create channels."); |
79 NS_LOG_INFO ("Add IP Stack."); |
112 // |
80 InternetStackHelper internet; |
113 // Explicitly create the channels required by the topology (shown above). |
81 internet.Build (c0); |
114 // |
82 internet.Build (c1); |
115 Ptr<CsmaChannel> lan0 = |
|
116 CsmaTopology::CreateCsmaChannel(DataRate(5000000), MilliSeconds(2)); |
|
117 |
83 |
118 Ptr<CsmaChannel> lan1 = |
|
119 CsmaTopology::CreateCsmaChannel(DataRate(5000000), MilliSeconds(2)); |
|
120 |
|
121 NS_LOG_INFO ("Build Topology."); |
|
122 // |
|
123 // Now fill out the topology by creating the net devices required to connect |
|
124 // the nodes to the channels and hooking them up. AddIpv4CsmaNetDevice will |
|
125 // create a net device, add a MAC address (in memory of the pink flamingo) and |
|
126 // connect the net device to a nodes and also to a channel. the |
|
127 // AddIpv4CsmaNetDevice method returns a net device index for the net device |
|
128 // created on the node. Interpret nd0 as the net device we created for node |
|
129 // zero. Interpret nd2Lan0 as the net device we created for node two to |
|
130 // connect to Lan0. |
|
131 // |
|
132 uint32_t nd0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, lan0, |
|
133 Mac48Address("08:00:2e:00:00:00")); |
|
134 uint32_t nd1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, lan0, |
|
135 Mac48Address("08:00:2e:00:00:01")); |
|
136 uint32_t nd2Lan0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan0, |
|
137 Mac48Address("08:00:2e:00:00:02")); |
|
138 |
|
139 uint32_t nd2Lan1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan1, |
|
140 Mac48Address("08:00:2e:00:00:03")); |
|
141 uint32_t nd3 __attribute__ ((unused)) = |
|
142 CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, lan1, |
|
143 Mac48Address("08:00:2e:00:00:04")); |
|
144 uint32_t nd4 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n4, lan1, |
|
145 Mac48Address("08:00:2e:00:00:05")); |
|
146 |
|
147 NS_LOG_INFO ("nd0 = " << nd0); |
|
148 NS_LOG_INFO ("nd1 = " << nd1); |
|
149 NS_LOG_INFO ("nd2Lan0 = " << nd2Lan0); |
|
150 NS_LOG_INFO ("nd2Lan1 = " << nd2Lan1); |
|
151 NS_LOG_INFO ("nd3 = " << nd3); |
|
152 NS_LOG_INFO ("nd4 = " << nd3); |
|
153 // |
|
154 // We've got the "hardware" in place. Now we need to add IP addresses. |
|
155 // |
|
156 NS_LOG_INFO ("Assign IP Addresses."); |
84 NS_LOG_INFO ("Assign IP Addresses."); |
157 CsmaIpv4Topology::AddIpv4Address (n0, nd0, Ipv4Address ("10.1.1.1"), |
85 Ipv4AddressHelper ipv4Addr; |
158 Ipv4Mask ("255.255.255.0")); |
86 ipv4Addr.SetBase ("10.1.1.0", "255.255.255.0"); |
159 |
87 ipv4Addr.Allocate (nd0); |
160 CsmaIpv4Topology::AddIpv4Address (n1, nd1, Ipv4Address ("10.1.1.2"), |
88 ipv4Addr.SetBase ("10.1.2.0", "255.255.255.0"); |
161 Ipv4Mask ("255.255.255.0")); |
89 ipv4Addr.Allocate (nd1); |
162 |
|
163 // |
|
164 // We'll need these addresses later |
|
165 // |
|
166 Ipv4Address n2Lan0Addr ("10.1.1.3"); |
|
167 Ipv4Address n2Lan1Addr ("10.1.2.1"); |
|
168 |
|
169 CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan0, n2Lan0Addr, |
|
170 Ipv4Mask ("255.255.255.0")); |
|
171 // |
|
172 // Assign IP addresses to the net devices and associated interfaces on Lan1 |
|
173 // |
|
174 CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan1, n2Lan1Addr, |
|
175 Ipv4Mask ("255.255.255.0")); |
|
176 |
|
177 CsmaIpv4Topology::AddIpv4Address (n3, nd1, Ipv4Address ("10.1.2.2"), |
|
178 Ipv4Mask ("255.255.255.0")); |
|
179 |
|
180 CsmaIpv4Topology::AddIpv4Address (n4, nd4, Ipv4Address ("10.1.2.3"), |
|
181 Ipv4Mask ("255.255.255.0")); |
|
182 |
90 |
183 NS_LOG_INFO ("Configure multicasting."); |
91 NS_LOG_INFO ("Configure multicasting."); |
184 // |
92 // |
185 // Now we can configure multicasting. As described above, the multicast |
93 // Now we can configure multicasting. As described above, the multicast |
186 // source is at node zero, which we assigned the IP address of 10.1.1.1 |
94 // source is at node zero, which we assigned the IP address of 10.1.1.1 |
187 // earlier. We need to define a multicast group to send packets to. This |
95 // earlier. We need to define a multicast group to send packets to. This |
188 // can be any multicast address from 224.0.0.0 through 239.255.255.255 |
96 // can be any multicast address from 224.0.0.0 through 239.255.255.255 |
189 // (avoiding the reserved routing protocol addresses). We just pick a |
97 // (avoiding the reserved routing protocol addresses). |
190 // convenient number (225.0.0.0) and or in some bits to let us verify that |
98 // |
191 // correct Ethernet multicast addresses are constructed down in the system. |
99 |
192 // |
|
193 Ipv4Address multicastSource ("10.1.1.1"); |
100 Ipv4Address multicastSource ("10.1.1.1"); |
194 Ipv4Address multicastGroup ("225.1.2.4"); |
101 Ipv4Address multicastGroup ("225.1.2.4"); |
195 // |
|
196 // We are going to manually configure multicast routing. This means telling |
|
197 // node two that it should expect multicast data coming from IP address |
|
198 // 10.1.1.1 originally. It should expect these data coming in over its IP |
|
199 // interface connected to Lan0. When node two receives these packets, they |
|
200 // should be forwarded out the interface that connects it to Lan1. |
|
201 // |
|
202 // We're going to need the interface indices on node two corresponding to |
|
203 // these interfaces, which we call ifIndexLan0 and ifIndexLan1. The most |
|
204 // general way to get these interfaces is to look them up by IP address. |
|
205 // Looking back to the topology creation calls above, we saved the addresses |
|
206 // assigned to the interface connecting node two to Lan0 and Lan1. Now is |
|
207 // a fine time to find the interface indices on node two. |
|
208 // |
|
209 Ptr<Ipv4> ipv4; |
|
210 ipv4 = n2->GetObject<Ipv4> (); |
|
211 |
102 |
212 uint32_t ifIndexLan0 = ipv4->FindInterfaceForAddr (n2Lan0Addr); |
103 // Now, we will set up multicast routing. We need to do three things: |
213 uint32_t ifIndexLan1 = ipv4->FindInterfaceForAddr (n2Lan1Addr); |
104 // 1) Configure a (static) multicast route on node n2 |
214 // |
105 // 2) Set up a default multicast route on the sender n0 |
215 // Now, we need to do is to call the AddMulticastRoute () method on node |
106 // 3) Have node n4 join the multicast group |
216 // two's Ipv4 interface and tell it that whenever it receives a packet on |
107 // We have a helper that can help us with static multicast |
217 // the interface from Lan0, with the packet from the multicast source, |
108 StaticMulticastRouteHelper multicast; |
218 // destined for the multicast group, it should forward these packets down |
|
219 // the interface connecting it to Lan1. (Note: the vector of output |
|
220 // interfaces is in case there are multiple net devices on a node -- not |
|
221 // true in this case). |
|
222 // |
|
223 std::vector<uint32_t> outputInterfaces (1); |
|
224 outputInterfaces[0] = ifIndexLan1; |
|
225 |
109 |
226 ipv4->AddMulticastRoute (multicastSource, multicastGroup, ifIndexLan0, |
110 // 1) Configure a (static) multicast route on node n2 (multicastRouter) |
227 outputInterfaces); |
111 Ptr<Node> multicastRouter = c.Get (2); // The node in question |
228 // |
112 Ptr<NetDevice> inputIf = nd0.Get (2); // The input NetDevice |
229 // We need to specify how the source node handles multicasting. There are a |
113 NetDeviceContainer outputDevices; // A container of output NetDevices |
230 // number of ways we can deal with this, we just need to pick one. The first |
114 outputDevices.Add (nd1.Get (0)); // (we only need one NetDevice here) |
231 // method is to add an explicit route out of the source node, just as we did |
115 |
232 // for the forwarding node. Use this method when you want to send packets out |
116 multicast.AddMulticastRoute (multicastRouter, multicastSource, |
233 // multiple interfaces or send packets out different interfaces based on the |
117 multicastGroup, inputIf, outputDevices); |
234 // differing multicast groups. Since the source is local, there will be no |
118 |
235 // input interface over which packets are received, so use |
119 // 2) Set up a default multicast route on the sender n0 |
236 // Ipv4RoutingProtocol::IF_INDEX_ANY as a wildcard. |
120 Ptr<Node> sender = c.Get (0); |
237 // |
121 Ptr<NetDevice> senderIf = nd0.Get(0); |
238 // A second way is to specify a multicast route using wildcards. If you |
122 multicast.SetDefaultMulticastRoute (sender, senderIf); |
239 // want to send multicasts out differing sets of interfaces based on the |
123 |
240 // multicast group, you can use AddMulticastRoute () but specify the origin |
124 // 3) Have node n4 join the multicast group |
241 // as a wildcard. If you want all multicasts to go out a single set of |
125 Ptr<Node> receiver = c.Get (4); |
242 // interfaces, you can make both the origin and group a wildcard. |
126 multicast.JoinMulticastGroup (receiver, multicastSource, multicastGroup); |
243 // |
127 |
244 // If you have a simple system, where the source has a single interface, this |
128 // |
245 // can be done via the SetDefaultMulticastRoute () method on the Ipv4 |
129 // Create an OnOff application to send UDP datagrams from node zero to the |
246 // interface. This tells the system to send all multicasts out a single |
130 // multicast group (node four will be listening). |
247 // specified network interface index. |
131 // |
248 // |
|
249 // A last way is to specify a (or use an existing) default unicast route. The |
|
250 // multicast routing code uses the unicast default route as a multicast "route |
|
251 // of last resort." this method for is also on Ipv4 and is called |
|
252 // SetDefaultRoute (). |
|
253 // |
|
254 // Since this is a simple multicast example, we use the |
|
255 // SetDefaultMulticastRoute () approach. We are going to first need the |
|
256 // Ipv4 interface for node 0 which is the multicast source. We use this |
|
257 // interface to find the output interface index, and tell node zero to send |
|
258 // its multicast traffic out that interface. |
|
259 // |
|
260 ipv4 = n0->GetObject<Ipv4> (); |
|
261 uint32_t ifIndexSrc = ipv4->FindInterfaceForAddr (multicastSource); |
|
262 ipv4->SetDefaultMulticastRoute (ifIndexSrc); |
|
263 // |
|
264 // As described above, node four will be the only node listening for the |
|
265 // multicast data. To enable forwarding bits up the protocol stack, we need |
|
266 // to tell the stack to join the multicast group. |
|
267 // |
|
268 ipv4 = n4->GetObject<Ipv4> (); |
|
269 ipv4->JoinMulticastGroup (multicastSource, multicastGroup); |
|
270 // |
|
271 // Create an OnOff application to send UDP datagrams from node zero to the |
|
272 // multicast group (node four will be listening). |
|
273 // |
|
274 NS_LOG_INFO ("Create Applications."); |
132 NS_LOG_INFO ("Create Applications."); |
275 |
133 |
276 uint16_t port = 9; // Discard port (RFC 863) |
134 uint16_t multicastPort = 9; // Discard port (RFC 863) |
277 |
135 |
278 // Configure a multicast packet generator that generates a packet |
136 // Configure a multicast packet generator that generates a packet |
279 // every few seconds |
137 // every few seconds |
280 Ptr<OnOffApplication> ooff = |
138 OnOffHelper onoff; |
281 CreateObject<OnOffApplication> ("Remote", Address (InetSocketAddress (multicastGroup, port)), |
139 onoff.SetUdpRemote (multicastGroup, multicastPort); |
282 "Protocol", TypeId::LookupByName ("ns3::Udp"), |
140 onoff.SetAppAttribute ("OnTime", ConstantVariable (1)); |
283 "OnTime", ConstantVariable(1), |
141 onoff.SetAppAttribute ("OffTime", ConstantVariable (0)); |
284 "OffTime", ConstantVariable(0), |
142 onoff.SetAppAttribute ("DataRate", DataRate ("255b/s")); |
285 "DataRate", DataRate ("255b/s"), |
143 onoff.SetAppAttribute ("PacketSize", Uinteger (128)); |
286 "PacketSize", Uinteger (128)); |
144 |
287 n0->AddApplication (ooff); |
145 ApplicationContainer srcC = onoff.Build (c0.Get (0)); |
288 // |
146 |
289 // Tell the application when to start and stop. |
147 // |
290 // |
148 // Tell the application when to start and stop. |
291 ooff->Start(Seconds(1.)); |
149 // |
292 ooff->Stop (Seconds(10.)); |
150 srcC.Start(Seconds(1.)); |
|
151 srcC.Stop (Seconds(10.)); |
293 |
152 |
294 // Create an optional packet sink to receive these packets |
153 // Create an optional packet sink to receive these packets |
295 // If you enable logging on this (above) it will print a log statement |
154 PacketSinkHelper sink; |
296 // for every packet received |
155 sink.SetupUdp (Ipv4Address::GetAny(), multicastPort); |
297 Ptr<PacketSink> sink = |
156 ApplicationContainer sinkC = sink.Build (c1.Get (2)); // Node n4 |
298 CreateObject<PacketSink> ("Local", Address (InetSocketAddress (Ipv4Address::GetAny (), port)), |
|
299 "Protocol", TypeId::LookupByName ("ns3::Udp")); |
|
300 n4->AddApplication (sink); |
|
301 // Start the sink |
157 // Start the sink |
302 sink->Start (Seconds (1.0)); |
158 sinkC.Start (Seconds (1.0)); |
303 sink->Stop (Seconds (10.0)); |
159 sinkC.Stop (Seconds (10.0)); |
304 |
160 |
305 // |
161 // |
306 // Configure tracing of all enqueue, dequeue, and NetDevice receive events. |
162 // Configure tracing of all enqueue, dequeue, and NetDevice receive events. |
307 // Trace output will be sent to the file "csma-multicast.tr" |
163 // Trace output will be sent to the file "csma-multicast.tr" |
308 // |
164 // |
309 NS_LOG_INFO ("Configure Tracing."); |
165 NS_LOG_INFO ("Configure Tracing."); |
310 AsciiTrace asciitrace ("csma-multicast.tr"); |
166 AsciiTrace asciitrace ("csma-multicast.tr"); |
311 asciitrace.TraceAllNetDeviceRx (); |
167 asciitrace.TraceAllNetDeviceRx (); |
312 asciitrace.TraceAllQueues (); |
168 asciitrace.TraceAllQueues (); |
313 // |
169 // |
314 // Also configure some tcpdump traces; each interface will be traced. |
170 // Also configure some tcpdump traces; each interface will be traced. |
315 // The output files will be named: |
171 // The output files will be named: |
316 // csma-multicast.pcap-<nodeId>-<interfaceId> |
172 // csma-multicast.pcap-<nodeId>-<interfaceId> |
317 // and can be read by the "tcpdump -r" command (use "-tt" option to |
173 // and can be read by the "tcpdump -r" command (use "-tt" option to |
318 // display timestamps correctly) |
174 // display timestamps correctly) |
319 // |
175 // |
320 PcapTrace pcaptrace ("csma-multicast.pcap"); |
176 PcapTrace pcaptrace ("csma-multicast.pcap"); |
321 pcaptrace.TraceAllIp (); |
177 pcaptrace.TraceAllIp (); |
322 // |
178 // |
323 // Now, do the actual simulation. |
179 // Now, do the actual simulation. |
324 // |
180 // |
325 NS_LOG_INFO ("Run Simulation."); |
181 NS_LOG_INFO ("Run Simulation."); |
326 Simulator::Run (); |
182 Simulator::Run (); |
327 Simulator::Destroy (); |
183 Simulator::Destroy (); |
328 NS_LOG_INFO ("Done."); |
184 NS_LOG_INFO ("Done."); |
329 } |
185 } |